|
|
@ -32,7 +32,7 @@ func (s *cacheShard) get(key string, hashedKey uint64) ([]byte, error) { |
|
|
|
if itemIndex == 0 { |
|
|
|
if itemIndex == 0 { |
|
|
|
s.lock.RUnlock() |
|
|
|
s.lock.RUnlock() |
|
|
|
s.miss() |
|
|
|
s.miss() |
|
|
|
return nil, notFound(key) |
|
|
|
return nil, ErrEntryNotFound |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
wrappedEntry, err := s.entries.Get(int(itemIndex)) |
|
|
|
wrappedEntry, err := s.entries.Get(int(itemIndex)) |
|
|
@ -47,11 +47,12 @@ func (s *cacheShard) get(key string, hashedKey uint64) ([]byte, error) { |
|
|
|
} |
|
|
|
} |
|
|
|
s.lock.RUnlock() |
|
|
|
s.lock.RUnlock() |
|
|
|
s.collision() |
|
|
|
s.collision() |
|
|
|
return nil, notFound(key) |
|
|
|
return nil, ErrEntryNotFound |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
entry := readEntry(wrappedEntry) |
|
|
|
s.lock.RUnlock() |
|
|
|
s.lock.RUnlock() |
|
|
|
s.hit() |
|
|
|
s.hit() |
|
|
|
return readEntry(wrappedEntry), nil |
|
|
|
return entry, nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (s *cacheShard) set(key string, hashedKey uint64, entry []byte) error { |
|
|
|
func (s *cacheShard) set(key string, hashedKey uint64, entry []byte) error { |
|
|
@ -85,17 +86,17 @@ func (s *cacheShard) set(key string, hashedKey uint64, entry []byte) error { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (s *cacheShard) del(key string, hashedKey uint64) error { |
|
|
|
func (s *cacheShard) del(key string, hashedKey uint64) error { |
|
|
|
|
|
|
|
// Optimistic pre-check using only readlock
|
|
|
|
s.lock.RLock() |
|
|
|
s.lock.RLock() |
|
|
|
itemIndex := s.hashmap[hashedKey] |
|
|
|
itemIndex := s.hashmap[hashedKey] |
|
|
|
|
|
|
|
|
|
|
|
if itemIndex == 0 { |
|
|
|
if itemIndex == 0 { |
|
|
|
s.lock.RUnlock() |
|
|
|
s.lock.RUnlock() |
|
|
|
s.delmiss() |
|
|
|
s.delmiss() |
|
|
|
return notFound(key) |
|
|
|
return ErrEntryNotFound |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
wrappedEntry, err := s.entries.Get(int(itemIndex)) |
|
|
|
if err := s.entries.CheckGet(int(itemIndex)); err != nil { |
|
|
|
if err != nil { |
|
|
|
|
|
|
|
s.lock.RUnlock() |
|
|
|
s.lock.RUnlock() |
|
|
|
s.delmiss() |
|
|
|
s.delmiss() |
|
|
|
return err |
|
|
|
return err |
|
|
@ -104,6 +105,23 @@ func (s *cacheShard) del(key string, hashedKey uint64) error { |
|
|
|
|
|
|
|
|
|
|
|
s.lock.Lock() |
|
|
|
s.lock.Lock() |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
// After obtaining the writelock, we need to read the same again,
|
|
|
|
|
|
|
|
// since the data delivered earlier may be stale now
|
|
|
|
|
|
|
|
itemIndex = s.hashmap[hashedKey] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if itemIndex == 0 { |
|
|
|
|
|
|
|
s.lock.Unlock() |
|
|
|
|
|
|
|
s.delmiss() |
|
|
|
|
|
|
|
return ErrEntryNotFound |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
wrappedEntry, err := s.entries.Get(int(itemIndex)) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
s.lock.Unlock() |
|
|
|
|
|
|
|
s.delmiss() |
|
|
|
|
|
|
|
return err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
delete(s.hashmap, hashedKey) |
|
|
|
delete(s.hashmap, hashedKey) |
|
|
|
s.onRemove(wrappedEntry, Deleted) |
|
|
|
s.onRemove(wrappedEntry, Deleted) |
|
|
|
resetKeyFromEntry(wrappedEntry) |
|
|
|
resetKeyFromEntry(wrappedEntry) |
|
|
@ -136,17 +154,22 @@ func (s *cacheShard) cleanUp(currentTimestamp uint64) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (s *cacheShard) getOldestEntry() ([]byte, error) { |
|
|
|
func (s *cacheShard) getOldestEntry() ([]byte, error) { |
|
|
|
|
|
|
|
s.lock.RLock() |
|
|
|
|
|
|
|
defer s.lock.RUnlock() |
|
|
|
return s.entries.Peek() |
|
|
|
return s.entries.Peek() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (s *cacheShard) getEntry(index int) ([]byte, error) { |
|
|
|
func (s *cacheShard) getEntry(index int) ([]byte, error) { |
|
|
|
return s.entries.Get(index) |
|
|
|
s.lock.RLock() |
|
|
|
|
|
|
|
entry, err := s.entries.Get(index) |
|
|
|
|
|
|
|
s.lock.RUnlock() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return entry, err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (s *cacheShard) copyKeys() (keys []uint32, next int) { |
|
|
|
func (s *cacheShard) copyKeys() (keys []uint32, next int) { |
|
|
|
keys = make([]uint32, len(s.hashmap)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
s.lock.RLock() |
|
|
|
s.lock.RLock() |
|
|
|
|
|
|
|
keys = make([]uint32, len(s.hashmap)) |
|
|
|
|
|
|
|
|
|
|
|
for _, index := range s.hashmap { |
|
|
|
for _, index := range s.hashmap { |
|
|
|
keys[next] = index |
|
|
|
keys[next] = index |
|
|
|