github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/database/leveldb/iterator.go (about)

     1  // Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package leveldb
     6  
     7  // #include <stdlib.h>
     8  // #include <leveldb/c.h>
     9  import "C"
    10  import "unsafe"
    11  
    12  // Iterator is a read-only iterator through a LevelDB database. It provides a
    13  // way to seek to specific keys and iterate through the keyspace from that
    14  // point, as well as access the values of those keys.
    15  //
    16  // Care must be taken when using an Iterator. If the method Valid returns
    17  // false, calls to Key, Value, Next, and Prev will result in panics. However,
    18  // Seek, SeekToFirst, SeekToLast, GetError, Valid, and Close will still be
    19  // safe to call.
    20  //
    21  // GetError will only return an error in the event of a LevelDB error. It will
    22  // return a nil on iterators that are simply invalid. Given that behavior,
    23  // GetError is not a replacement for a Valid.
    24  //
    25  // A typical use looks like:
    26  //
    27  // 	db := levigo.Open(...)
    28  //
    29  // 	it := db.NewIterator(readOpts)
    30  // 	defer it.Close()
    31  // 	it.Seek(mykey)
    32  // 	for it = it; it.Valid(); it.Next() {
    33  // 		useKeyAndValue(it.Key(), it.Value())
    34  // 	}
    35  // 	if err := it.GetError() {
    36  // 		...
    37  // 	}
    38  //
    39  // To prevent memory leaks, an Iterator must have Close called on it when it
    40  // is no longer needed by the program.
    41  type Iterator struct {
    42  	iter *C.leveldb_iterator_t
    43  }
    44  
    45  // Valid returns false only when an Iterator has iterated past either the
    46  // first or the last key in the database.
    47  func (it *Iterator) Valid() bool {
    48  	return ucharToBool(C.leveldb_iter_valid(it.iter))
    49  }
    50  
    51  // Key returns a copy the key in the database the iterator currently holds.
    52  //
    53  // If Valid returns false, this method will panic.
    54  func (it *Iterator) Key() []byte {
    55  	var klen C.size_t
    56  	kdata := C.leveldb_iter_key(it.iter, &klen)
    57  	if kdata == nil {
    58  		return nil
    59  	}
    60  	// Unlike DB.Get, the key, kdata, returned is not meant to be freed by the
    61  	// client. It's a direct reference to data managed by the iterator_t
    62  	// instead of a copy.  So, we must not free it here but simply copy it
    63  	// with GoBytes.
    64  	return C.GoBytes(unsafe.Pointer(kdata), C.int(klen))
    65  }
    66  
    67  // Value returns a copy of the value in the database the iterator currently
    68  // holds.
    69  //
    70  // If Valid returns false, this method will panic.
    71  func (it *Iterator) Value() []byte {
    72  	var vlen C.size_t
    73  	vdata := C.leveldb_iter_value(it.iter, &vlen)
    74  	if vdata == nil {
    75  		return nil
    76  	}
    77  	// Unlike DB.Get, the value, vdata, returned is not meant to be freed by
    78  	// the client. It's a direct reference to data managed by the iterator_t
    79  	// instead of a copy. So, we must not free it here but simply copy it with
    80  	// GoBytes.
    81  	return C.GoBytes(unsafe.Pointer(vdata), C.int(vlen))
    82  }
    83  
    84  // Next moves the iterator to the next sequential key in the database, as
    85  // defined by the Comparator in the ReadOptions used to create this Iterator.
    86  //
    87  // If Valid returns false, this method will panic.
    88  func (it *Iterator) Next() {
    89  	C.leveldb_iter_next(it.iter)
    90  }
    91  
    92  // Prev moves the iterator to the previous sequential key in the database, as
    93  // defined by the Comparator in the ReadOptions used to create this Iterator.
    94  //
    95  // If Valid returns false, this method will panic.
    96  func (it *Iterator) Prev() {
    97  	C.leveldb_iter_prev(it.iter)
    98  }
    99  
   100  // SeekToFirst moves the iterator to the first key in the database, as defined
   101  // by the Comparator in the ReadOptions used to create this Iterator.
   102  //
   103  // This method is safe to call when Valid returns false.
   104  func (it *Iterator) SeekToFirst() {
   105  	C.leveldb_iter_seek_to_first(it.iter)
   106  }
   107  
   108  // SeekToLast moves the iterator to the last key in the database, as defined
   109  // by the Comparator in the ReadOptions used to create this Iterator.
   110  //
   111  // This method is safe to call when Valid returns false.
   112  func (it *Iterator) SeekToLast() {
   113  	C.leveldb_iter_seek_to_last(it.iter)
   114  }
   115  
   116  // Seek moves the iterator the position of the key given or, if the key
   117  // doesn't exist, the next key that does exist in the database. If the key
   118  // doesn't exist, and there is no next key, the Iterator becomes invalid.
   119  //
   120  // This method is safe to call when Valid returns false.
   121  func (it *Iterator) Seek(key []byte) {
   122  	C.leveldb_iter_seek(it.iter, (*C.char)(unsafe.Pointer(&key[0])), C.size_t(len(key)))
   123  }
   124  
   125  // GetError returns an IteratorError from LevelDB if it had one during
   126  // iteration.
   127  //
   128  // This method is safe to call when Valid returns false.
   129  func (it *Iterator) GetError() error {
   130  	var errStr *C.char
   131  	C.leveldb_iter_get_error(it.iter, &errStr)
   132  	if errStr != nil {
   133  		gs := C.GoString(errStr)
   134  		C.leveldb_free(unsafe.Pointer(errStr))
   135  		return leveldb_error(gs)
   136  	}
   137  	return nil
   138  }
   139  
   140  // Close deallocates the given Iterator, freeing the underlying C struct.
   141  func (it *Iterator) Close() {
   142  	C.leveldb_iter_destroy(it.iter)
   143  	it.iter = nil
   144  }