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 }