github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/database/vedis/vedis.go (about) 1 package vedis 2 3 import ( 4 "bytes" 5 "errors" 6 "reflect" 7 "unsafe" 8 ) 9 10 /* 11 #include "vedis.h" 12 #include <stdlib.h> 13 14 static int fetch_callback(const void* pData, unsigned int iDataLen, void *pUserData) { 15 extern int go_vedis_InvokeFetchCallback(void*, void*, int); 16 return go_vedis_InvokeFetchCallback(pUserData, (void*)pData, iDataLen); 17 } 18 19 static int vedis_kv_fetch_invoke_callback(vedis *pStore, const void *pKey, int nKeyLen, void *pUserData) { 20 return vedis_kv_fetch_callback(pStore, pKey, nKeyLen, &fetch_callback, pUserData); 21 } 22 23 static void get_last_error_from_log(vedis *pStore, char *pDest) { 24 int iLen = 0; 25 vedis_config(pStore, VEDIS_CONFIG_ERR_LOG, &pDest, &iLen); 26 } 27 */ 28 import "C" 29 30 var ( 31 ErrReadOnly = errors.New("vedis: Read-only database") 32 ErrBusy = errors.New("vedis: Another thread or process has an exclusive lock on the database") 33 ErrIO = errors.New("vedis: Input/Output error") 34 ErrNoMemory = errors.New("vedis: Out of Memory") 35 ErrAbort = errors.New("vedis: Another thread has released the database handle") 36 ErrNotImplemented = errors.New("vedis: The underlying KV storage engine does not implement the xReplace() method") 37 ErrPermission = errors.New("vedis: Permission error") 38 ErrLimit = errors.New("vedis: Journal file record limit reached") 39 ErrNotFound = errors.New("vedis: Nonexistent record") 40 ErrUnknown = errors.New("vedis: Unknown error") 41 ) 42 43 func getError(cErr C.int) error { 44 switch cErr { 45 case C.VEDIS_READ_ONLY: 46 return ErrReadOnly 47 case C.VEDIS_BUSY: 48 return ErrBusy 49 case C.VEDIS_IOERR: 50 return ErrIO 51 case C.VEDIS_NOMEM: 52 return ErrNoMemory 53 case C.VEDIS_ABORT: 54 return ErrAbort 55 case C.VEDIS_NOTIMPLEMENTED: 56 return ErrNotImplemented 57 case C.VEDIS_PERM: 58 return ErrPermission 59 case C.VEDIS_LIMIT: 60 return ErrLimit 61 case C.VEDIS_NOTFOUND: 62 return ErrNotFound 63 default: 64 return ErrUnknown 65 } 66 } 67 68 func Init() { C.vedis_lib_init() } 69 func Shutdown() { C.vedis_lib_shutdown() } 70 func Version() string { return C.GoString(C.vedis_lib_version()) } 71 func Signature() string { return C.GoString(C.vedis_lib_signature()) } 72 func Identity() string { return C.GoString(C.vedis_lib_ident()) } 73 func Copyright() string { return C.GoString(C.vedis_lib_copyright()) } 74 75 type Value struct{ p *C.vedis_value } 76 77 func (v *Value) String() string { 78 var csLen C.int 79 return C.GoString(C.vedis_value_to_string(v.p, &csLen)) 80 } 81 82 func (v *Value) Int() int { return int(C.vedis_value_to_int(v.p)) } 83 func (v *Value) Int64() int64 { return int64(C.vedis_value_to_int64(v.p)) } 84 func (v *Value) Bool() bool { return C.vedis_value_to_bool(v.p) != 0 } 85 func (v *Value) Float64() float64 { return float64(C.vedis_value_to_double(v.p)) } 86 func (v *Value) Array() *ArrayValue { return &ArrayValue{v.p} } 87 88 func (v *Value) IsInt() bool { return C.vedis_value_is_int(v.p) != 0 } 89 func (v *Value) IsFloat() bool { return C.vedis_value_is_float(v.p) != 0 } 90 func (v *Value) IsBool() bool { return C.vedis_value_is_bool(v.p) != 0 } 91 func (v *Value) IsString() bool { return C.vedis_value_is_string(v.p) != 0 } 92 func (v *Value) IsNull() bool { return C.vedis_value_is_null(v.p) != 0 } 93 func (v *Value) IsNumeric() bool { return C.vedis_value_is_numeric(v.p) != 0 } 94 func (v *Value) IsScalar() bool { return C.vedis_value_is_scalar(v.p) != 0 } 95 func (v *Value) IsArray() bool { return C.vedis_value_is_array(v.p) != 0 } 96 97 type ArrayValue Value 98 99 func (a *ArrayValue) Next() *Value { 100 var value Value 101 value.p = C.vedis_array_next_elem(a.p) 102 if value.p == nil { 103 return nil 104 } 105 return &value 106 } 107 108 func (a *ArrayValue) Index(i int) *Value { 109 var value Value 110 value.p = C.vedis_array_fetch(a.p, C.uint(i)) 111 if value.p == nil { 112 panic("index out of range") 113 } 114 return &value 115 } 116 117 func (a *ArrayValue) Insert(val *Value) error { 118 if rc := C.vedis_array_insert(a.p, val.p); rc != C.VEDIS_OK { 119 return getError(rc) 120 } 121 return nil 122 } 123 124 func (a *ArrayValue) Count() int { 125 return int(C.vedis_array_count(a.p)) 126 } 127 128 func (a *ArrayValue) Reset() error { 129 if rc := C.vedis_array_reset(a.p); rc != C.VEDIS_OK { 130 return getError(rc) 131 } 132 return nil 133 } 134 135 type Store struct{ p *C.vedis } 136 137 func Open(name string) (*Store, error) { 138 var store Store 139 rc := C.vedis_open(&store.p, C.CString(name)) 140 if rc != C.VEDIS_OK { 141 return nil, getError(rc) 142 } 143 return &store, nil 144 } 145 146 func (s *Store) Close() { C.vedis_close(s.p) } 147 148 func (s *Store) Begin() error { 149 if rc := C.vedis_begin(s.p); rc != C.VEDIS_OK { 150 return getError(rc) 151 } 152 return nil 153 } 154 155 func (s *Store) Commit() error { 156 if rc := C.vedis_commit(s.p); rc != C.VEDIS_OK { 157 return getError(rc) 158 } 159 return nil 160 } 161 162 func (s *Store) Rollback() error { 163 if rc := C.vedis_rollback(s.p); rc != C.VEDIS_OK { 164 return getError(rc) 165 } 166 return nil 167 } 168 169 func (s *Store) Exec(cmd string) error { 170 rc := C.vedis_exec(s.p, C.CString(cmd), -1) 171 if rc != C.VEDIS_OK { 172 return getError(rc) 173 } 174 return nil 175 } 176 177 func (s *Store) ExecResult(cmd string) (*Value, error) { 178 if err := s.Exec(cmd); err != nil { 179 return nil, err 180 } 181 return s.Result() 182 } 183 184 func (s *Store) Result() (*Value, error) { 185 var value Value 186 C.vedis_exec_result(s.p, &value.p) 187 return &value, nil 188 } 189 190 func prepareByteSlice(b []byte) (unsafe.Pointer, int) { 191 header := (*reflect.SliceHeader)(unsafe.Pointer(&b)) 192 return unsafe.Pointer(header.Data), header.Len 193 } 194 195 func (s *Store) KvStore(key, val []byte) error { 196 pKeyData, pKeyLen := prepareByteSlice(key) 197 pValData, pValLen := prepareByteSlice(val) 198 if rc := C.vedis_kv_store( 199 s.p, 200 pKeyData, C.int(pKeyLen), 201 pValData, C.vedis_int64(pValLen), 202 ); rc != C.VEDIS_OK { 203 return getError(rc) 204 } 205 return nil 206 } 207 208 //export go_vedis_InvokeFetchCallback 209 func go_vedis_InvokeFetchCallback(pFn, pData unsafe.Pointer, iLen C.int) C.int { 210 fn := *(*func(unsafe.Pointer, C.int))(pFn) 211 fn(pData, iLen) 212 return C.VEDIS_OK 213 } 214 215 func (s *Store) KvFetch(key []byte) ([]byte, error) { 216 pKeyData, pKeyLen := prepareByteSlice(key) 217 var buffer bytes.Buffer 218 pUserData := func(pData unsafe.Pointer, iLen C.int) { 219 buffer.Write(C.GoBytes(pData, iLen)) 220 } 221 if rc := C.vedis_kv_fetch_invoke_callback( 222 s.p, 223 pKeyData, C.int(pKeyLen), 224 unsafe.Pointer(&pUserData), 225 ); rc != C.VEDIS_OK { 226 return nil, getError(rc) 227 } 228 return buffer.Bytes(), nil 229 } 230 231 func (s *Store) KvAppend(key, val []byte) error { 232 pKeyData, pKeyLen := prepareByteSlice(key) 233 pValData, pValLen := prepareByteSlice(val) 234 if rc := C.vedis_kv_append( 235 s.p, 236 pKeyData, C.int(pKeyLen), 237 pValData, C.vedis_int64(pValLen), 238 ); rc != C.VEDIS_OK { 239 return getError(rc) 240 } 241 return nil 242 } 243 244 func (s *Store) KvDelete(key []byte) error { 245 pKeyData, pKeyLen := prepareByteSlice(key) 246 if rc := C.vedis_kv_delete( 247 s.p, pKeyData, C.int(pKeyLen), 248 ); rc != C.VEDIS_OK { 249 return getError(rc) 250 } 251 return nil 252 } 253 254 func (s *Store) LastError() error { 255 var msg *C.char 256 C.get_last_error_from_log(s.p, msg) 257 defer C.free(unsafe.Pointer(msg)) 258 return errors.New(C.GoString(msg)) 259 }