Symisc UnQLite

An Embeddable NoSQL Database Engine

Star

Follow @symisc



unQLite C/C++ API Reference - List of Objects.

This is a list of all abstract objects and datatypes used by the UnQLite library. There are eleven exported objects in total, but the two most important are:

An database handle: unqlite and a virtual machine object: unqlite_vm.


unqlite

unqlite_vm

unqlite_value

unqlite_context

unqlite_int64

unqlite_io_methods

unqlite_vfs

unqlite_kv_methods

unqlite_kv_engine

SyMemMethods

SyMutexMethods




Database Engine Handle.

typedef struct unqlite unqlite;


Each open UnQLite database is represented by a pointer to an instance of the opaque structure named unqlite. It is useful to think of an unqlite pointer as an object. The unqlite_open() is its constructor, and unqlite_close() is its destructor. Most of exported interface such as unqlite_kv_store(), unqlite_kv_append(), unqlite_kv_delete(), unqlite_config(), unqlite_kv_cursor_init(), unqlite_compile(), etc. expect a pointer to an instance of this structure as their first arguments.



Virtual Machine Object.

typedef struct unqlite_vm unqlite_vm;

An instance of this structure represents a compiled Jx9 program. this structure hold the Jx9 bytecode program resulting from successful compilation of the target Jx9 script using one of the compile interfaces such as unqlite_compile() or unqlite_compile_file().

The life of a UnQLite virtual machine goes something like this:

  1. Obtain a new database handle via unqlite_open(). This routine is often the first API call that an application makes and is a prerequisite in order to work with the database library.

  2. Compile your Jx9 script using one of the compile iterfaces such as unqlite_compile() or unqlite_compile_file(). On successful compilation, the engine will automatically create an instance of this structure (unqlite_vm) and a pointer to this structure is made available to the caller.

  3. When something goes wrong during compilation of the target Jx9 script due to a compile-time error, the caller must discard this pointer and fix its erroneous Jx9 code. Compile-time error logs can be extracted via a call to unqlite_config() with a configuration verb set to UNQLITE_CONFIG_JX9_ERR_LOG.

  4. Optionally, configure the virtual machine using  unqlite_vm_config().

  5. Optionally, register one or more foreign functions or constants using the unqlite_create_function() or unqlite_create_constant() interfaces.

  6. Execute the compiled Jx9 program by calling unqlite_vm_exec().

  7. Optionally, extract the contents of one or more variables declared inside your Jx9 script using unqlite_vm_extract_variable().

  8. Optionally, Reset the virtual machine using unqlite_vm_reset(), then go back to step 6. Do this zero or more times.

  9. Destroy the virtual machine using unqlite_vm_release().


Dynamically Typed Value Object.

typedef struct jx9_value unqlite_value;

UnQLite (Via Jx9) uses the unqlite_value object to represent all values that can be stored in a Jx9 variable. Since Jx9 uses dynamic typing for the values it stores. Values stored unqlite_value objects can be integers, floating point values, strings, JSON arrays, JSON objects and so forth.

Internally, the Jx9 virtual machine manipulates nearly all Jx9 values as jx9_value structures. Each unqlite_value may cache multiple representations (string, integer, etc.) of the same value.

The unqlite_value object is heavily used in the interaction between the Jx9 virtual machine and the host application especially in the implementation of application-defined foreign functions and/or constant expansion callbacks.

There are a dozens of interfaces that allow the host application to extract and manipulates unqlite_value cleanly, these includes:

unqlite_value_to_string(), unqlite_result_value(), unqlite_value_int64(), unqlite_value_is_null(), unqlite_value_string_format() and many more. Refer to the C/C++ Interfaces documentation for additional information.



Foreign Function Context Object.

typedef struct jx9_context unqlite_context;

The context in which a foreign function executes is stored in a unqlite_context object. A pointer to a unqlite_context object is always first parameter to application-defined foreign functions. The application-defined foreign function implementation will pass this pointer through into calls to dozens of interfaces, these includes unqlite_result_string(), unqlite_result_value(), unqlite_context_output(), unqlite_context_throw_error() and many more. Refer to the C/C++ Interfaces documentation for additional information. You can refer to the following guide for an introductory course to the foreign function mechanism.



