Skip to content

Commit e72ba2b

Browse files
Return error and reject requests
1 parent 8a9d9d0 commit e72ba2b

File tree

5 files changed

+64
-42
lines changed

5 files changed

+64
-42
lines changed

cache/disk/disk.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -393,10 +393,8 @@ func (c *diskCache) commit(key string, legacy bool, tempfile string, reservedSiz
393393
random: random,
394394
}
395395

396-
if !c.lru.Add(key, newItem) {
397-
err = fmt.Errorf("INTERNAL ERROR: failed to add: %s, size %d (on disk: %d)",
398-
key, logicalSize, sizeOnDisk)
399-
log.Println(err.Error())
396+
if err := c.lru.Add(key, newItem); err != nil {
397+
log.Println(err)
400398
return unreserve, removeTempfile, err
401399
}
402400

cache/disk/disk_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,9 +455,10 @@ func TestCacheExistingFiles(t *testing.T) {
455455

456456
evicted := []Key{}
457457
origOnEvict := testCache.lru.onEvict
458-
testCache.lru.onEvict = func(key Key, value lruItem) {
458+
testCache.lru.onEvict = func(key Key, value lruItem) error {
459459
evicted = append(evicted, key.(string))
460460
origOnEvict(key, value)
461+
return nil
461462
}
462463

463464
if testCache.lru.Len() != 4 {

cache/disk/load.go

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -599,14 +599,15 @@ func (c *diskCache) loadExistingFiles(maxSizeBytes int64) error {
599599
// The eviction callback deletes the file from disk.
600600
// This function is only called while the lock is held
601601
// by the current goroutine.
602-
onEvict := func(key Key, value lruItem) {
602+
onEvict := func(key Key, value lruItem) error {
603603
select {
604604
case evictionQueue <- EvictionTask{Key: key, lruItem: value}:
605605
c.evictionGauge.Inc()
606606
c.evictionBytesGauge.Add(float64(value.sizeOnDisk))
607+
return nil
607608
default:
608609
c.evictionCounter.WithLabelValues("full").Inc()
609-
log.Printf("Too many enqueued evictions, could not evict %s", key)
610+
return fmt.Errorf("Too many enqueued evictions, could not evict %s", key)
610611
}
611612
}
612613

@@ -615,12 +616,10 @@ func (c *diskCache) loadExistingFiles(maxSizeBytes int64) error {
615616
c.lru = NewSizedLRU(maxSizeBytes, onEvict, len(result.item))
616617

617618
for i := 0; i < len(result.item); i++ {
618-
ok := c.lru.Add(result.metadata[i].lookupKey, *result.item[i])
619-
if !ok {
620-
err = os.Remove(filepath.Join(c.dir, result.metadata[i].lookupKey))
621-
if err != nil {
622-
return err
623-
}
619+
err := c.lru.Add(result.metadata[i].lookupKey, *result.item[i])
620+
if err != nil {
621+
_ = os.Remove(filepath.Join(c.dir, result.metadata[i].lookupKey))
622+
return err
624623
}
625624
}
626625

cache/disk/lru.go

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import (
1717
type Key interface{}
1818

1919
// EvictCallback is the type of callbacks that are invoked when items are evicted.
20-
type EvictCallback func(key Key, value lruItem)
20+
type EvictCallback func(key Key, value lruItem) error
2121

2222
// SizedLRU is an LRU cache that will keep its total size below maxSize by evicting
2323
// items.
@@ -101,25 +101,27 @@ func (c *SizedLRU) RegisterMetrics() {
101101
// Note that this function rounds file sizes up to the nearest
102102
// BlockSize (4096) bytes, as an estimate of actual disk usage since
103103
// most linux filesystems default to 4kb blocks.
104-
func (c *SizedLRU) Add(key Key, value lruItem) (ok bool) {
104+
func (c *SizedLRU) Add(key Key, value lruItem) error {
105105

106106
roundedUpSizeOnDisk := roundUp4k(value.sizeOnDisk)
107107

108108
if roundedUpSizeOnDisk > c.maxSize {
109-
return false
109+
return fmt.Errorf("Unable to reserve space for blob (size: %d) larger than cache size %d", roundedUpSizeOnDisk, c.maxSize)
110110
}
111111

112112
var sizeDelta, uncompressedSizeDelta int64
113113
if ee, ok := c.cache[key]; ok {
114114
sizeDelta = roundedUpSizeOnDisk - roundUp4k(ee.Value.(*entry).value.sizeOnDisk)
115115
if c.reservedSize+sizeDelta > c.maxSize {
116-
return false
116+
return fmt.Errorf("INTERNAL ERROR: not enough space for blob with size %d (undersized cache?)", value.size)
117117
}
118118
uncompressedSizeDelta = roundUp4k(value.size) - roundUp4k(ee.Value.(*entry).value.size)
119119

120120
prevValue := ee.Value.(*entry).value
121121
if c.onEvict != nil {
122-
c.onEvict(key, prevValue)
122+
if err := c.onEvict(key, prevValue); err != nil {
123+
return err
124+
}
123125
}
124126

125127
c.ll.MoveToFront(ee)
@@ -128,7 +130,7 @@ func (c *SizedLRU) Add(key Key, value lruItem) (ok bool) {
128130
} else {
129131
sizeDelta = roundedUpSizeOnDisk
130132
if c.reservedSize+sizeDelta > c.maxSize {
131-
return false
133+
return fmt.Errorf("INTERNAL ERROR: unable to reclaim enough space for blob with size %d (undersized cache?)", value.size)
132134
}
133135
uncompressedSizeDelta = roundUp4k(value.size)
134136
ele := c.ll.PushFront(&entry{key, value})
@@ -140,7 +142,11 @@ func (c *SizedLRU) Add(key Key, value lruItem) (ok bool) {
140142
for c.currentSize+sizeDelta > c.maxSize {
141143
ele := c.ll.Back()
142144
if ele != nil {
143-
c.removeElement(ele)
145+
err := c.removeElement(ele)
146+
if err != nil {
147+
delete(c.cache, key)
148+
return err
149+
}
144150
}
145151
}
146152

@@ -150,7 +156,7 @@ func (c *SizedLRU) Add(key Key, value lruItem) (ok bool) {
150156
c.gaugeCacheSizeBytes.Set(float64(c.currentSize))
151157
c.gaugeCacheLogicalBytes.Set(float64(c.uncompressedSize))
152158

153-
return true
159+
return nil
154160
}
155161

156162
// Get looks up a key in the cache
@@ -164,12 +170,16 @@ func (c *SizedLRU) Get(key Key) (value lruItem, ok bool) {
164170
}
165171

166172
// Remove removes a (key, value) from the cache
167-
func (c *SizedLRU) Remove(key Key) {
173+
func (c *SizedLRU) Remove(key Key) error {
168174
if ele, hit := c.cache[key]; hit {
169-
c.removeElement(ele)
175+
err := c.removeElement(ele)
176+
if err != nil {
177+
return err
178+
}
170179
c.gaugeCacheSizeBytes.Set(float64(c.currentSize))
171180
c.gaugeCacheLogicalBytes.Set(float64(c.uncompressedSize))
172181
}
182+
return nil
173183
}
174184

175185
// Len returns the number of items in the cache
@@ -234,7 +244,10 @@ func (c *SizedLRU) Reserve(size int64) (bool, error) {
234244
for sumLargerThan(size, c.currentSize, c.maxSize) {
235245
ele := c.ll.Back()
236246
if ele != nil {
237-
c.removeElement(ele)
247+
err := c.removeElement(ele)
248+
if err != nil {
249+
return false, err
250+
}
238251
} else {
239252
return false, errReservation // This should have been caught at the start.
240253
}
@@ -267,7 +280,7 @@ func (c *SizedLRU) Unreserve(size int64) error {
267280
return nil
268281
}
269282

270-
func (c *SizedLRU) removeElement(e *list.Element) {
283+
func (c *SizedLRU) removeElement(e *list.Element) error {
271284
c.ll.Remove(e)
272285
kv := e.Value.(*entry)
273286
delete(c.cache, kv.key)
@@ -276,8 +289,12 @@ func (c *SizedLRU) removeElement(e *list.Element) {
276289
c.counterEvictedBytes.Add(float64(kv.value.sizeOnDisk))
277290

278291
if c.onEvict != nil {
279-
c.onEvict(kv.key, kv.value)
292+
err := c.onEvict(kv.key, kv.value)
293+
if err != nil {
294+
return err
295+
}
280296
}
297+
return nil
281298
}
282299

283300
// Round n up to the nearest multiple of BlockSize (4096).

cache/disk/lru_test.go

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ func TestBasics(t *testing.T) {
3737
// Add an item
3838
aKey := "akey"
3939
anItem := lruItem{size: 5, sizeOnDisk: 5}
40-
ok = lru.Add(aKey, anItem)
41-
if !ok {
42-
t.Fatalf("Add: failed inserting item")
40+
err := lru.Add(aKey, anItem)
41+
if err != nil {
42+
t.Fatalf("Add: failed inserting item: %s", err)
4343
}
4444

4545
getItem, getOk := lru.Get(aKey)
@@ -53,15 +53,19 @@ func TestBasics(t *testing.T) {
5353
checkSizeAndNumItems(t, lru, BlockSize, 1)
5454

5555
// Remove the item
56-
lru.Remove(aKey)
56+
err = lru.Remove(aKey)
57+
if err != nil {
58+
t.Fatal(err)
59+
}
5760
checkSizeAndNumItems(t, lru, 0, 0)
5861
}
5962

6063
func TestEviction(t *testing.T) {
6164
// Keep track of evictions using the callback
6265
var evictions []int
63-
onEvict := func(key Key, value lruItem) {
66+
onEvict := func(key Key, value lruItem) error {
6467
evictions = append(evictions, key.(int))
68+
return nil
6569
}
6670

6771
lru := NewSizedLRU(10*BlockSize, onEvict, 0)
@@ -85,9 +89,9 @@ func TestEviction(t *testing.T) {
8589

8690
for i, thisExpected := range expectedSizesNumItems {
8791
item := lruItem{size: int64(i) * BlockSize, sizeOnDisk: int64(i) * BlockSize}
88-
ok := lru.Add(i, item)
89-
if !ok {
90-
t.Fatalf("Add: failed adding %d", i)
92+
err := lru.Add(i, item)
93+
if err != nil {
94+
t.Fatalf("Add: failed adding %d: %s", i, err)
9195
}
9296

9397
checkSizeAndNumItems(t, lru, thisExpected.expBlocks*BlockSize, thisExpected.expNumItems)
@@ -103,8 +107,8 @@ func TestRejectBigItem(t *testing.T) {
103107
// Bounded caches should reject big items
104108
lru := NewSizedLRU(10, nil, 0)
105109

106-
ok := lru.Add("hello", lruItem{size: 11, sizeOnDisk: 11})
107-
if ok {
110+
err := lru.Add("hello", lruItem{size: 11, sizeOnDisk: 11})
111+
if err == nil {
108112
t.Fatalf("Add succeeded, expected it to fail")
109113
}
110114

@@ -115,7 +119,10 @@ func TestReserveZeroAlwaysPossible(t *testing.T) {
115119
largeItem := lruItem{size: math.MaxInt64, sizeOnDisk: math.MaxInt64}
116120

117121
lru := NewSizedLRU(math.MaxInt64, nil, 0)
118-
lru.Add("foo", largeItem)
122+
err := lru.Add("foo", largeItem)
123+
if err != nil {
124+
t.Fatal(err)
125+
}
119126
ok, err := lru.Reserve(0)
120127
if err != nil {
121128
t.Fatal(err)
@@ -246,8 +253,8 @@ func TestAddWithSpaceReserved(t *testing.T) {
246253
t.Fatalf("Expected to be able to reserve 1")
247254
}
248255

249-
ok = lru.Add("hello", lruItem{size: 2, sizeOnDisk: 2})
250-
if ok {
256+
err = lru.Add("hello", lruItem{size: 2, sizeOnDisk: 2})
257+
if err == nil {
251258
t.Fatal("Expected to not be able to add item with size 2")
252259
}
253260

@@ -256,8 +263,8 @@ func TestAddWithSpaceReserved(t *testing.T) {
256263
t.Fatal("Expected to be able to unreserve 1:", err)
257264
}
258265

259-
ok = lru.Add("hello", lruItem{size: 2, sizeOnDisk: 2})
260-
if !ok {
261-
t.Fatal("Expected to be able to add item with size 2")
266+
err = lru.Add("hello", lruItem{size: 2, sizeOnDisk: 2})
267+
if err != nil {
268+
t.Fatalf("Expected to be able to add item with size 2: %s", err)
262269
}
263270
}

0 commit comments

Comments
 (0)