diff --git a/datastruct/dict/concurrent.go b/datastruct/dict/concurrent.go index 2ece9cd6..217143bf 100644 --- a/datastruct/dict/concurrent.go +++ b/datastruct/dict/concurrent.go @@ -185,7 +185,7 @@ func (dict *ConcurrentDict) PutIfAbsentWithLock(key string, val interface{}) (re return 1 } -// PutIfExists puts value if the key is exist and returns the number of inserted key-value +// PutIfExists puts value if the key is existed and returns the number of inserted key-value func (dict *ConcurrentDict) PutIfExists(key string, val interface{}) (result int) { if dict == nil { panic("dict is nil") @@ -262,7 +262,7 @@ func (dict *ConcurrentDict) decreaseCount() int32 { } // ForEach traversal the dict -// it may not visits new entry inserted during traversal +// it may not visit new entry inserted during traversal func (dict *ConcurrentDict) ForEach(consumer Consumer) { if dict == nil { panic("dict is nil") diff --git a/datastruct/dict/simple.go b/datastruct/dict/simple.go index 61839656..49be8f33 100644 --- a/datastruct/dict/simple.go +++ b/datastruct/dict/simple.go @@ -46,7 +46,7 @@ func (dict *SimpleDict) PutIfAbsent(key string, val interface{}) (result int) { return 1 } -// PutIfExists puts value if the key is exist and returns the number of inserted key-value +// PutIfExists puts value if the key is existed and returns the number of inserted key-value func (dict *SimpleDict) PutIfExists(key string, val interface{}) (result int) { _, existed := dict.m[key] if existed { diff --git a/datastruct/lock/lock_map.go b/datastruct/lock/lock_map.go index e4bb4ef5..72fd0963 100644 --- a/datastruct/lock/lock_map.go +++ b/datastruct/lock/lock_map.go @@ -39,7 +39,7 @@ func (locks *Locks) spread(hashCode uint32) uint32 { panic("dict is nil") } tableSize := uint32(len(locks.table)) - return (tableSize - 1) & uint32(hashCode) + return (tableSize - 1) & hashCode } // Lock obtains exclusive lock for writing @@ -90,7 +90,7 @@ func (locks *Locks) toLockIndices(keys []string, reverse bool) []uint32 { } // Locks obtains multiple exclusive locks for writing -// invoking Lock in loop may cause dead lock, please use Locks +// invoking Lock in loop may cause deadlock, please use Locks func (locks *Locks) Locks(keys ...string) { indices := locks.toLockIndices(keys, false) for _, index := range indices { @@ -100,7 +100,7 @@ func (locks *Locks) Locks(keys ...string) { } // RLocks obtains multiple shared locks for reading -// invoking RLock in loop may cause dead lock, please use RLocks +// invoking RLock in loop may cause deadlock, please use RLocks func (locks *Locks) RLocks(keys ...string) { indices := locks.toLockIndices(keys, false) for _, index := range indices { diff --git a/datastruct/sortedset/sortedset.go b/datastruct/sortedset/sortedset.go index 67f7942d..52eacf3a 100644 --- a/datastruct/sortedset/sortedset.go +++ b/datastruct/sortedset/sortedset.go @@ -78,7 +78,7 @@ func (sortedSet *SortedSet) GetRank(member string, desc bool) (rank int64) { // ForEachByRank visits each member which rank within [start, stop), sort by ascending order, rank starts from 0 func (sortedSet *SortedSet) ForEachByRank(start int64, stop int64, desc bool, consumer func(element *Element) bool) { - size := int64(sortedSet.Len()) + size := sortedSet.Len() if start < 0 || start >= size { panic("illegal start " + strconv.FormatInt(start, 10)) } @@ -91,12 +91,12 @@ func (sortedSet *SortedSet) ForEachByRank(start int64, stop int64, desc bool, co if desc { node = sortedSet.skiplist.tail if start > 0 { - node = sortedSet.skiplist.getByRank(int64(size - start)) + node = sortedSet.skiplist.getByRank(size - start) } } else { node = sortedSet.skiplist.header.level[0].forward if start > 0 { - node = sortedSet.skiplist.getByRank(int64(start + 1)) + node = sortedSet.skiplist.getByRank(start + 1) } } diff --git a/tcp/echo_test.go b/tcp/echo_test.go index 1bc211c8..ef2bd5cc 100644 --- a/tcp/echo_test.go +++ b/tcp/echo_test.go @@ -51,3 +51,38 @@ func TestListenAndServe(t *testing.T) { closeChan <- struct{}{} time.Sleep(time.Second) } + +func TestClientCounter(t *testing.T) { + var err error + closeChan := make(chan struct{}) + listener, err := net.Listen("tcp", ":0") + if err != nil { + t.Error(err) + return + } + addr := listener.Addr().String() + go ListenAndServe(listener, MakeEchoHandler(), closeChan) + + sleepUntil := time.Now().Add(3 * time.Second) + subtime := func() time.Duration { + return sleepUntil.Sub(time.Now()) + } + + for i := 0; i < 1000; i++ { + go func() { + conn, err := net.Dial("tcp", addr) + if err != nil { + t.Errorf(err.Error()) + } + defer conn.Close() + + time.Sleep(subtime()) + }() + time.Sleep(5 * time.Microsecond) + } + + time.Sleep(3 * time.Second) + if ClientCounter != 0 { + t.Errorf("client counter error: %d", ClientCounter) + } +} diff --git a/tcp/server.go b/tcp/server.go index e381de17..b74de25d 100644 --- a/tcp/server.go +++ b/tcp/server.go @@ -11,6 +11,7 @@ import ( "os" "os/signal" "sync" + "sync/atomic" "syscall" "time" @@ -26,7 +27,7 @@ type Config struct { } // ClientCounter Record the number of clients in the current Godis server -var ClientCounter int +var ClientCounter int32 // ListenAndServeWithSignal binds port and handle requests, blocking until receive stop signal func ListenAndServeWithSignal(cfg *Config, handler tcp.Handler) error { @@ -88,7 +89,7 @@ func ListenAndServe(listener net.Listener, handler tcp.Handler, closeChan <-chan go func() { defer func() { waitDone.Done() - ClientCounter-- + atomic.AddInt32(&ClientCounter, -1) }() handler.Handle(ctx, conn) }()