64-Bit Integer Type.

#if defined(_MSC_VER) || defined(__BORLANDC__)

typedef signed __int64 unqlite_int64;

#else

typedef signed long long int unqlite_int64;

#endif /* _MSC_VER */


UnQLite uses 64-bit integer for integers arithmetic and data size regardless of the target platform. Because there is no cross-platform way to specify 64-bit integer types, UnQLite includes typedefs for 64-bit signed integers. The unqlite_int64 type can store integer values between -9223372036854775808 and +9223372036854775807 inclusive. Some of the interface that manipulates 64-bit integers are unqlite_kv_store(), unqlite_kv_append(), etc.



OS Interfaces Object.

typedef struct unqlite_vfs unqlite_vfs;

struct unqlite_vfs {

  const char *zName;  /* Name of this virtual file system [i.e: Windows, UNIX, etc.] */

  int iVersion;       /* Structure version number (currently 1) */

  int szOsFile;       /* Size of subclassed unqlite_file */

  int mxPathname;     /* Maximum file pathname length */

  int (*xOpen)(unqlite_vfs*, const char *zName, unqlite_file*,unsigned int flags);

  int (*xDelete)(unqlite_vfs*, const char *zName, int syncDir);

  int (*xAccess)(unqlite_vfs*, const char *zName, int flags, int *pResOut);

  int (*xFullPathname)(unqlite_vfs*, const char *zName,int buf_len,char *zBuf);

  int (*xTmpDir)(unqlite_vfs*,char *zBuf,int buf_len);

  int (*xSleep)(unqlite_vfs*, int microseconds);

  int (*xCurrentTime)(unqlite_vfs*,Sytm *pOut);

  int (*xGetLastError)(unqlite_vfs*, int, char *);

};


An instance of the unqlite_vfs object defines the interface between the UnQLite core and the underlying operating system. The "vfs" in the name of the object stands for "Virtual File System".

Only a single vfs can be registered within the UnQLite core. Vfs registration is done using unqlite_lib_config() with a configuration verb set to UNQLITE_LIB_CONFIG_VFS.

Note that Windows and UNIX (Linux, FreeBSD, Solaris, Mac OS X, etc.) users does not have to worry about registering and installing a vfs since UnQLite come with a built-in vfs for these platforms that implements most the methods defined above. Clients running on exotic systems (i.e. Other than Windows and UNIX systems) must register their own vfs in order to be able to use the UnQLite library.

The value of the iVersion field is initially 1 but may be larger in future versions of UnQLite.

The szOsFile field is the size of the subclassed unqlite_file structure used by this VFS. mxPathname is the maximum length of a pathname in this VFS. At least szOsFile bytes of memory are allocated by UnQLite to hold the unqlite_file structure passed as the third argument to xOpen. The xOpen method does not have to allocate the structure; it should just fill it in. Note that the xOpen method must set the unqlite_file.pMethods to either a valid unqlite_io_methods object or to NULL.



File Methods Object.

typedef struct unqlite_io_methods unqlite_io_methods;

typedef struct unqlite_file unqlite_file;

struct unqlite_file {

  const unqlite_io_methods *pMethods; /* Methods for an open file. MUST BE FIRST */

};

struct unqlite_io_methods {

  int iVersion; /* Structure version number (currently 1) */

  int (*xClose)(unqlite_file*);

  int (*xRead)(unqlite_file*, void*, unqlite_int64 iAmt, unqlite_int64 iOfst);

  int (*xWrite)(unqlite_file*, const void*, unqlite_int64 iAmt, unqlite_int64 iOfst);

  int (*xTruncate)(unqlite_file*, unqlite_int64 size);

  int (*xSync)(unqlite_file*, int flags);

  int (*xFileSize)(unqlite_file*, unqlite_int64 *pSize);

  int (*xLock)(unqlite_file*, int);

  int (*xUnlock)(unqlite_file*, int);

  int (*xCheckReservedLock)(unqlite_file*, int *pResOut);

  int (*xSectorSize)(unqlite_file*);

};


