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  }