github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/database/unqlite/unqlite.go (about) 1 // Copyright 2014 <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 unqlite provides access to the UnQLite C API. 6 package unqlite 7 8 /* 9 #cgo freebsd linux darwin CFLAGS: -DUNQLITE_ENABLE_THREADS=1 10 #cgo freebsd linux darwin LDFLAGS: -lpthread 11 #include <stdlib.h> 12 #include "unqlite.h" 13 */ 14 import "C" 15 16 import ( 17 "errors" 18 "fmt" 19 "unsafe" 20 ) 21 22 // Errno is an UnQLite library error number. 23 type Errno int 24 25 func (e Errno) Error() string { 26 s := errText[e] 27 if s == "" { 28 return fmt.Sprintf("errno %d", int(e)) 29 } 30 return s 31 } 32 33 var ( 34 ErrLock error = Errno(-76) // /* Locking protocol error */ 35 ErrReadOnly error = Errno(-75) // /* Read only Key/Value storage engine */ 36 ErrOpen error = Errno(-74) // /* Unable to open the database file */ 37 ErrFull error = Errno(-73) // /* Full database (unlikely) */ 38 ErrVM error = Errno(-71) // /* Virtual machine error */ 39 ErrCompile error = Errno(-70) // /* Compilation error */ 40 Done = Errno(-28) // Not an error. /* Operation done */ 41 ErrCorrupt error = Errno(-24) // /* Corrupt pointer */ 42 ErrNoOp error = Errno(-20) // /* No such method */ 43 ErrPerm error = Errno(-19) // /* Permission error */ 44 ErrEOF error = Errno(-18) // /* End Of Input */ 45 ErrNotImpl error = Errno(-17) // /* Method not implemented by the underlying Key/Value storage engine */ 46 ErrBusy error = Errno(-14) // /* The database file is locked */ 47 ErrUnknown error = Errno(-13) // /* Unknown configuration option */ 48 ErrExists error = Errno(-11) // /* Record exists */ 49 ErrAbort error = Errno(-10) // /* Another thread have released this instance */ 50 ErrInvalid error = Errno(-9) // /* Invalid parameter */ 51 ErrLimit error = Errno(-7) // /* Database limit reached */ 52 ErrNotFound error = Errno(-6) // /* No such record */ 53 ErrLocked error = Errno(-4) // /* Forbidden Operation */ 54 ErrEmpty error = Errno(-3) // /* Empty record */ 55 ErrIO error = Errno(-2) // /* IO error */ 56 ErrNoMem error = Errno(-1) // /* Out of memory */ 57 ) 58 59 var errText = map[Errno]string{ 60 -76: "Locking protocol error", 61 -75: "Read only Key/Value storage engine", 62 -74: "Unable to open the database file", 63 -73: "Full database", 64 -71: "Virtual machine error", 65 -70: "Compilation error", 66 -28: "Operation done", // Not an error. 67 -24: "Corrupt pointer", 68 -20: "No such method", 69 -19: "Permission error", 70 -18: "End Of Input", 71 -17: "Method not implemented by the underlying Key/Value storage engine", 72 -14: "The database file is locked", 73 -13: "Unknown configuration option", 74 -11: "Record exists", 75 -10: "Another thread have released this instance", 76 -9: "Invalid parameter", 77 -7: "Database limit reached", 78 -6: "No such record", 79 -4: "Forbidden Operation", 80 -3: "Empty record", 81 -2: "IO error", 82 -1: "Out of memory", 83 } 84 85 // Handle is a UnQLite database engine handle. 86 type Handle struct { 87 db *C.unqlite 88 } 89 90 // init initializes the UnQlite library. 91 func init() { 92 C.unqlite_lib_init() 93 } 94 95 // Open creates a database handle. 96 func Open(filename string) (*Handle, error) { 97 if !Threadsafe() { 98 return nil, errors.New("unqlite library was not compiled for thread-safe operation") 99 } 100 var db *C.unqlite 101 name := C.CString(filename) 102 defer C.free(unsafe.Pointer(name)) 103 rv := C.unqlite_open(&db, name, C.UNQLITE_OPEN_CREATE) 104 if rv != C.UNQLITE_OK { 105 return nil, Errno(rv) 106 } 107 if db == nil { 108 return nil, errors.New("unqlite unable to allocate memory to hold the database") 109 } 110 return &Handle{db}, nil 111 } 112 113 // Close closes the database handle. 114 func (h *Handle) Close() error { 115 if h == nil || h.db == nil { 116 return errors.New("nil unqlite database") 117 } 118 rv := C.unqlite_close(h.db) 119 if rv != C.UNQLITE_OK { 120 return Errno(rv) 121 } 122 h.db = nil 123 return nil 124 } 125 126 // Store inserts or updates a key-value pair in the database. 127 // 128 // If the key exists, its value is updated. Otherwise, a new key-value pair is created. 129 func (h *Handle) Store(key, value []byte) error { 130 rv := C.unqlite_kv_store(h.db, unsafe.Pointer(&key[0]), C.int(len(key)), unsafe.Pointer(&value[0]), C.unqlite_int64(len(value))) 131 if rv == C.UNQLITE_OK { 132 return nil 133 } 134 return Errno(rv) 135 } 136 137 // Append appends value to the key-value pair in the database. 138 func (h *Handle) Append(key, value []byte) error { 139 rv := C.unqlite_kv_append(h.db, unsafe.Pointer(&key[0]), C.int(len(key)), unsafe.Pointer(&value[0]), C.unqlite_int64(len(value))) 140 if rv == C.UNQLITE_OK { 141 return nil 142 } 143 return Errno(rv) 144 } 145 146 // Fetch retrieves the value for the specified key from the database. 147 func (h *Handle) Fetch(key []byte) (value []byte, err error) { 148 // Fetch size of value. 149 var n C.unqlite_int64 150 rv := C.unqlite_kv_fetch(h.db, unsafe.Pointer(&key[0]), C.int(len(key)), nil, &n) 151 if rv != C.UNQLITE_OK { 152 return nil, Errno(rv) 153 } 154 // Fetch value. 155 b := make([]byte, int(n)) 156 rv = C.unqlite_kv_fetch(h.db, unsafe.Pointer(&key[0]), C.int(len(key)), unsafe.Pointer(&b[0]), &n) 157 if rv != C.UNQLITE_OK { 158 return nil, Errno(rv) 159 } 160 return b, nil 161 } 162 163 // Delete removes a key-value pair from the database. 164 func (h *Handle) Delete(key []byte) error { 165 rv := C.unqlite_kv_delete(h.db, unsafe.Pointer(&key[0]), C.int(len(key))) 166 if rv != C.UNQLITE_OK { 167 return Errno(rv) 168 } 169 return nil 170 } 171 172 // Commit commits all changes to the database. 173 func (h *Handle) Commit() error { 174 rv := C.unqlite_commit(h.db) 175 if rv != C.UNQLITE_OK { 176 return Errno(rv) 177 } 178 return nil 179 } 180 181 // Threadsafe returns true if the UnQlite library was compiled for thread-safe operation, else false. 182 func Threadsafe() bool { 183 return C.unqlite_lib_is_threadsafe() == 1 184 } 185 186 // Version returns the UnQLite library version. 187 func Version() string { 188 p := C.unqlite_lib_version() 189 return C.GoString(p) 190 } 191 192 // Signature returns the UnQLite library signature. 193 func Signature() string { 194 p := C.unqlite_lib_signature() 195 return C.GoString(p) 196 } 197 198 // Ident returns the UnQLite library revision identifier. 199 func Ident() string { 200 p := C.unqlite_lib_ident() 201 return C.GoString(p) 202 } 203 204 // Copyright returns the UnQLite library copyright notice. 205 func Copyright() string { 206 p := C.unqlite_lib_copyright() 207 return C.GoString(p) 208 }