1
Fork 0

Implement packetcache resizing.

This commit is contained in:
Juliusz Chroboczek 2020-06-04 00:16:21 +02:00
parent b1542af47c
commit b00d2abacf
2 changed files with 97 additions and 0 deletions

View File

@ -139,6 +139,9 @@ func (cache *Cache) GetAt(seqno uint16, index uint16, result []byte) uint16 {
cache.mu.Lock()
defer cache.mu.Unlock()
if int(index) > len(cache.entries) {
return 0
}
if cache.entries[index].seqno != seqno {
return 0
}
@ -148,6 +151,57 @@ func (cache *Cache) GetAt(seqno uint16, index uint16, result []byte) uint16 {
)
}
func (cache *Cache) resize(capacity int) {
if len(cache.entries) == capacity {
return
}
entries := make([]entry, capacity)
if capacity > len(cache.entries) {
copy(entries, cache.entries[:cache.tail])
copy(entries[int(cache.tail)+capacity-len(cache.entries):],
cache.entries[cache.tail:])
} else if capacity > int(cache.tail) {
copy(entries, cache.entries[:cache.tail])
copy(entries[cache.tail:],
cache.entries[int(cache.tail)+
len(cache.entries)-capacity:])
} else {
// too bad, invalidate all indices
copy(entries,
cache.entries[int(cache.tail)-capacity:cache.tail])
cache.tail = 0
}
cache.entries = entries
}
func (cache *Cache) Resize(capacity int) {
cache.mu.Lock()
defer cache.mu.Unlock()
cache.resize(capacity)
}
func (cache *Cache) ResizeCond(capacity int) bool {
cache.mu.Lock()
defer cache.mu.Unlock()
current := len(cache.entries)
if current >= capacity/2 && current < capacity*2 {
return false
}
if int(cache.tail) > current/2 && int(cache.tail) > capacity/2 {
// bad time to resize, this would invalidate too many indices
return false
}
cache.resize(capacity)
return true
}
// Shift 17 bits out of the bitmap. Return a boolean indicating if any
// were 0, the index of the first 0 bit, and a bitmap indicating any
// 0 bits after the first one.

View File

@ -81,6 +81,49 @@ func TestCacheOverflow(t *testing.T) {
}
}
func TestCacheGrow(t *testing.T) {
cache := New(16)
for i := 0; i < 24; i++ {
cache.Store(uint16(i), []byte{uint8(i)})
}
cache.Resize(32)
for i := 0; i < 32; i++ {
expected := uint16(0)
if i < 8 {
expected = uint16(i + 16)
}
if i >= 24 {
expected = uint16(i - 16)
}
if cache.entries[i].seqno != expected {
t.Errorf("At %v, got %v, expected %v",
i, cache.entries[i].seqno, expected)
}
}
}
func TestCacheShrink(t *testing.T) {
cache := New(16)
for i := 0; i < 24; i++ {
cache.Store(uint16(i), []byte{uint8(i)})
}
cache.Resize(12)
for i := 0; i < 12; i++ {
expected := uint16(i + 16)
if i >= 8 {
expected = uint16(i + 4)
}
if cache.entries[i].seqno != expected {
t.Errorf("At %v, got %v, expected %v",
i, cache.entries[i].seqno, expected)
}
}
}
func TestBitmap(t *testing.T) {
value := uint64(0xcdd58f1e035379c0)
packet := make([]byte, 1)