Skip to content

Commit 3579964

Browse files
Add GetWithExpirationAndBuf (#137)
* Add GetWithExpirationAndBuf * add tests
1 parent eadf666 commit 3579964

2 files changed

Lines changed: 51 additions & 4 deletions

File tree

‎cache.go‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,17 @@ func (cache *Cache) GetWithExpiration(key []byte) (value []byte, expireAt uint32
217217
return
218218
}
219219

220+
// GetWithExpirationAndBuf copies the value to the buf and gets with expiration or returns a not found error.
221+
// This method doesn't allocate memory when the capacity of buf is greater or equal to value.
222+
func (cache *Cache) GetWithExpirationAndBuf(key []byte, buf []byte) (value []byte, expireAt uint32, err error) {
223+
hashVal := hashFunc(key)
224+
segID := hashVal & segmentAndOpVal
225+
cache.locks[segID].Lock()
226+
value, expireAt, err = cache.segments[segID].get(key, buf, hashVal, false)
227+
cache.locks[segID].Unlock()
228+
return
229+
}
230+
220231
// TTL returns the TTL time left for a given key or a not found error.
221232
func (cache *Cache) TTL(key []byte) (timeLeft uint32, err error) {
222233
hashVal := hashFunc(key)

‎cache_test.go‎

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ func TestGetWithExpiration(t *testing.T) {
213213

214214
res, expiry, err := cache.GetWithExpiration(key)
215215
var expireTime time.Time
216-
var startTime = time.Now()
216+
startTime := time.Now()
217217
for {
218218
_, _, err := cache.GetWithExpiration(key)
219219
expireTime = time.Now()
@@ -237,6 +237,42 @@ func TestGetWithExpiration(t *testing.T) {
237237
}
238238
}
239239

240+
func TestGetWithExpirationAndBuf(t *testing.T) {
241+
cache := NewCache(1024)
242+
key := []byte("abcd")
243+
val := []byte("efgh")
244+
err := cache.Set(key, val, 2)
245+
if err != nil {
246+
t.Error("err should be nil", err.Error())
247+
}
248+
249+
buf := make([]byte, 0, len(val))
250+
res, expiry, err := cache.GetWithExpirationAndBuf(key, buf)
251+
var expireTime time.Time
252+
startTime := time.Now()
253+
for {
254+
_, _, err := cache.GetWithExpirationAndBuf(key, buf)
255+
expireTime = time.Now()
256+
if err != nil {
257+
break
258+
}
259+
if time.Now().Unix() > int64(expiry+1) {
260+
break
261+
}
262+
time.Sleep(1 * time.Millisecond)
263+
}
264+
if time.Second > expireTime.Sub(startTime) || 3*time.Second < expireTime.Sub(startTime) {
265+
t.Error("Cache should expire within a second of the expire time")
266+
}
267+
268+
if err != nil {
269+
t.Error("err should be nil", err.Error())
270+
}
271+
if !bytes.Equal(val, res) {
272+
t.Fatalf("%s should be the same as %s but isn't", res, val)
273+
}
274+
}
275+
240276
func TestExpire(t *testing.T) {
241277
cache := NewCache(1024)
242278
key := []byte("abcd")
@@ -283,7 +319,6 @@ func testTTLWithNoExpireKey(t *testing.T) {
283319

284320
// act
285321
ttl, err := cache.TTL(key)
286-
287322
// assert
288323
if err != nil {
289324
t.Errorf("expected nil, but got %v", err)
@@ -315,7 +350,6 @@ func testTTLWithNotYetExpiredKey(t *testing.T) {
315350

316351
// act
317352
ttl, err := cache.TTL(key)
318-
319353
// assert
320354
if err != nil {
321355
t.Errorf("expected nil, but got %v", err)
@@ -817,6 +851,7 @@ func BenchmarkCacheSet(b *testing.B) {
817851
cache.Set(key[:], make([]byte, 8), 0)
818852
}
819853
}
854+
820855
func BenchmarkParallelCacheSet(b *testing.B) {
821856
cache := NewCache(256 * 1024 * 1024)
822857
var key [8]byte
@@ -1079,7 +1114,8 @@ func TestUpdate(t *testing.T) {
10791114
}
10801115

10811116
assertExpectations := func(testCase int, expectedFound, expectedReplaced bool, expectedPrevVal []byte,
1082-
expectedVal []byte) {
1117+
expectedVal []byte,
1118+
) {
10831119
failPrefix := fmt.Sprintf("%s(%d)", testName, testCase)
10841120

10851121
if expectedFound != found {

0 commit comments

Comments
 (0)