github.com/coocood/badger@v1.5.1-0.20200528065104-c02ac3616d04/table/memtable/table.go (about) 1 package memtable 2 3 import ( 4 "bytes" 5 "sort" 6 "sync/atomic" 7 "unsafe" 8 9 "github.com/coocood/badger/table" 10 "github.com/coocood/badger/y" 11 ) 12 13 type Entry struct { 14 Key []byte 15 Value y.ValueStruct 16 } 17 18 func (e *Entry) EstimateSize() int64 { 19 return int64(len(e.Key) + int(e.Value.EncodedSize()) + EstimateNodeSize) 20 } 21 22 type Table struct { 23 skl *skiplist 24 id uint64 25 pendingList unsafe.Pointer // *listNode 26 compacting int32 27 } 28 29 func New(arenaSize int64, id uint64) *Table { 30 return &Table{ 31 skl: newSkiplist(arenaSize), 32 id: id, 33 } 34 } 35 36 func (t *Table) ID() uint64 { 37 return t.id 38 } 39 40 func (t *Table) Delete() error { 41 t.skl.Delete() 42 return nil 43 } 44 45 func (t *Table) Close() error { 46 return nil 47 } 48 49 func (t *Table) Empty() bool { 50 return atomic.LoadPointer(&t.pendingList) == nil && t.skl.Empty() 51 } 52 53 func (t *Table) Get(key y.Key, keyHash uint64) (y.ValueStruct, error) { 54 curr := (*listNode)(atomic.LoadPointer(&t.pendingList)) 55 for curr != nil { 56 if v, ok := curr.get(key); ok { 57 return v, nil 58 } 59 curr = (*listNode)(atomic.LoadPointer(&curr.next)) 60 } 61 return t.skl.Get(key.UserKey, key.Version), nil 62 } 63 64 func (t *Table) NewIterator(reverse bool) y.Iterator { 65 var ( 66 sklItr = t.skl.NewUniIterator(reverse) 67 its []y.Iterator 68 ) 69 curr := (*listNode)(atomic.LoadPointer(&t.pendingList)) 70 for curr != nil { 71 its = append(its, curr.newIterator(reverse)) 72 curr = (*listNode)(atomic.LoadPointer(&curr.next)) 73 } 74 75 if len(its) == 0 { 76 return sklItr 77 } 78 its = append(its, sklItr) 79 return table.NewMergeIterator(its, reverse) 80 } 81 82 func (t *Table) Size() int64 { 83 var sz int64 84 curr := (*listNode)(atomic.LoadPointer(&t.pendingList)) 85 for curr != nil { 86 sz += curr.memSize 87 curr = (*listNode)(atomic.LoadPointer(&curr.next)) 88 } 89 return t.skl.MemSize() + sz 90 } 91 92 func (t *Table) Smallest() y.Key { 93 it := t.NewIterator(false) 94 it.Rewind() 95 return it.Key() 96 } 97 98 func (t *Table) Biggest() y.Key { 99 it := t.NewIterator(true) 100 it.Rewind() 101 return it.Key() 102 } 103 104 func (t *Table) HasOverlap(start, end y.Key, includeEnd bool) bool { 105 it := t.NewIterator(false) 106 it.Seek(start.UserKey) 107 if !it.Valid() { 108 return false 109 } 110 if cmp := it.Key().Compare(end); cmp > 0 { 111 return false 112 } else if cmp == 0 { 113 return includeEnd 114 } 115 return true 116 } 117 118 func (t *Table) MarkCompacting(flag bool) { 119 if flag { 120 atomic.StoreInt32(&t.compacting, 1) 121 } 122 atomic.StoreInt32(&t.compacting, 0) 123 } 124 125 func (t *Table) IsCompacting() bool { 126 return atomic.LoadInt32(&t.compacting) == 1 127 } 128 129 // PutToSkl directly insert entry into SkipList. 130 func (t *Table) PutToSkl(key []byte, v y.ValueStruct) { 131 t.skl.Put(key, v) 132 } 133 134 // PutToPendingList put entries to pending list, and you can call MergeListToSkl to merge them to SkipList later. 135 func (t *Table) PutToPendingList(entries []Entry) { 136 t.putToList(entries) 137 } 138 139 // MergeListToSkl merge all entries in pending list to SkipList. 140 func (t *Table) MergeListToSkl() { 141 head := (*listNode)(atomic.LoadPointer(&t.pendingList)) 142 if head == nil { 143 return 144 } 145 146 head.mergeToSkl(t.skl) 147 // No new node inserted, just update head of list. 148 if atomic.CompareAndSwapPointer(&t.pendingList, unsafe.Pointer(head), nil) { 149 return 150 } 151 // New node inserted, iterate to find `prev` of old head. 152 curr := (*listNode)(atomic.LoadPointer(&t.pendingList)) 153 for curr != nil { 154 next := atomic.LoadPointer(&curr.next) 155 if unsafe.Pointer(head) == next { 156 atomic.StorePointer(&curr.next, nil) 157 return 158 } 159 curr = (*listNode)(next) 160 } 161 } 162 163 func (t *Table) putToList(entries []Entry) { 164 n := newListNode(entries) 165 for { 166 old := atomic.LoadPointer(&t.pendingList) 167 n.next = old 168 if atomic.CompareAndSwapPointer(&t.pendingList, old, unsafe.Pointer(n)) { 169 return 170 } 171 } 172 } 173 174 type listNode struct { 175 next unsafe.Pointer // *listNode 176 entries []Entry 177 latestOffs []uint32 178 memSize int64 179 } 180 181 func newListNode(entries []Entry) *listNode { 182 n := &listNode{entries: entries, latestOffs: make([]uint32, 0, len(entries))} 183 var curKey []byte 184 for i, e := range n.entries { 185 sz := e.EstimateSize() 186 n.memSize += sz 187 if !bytes.Equal(e.Key, curKey) { 188 n.latestOffs = append(n.latestOffs, uint32(i)) 189 curKey = e.Key 190 } 191 } 192 return n 193 } 194 195 func (n *listNode) putToSkl(s *skiplist, entries []Entry) { 196 var h hint 197 for _, e := range entries { 198 s.PutWithHint(e.Key, e.Value, &h) 199 } 200 } 201 202 func (n *listNode) mergeToSkl(skl *skiplist) { 203 next := (*listNode)(atomic.LoadPointer(&n.next)) 204 if next != nil { 205 next.mergeToSkl(skl) 206 } 207 atomic.StorePointer(&n.next, nil) 208 n.putToSkl(skl, n.entries) 209 } 210 211 func (n *listNode) get(key y.Key) (y.ValueStruct, bool) { 212 i := sort.Search(len(n.entries), func(i int) bool { 213 e := n.entries[i] 214 return y.KeyWithTs(e.Key, e.Value.Version).Compare(key) >= 0 215 }) 216 if i < len(n.entries) && bytes.Equal(key.UserKey, n.entries[i].Key) { 217 return n.entries[i].Value, true 218 } 219 return y.ValueStruct{}, false 220 } 221 222 func (n *listNode) newIterator(reverse bool) *listNodeIterator { 223 return &listNodeIterator{reversed: reverse, n: n} 224 } 225 226 type listNodeIterator struct { 227 idx int 228 verIdx uint32 229 n *listNode 230 reversed bool 231 } 232 233 func (it *listNodeIterator) Next() { 234 if !it.reversed { 235 it.idx++ 236 it.verIdx = 0 237 } else { 238 it.idx-- 239 it.verIdx = 0 240 } 241 } 242 243 func (it *listNodeIterator) NextVersion() bool { 244 nextKeyEntryOff := uint32(len(it.n.entries)) 245 if it.idx+1 < len(it.n.latestOffs) { 246 nextKeyEntryOff = it.n.latestOffs[it.idx+1] 247 } 248 if it.getEntryIdx()+1 < nextKeyEntryOff { 249 it.verIdx++ 250 return true 251 } 252 return false 253 } 254 255 func (it *listNodeIterator) getEntryIdx() uint32 { 256 return it.n.latestOffs[it.idx] + it.verIdx 257 } 258 259 func (it *listNodeIterator) Rewind() { 260 if !it.reversed { 261 it.idx = 0 262 it.verIdx = 0 263 } else { 264 it.idx = len(it.n.latestOffs) - 1 265 it.verIdx = 0 266 } 267 } 268 269 func (it *listNodeIterator) Seek(key []byte) { 270 it.idx = sort.Search(len(it.n.latestOffs), func(i int) bool { 271 e := &it.n.entries[it.n.latestOffs[i]] 272 return bytes.Compare(e.Key, key) >= 0 273 }) 274 it.verIdx = 0 275 if it.reversed { 276 if !it.Valid() || !bytes.Equal(it.Key().UserKey, key) { 277 it.idx-- 278 } 279 } 280 } 281 282 func (it *listNodeIterator) Key() y.Key { 283 e := &it.n.entries[it.getEntryIdx()] 284 return y.KeyWithTs(e.Key, e.Value.Version) 285 } 286 287 func (it *listNodeIterator) Value() y.ValueStruct { return it.n.entries[it.idx].Value } 288 289 func (it *listNodeIterator) FillValue(vs *y.ValueStruct) { *vs = it.Value() } 290 291 func (it *listNodeIterator) Valid() bool { return it.idx >= 0 && it.idx < len(it.n.latestOffs) }