Преглед на файлове

Generate user hash on demand

V2Ray преди 10 години
родител
ревизия
ab723fa0b5
променени са 1 файла, в които са добавени 57 реда и са изтрити 13 реда
  1. 57 13
      userset.go

+ 57 - 13
userset.go

@@ -1,9 +1,11 @@
 package core
 
 import (
+	"container/heap"
 	"time"
 
 	v2hash "github.com/v2ray/v2ray-core/hash"
+	"github.com/v2ray/v2ray-core/log"
 )
 
 const (
@@ -19,6 +21,7 @@ type UserSet interface {
 type TimedUserSet struct {
 	validUserIds []ID
 	userHashes   map[string]indexTimePair
+	hash2Remove  hashEntrySet
 }
 
 type indexTimePair struct {
@@ -31,22 +34,62 @@ type hashEntry struct {
 	timeSec int64
 }
 
+type hashEntrySet []*hashEntry
+
+func (set hashEntrySet) Len() int {
+	return len(set)
+}
+
+func (set hashEntrySet) Less(i, j int) bool {
+	return set[i].timeSec < set[j].timeSec
+}
+
+func (set hashEntrySet) Swap(i, j int) {
+	tmp := set[i]
+	set[i] = set[j]
+	set[j] = tmp
+}
+
+func (set *hashEntrySet) Push(value interface{}) {
+	entry := value.(*hashEntry)
+	*set = append(*set, entry)
+}
+
+func (set *hashEntrySet) Pop() interface{} {
+	old := *set
+	n := len(old)
+	v := old[n-1]
+	*set = old[:n-1]
+	return v
+}
+
 func NewTimedUserSet() UserSet {
 	vuSet := new(TimedUserSet)
 	vuSet.validUserIds = make([]ID, 0, 16)
 	vuSet.userHashes = make(map[string]indexTimePair)
+	vuSet.hash2Remove = make(hashEntrySet, 0, cacheDurationSec*10)
 
 	go vuSet.updateUserHash(time.Tick(updateIntervalSec * time.Second))
 	return vuSet
 }
 
+func (us *TimedUserSet) generateNewHashes(lastSec, nowSec int64, idx int, id ID) {
+	idHash := v2hash.NewTimeHash(v2hash.HMACHash{})
+	for lastSec < nowSec+cacheDurationSec {
+
+		idHash := idHash.Hash(id.Bytes, lastSec)
+		log.Debug("Valid User Hash: %v", idHash)
+		heap.Push(&us.hash2Remove, &hashEntry{string(idHash), lastSec})
+		us.userHashes[string(idHash)] = indexTimePair{idx, lastSec}
+		lastSec++
+	}
+}
+
 func (us *TimedUserSet) updateUserHash(tick <-chan time.Time) {
 	now := time.Now().UTC()
-	lastSec := now.Unix() - cacheDurationSec
-
-	hash2Remove := make(chan hashEntry, cacheDurationSec*3*len(us.validUserIds))
+	lastSec := now.Unix()
 	lastSec2Remove := now.Unix()
-	idHash := v2hash.NewTimeHash(v2hash.HMACHash{})
+
 	for {
 		now := <-tick
 		nowSec := now.UTC().Unix()
@@ -54,26 +97,27 @@ func (us *TimedUserSet) updateUserHash(tick <-chan time.Time) {
 		remove2Sec := nowSec - cacheDurationSec
 		if remove2Sec > lastSec2Remove {
 			for lastSec2Remove+1 < remove2Sec {
-				entry := <-hash2Remove
+				front := heap.Pop(&us.hash2Remove)
+				entry := front.(*hashEntry)
 				lastSec2Remove = entry.timeSec
 				delete(us.userHashes, entry.hash)
 			}
 		}
-
-		for lastSec < nowSec+cacheDurationSec {
-			for idx, id := range us.validUserIds {
-				idHash := idHash.Hash(id.Bytes, lastSec)
-				hash2Remove <- hashEntry{string(idHash), lastSec}
-				us.userHashes[string(idHash)] = indexTimePair{idx, lastSec}
-			}
-			lastSec++
+		for idx, id := range us.validUserIds {
+			us.generateNewHashes(lastSec, nowSec, idx, id)
 		}
 	}
 }
 
 func (us *TimedUserSet) AddUser(user User) error {
 	id := user.Id
+	idx := len(us.validUserIds)
 	us.validUserIds = append(us.validUserIds, id)
+
+	nowSec := time.Now().UTC().Unix()
+	lastSec := nowSec - cacheDurationSec
+	us.generateNewHashes(lastSec, nowSec, idx, id)
+
 	return nil
 }