github.com/decred/dcrlnd@v0.7.6/kvdb/etcd/readwrite_cursor.go (about) 1 //go:build kvdb_etcd 2 // +build kvdb_etcd 3 4 package etcd 5 6 // readWriteCursor holds a reference to the cursors bucket, the value 7 // prefix and the current key used while iterating. 8 type readWriteCursor struct { 9 // bucket holds the reference to the parent bucket. 10 bucket *readWriteBucket 11 12 // prefix holds the value prefix which is in front of each 13 // value key in the bucket. 14 prefix string 15 16 // currKey holds the current key of the cursor. 17 currKey string 18 } 19 20 func newReadWriteCursor(bucket *readWriteBucket) *readWriteCursor { 21 return &readWriteCursor{ 22 bucket: bucket, 23 prefix: string(bucket.id), 24 } 25 } 26 27 // First positions the cursor at the first key/value pair and returns 28 // the pair. 29 func (c *readWriteCursor) First() (key, value []byte) { 30 // Get the first key with the value prefix. 31 kv, err := c.bucket.tx.stm.First(c.prefix) 32 if err != nil { 33 // TODO: revise this once kvdb interface supports errors 34 return nil, nil 35 } 36 37 if kv != nil { 38 c.currKey = kv.key 39 return getKeyVal(kv) 40 } 41 42 return nil, nil 43 } 44 45 // Last positions the cursor at the last key/value pair and returns the 46 // pair. 47 func (c *readWriteCursor) Last() (key, value []byte) { 48 kv, err := c.bucket.tx.stm.Last(c.prefix) 49 if err != nil { 50 // TODO: revise this once kvdb interface supports errors 51 return nil, nil 52 } 53 54 if kv != nil { 55 c.currKey = kv.key 56 return getKeyVal(kv) 57 } 58 59 return nil, nil 60 } 61 62 // Next moves the cursor one key/value pair forward and returns the new 63 // pair. 64 func (c *readWriteCursor) Next() (key, value []byte) { 65 kv, err := c.bucket.tx.stm.Next(c.prefix, c.currKey) 66 if err != nil { 67 // TODO: revise this once kvdb interface supports errors 68 return nil, nil 69 } 70 71 if kv != nil { 72 c.currKey = kv.key 73 return getKeyVal(kv) 74 } 75 76 return nil, nil 77 } 78 79 // Prev moves the cursor one key/value pair backward and returns the new 80 // pair. 81 func (c *readWriteCursor) Prev() (key, value []byte) { 82 kv, err := c.bucket.tx.stm.Prev(c.prefix, c.currKey) 83 if err != nil { 84 // TODO: revise this once kvdb interface supports errors 85 return nil, nil 86 } 87 88 if kv != nil { 89 c.currKey = kv.key 90 return getKeyVal(kv) 91 } 92 93 return nil, nil 94 } 95 96 // Seek positions the cursor at the passed seek key. If the key does 97 // not exist, the cursor is moved to the next key after seek. Returns 98 // the new pair. 99 func (c *readWriteCursor) Seek(seek []byte) (key, value []byte) { 100 // Seek to the first key with prefix + seek. If that key is not present 101 // STM will seek to the next matching key with prefix. 102 kv, err := c.bucket.tx.stm.Seek(c.prefix, c.prefix+string(seek)) 103 if err != nil { 104 // TODO: revise this once kvdb interface supports errors 105 return nil, nil 106 } 107 108 if kv != nil { 109 c.currKey = kv.key 110 return getKeyVal(kv) 111 } 112 113 return nil, nil 114 } 115 116 // Delete removes the current key/value pair the cursor is at without 117 // invalidating the cursor. Returns ErrIncompatibleValue if attempted 118 // when the cursor points to a nested bucket. 119 func (c *readWriteCursor) Delete() error { 120 if isBucketKey(c.currKey) { 121 c.bucket.DeleteNestedBucket(getKey(c.currKey)) 122 } else { 123 c.bucket.Delete(getKey(c.currKey)) 124 } 125 126 return nil 127 }