From 3a6bf386866e92f3240894e8dd77b792cf11292e Mon Sep 17 00:00:00 2001 From: v2ray Date: Tue, 31 May 2016 00:21:29 +0200 Subject: [PATCH] remove validity map --- app/router/rules/router.go | 42 +++--------------- app/router/rules/routing_table.go | 70 +++++++++++++++++++++++++++++ common/collect/validity_map.go | 73 ------------------------------- 3 files changed, 76 insertions(+), 109 deletions(-) create mode 100644 app/router/rules/routing_table.go delete mode 100644 common/collect/validity_map.go diff --git a/app/router/rules/router.go b/app/router/rules/router.go index f73faecb..37113cc0 100644 --- a/app/router/rules/router.go +++ b/app/router/rules/router.go @@ -2,12 +2,10 @@ package rules import ( "errors" - "time" "github.com/v2ray/v2ray-core/app" "github.com/v2ray/v2ray-core/app/dns" "github.com/v2ray/v2ray-core/app/router" - "github.com/v2ray/v2ray-core/common/collect" "github.com/v2ray/v2ray-core/common/log" v2net "github.com/v2ray/v2ray-core/common/net" ) @@ -17,43 +15,16 @@ var ( ErrorNoRuleApplicable = errors.New("No rule applicable") ) -type cacheEntry struct { - tag string - err error - validUntil time.Time -} - -func newCacheEntry(tag string, err error) *cacheEntry { - this := &cacheEntry{ - tag: tag, - err: err, - } - this.Extend() - return this -} - -func (this *cacheEntry) IsValid() bool { - return this.validUntil.Before(time.Now()) -} - -func (this *cacheEntry) Extend() { - this.validUntil = time.Now().Add(time.Hour) -} - -func (this *cacheEntry) Release() { - -} - type Router struct { config *RouterRuleConfig - cache *collect.ValidityMap + cache *RoutingTable dnsServer dns.Server } func NewRouter(config *RouterRuleConfig, space app.Space) *Router { r := &Router{ config: config, - cache: collect.NewValidityMap(3600), + cache: NewRoutingTable(), } space.InitializeApplication(func() error { if !space.HasApp(dns.APP_ID) { @@ -113,14 +84,13 @@ func (this *Router) takeDetourWithoutCache(dest v2net.Destination) (string, erro func (this *Router) TakeDetour(dest v2net.Destination) (string, error) { destStr := dest.String() - rawEntry := this.cache.Get(destStr) - if rawEntry == nil { + found, tag, err := this.cache.Get(destStr) + if !found { tag, err := this.takeDetourWithoutCache(dest) - this.cache.Set(destStr, newCacheEntry(tag, err)) + this.cache.Set(destStr, tag, err) return tag, err } - entry := rawEntry.(*cacheEntry) - return entry.tag, entry.err + return tag, err } type RouterFactory struct { diff --git a/app/router/rules/routing_table.go b/app/router/rules/routing_table.go new file mode 100644 index 00000000..4d3a1b33 --- /dev/null +++ b/app/router/rules/routing_table.go @@ -0,0 +1,70 @@ +package rules + +import ( + "sync" + "time" +) + +type RoutingEntry struct { + tag string + err error + expire time.Time +} + +func (this *RoutingEntry) Extend() { + this.expire = time.Now().Add(time.Hour) +} + +func (this *RoutingEntry) Expired() bool { + return this.expire.Before(time.Now()) +} + +type RoutingTable struct { + sync.RWMutex + table map[string]*RoutingEntry +} + +func NewRoutingTable() *RoutingTable { + return &RoutingTable{ + table: make(map[string]*RoutingEntry), + } +} + +func (this *RoutingTable) Cleanup() { + this.Lock() + defer this.Unlock() + + for key, value := range this.table { + if value.Expired() { + delete(this.table, key) + } + } +} + +func (this *RoutingTable) Set(destination string, tag string, err error) { + this.Lock() + defer this.Unlock() + + entry := &RoutingEntry{ + tag: tag, + err: err, + } + entry.Extend() + this.table[destination] = entry + + if len(this.table) > 1000 { + go this.Cleanup() + } +} + +func (this *RoutingTable) Get(destination string) (bool, string, error) { + this.RLock() + defer this.RUnlock() + + entry, found := this.table[destination] + if !found { + return false, "", nil + } + entry.Extend() + return true, entry.tag, entry.err +} diff --git a/common/collect/validity_map.go b/common/collect/validity_map.go deleted file mode 100644 index 045ee9b6..00000000 --- a/common/collect/validity_map.go +++ /dev/null @@ -1,73 +0,0 @@ -package collect - -import ( - "sync" - "sync/atomic" - - "github.com/v2ray/v2ray-core/common" -) - -type Validity interface { - common.Releasable - IsValid() bool -} - -type ValidityMap struct { - sync.RWMutex - cache map[string]Validity - opCount int32 -} - -func NewValidityMap(cleanupIntervalSec int) *ValidityMap { - instance := &ValidityMap{ - cache: make(map[string]Validity), - } - return instance -} - -func (this *ValidityMap) cleanup() { - type entry struct { - key string - value Validity - } - - entry2Remove := make([]entry, 0, 128) - this.RLock() - for key, value := range this.cache { - if !value.IsValid() { - entry2Remove = append(entry2Remove, entry{ - key: key, - value: value, - }) - } - } - this.RUnlock() - - for _, e := range entry2Remove { - if !e.value.IsValid() { - this.Lock() - delete(this.cache, e.key) - this.Unlock() - } - } -} - -func (this *ValidityMap) Set(key string, value Validity) { - this.Lock() - this.cache[key] = value - this.Unlock() - opCount := atomic.AddInt32(&this.opCount, 1) - if opCount > 1000 { - atomic.StoreInt32(&this.opCount, 0) - go this.cleanup() - } -} - -func (this *ValidityMap) Get(key string) Validity { - this.RLock() - defer this.RUnlock() - if value, found := this.cache[key]; found { - return value - } - return nil -}