github.com/weaviate/weaviate@v1.24.6/adapters/repos/db/lsmkv/cursor_memtable_collection.go (about) 1 // _ _ 2 // __ _____ __ ___ ___ __ _| |_ ___ 3 // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ 4 // \ V V / __/ (_| |\ V /| | (_| | || __/ 5 // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| 6 // 7 // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. 8 // 9 // CONTACT: hello@weaviate.io 10 // 11 12 package lsmkv 13 14 import ( 15 "bytes" 16 17 "github.com/weaviate/weaviate/entities/lsmkv" 18 ) 19 20 type memtableCursorCollection struct { 21 data []*binarySearchNodeMulti 22 current int 23 lock func() 24 unlock func() 25 } 26 27 func (m *Memtable) newCollectionCursor() innerCursorCollection { 28 // This cursor is a really primitive approach, it actually requires 29 // flattening the entire memtable - even if the cursor were to point to the 30 // very last element. However, given that the memtable will on average be 31 // only half it's max capacity and even that is relatively small, we might 32 // get away with the full-flattening and a linear search. Let's not optimize 33 // prematurely. 34 35 m.RLock() 36 defer m.RUnlock() 37 38 data := m.keyMulti.flattenInOrder() 39 40 return &memtableCursorCollection{ 41 data: data, 42 lock: m.RLock, 43 unlock: m.RUnlock, 44 } 45 } 46 47 func (c *memtableCursorCollection) first() ([]byte, []value, error) { 48 c.lock() 49 defer c.unlock() 50 51 if len(c.data) == 0 { 52 return nil, nil, lsmkv.NotFound 53 } 54 55 c.current = 0 56 57 // there is no key-level tombstone, only individual values can have 58 // tombstones 59 return c.data[c.current].key, c.data[c.current].values, nil 60 } 61 62 func (c *memtableCursorCollection) seek(key []byte) ([]byte, []value, error) { 63 c.lock() 64 defer c.unlock() 65 66 pos := c.posLargerThanEqual(key) 67 if pos == -1 { 68 return nil, nil, lsmkv.NotFound 69 } 70 71 c.current = pos 72 // there is no key-level tombstone, only individual values can have 73 // tombstones 74 return c.data[pos].key, c.data[pos].values, nil 75 } 76 77 func (c *memtableCursorCollection) posLargerThanEqual(key []byte) int { 78 for i, node := range c.data { 79 if bytes.Compare(node.key, key) >= 0 { 80 return i 81 } 82 } 83 84 return -1 85 } 86 87 func (c *memtableCursorCollection) next() ([]byte, []value, error) { 88 c.lock() 89 defer c.unlock() 90 91 c.current++ 92 if c.current >= len(c.data) { 93 return nil, nil, lsmkv.NotFound 94 } 95 96 // there is no key-level tombstone, only individual values can have 97 // tombstones 98 return c.data[c.current].key, c.data[c.current].values, nil 99 }