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  }