An unqlite_file object represents an open file in the unqlite_vfs OS interface layer. Individual OS interface implementations will want to subclass this object by appending additional fields for their own use. The pMethods entry is a pointer to an unqlite_io_methods object that defines methods for performing I/O operations on the open file.


Every file opened by the unqlite_vfs xOpen method populates an unqlite_file object (or, more commonly, a subclass of the unqlite_file object) with a pointer to an instance of this object.
This object defines the methods used to perform various operations against the open file represented by the unqlite_file object.
If the xOpen method sets the unqlite_file.pMethods element to a non-NULL pointer, then the unqlite_io_methods.xClose method may be invoked even if the xOpen reported that it failed. The only way to prevent a call to xClose following a failed xOpen is for the xOpen to set the unqlite_file.pMethods element to NULL.

The flags argument to xSync may be one of UNQLITE_SYNC_NORMAL or UNQLITE_SYNC_FULL The first choice is the normal fsync(). The second choice is a Mac OS X style fullsync. The UNQLITE_SYNC_DATAONLY flag may be ORed in to indicate that only the data of the file and not its inode needs to be synced.

The integer values to xLock() and xUnlock() are one of:


UNQLITE_LOCK_NONE
UNQLITE_LOCK_SHARED
UNQLITE_LOCK_RESERVED
UNQLITE_LOCK_PENDING
UNQLITE_LOCK_EXCLUSIVE

xLock() increases the lock. xUnlock() decreases the lock.


The xCheckReservedLock() method checks whether any database connection, either in this process or in some other process, is holding a RESERVED, PENDING, or EXCLUSIVE lock on the file. It returns true if such a lock exists and false otherwise.

The xSectorSize() method returns the sector size of the device that underlies the file. The sector size is the minimum write that can be performed without disturbing other bytes in the file.



Pluggable Key/Value Storage Engine.

struct unqlite_kv_engine

{

  const unqlite_kv_io *pIo; /* IO methods: MUST be first */

  /* Subclasses will typically add additional fields */

};


A Key-Value storage engine is defined by an instance of the unqlite_kv_engine object. UnQLite works with run-time interchangeable storage engines (i.e. Hash, B+Tree, R+Tree, LSM, etc.).

The storage engine works with key/value pairs where both the key and the value are byte arrays of arbitrary length and with no restrictions on content.
UnQLite come with two built-in KV storage engine: A Virtual Linear Hash (VLH) storage engine is used for persistent on-disk databases with O(1) lookup time and an in-memory hash-table or Red-black tree storage engine is used for in-memory databases.

Future versions of UnQLite might add other built-in storage engines (i.e. LSM).

Registration of a Key/Value storage engine at run-time is done via unqlite_lib_config() with a configuration verb set to UNQLITE_LIB_CONFIG_STORAGE_ENGINE.



Key/Value Storage Engine Virtual Method Table.

typedef struct unqlite_kv_cursor unqlite_kv_cursor;

struct unqlite_kv_cursor

{

    unqlite_kv_engine *pStore; /* Must be first */

   /* Subclasses will typically add additional fields */

};

typed struct unqlite_kv_methods unqlite_kv_methods;

struct unqlite_kv_methods

{

  const char *zName; /* Storage engine name [i.e. Hash, B+tree, LSM, R-tree, Mem, etc.]*/

  int szKv;          /* unqlite_kv_engine subclass size */

  int szCursor;      /* unqlite_kv_cursor subclass size */

  int iVersion;      /* Structure version, currently 1 */

  /* Storage engine methods */

  int (*xInit)(unqlite_kv_engine *,int iPageSize);

  void (*xRelease)(unqlite_kv_engine *);

  int (*xConfig)(unqlite_kv_engine *,int op,va_list ap);

  int (*xOpen)(unqlite_kv_engine *,pgno);

  int (*xReplace)(

    unqlite_kv_engine *,

    const void *pKey,int nKeyLen,

    const void *pData,unqlite_int64 nDataLen

  );

  int (*xAppend)(

    unqlite_kv_engine *,

    const void *pKey,int nKeyLen,

    const void *pData,unqlite_int64 nDataLen

  );

