-
Notifications
You must be signed in to change notification settings - Fork 392
/
iterator.go
81 lines (74 loc) · 1.86 KB
/
iterator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package freecache
import (
"unsafe"
)
// Iterator iterates the entries for the cache.
type Iterator struct {
cache *Cache
segmentIdx int
slotIdx int
entryIdx int
}
// Entry represents a key/value pair.
type Entry struct {
Key []byte
Value []byte
ExpireAt uint32
}
// Next returns the next entry for the iterator.
// The order of the entries is not guaranteed.
// If there is no more entries to return, nil will be returned.
func (it *Iterator) Next() *Entry {
for it.segmentIdx < 256 {
entry := it.nextForSegment(it.segmentIdx)
if entry != nil {
return entry
}
it.segmentIdx++
it.slotIdx = 0
it.entryIdx = 0
}
return nil
}
func (it *Iterator) nextForSegment(segIdx int) *Entry {
it.cache.locks[segIdx].Lock()
defer it.cache.locks[segIdx].Unlock()
seg := &it.cache.segments[segIdx]
for it.slotIdx < 256 {
entry := it.nextForSlot(seg, it.slotIdx)
if entry != nil {
return entry
}
it.slotIdx++
it.entryIdx = 0
}
return nil
}
func (it *Iterator) nextForSlot(seg *segment, slotId int) *Entry {
slotOff := int32(it.slotIdx) * seg.slotCap
slot := seg.slotsData[slotOff : slotOff+seg.slotLens[it.slotIdx] : slotOff+seg.slotCap]
for it.entryIdx < len(slot) {
ptr := slot[it.entryIdx]
it.entryIdx++
now := seg.timer.Now()
var hdrBuf [ENTRY_HDR_SIZE]byte
seg.rb.ReadAt(hdrBuf[:], ptr.offset)
hdr := (*entryHdr)(unsafe.Pointer(&hdrBuf[0]))
if hdr.expireAt == 0 || hdr.expireAt > now {
entry := new(Entry)
entry.Key = make([]byte, hdr.keyLen)
entry.Value = make([]byte, hdr.valLen)
entry.ExpireAt = hdr.expireAt
seg.rb.ReadAt(entry.Key, ptr.offset+ENTRY_HDR_SIZE)
seg.rb.ReadAt(entry.Value, ptr.offset+ENTRY_HDR_SIZE+int64(hdr.keyLen))
return entry
}
}
return nil
}
// NewIterator creates a new iterator for the cache.
func (cache *Cache) NewIterator() *Iterator {
return &Iterator{
cache: cache,
}
}