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  }