  void (*xCursorInit)(unqlite_kv_cursor *);

  int (*xSeek)(unqlite_kv_cursor *,const void *pKey,int nByte,int iPos); /* Mandatory */

  int (*xFirst)(unqlite_kv_cursor *);

  int (*xLast)(unqlite_kv_cursor *);

  int (*xValid)(unqlite_kv_cursor *);

  int (*xNext)(unqlite_kv_cursor *);

  int (*xPrev)(unqlite_kv_cursor *);

  int (*xDelete)(unqlite_kv_cursor *);

  int (*xKeyLength)(unqlite_kv_cursor *,int *);

  int (*xKey)(unqlite_kv_cursor *,int (*xConsumer)(const void *,unsigned int,void *),void *pUserData);

  int (*xDataLength)(unqlite_kv_cursor *,unqlite_int64 *);

  int (*xData)(unqlite_kv_cursor *,int (*xConsumer)(const void *,unsigned int,void *),void *pUserData);

  void (*xReset)(unqlite_kv_cursor *);

  void (*xCursorRelease)(unqlite_kv_cursor *);

};


An instance of a subclass of the unqlite_kv_cursor object defines a cursor used to scan through a key-value storage engine.

Key/Value storage engine methods is defined by an instance of the unqlite_kv_methods object.

Registration of a Key/Value storage engine at run-time is done via unqlite_lib_config() with a configuration verb set to UNQLITE_LIB_CONFIG_STORAGE_ENGINE.


Memory Allocation Routines.

typedef struct SyMemMethods SyMemMethods;

struct SyMemMethods

{

  void * (*xAlloc)(unsigned int);             /* [Required:] Allocate a memory chunk */

  void * (*xRealloc)(void *, unsigned int);   /* [Required:] Re-allocate a memory chunk */

  void (*xFree)(void*);                      /* [Required:] Release a memory chunk */

  unsigned int (*xChunkSize)(void *);         /* [Optional:] Return chunk size */

  int (*xInit)(void*);                       /* [Optional:] Initialization callback */

  void (*xRelease)(void *);                   /* [Optional:] Release callback */

  void *pUserData;                            /* [Optional:] First argument to xInit() and xRelease() */

};


An instance of this object defines the interface between UnQLite and low-level memory allocation routines. This object is used in only one place in the UnQLite interface. A pointer to an instance of this object is the argument to unqlite_lib_config() when the configuration option is UNQLITE_LIB_CONFIG_USER_MALLOC. By creating an instance of this object and passing it to unqlite_lib_config(UNQLITE_LIB_CONFIG_USER_MALLOC,pMemMethods); during configuration, an application can specify an alternative memory allocation subsystem for UnQLite to use for all of its dynamic memory needs.

Note that UnQLite is shipped with a built-in memory allocator which is perfectly adequate for the overwhelming majority of applications and that this object is only useful to a tiny minority of applications with specialized memory allocation requirements.



Mutex Methods.

typedef struct SyMutexMethods SyMutexMethods;

struct SyMutexMethods

{

  int (*xGlobalInit)(void);     /* [Optional:] Global mutex initialization */

  void (*xGlobalRelease)(void); /* [Optional:] Global Release callback () */

  SyMutex * (*xNew)(int);       /* [Required:] Request a new mutex */

  void (*xRelease)(SyMutex *);  /* [Optional:] Release a mutex */

  void (*xEnter)(SyMutex *);    /* [Required:] Enter mutex */

  int (*xTryEnter)(SyMutex *);  /* [Optional:] Try to enter a mutex */

  void (*xLeave)(SyMutex *);    /* [Required:] Leave a locked mutex */

};


An instance of this structure defines the low-level routines used to allocate and use mutexes. Usually, the default mutex implementations provided by UnQLite are sufficient, however the user has the option of substituting a custom implementation for specialized deployments or systems for which UnQLite does not provide a suitable implementation. In this case, the user creates and populates an instance of this structure to pass to unqlite_lib_config() along with the UNQLITE_LIB_CONFIG_USER_MUTEX option.



Symisc Systems
Copyright © Symisc Systems