/*
* Copyright (C) 2005-2015 Christoph Rupp (chris@crupp.de).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file hamsterdb.h
* @brief Include file for hamsterdb Embedded Storage
* @author Christoph Rupp, chris@crupp.de
* @version 2.1.10
*
* @mainpage
*
* This manual documents the hamsterdb C API. hamsterdb is a key/value database
* that is linked directly into your application, avoiding all the overhead
* that is related to external databases and RDBMS systems.
*
* This header file declares all functions and macros that are needed to use
* hamsterdb. The comments are formatted in Doxygen style and can be extracted
* to automagically generate documentation. The documentation is also available
* online here:
http://hamsterdb.com/public/scripts/html_www.
*
* In addition, there's a tutorial book hosted on github:
*
http://github.com/cruppstahl/hamsterdb/wiki/Tutorial.
*
* If you want to create or open Databases or Environments (a collection of
* multiple Databases), the following functions will be interesting for you:
*
* @ref ham_env_create | Creates an Environment |
* @ref ham_env_open | Opens an Environment |
* @ref ham_env_close | Closes an Environment |
* @ref ham_env_create_db | Creates a Database in an
Environment |
* @ref ham_env_open_db | Opens a Database from an
Environment |
* @ref ham_db_close | Closes a Database |
*
*
* To insert, lookup or delete key/value pairs, the following functions are
* used:
*
* @ref ham_db_insert | Inserts a key/value pair into a
Database |
* @ref ham_db_find | Lookup of a key/value pair in a
Database |
* @ref ham_db_erase | Erases a key/value pair from a
Database |
*
*
* Alternatively, you can use Cursors to iterate over a Database:
*
* @ref ham_cursor_create | Creates a new Cursor |
* @ref ham_cursor_find | Positions the Cursor on a key |
* @ref ham_cursor_insert | Inserts a new key/value pair with a
Cursor |
* @ref ham_cursor_erase | Deletes the key/value pair that
the Cursor points to |
* @ref ham_cursor_overwrite | Overwrites the value of the current key |
* @ref ham_cursor_move | Moves the Cursor to the first, next,
previous or last key in the Database |
* @ref ham_cursor_close | Closes the Cursor |
*
*
* If you want to use Transactions, then the following functions are required:
*
* @ref ham_txn_begin | Begins a new Transaction |
* @ref ham_txn_commit | Commits the current
Transaction |
* @ref ham_txn_abort | Aborts the current Transaction |
*
*
* hamsterdb supports remote Databases. The server can be embedded
* into your application or run standalone (see tools/hamzilla for a Unix
* daemon or Win32 service which hosts Databases). If you want to embed the
* server then the following functions have to be used:
*
* @ref ham_srv_init | Initializes the server |
* @ref ham_srv_add_env | Adds an Environment to the
server. The Environment with all its Databases will then be available
remotely. |
* @ref ham_srv_close | Closes the server and frees all allocated
resources |
*
*
* If you need help then you're always welcome to use the
mailing list,
* drop a message (chris at crupp dot de) or use the contact form.
*
* Have fun!
*/
#ifndef HAM_HAMSTERDB_H
#define HAM_HAMSTERDB_H
#include
#ifdef __cplusplus
extern "C" {
#endif
/* deprecated */
#define HAM_API_REVISION 3
/**
* The version numbers
*
* @remark A change of the major revision means a significant update
* with a lot of new features and API changes.
*
* The minor version means a significant update without API changes, and the
* revision is incremented for each release with minor improvements only.
*
* The file version describes the version of the binary database format.
* hamsterdb is neither backwards- nor forwards-compatible regarding file
* format changes.
*
* If a file was created with hamsterdb pro then the msb of the file version
* is set. hamsterdb pro is able to open files created with hamsterdb (APL
* version), but not vice versa.
*
* History of file versions:
* 2.1.0: introduced the file version; version is 0
* 2.1.3: new btree format, file format cleanups; version is 1
* 2.1.4: new btree format for duplicate keys/var. length keys; version is 2
* 2.1.5: new freelist; version is 3
* 2.1.10: changes in btree node format; version is 4
*/
#define HAM_VERSION_MAJ 2
#define HAM_VERSION_MIN 1
#define HAM_VERSION_REV 10
#define HAM_FILE_VERSION 4
/**
* The hamsterdb Database structure
*
* This structure is allocated in @ref ham_env_create_db and
* @ref ham_env_open_db. It is deleted in @a ham_db_close.
*/
struct ham_db_t;
typedef struct ham_db_t ham_db_t;
/**
* The hamsterdb Environment structure
*
* This structure is allocated with @ref ham_env_create and @ref ham_env_open
* and is deleted in @ref ham_env_close.
*/
struct ham_env_t;
typedef struct ham_env_t ham_env_t;
/**
* A Database Cursor
*
* A Cursor is used for bi-directionally traversing the Database and
* for inserting/deleting/searching Database items.
*
* This structure is allocated with @ref ham_cursor_create and deleted with
* @ref ham_cursor_close.
*/
struct ham_cursor_t;
typedef struct ham_cursor_t ham_cursor_t;
/**
* A generic record.
*
* A record represents data items in hamsterdb. Before using a record, it
* is important to initialize all record fields with zeroes, i.e. with
* the C library routines memset(3) or bzero(2).
*
* When hamsterdb returns a record structure, the pointer to the record
* data is provided in @a data. This pointer is only temporary and will be
* overwritten by subsequent hamsterdb API calls using the same Transaction
* (or, if Transactions are disabled, using the same Database). The pointer
* will also be invalidated after the Transaction is aborted or committed.
*
* To avoid this, the calling application can allocate the @a data pointer.
* In this case, you have to set the flag @ref HAM_RECORD_USER_ALLOC. The
* @a size parameter will then return the size of the record. It's the
* responsibility of the caller to make sure that the @a data parameter is
* large enough for the record.
*
* The record->data pointer is not threadsafe. For threadsafe access it is
* recommended to use @a HAM_RECORD_USER_ALLOC or have each thread manage its
* own Transaction.
*/
typedef struct {
/** The size of the record data, in bytes */
uint32_t size;
/** Pointer to the record data */
void *data;
/** The record flags; see @ref HAM_RECORD_USER_ALLOC */
uint32_t flags;
/** Offset for partial reading/writing; see @ref HAM_PARTIAL */
uint32_t partial_offset;
/** Size for partial reading/writing; see @ref HAM_PARTIAL */
uint32_t partial_size;
} ham_record_t;
/** Flag for @ref ham_record_t (only really useful in combination with
* @ref ham_cursor_move, @ref ham_cursor_find and @ref ham_db_find)
*/
#define HAM_RECORD_USER_ALLOC 1
/**
* A macro to statically initialize a @ref ham_record_t structure.
*
* Usage:
* ham_record_t rec = ham_make_record(ptr, size);
*/
#define ham_make_record(PTR, SIZE) { SIZE, PTR, 0 }
/**
* A generic key.
*
* A key represents key items in hamsterdb. Before using a key, it
* is important to initialize all key fields with zeroes, i.e. with
* the C library routines memset(3) or bzero(2).
*
* hamsterdb usually uses keys to insert, delete or search for items.
* However, when using Database Cursors and the function @ref ham_cursor_move,
* hamsterdb also returns keys. In this case, the pointer to the key
* data is provided in @a data. This pointer is only temporary and will be
* overwritten by subsequent calls to @ref ham_cursor_move using the
* same Transaction (or, if Transactions are disabled, using the same Database).
* The pointer will also be invalidated after the Transaction is aborted
* or committed.
*
* To avoid this, the calling application can allocate the @a data pointer.
* In this case, you have to set the flag @ref HAM_KEY_USER_ALLOC. The
* @a size parameter will then return the size of the key. It's the
* responsibility of the caller to make sure that the @a data parameter is
* large enough for the key.
*
* The key->data pointer is not threadsafe. For threadsafe access it is
* recommended to use @a HAM_KEY_USER_ALLOC or have each thread manage its
* own Transaction.
*/
typedef struct {
/** The size of the key, in bytes */
uint16_t size;
/** The data of the key */
void *data;
/** The key flags; see @ref HAM_KEY_USER_ALLOC */
uint32_t flags;
/** For internal use */
uint32_t _flags;
} ham_key_t;
/**
* A macro to statically initialize a @ref ham_key_t structure.
*
* Usage:
* ham_key_t key = ham_make_key(ptr, size);
*/
#define ham_make_key(PTR, SIZE) { SIZE, PTR, 0 }
/** Flag for @ref ham_key_t (only really useful in combination with
* @ref ham_cursor_move, @ref ham_cursor_find and @ref ham_db_find)
*/
#define HAM_KEY_USER_ALLOC 1
/**
* A named parameter.
*
* These parameter structures are used for functions like @ref ham_env_open,
* @ref ham_env_create, etc. to pass variable length parameter lists.
*
* The lists are always arrays of type ham_parameter_t, with a terminating
* element of { 0, NULL}, e.g.
*
*
* ham_parameter_t parameters[] = {
* { HAM_PARAM_CACHE_SIZE, 2 * 1024 * 1024 }, // set cache size to 2 mb
* { HAM_PARAM_PAGE_SIZE, 4096 }, // set page size to 4 kb
* { 0, NULL }
* };
*
*/
typedef struct {
/** The name of the parameter; all HAM_PARAM_*-constants */
uint32_t name;
/** The value of the parameter. */
uint64_t value;
} ham_parameter_t;
/**
* @defgroup ham_key_types hamsterdb Key Types
* @{
*/
/** A binary blob without type; sorted by memcmp */
#define HAM_TYPE_BINARY 0
/** A binary blob without type; sorted by callback function */
#define HAM_TYPE_CUSTOM 1
/** An unsigned 8-bit integer */
#define HAM_TYPE_UINT8 3
/** An unsigned 16-bit integer */
#define HAM_TYPE_UINT16 5
/** An unsigned 32-bit integer */
#define HAM_TYPE_UINT32 7
/** An unsigned 64-bit integer */
#define HAM_TYPE_UINT64 9
/** An 32-bit float */
#define HAM_TYPE_REAL32 11
/** An 64-bit double */
#define HAM_TYPE_REAL64 12
/**
* @}
*/
/**
* @defgroup ham_status_codes hamsterdb Status Codes
* @{
*/
/** Operation completed successfully */
#define HAM_SUCCESS ( 0)
/** Invalid record size */
#define HAM_INV_RECORD_SIZE ( -2)
/** Invalid key size */
#define HAM_INV_KEY_SIZE ( -3)
/* deprecated */
#define HAM_INV_KEYSIZE HAM_INV_KEY_SIZE
/** Invalid page size (must be 1024 or a multiple of 2048) */
#define HAM_INV_PAGE_SIZE ( -4)
/* deprecated */
#define HAM_INV_PAGESIZE HAM_INV_PAGE_SIZE
/** Memory allocation failed - out of memory */
#define HAM_OUT_OF_MEMORY ( -6)
/** Invalid function parameter */
#define HAM_INV_PARAMETER ( -8)
/** Invalid file header */
#define HAM_INV_FILE_HEADER ( -9)
/** Invalid file version */
#define HAM_INV_FILE_VERSION (-10)
/** Key was not found */
#define HAM_KEY_NOT_FOUND (-11)
/** Tried to insert a key which already exists */
#define HAM_DUPLICATE_KEY (-12)
/** Internal Database integrity violated */
#define HAM_INTEGRITY_VIOLATED (-13)
/** Internal hamsterdb error */
#define HAM_INTERNAL_ERROR (-14)
/** Tried to modify the Database, but the file was opened as read-only */
#define HAM_WRITE_PROTECTED (-15)
/** Database record not found */
#define HAM_BLOB_NOT_FOUND (-16)
/** Generic file I/O error */
#define HAM_IO_ERROR (-18)
/** Function is not yet implemented */
#define HAM_NOT_IMPLEMENTED (-20)
/** File not found */
#define HAM_FILE_NOT_FOUND (-21)
/** Operation would block */
#define HAM_WOULD_BLOCK (-22)
/** Object was not initialized correctly */
#define HAM_NOT_READY (-23)
/** Database limits reached */
#define HAM_LIMITS_REACHED (-24)
/** Object was already initialized */
#define HAM_ALREADY_INITIALIZED (-27)
/** Database needs recovery */
#define HAM_NEED_RECOVERY (-28)
/** Cursor must be closed prior to Transaction abort/commit */
#define HAM_CURSOR_STILL_OPEN (-29)
/** Record filter or file filter not found */
#define HAM_FILTER_NOT_FOUND (-30)
/** Operation conflicts with another Transaction */
#define HAM_TXN_CONFLICT (-31)
/* internal use: key was erased in a Transaction */
#define HAM_KEY_ERASED_IN_TXN (-32)
/** Database cannot be closed because it is modified in a Transaction */
#define HAM_TXN_STILL_OPEN (-33)
/** Cursor does not point to a valid item */
#define HAM_CURSOR_IS_NIL (-100)
/** Database not found */
#define HAM_DATABASE_NOT_FOUND (-200)
/** Database name already exists */
#define HAM_DATABASE_ALREADY_EXISTS (-201)
/** Database already open, or: Database handle is already initialized */
#define HAM_DATABASE_ALREADY_OPEN (-202)
/** Environment already open, or: Environment handle is already initialized */
#define HAM_ENVIRONMENT_ALREADY_OPEN (-203)
/** Invalid log file header */
#define HAM_LOG_INV_FILE_HEADER (-300)
/** Remote I/O error/Network error */
#define HAM_NETWORK_ERROR (-400)
/**
* @}
*/
/**
* @defgroup ham_static hamsterdb Static Functions
* @{
*/
/**
* A typedef for a custom error handler function
*
* This error handler can be used in combination with
* @ref ham_set_errhandler().
*
* @param message The error message
* @param level The error level:
*
* - @ref HAM_DEBUG_LEVEL_DEBUG (0)
a debug message
* - @ref HAM_DEBUG_LEVEL_NORMAL (1)
a normal error message
* - 2
reserved
* - @ref HAM_DEBUG_LEVEL_FATAL (3)
a fatal error message
*
*
* @sa error_levels
*/
typedef void HAM_CALLCONV (*ham_errhandler_fun)(int level, const char *message);
/** A debug message */
#define HAM_DEBUG_LEVEL_DEBUG 0
/** A normal error message */
#define HAM_DEBUG_LEVEL_NORMAL 1
/** A fatal error message */
#define HAM_DEBUG_LEVEL_FATAL 3
/**
* Sets the global error handler
*
* This handler will receive all debug messages that are emitted
* by hamsterdb. You can install the default handler by setting @a f to 0.
*
* The default error handler prints all messages to stderr. To install a
* different logging facility, you can provide your own error handler.
*
* Note that the callback function must have the same calling convention
* as the hamsterdb library.
*
* @param f A pointer to the error handler function, or NULL to restore
* the default handler
*/
HAM_EXPORT void HAM_CALLCONV
ham_set_errhandler(ham_errhandler_fun f);
/**
* Translates a hamsterdb status code to a descriptive error string
*
* @param status The hamsterdb status code
*
* @return A pointer to a descriptive error string
*/
HAM_EXPORT const char * HAM_CALLCONV
ham_strerror(ham_status_t status);
/**
* Returns the version of the hamsterdb library
*
* @param major If not NULL, will return the major version number
* @param minor If not NULL, will return the minor version number
* @param revision If not NULL, will return the revision version number
*/
HAM_EXPORT void HAM_CALLCONV
ham_get_version(uint32_t *major, uint32_t *minor,
uint32_t *revision);
/**
* @}
*/
/**
* @defgroup ham_env hamsterdb Environment Functions
* @{
*/
/**
* Creates a Database Environment
*
* A Database Environment is a collection of Databases, which are all stored
* in one physical file (or in-memory). The maximum number of Databases
* depends on the page size; the default is above 600.
*
* Each Database in an Environment is identified by a positive 16bit
* value (except 0 and values at or above 0xf000).
* Databases in an Environment can be created with @ref ham_env_create_db
* or opened with @ref ham_env_open_db.
*
* Specify a URL instead of a filename (i.e.
* "ham://localhost:8080/customers.db") to access a remote hamsterdb Server.
*
* To enable ACID Transactions, supply the flag @ref HAM_ENABLE_TRANSACTIONS.
* By default, hamsterdb will use a Journal for recovering the Environment
* and its data in case of a crash, and also to re-apply committed Transactions
* which were not yet flushed to disk. This Journalling can be disabled
* with the flag @ref HAM_DISABLE_RECOVERY. (It is disabled if the Environment
* is in-memory.)
*
* If Transactions are not required, but hamsterdb should still be able to
* recover in case of a crash or power outage, then the flag
* @ref HAM_ENABLE_RECOVERY will enable the Journal (without allowing
* Transactions.)
*
* For performance reasons the Journal does not use fsync(2) (or
* FlushFileBuffers on Win32) to flush modified buffers to disk. Use the flag
* @ref HAM_ENABLE_FSYNC to force the use of fsync.
*
* @param env A pointer to an Environment handle
* @param filename The filename of the Environment file. If the file already
* exists, it is overwritten. Can be NULL for an In-Memory
* Environment. Can be a URL ("ham://:/")
* for remote access.
* @param flags Optional flags for opening the Environment, combined with
* bitwise OR. Possible flags are:
*
* - @ref HAM_ENABLE_FSYNC
Flushes all file handles after
* committing or aborting a Transaction using fsync(), fdatasync()
* or FlushFileBuffers(). This file has no effect
* if Transactions are disabled. Slows down performance but makes
* sure that all file handles and operating system caches are
* transferred to disk, thus providing a stronger durability.
* - @ref HAM_IN_MEMORY
Creates an In-Memory Environment. No
* file will be created, and the Database contents are lost after
* the Environment is closed. The @a filename parameter can
* be NULL. Do NOT specify @a cache_size other than 0.
* - @ref HAM_DISABLE_MMAP
Do not use memory mapped files for I/O.
* By default, hamsterdb checks if it can use mmap,
* since mmap is faster than read/write. For performance
* reasons, this flag should not be used.
* - @ref HAM_CACHE_UNLIMITED
Do not limit the cache. Nearly as
* fast as an In-Memory Database. Not allowed in combination
* with a limited cache size.
* - @ref HAM_ENABLE_TRANSACTIONS
Enables Transactions for this
* Environment. This flag implies @ref HAM_ENABLE_RECOVERY.
* - @ref HAM_ENABLE_RECOVERY
Enables logging/recovery for this
* Environment. Not allowed in combination with @ref HAM_IN_MEMORY.
* - @ref HAM_DISABLE_RECOVERY
Disables logging/recovery for this
* Environment.
* - @ref HAM_FLUSH_WHEN_COMMITTED
Immediately flushes committed
* Transactions and writes them to the Btree. Disabled by default. If
* disabled then hamsterdb buffers committed Transactions and only starts
* flushing when too many Transactions were committed.
*
*
* @param mode File access rights for the new file. This is the @a mode
* parameter for creat(2). Ignored on Microsoft Windows. Default
* is 0644.
* @param param An array of ham_parameter_t structures. The following
* parameters are available:
*
* - @ref HAM_PARAM_CACHE_SIZE
The size of the Database cache,
* in bytes. The default size is defined in src/config.h
* as @a HAM_DEFAULT_CACHE_SIZE - usually 2MB
* - @ref HAM_PARAM_POSIX_FADVISE
Sets the "advice" for
* posix_fadvise(). Only on supported platforms. Allowed values are
* @ref HAM_POSIX_FADVICE_NORMAL (which is the default) or
* @ref HAM_POSIX_FADVICE_RANDOM.
* - @ref HAM_PARAM_PAGE_SIZE
The size of a file page, in
* bytes. It is recommended not to change the default size. The
* default size depends on hardware and operating system.
* Page sizes must be 1024 or a multiple of 2048.
* - @ref HAM_PARAM_FILE_SIZE_LIMIT
Sets a file size limit (in bytes).
* Disabled by default. Not allowed in combination with @ref HAM_IN_MEMORY.
* If the limit is exceeded, API functions return @ref HAM_LIMITS_REACHED.
* - @ref HAM_PARAM_LOG_DIRECTORY
The path of the log file
* and the journal files; default is the same path as the database
* file. Ignored for remote Environments.
* - @ref HAM_PARAM_NETWORK_TIMEOUT_SEC
Timeout (in seconds) when
* waiting for data from a remote server. By default, no timeout is set.
*
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_INV_PARAMETER if the @a env pointer is NULL or an
* invalid combination of flags or parameters was specified
* @return @ref HAM_IO_ERROR if the file could not be opened or
* reading/writing failed
* @return @ref HAM_INV_FILE_VERSION if the Environment version is not
* compatible with the library version
* @return @ref HAM_OUT_OF_MEMORY if memory could not be allocated
* @return @ref HAM_INV_PAGE_SIZE if @a page_size is not 1024 or
* a multiple of 2048
* @return @ref HAM_INV_KEY_SIZE if @a key_size is too large (at least 4
* keys must fit in a page)
* @return @ref HAM_WOULD_BLOCK if another process has locked the file
* @return @ref HAM_ENVIRONMENT_ALREADY_OPEN if @a env is already in use
*
* @sa ham_env_create
* @sa ham_env_close
* @sa ham_env_open
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_env_create(ham_env_t **env, const char *filename,
uint32_t flags, uint32_t mode, const ham_parameter_t *param);
/**
* Opens an existing Database Environment
*
* This function opens an existing Database Environment.
*
* A Database Environment is a collection of Databases, which are all stored
* in one physical file (or in-memory).
*
* Each Database in an Environment is identified by a positive 16bit
* value (except 0 and values at or above 0xf000).
* Databases in an Environment can be created with @ref ham_env_create_db
* or opened with @ref ham_env_open_db.
*
* Specify a URL instead of a filename (i.e.
* "ham://localhost:8080/customers.db") to access a remote hamsterdb Server.
*
* Also see the documentation @ref ham_env_create about Transactions, Recovery
* and the use of fsync.
*
* @param env A valid Environment handle
* @param filename The filename of the Environment file, or URL of a hamsterdb
* Server
* @param flags Optional flags for opening the Environment, combined with
* bitwise OR. Possible flags are:
*
* - @ref HAM_READ_ONLY
Opens the file for reading only.
* Operations that need write access (i.e. @ref ham_db_insert) will
* return @ref HAM_WRITE_PROTECTED.
* - @ref HAM_ENABLE_FSYNC
Flushes all file handles after
* committing or aborting a Transaction using fsync(), fdatasync()
* or FlushFileBuffers(). This file has no effect
* if Transactions are disabled. Slows down performance but makes
* sure that all file handles and operating system caches are
* transferred to disk, thus providing a stronger durability.
* - @ref HAM_DISABLE_MMAP
Do not use memory mapped files for I/O.
* By default, hamsterdb checks if it can use mmap,
* since mmap is faster than read/write. For performance
* reasons, this flag should not be used.
* - @ref HAM_CACHE_UNLIMITED
Do not limit the cache. Nearly as
* fast as an In-Memory Database. Not allowed in combination
* with a limited cache size.
* - @ref HAM_ENABLE_TRANSACTIONS
Enables Transactions for this
* Environment. This flag imples @ref HAM_ENABLE_RECOVERY.
* - @ref HAM_ENABLE_RECOVERY
Enables logging/recovery for this
* Environment. Will return @ref HAM_NEED_RECOVERY, if the Environment
* is in an inconsistent state. Not allowed in combination
* with @ref HAM_IN_MEMORY.
* - @ref HAM_DISABLE_RECOVERY
Disables logging/recovery for this
* Environment.
* - @ref HAM_AUTO_RECOVERY
Automatically recover the Environment,
* if necessary. This flag implies @ref HAM_ENABLE_RECOVERY.
* - @ref HAM_FLUSH_WHEN_COMMITTED
Immediately flushes committed
* Transactions and writes them to the Btree. Disabled by default. If
* disabled then hamsterdb buffers committed Transactions and only starts
* flushing when too many Transactions were committed.
*
* @param param An array of ham_parameter_t structures. The following
* parameters are available:
*
* - @ref HAM_PARAM_CACHE_SIZE
The size of the Database cache,
* in bytes. The default size is defined in src/config.h
* as @a HAM_DEFAULT_CACHE_SIZE - usually 2MB
* - @ref HAM_PARAM_POSIX_FADVISE
Sets the "advice" for
* posix_fadvise(). Only on supported platforms. Allowed values are
* @ref HAM_POSIX_FADVICE_NORMAL (which is the default) or
* @ref HAM_POSIX_FADVICE_RANDOM.
* - @ref HAM_PARAM_FILE_SIZE_LIMIT
Sets a file size limit (in bytes).
* Disabled by default. If the limit is exceeded, API functions
* return @ref HAM_LIMITS_REACHED.
* - @ref HAM_PARAM_LOG_DIRECTORY
The path of the log file
* and the journal files; default is the same path as the database
* file. Ignored for remote Environments.
* - @ref HAM_PARAM_NETWORK_TIMEOUT_SEC
Timeout (in seconds) when
* waiting for data from a remote server. By default, no timeout is set.
*
*
* @return @ref HAM_SUCCESS upon success.
* @return @ref HAM_INV_PARAMETER if the @a env pointer is NULL, an
* invalid combination of flags was specified
* @return @ref HAM_FILE_NOT_FOUND if the file does not exist
* @return @ref HAM_IO_ERROR if the file could not be opened or reading failed
* @return @ref HAM_INV_FILE_VERSION if the Environment version is not
* compatible with the library version.
* @return @ref HAM_OUT_OF_MEMORY if memory could not be allocated
* @return @ref HAM_WOULD_BLOCK if another process has locked the file
* @return @ref HAM_NEED_RECOVERY if the Database is in an inconsistent state
* @return @ref HAM_LOG_INV_FILE_HEADER if the logfile is corrupt
* @return @ref HAM_ENVIRONMENT_ALREADY_OPEN if @a env is already in use
* @return @ref HAM_NETWORK_ERROR if a remote server is not reachable
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_env_open(ham_env_t **env, const char *filename,
uint32_t flags, const ham_parameter_t *param);
/**
* Retrieve the current value for a given Environment setting
*
* Only those values requested by the parameter array will be stored.
*
* The following parameters are supported:
*
* - HAM_PARAM_CACHE_SIZE
returns the cache size
* - HAM_PARAM_PAGE_SIZE
returns the page size
* - HAM_PARAM_MAX_DATABASES
returns the max. number of
* Databases of this Database's Environment
* - HAM_PARAM_FLAGS
returns the flags which were used to
* open or create this Database
* - HAM_PARAM_FILEMODE
returns the @a mode parameter which
* was specified when creating this Database
* - HAM_PARAM_FILENAME
returns the filename (the @a value
* of this parameter is a const char * pointer casted to a
* uint64_t variable)
* - @ref HAM_PARAM_LOG_DIRECTORY
The path of the log file
* and the journal files. Ignored for remote Environments.
* - @ref HAM_PARAM_JOURNAL_COMPRESSION
Returns the
* selected algorithm for journal compression, or 0 if compression
* is disabled
*
*
* @param env A valid Environment handle
* @param param An array of ham_parameter_t structures
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_INV_PARAMETER if the @a env pointer is NULL or
* @a param is NULL
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_env_get_parameters(ham_env_t *env, ham_parameter_t *param);
/**
* Creates a new Database in a Database Environment
*
* An Environment can contain a (limited) amount of Databases; the exact
* limit depends on the page size and is above 600.
*
* Each Database in an Environment is identified by a positive 16bit
* value. 0 and values at or above 0xf000 are reserved.
*
* This function initializes the ham_db_t handle (the second parameter).
* When the handle is no longer in use, it should be closed with
* @ref ham_db_close. Alternatively, the Database handle is closed
* automatically if @ref ham_env_close is called with the flag
* @ref HAM_AUTO_CLEANUP.
*
* A Database can (and should) be configured and optimized for the data that
* is inserted. The data is described through flags and parameters. hamsterdb
* differentiates between several data characteristics, and offers predefined
* "types" to describe the keys. In general, the default key type
* (@ref HAM_TYPE_BINARY) is slower than the other types, and
* fixed-length binary keys (@ref HAM_TYPE_BINARY in combination with
* @ref HAM_PARAM_KEY_SIZE) is faster than variable-length binary
* keys. It is therefore recommended to always set the key size and record size,
* although it is not required.
*
* Internally, hamsterdb uses two different layouts ("default" and "pax)
* depending on the settings specified by the user. The "default" layout
* is enabled for variable-length keys or if duplicate keys are enabled.
* For fixed-length keys (without duplicates) the "pax" layout is chosen.
* The "pax" layout is more compact and usually faster.
*
* A word of warning regarding the use of fixed length binary keys
* (@ref HAM_TYPE_CUSTOM or @ref HAM_TYPE_BINARY in combination with
* @ref HAM_PARAM_KEY_SIZE): if your key size is too large, only few keys
* will fit in a Btree node. The Btree fanout will be very high, which will
* decrease performance. In such cases it might be better to NOT specify
* the key size; then hamsterdb will store keys as blobs if they are too large.
*
* See the Wiki documentation for
* Evaluating and Benchmarking on how to test different configurations and
* optimize for performance.
*
* The key type is set with @ref HAM_PARAM_KEY_TYPE and can have either
* of the following values:
*
*
* - HAM_TYPE_BINARY
This is the default key type: a binary blob.
* Internally, hamsterdb uses memcmp(3) for the sort order. Key size depends
* on @ref HAM_PARAM_KEY_SIZE and is unlimited (@ref HAM_KEY_SIZE_UNLIMITED)
* by default.
* - HAM_TYPE_CUSTOM
Similar to @ref HAM_TYPE_BINARY, but
* uses a callback function for the sort order. This function is supplied
* by the application with @sa ham_db_set_compare_func.
* - HAM_TYPE_UINT8
Key is a 8bit (1 byte) unsigned integer
* - HAM_TYPE_UINT16
Key is a 16bit (2 byte) unsigned integer
* - HAM_TYPE_UINT32
Key is a 32bit (4 byte) unsigned integer
* - HAM_TYPE_UINT64
Key is a 64bit (8 byte) unsigned integer
* - HAM_TYPE_REAL32
Key is a 32bit (4 byte) float
* - HAM_TYPE_REAL64
Key is a 64bit (8 byte) double
*
*
* If the key type is ommitted then @ref HAM_TYPE_BINARY is the default.
*
* If binary/custom keys are so big that they cannot be stored in the Btree,
* then the full key will be stored in an overflow area, which has
* performance implications when accessing such keys.
*
* In addition to the flags above, you can specify @a HAM_ENABLE_DUPLICATE_KEYS
* to insert duplicate keys, i.e. to model 1:n or n:m relationships.
*
* If the size of the records is always constant, then
* @ref HAM_PARAM_RECORD_SIZE should be used to specify this size. This allows
* hamsterdb to optimize the record storage, and small records will
* automatically be stored in the Btree's leaf nodes instead of a separately
* allocated blob, allowing faster access.
* A record size of 0 is valid and suited for boolean values ("key exists"
* vs "key doesn't exist"). The default record size is
* @ref HAM_RECORD_SIZE_UNLIMITED.
*
* @param env A valid Environment handle.
* @param db A valid Database handle, which will point to the created
* Database. To close the handle, use @ref ham_db_close.
* @param name The name of the Database. If a Database with this name
* already exists, the function will fail with
* @ref HAM_DATABASE_ALREADY_EXISTS. Database names from 0xf000 to
* 0xffff and 0 are reserved.
* @param flags Optional flags for creating the Database, combined with
* bitwise OR. Possible flags are:
*
* - @ref HAM_ENABLE_DUPLICATE_KEYS
Enable duplicate keys for this
* Database. By default, duplicate keys are disabled.
* - @ref HAM_RECORD_NUMBER32
Creates an "auto-increment" Database.
* Keys in Record Number Databases are automatically assigned an
* incrementing 32bit value. If key->data is not NULL
* (and key->flags is @ref HAM_KEY_USER_ALLOC), the value of the current
* key is returned in @a key. If key-data is NULL and key->size is 0,
* key->data is temporarily allocated by hamsterdb.
* - @ref HAM_RECORD_NUMBER64
Creates an "auto-increment" Database.
* Keys in Record Number Databases are automatically assigned an
* incrementing 64bit value. If key->data is not NULL
* (and key->flags is @ref HAM_KEY_USER_ALLOC), the value of the current
* key is returned in @a key. If key-data is NULL and key->size is 0,
* key->data is temporarily allocated by hamsterdb.
*
*
* @param params An array of ham_parameter_t structures. The following
* parameters are available:
*
* - @ref HAM_PARAM_KEY_TYPE
The type of the keys in the B+Tree
* index. The default is @ref HAM_TYPE_BINARY. See above for more
* information.
* - @ref HAM_PARAM_KEY_SIZE
The (fixed) size of the keys in
* the B+Tree index; or @ref HAM_KEY_SIZE_UNLIMITED for unlimited and
* variable keys (this is the default).
* - @ref HAM_PARAM_RECORD_SIZE
The (fixed) size of the records;
* or @ref HAM_RECORD_SIZE_UNLIMITED if there was no fixed record size
* specified (this is the default).
*
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_INV_PARAMETER if the @a env pointer is NULL or an
* invalid combination of flags was specified
* @return @ref HAM_DATABASE_ALREADY_EXISTS if a Database with this @a name
* already exists in this Environment
* @return @ref HAM_OUT_OF_MEMORY if memory could not be allocated
* @return @ref HAM_LIMITS_REACHED if the maximum number of Databases per
* Environment was already created
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_env_create_db(ham_env_t *env, ham_db_t **db,
uint16_t name, uint32_t flags, const ham_parameter_t *params);
/**
* Opens a Database in a Database Environment
*
* Each Database in an Environment is identified by a positive 16bit
* value (except 0 and values at or above 0xf000).
*
* This function initializes the ham_db_t handle (the second parameter).
* When the handle is no longer in use, it should be closed with
* @ref ham_db_close. Alternatively, the Database handle is closed
* automatically if @ref ham_env_close is called with the flag
* @ref HAM_AUTO_CLEANUP.
*
* @param env A valid Environment handle
* @param db A valid Database handle, which will point to the opened
* Database. To close the handle, use @see ham_db_close.
* @param name The name of the Database. If a Database with this name
* does not exist, the function will fail with
* @ref HAM_DATABASE_NOT_FOUND.
* @param flags Optional flags for opening the Database, combined with
* bitwise OR. Possible flags are:
*
* - @ref HAM_READ_ONLY
Opens the Database for reading only.
* Operations that need write access (i.e. @ref ham_db_insert) will
* return @ref HAM_WRITE_PROTECTED.
*
* @param params Reserved; set to NULL
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_INV_PARAMETER if the @a env pointer is NULL or an
* invalid combination of flags was specified
* @return @ref HAM_DATABASE_NOT_FOUND if a Database with this @a name
* does not exist in this Environment.
* @return @ref HAM_DATABASE_ALREADY_OPEN if this Database was already
* opened
* @return @ref HAM_OUT_OF_MEMORY if memory could not be allocated
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_env_open_db(ham_env_t *env, ham_db_t **db,
uint16_t name, uint32_t flags, const ham_parameter_t *params);
/**
* Renames a Database in an Environment.
*
* @param env A valid Environment handle.
* @param oldname The old name of the existing Database. If a Database
* with this name does not exist, the function will fail with
* @ref HAM_DATABASE_NOT_FOUND.
* @param newname The new name of this Database. If a Database
* with this name already exists, the function will fail with
* @ref HAM_DATABASE_ALREADY_EXISTS.
* @param flags Optional flags for renaming the Database, combined with
* bitwise OR; unused, set to 0.
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_INV_PARAMETER if the @a env pointer is NULL or if
* the new Database name is reserved
* @return @ref HAM_DATABASE_NOT_FOUND if a Database with this @a name
* does not exist in this Environment
* @return @ref HAM_DATABASE_ALREADY_EXISTS if a Database with the new name
* already exists
* @return @ref HAM_OUT_OF_MEMORY if memory could not be allocated
* @return @ref HAM_NOT_READY if the Environment @a env was not initialized
* correctly (i.e. not yet opened or created)
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_env_rename_db(ham_env_t *env, uint16_t oldname,
uint16_t newname, uint32_t flags);
/**
* Deletes a Database from an Environment
*
* @param env A valid Environment handle
* @param name The name of the Database to delete. If a Database
* with this name does not exist, the function will fail with
* @ref HAM_DATABASE_NOT_FOUND. If the Database was already opened,
* the function will fail with @ref HAM_DATABASE_ALREADY_OPEN.
* @param flags Optional flags for deleting the Database; unused, set to 0.
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_INV_PARAMETER if the @a env pointer is NULL or if
* the new Database name is reserved
* @return @ref HAM_DATABASE_NOT_FOUND if a Database with this @a name
* does not exist
* @return @ref HAM_DATABASE_ALREADY_OPEN if a Database with this name is
* still open
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_env_erase_db(ham_env_t *env, uint16_t name, uint32_t flags);
/* internal flag - only flush committed transactions, not the btree pages */
#define HAM_FLUSH_COMMITTED_TRANSACTIONS 1
/**
* Flushes the Environment
*
* This function flushes the Environment caches and writes the whole file
* to disk. All Databases of this Environment are flushed as well.
*
* Since In-Memory Databases do not have a file on disk, the
* function will have no effect and will return @ref HAM_SUCCESS.
*
* @param env A valid Environment handle
* @param flags Optional flags for flushing; unused, set to 0
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_INV_PARAMETER if @a db is NULL
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_env_flush(ham_env_t *env, uint32_t flags);
/* internal use only - don't lock mutex */
#define HAM_DONT_LOCK 0xf0000000
/**
* Returns the names of all Databases in an Environment
*
* This function returns the names of all Databases and the number of
* Databases in an Environment.
*
* The memory for @a names must be allocated by the user. @a count
* must be the size of @a names when calling the function, and will be
* the number of Databases when the function returns. The function returns
* @ref HAM_LIMITS_REACHED if @a names is not big enough; in this case, the
* caller should resize the array and call the function again.
*
* @param env A valid Environment handle
* @param names Pointer to an array for the Database names
* @param count Pointer to the size of the array; will be used to store the
* number of Databases when the function returns.
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_INV_PARAMETER if @a env, @a names or @a count is NULL
* @return @ref HAM_LIMITS_REACHED if @a names is not large enough to hold
* all Database names
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_env_get_database_names(ham_env_t *env, uint16_t *names,
uint32_t *count);
/**
* Closes the Database Environment
*
* This function closes the Database Environment. It also frees the
* memory resources allocated in the @a env handle, and tries to truncate
* the file (see below).
*
* If the flag @ref HAM_AUTO_CLEANUP is specified, hamsterdb automatically
* calls @ref ham_db_close with flag @ref HAM_AUTO_CLEANUP on all open
* Databases (which closes all open Databases and their Cursors). This
* invalidates the ham_db_t and ham_cursor_t handles!
*
* If the flag is not specified, the application must close all Database
* handles with @ref ham_db_close to prevent memory leaks.
*
* This function also aborts all Transactions which were not yet committed,
* and therefore renders all Transaction handles invalid. If the flag
* @ref HAM_TXN_AUTO_COMMIT is specified, all Transactions will be committed.
*
* This function also tries to truncate the file and "cut off" unused space
* at the end of the file to reduce the file size. This feature is disabled
* on Win32 if memory mapped I/O is used (see @ref HAM_DISABLE_MMAP).
*
* @param env A valid Environment handle
* @param flags Optional flags for closing the handle. Possible flags are:
*
* - @ref HAM_AUTO_CLEANUP. Calls @ref ham_db_close with the flag
* @ref HAM_AUTO_CLEANUP on every open Database
*
- @ref HAM_TXN_AUTO_COMMIT. Automatically commit all open
* Transactions
*
- @ref HAM_TXN_AUTO_ABORT. Automatically abort all open
* Transactions; this is the default behaviour
*
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_INV_PARAMETER if @a env is NULL
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_env_close(ham_env_t *env, uint32_t flags);
/**
* @}
*/
/**
* @defgroup ham_txn hamsterdb Transaction Functions
* @{
*/
/**
* The hamsterdb Transaction structure
*
* This structure is allocated with @ref ham_txn_begin and deleted with
* @ref ham_txn_commit or @ref ham_txn_abort.
*/
struct ham_txn_t;
typedef struct ham_txn_t ham_txn_t;
/**
* Begins a new Transaction
*
* A Transaction is an atomic sequence of Database operations. With @ref
* ham_txn_begin such a new sequence is started. To write all operations of this
* sequence to the Database use @ref ham_txn_commit. To abort and cancel
* this sequence use @ref ham_txn_abort.
*
* In order to use Transactions, the Environment has to be created or
* opened with the flag @ref HAM_ENABLE_TRANSACTIONS.
*
* You can create as many Transactions as you want (older versions of
* hamsterdb did not allow to create more than one Transaction in parallel).
*
* @param txn Pointer to a pointer of a Transaction structure
* @param env A valid Environment handle
* @param name An optional Transaction name
* @param reserved A reserved pointer; always set to NULL
* @param flags Optional flags for beginning the Transaction, combined with
* bitwise OR. Possible flags are:
*
* - @ref HAM_TXN_READ_ONLY
This Transaction is read-only and
* will not modify the Database.
*
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_OUT_OF_MEMORY if memory allocation failed
*/
HAM_EXPORT ham_status_t
ham_txn_begin(ham_txn_t **txn, ham_env_t *env, const char *name,
void *reserved, uint32_t flags);
/** Flag for @ref ham_txn_begin */
#define HAM_TXN_READ_ONLY 1
/* Internal flag for @ref ham_txn_begin */
#define HAM_TXN_TEMPORARY 2
/**
* Retrieves the Transaction name
*
* @returns NULL if the name was not assigned or if @a txn is invalid
*/
HAM_EXPORT const char *
ham_txn_get_name(ham_txn_t *txn);
/**
* Commits a Transaction
*
* This function applies the sequence of Database operations.
*
* Note that the function will fail with @ref HAM_CURSOR_STILL_OPEN if
* a Cursor was attached to this Transaction (with @ref ham_cursor_create
* or @ref ham_cursor_clone), and the Cursor was not closed.
*
* @param txn Pointer to a Transaction structure
* @param flags Optional flags for committing the Transaction, combined with
* bitwise OR. Unused, set to 0.
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_IO_ERROR if writing to the file failed
* @return @ref HAM_CURSOR_STILL_OPEN if there are Cursors attached to this
* Transaction
*/
HAM_EXPORT ham_status_t
ham_txn_commit(ham_txn_t *txn, uint32_t flags);
/**
* Aborts a Transaction
*
* This function aborts (= cancels) the sequence of Database operations.
*
* Note that the function will fail with @ref HAM_CURSOR_STILL_OPEN if
* a Cursor was attached to this Transaction (with @ref ham_cursor_create
* or @ref ham_cursor_clone), and the Cursor was not closed.
*
* @param txn Pointer to a Transaction structure
* @param flags Optional flags for aborting the Transaction, combined with
* bitwise OR. Unused, set to 0.
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_IO_ERROR if writing to the Database file or logfile failed
* @return @ref HAM_CURSOR_STILL_OPEN if there are Cursors attached to this
* Transaction
*/
HAM_EXPORT ham_status_t
ham_txn_abort(ham_txn_t *txn, uint32_t flags);
/**
* @}
*/
/**
* @defgroup ham_database hamsterdb Database Functions
* @{
*/
/** Flag for @ref ham_env_open, @ref ham_env_create.
* This flag is non persistent. */
#define HAM_ENABLE_FSYNC 0x00000001
/* unused 0x00000002 */
/** Flag for @ref ham_env_open, @ref ham_env_open_db.
* This flag is non persistent. */
#define HAM_READ_ONLY 0x00000004
/* unused 0x00000008 */
/* unused 0x00000010 */
/* reserved 0x00000020 */
/* unused 0x00000040 */
/** Flag for @ref ham_env_create.
* This flag is non persistent. */
#define HAM_IN_MEMORY 0x00000080
/* reserved: DB_USE_MMAP (not persistent) 0x00000100 */
/** Flag for @ref ham_env_open, @ref ham_env_create.
* This flag is non persistent. */
#define HAM_DISABLE_MMAP 0x00000200
/* deprecated */
#define HAM_RECORD_NUMBER HAM_RECORD_NUMBER64
/** Flag for @ref ham_env_create_db.
* This flag is persisted in the Database. */
#define HAM_RECORD_NUMBER32 0x00001000
/** Flag for @ref ham_env_create_db.
* This flag is persisted in the Database. */
#define HAM_RECORD_NUMBER64 0x00002000
/** Flag for @ref ham_env_create_db.
* This flag is persisted in the Database. */
#define HAM_ENABLE_DUPLICATE_KEYS 0x00004000
/* deprecated */
#define HAM_ENABLE_DUPLICATES HAM_ENABLE_DUPLICATE_KEYS
/** Flag for @ref ham_env_create, @ref ham_env_open.
* This flag is non persistent. */
#define HAM_ENABLE_RECOVERY 0x00008000
/** Flag for @ref ham_env_open.
* This flag is non persistent. */
#define HAM_AUTO_RECOVERY 0x00010000
/** Flag for @ref ham_env_create, @ref ham_env_open.
* This flag is non persistent. */
#define HAM_ENABLE_TRANSACTIONS 0x00020000
/** Flag for @ref ham_env_open, @ref ham_env_create.
* This flag is non persistent. */
#define HAM_CACHE_UNLIMITED 0x00040000
/** Flag for @ref ham_env_create, @ref ham_env_open.
* This flag is non persistent. */
#define HAM_DISABLE_RECOVERY 0x00080000
/* internal use only! (not persistent) */
#define HAM_IS_REMOTE_INTERNAL 0x00200000
/* internal use only! (not persistent) */
#define HAM_DISABLE_RECLAIM_INTERNAL 0x00400000
/* internal use only! (persistent) */
#define HAM_FORCE_RECORDS_INLINE 0x00800000
/** Flag for @ref ham_env_open, @ref ham_env_create.
* This flag is non persistent. */
#define HAM_FLUSH_WHEN_COMMITTED 0x01000000
/** Pro: Flag for @ref ham_env_open, @ref ham_env_create.
* This flag is non persistent. */
#define HAM_ENABLE_CRC32 0x02000000
/**
* Returns the last error code
*
* @note This API is deprecated! It will be removed in one of the
* next versions.
*
* @param db A valid Database handle
*
* @return The last error code which was returned by one of the
* hamsterdb API functions. Use @ref ham_strerror to translate
* this code to a descriptive string
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_db_get_error(ham_db_t *db);
/**
* Typedef for a key comparison function
*
* @remark This function compares two index keys. It returns -1, if @a lhs
* ("left-hand side", the parameter on the left side) is smaller than
* @a rhs ("right-hand side"), 0 if both keys are equal, and 1 if @a lhs
* is larger than @a rhs.
*/
typedef int HAM_CALLCONV (*ham_compare_func_t)(ham_db_t *db,
const uint8_t *lhs, uint32_t lhs_length,
const uint8_t *rhs, uint32_t rhs_length);
/**
* Sets the comparison function
*
* The comparison function compares two index keys. It returns -1 if the
* first key is smaller, +1 if the second key is smaller or 0 if both
* keys are equal.
*
* Supplying a comparison function is only allowed for the key type
* @ref HAM_TYPE_CUSTOM; see the documentation of @sa ham_env_create_db
* for more information.
*
* @param db A valid Database handle
* @param foo A pointer to the compare function
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_INV_PARAMETER if one of the parameters is NULL
* @return @ref HAM_INV_PARAMETER if the database's key type was not
* specified as @ref HAM_TYPE_CUSTOM
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_db_set_compare_func(ham_db_t *db, ham_compare_func_t foo);
/**
* Searches an item in the Database
*
* This function searches the Database for @a key. If the key
* is found, @a record will receive the record of this item and
* @ref HAM_SUCCESS is returned. If the key is not found, the function
* returns @ref HAM_KEY_NOT_FOUND.
*
* A ham_record_t structure should be initialized with
* zeroes before it is being used. This can be done with the C library
* routines memset(3) or bzero(2).
*
* If the function completes successfully, the @a record pointer is
* initialized with the size of the record (in @a record.size) and the
* actual record data (in @a record.data). If the record is empty,
* @a size is 0 and @a data points to NULL.
*
* The @a data pointer is a temporary pointer and will be overwritten
* by subsequent hamsterdb API calls using the same Transaction
* (or, if Transactions are disabled, using the same Database).
* You can alter this behaviour by allocating the @a data pointer in
* the application and setting @a record.flags to @ref HAM_RECORD_USER_ALLOC.
* Make sure that the allocated buffer is large enough.
*
* When specifying @ref HAM_DIRECT_ACCESS, the @a data pointer will point
* directly to the record that is stored in hamsterdb; the data can be modified,
* but the pointer must not be reallocated or freed. The flag @ref
* HAM_DIRECT_ACCESS is only allowed in In-Memory Databases and not if
* Transactions are enabled.
*
* @ref ham_db_find can not search for duplicate keys. If @a key has
* multiple duplicates, only the first duplicate is returned.
*
* You can read only portions of the record by specifying the flag
* @ref HAM_PARTIAL. In this case, hamsterdb will read
* record->partial_size bytes of the record data at offset
* record->partial_offset. If necessary, the record data will
* be limited to the original record size. The number of actually read
* bytes is returned in record->partial_size. The original size of
* the record is stored in record->size.
*
* @ref HAM_PARTIAL is not allowed if record->size is <= 8 or if Transactions
* are enabled. In such a case, @ref HAM_INV_PARAMETER is returned.
*
* If Transactions are enabled (see @ref HAM_ENABLE_TRANSACTIONS) and
* @a txn is NULL then hamsterdb will create a temporary Transaction.
* When moving the Cursor, and the new key is currently modified in an
* active Transaction (one that is not yet committed or aborted) then
* hamsterdb will skip this key and move to the next/previous one. However if
* @a flags are 0 (and the Cursor is not moved), and @a key or @a rec
* is NOT NULL, then hamsterdb will return error @ref HAM_TXN_CONFLICT.
*
* @param db A valid Database handle
* @param txn A Transaction handle, or NULL
* @param key The key of the item
* @param record The record of the item
* @param flags Optional flags for searching, which can be combined with
* bitwise OR. Possible flags are:
*
* - @ref HAM_FIND_LT_MATCH
Cursor 'find' flag 'Less Than': the
* cursor is moved to point at the last record which' key
* is less than the specified key. When such a record cannot
* be located, an error is returned.
* - @ref HAM_FIND_GT_MATCH
Cursor 'find' flag 'Greater Than':
* the cursor is moved to point at the first record which' key is
* larger than the specified key. When such a record cannot be
* located, an error is returned.
* - @ref HAM_FIND_LEQ_MATCH
Cursor 'find' flag 'Less or EQual':
* the cursor is moved to point at the record which' key matches
* the specified key and when such a record is not available
* the cursor is moved to point at the last record which' key
* is less than the specified key. When such a record cannot be
* located, an error is returned.
* - @ref HAM_FIND_GEQ_MATCH
Cursor 'find' flag 'Greater or
* Equal': the cursor is moved to point at the record which' key
* matches the specified key and when such a record
* is not available the cursor is moved to point at the first
* record which' key is larger than the specified key.
* When such a record cannot be located, an error is returned.
* - @ref HAM_FIND_NEAR_MATCH
Cursor 'find' flag 'Any Near Or
* Equal': the cursor is moved to point at the record which'
* key matches the specified key and when such a record is
* not available the cursor is moved to point at either the
* last record which' key is less than the specified key or
* the first record which' key is larger than the specified
* key, whichever of these records is located first.
* When such records cannot be located, an error is returned.
* - @ref HAM_DIRECT_ACCESS
Only for In-Memory Databases
* and not if Transactions are enabled!
* Returns a direct pointer to the data blob stored by the
* hamsterdb engine. This pointer must not be resized or freed,
* but the data in this memory can be modified.
*
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_INV_PARAMETER if @a db, @a key or @a record is NULL
* @return @ref HAM_INV_PARAMETER if @a HAM_DIRECT_ACCESS is specified,
* but the Database is not an In-Memory Database.
* @return @ref HAM_INV_PARAMETER if @a HAM_DIRECT_ACCESS and
* @a HAM_ENABLE_TRANSACTIONS were both specified.
* @return @ref HAM_INV_PARAMETER if @ref HAM_PARTIAL is set but record
* size is <= 8 or Transactions are enabled
* @return @ref HAM_KEY_NOT_FOUND if the @a key does not exist
* @return @ref HAM_TXN_CONFLICT if the same key was inserted in another
* Transaction which was not yet committed or aborted
*
* @remark When either or both @ref HAM_FIND_LT_MATCH and/or @ref
* HAM_FIND_GT_MATCH have been specified as flags, the @a key structure
* will be overwritten when an approximate match was found: the
* @a key and @a record structures will then point at the located
* @a key and @a record. In this case the caller should ensure @a key
* points at a structure which must adhere to the same restrictions
* and conditions as specified for @ref ham_cursor_move(...,
* HAM_CURSOR_NEXT).
*
* @sa HAM_RECORD_USER_ALLOC
* @sa HAM_KEY_USER_ALLOC
* @sa ham_record_t
* @sa ham_key_t
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_db_find(ham_db_t *db, ham_txn_t *txn, ham_key_t *key,
ham_record_t *record, uint32_t flags);
/**
* Inserts a Database item
*
* This function inserts a key/record pair as a new Database item.
*
* If the key already exists in the Database, error @ref HAM_DUPLICATE_KEY
* is returned.
*
* If you wish to overwrite an existing entry specify the
* flag @ref HAM_OVERWRITE.
*
* You can write only portions of the record by specifying the flag
* @ref HAM_PARTIAL. In this case, hamsterdb will write partial_size
* bytes of the record data at offset partial_offset. The full record
* size will always be given in record->size! If
* partial_size+partial_offset exceed record->size then partial_size will
* be limited. To shrink or grow the record, adjust record->size.
* @ref HAM_PARTIAL automatically overwrites existing records.
* Gaps will be filled with null-bytes if the record did not yet exist.
*
* @ref HAM_PARTIAL is not allowed if record->size is <= 8 or if Transactions
* are enabled. In such a case, @ref HAM_INV_PARAMETER is returned.
*
* If you wish to insert a duplicate key specify the flag @ref HAM_DUPLICATE.
* (Note that the Database has to be created with @ref HAM_ENABLE_DUPLICATE_KEYS
* in order to use duplicate keys.)
* The duplicate key is inserted after all other duplicate keys (see
* @ref HAM_DUPLICATE_INSERT_LAST).
*
* Record Number Databases (created with @ref HAM_RECORD_NUMBER32 or
* @ref HAM_RECORD_NUMBER64) expect either an empty @a key (with a size of
* 0 and data pointing to NULL), or a user-supplied key (with key.flag
* @ref HAM_KEY_USER_ALLOC and a valid data pointer).
* If key.size is 0 and key.data is NULL, hamsterdb will temporarily
* allocate memory for key->data, which will then point to an 4-byte (or 8-byte)
* unsigned integer.
*
* For very fast sequential inserts please use @ref ham_cursor_insert in
* combination with the flag @ref HAM_HINT_APPEND.
*
* @param db A valid Database handle
* @param txn A Transaction handle, or NULL
* @param key The key of the new item
* @param record The record of the new item
* @param flags Optional flags for inserting. Possible flags are:
*
* - @ref HAM_OVERWRITE. If the @a key already exists, the record is
* overwritten. Otherwise, the key is inserted. Flag is not
* allowed in combination with @ref HAM_DUPLICATE.
*
- @ref HAM_DUPLICATE. If the @a key already exists, a duplicate
* key is inserted. The key is inserted before the already
* existing key, or according to the sort order. Flag is not
* allowed in combination with @ref HAM_OVERWRITE.
*
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_INV_PARAMETER if @a db, @a key or @a record is NULL
* @return @ref HAM_INV_PARAMETER if the Database is a Record Number Database
* and the key is invalid (see above)
* @return @ref HAM_INV_PARAMETER if @ref HAM_PARTIAL is set but record
* size is <= 8 or Transactions are enabled
* @return @ref HAM_INV_PARAMETER if the flags @ref HAM_OVERWRITE and
* @ref HAM_DUPLICATE were specified, or if @ref HAM_DUPLICATE
* was specified, but the Database was not created with
* flag @ref HAM_ENABLE_DUPLICATE_KEYS.
* @return @ref HAM_INV_PARAMETER if @ref HAM_PARTIAL is specified and
* record->partial_offset+record->partial_size exceeds the
* record->size
* @return @ref HAM_WRITE_PROTECTED if you tried to insert a key in a read-only
* Database
* @return @ref HAM_TXN_CONFLICT if the same key was inserted in another
* Transaction which was not yet committed or aborted
* @return @ref HAM_INV_KEY_SIZE if the key size is larger than the
* @a HAM_PARAMETER_KEY_SIZE parameter specified for
* @ref ham_env_create_db
* OR if the key's size is greater than the Btree key size (see
* @ref HAM_PARAM_KEY_SIZE).
* @return @ref HAM_INV_RECORD_SIZE if the record size is different from
* the one specified with @a HAM_PARAM_RECORD_SIZE
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_db_insert(ham_db_t *db, ham_txn_t *txn, ham_key_t *key,
ham_record_t *record, uint32_t flags);
/**
* Flag for @ref ham_db_insert and @ref ham_cursor_insert
*
* When specified with @ref ham_db_insert and in case a key
* is specified which stores duplicates in the Database, the first
* duplicate record will be overwritten.
*
* When used with @ref ham_cursor_insert and assuming the same
* conditions, the duplicate currently referenced by the Cursor
* will be overwritten.
*/
#define HAM_OVERWRITE 0x0001
/** Flag for @ref ham_db_insert and @ref ham_cursor_insert */
#define HAM_DUPLICATE 0x0002
/** Flag for @ref ham_cursor_insert */
#define HAM_DUPLICATE_INSERT_BEFORE 0x0004
/** Flag for @ref ham_cursor_insert */
#define HAM_DUPLICATE_INSERT_AFTER 0x0008
/** Flag for @ref ham_cursor_insert */
#define HAM_DUPLICATE_INSERT_FIRST 0x0010
/** Flag for @ref ham_cursor_insert */
#define HAM_DUPLICATE_INSERT_LAST 0x0020
/** Flag for @ref ham_db_find, @ref ham_cursor_find, @ref ham_cursor_move */
#define HAM_DIRECT_ACCESS 0x0040
/** Flag for @ref ham_db_insert, @ref ham_cursor_insert, @ref ham_db_find,
* @ref ham_cursor_find, @ref ham_cursor_move */
#define HAM_PARTIAL 0x0080
/* Internal flag for @ref ham_db_find, @ref ham_cursor_find,
* @ref ham_cursor_move */
#define HAM_FORCE_DEEP_COPY 0x0100
/**
* Flag for @ref ham_cursor_insert
*
* Mutually exclusive with flag @ref HAM_HINT_PREPEND.
*
* Hints the hamsterdb engine that the current key will
* compare as @e larger than any key already existing in the Database.
* The hamsterdb engine will verify this postulation and when found not
* to be true, will revert to a regular insert operation
* as if this flag was not specified. The incurred cost then is only one
* additional key comparison.
*/
#define HAM_HINT_APPEND 0x00080000
/**
* Flag for @ref ham_cursor_insert
*
* Mutually exclusive with flag @ref HAM_HINT_APPEND.
*
* Hints the hamsterdb engine that the current key will
* compare as @e smaller than any key already existing in the Database.
* The hamsterdb engine will verify this postulation and when found not
* to be true, will revert to a regular insert operation
* as if this flag was not specified. The incurred cost then is only one
* additional key comparison.
*/
#define HAM_HINT_PREPEND 0x00100000
/**
* Flag mask to extract the common hint flags from a find/move/insert/erase
* flag value.
*/
#define HAM_HINTS_MASK 0x001F0000
/**
* Erases a Database item
*
* This function erases a Database item. If the item @a key
* does not exist, @ref HAM_KEY_NOT_FOUND is returned.
*
* Note that ham_db_erase can not erase a single duplicate key. If the key
* has multiple duplicates, all duplicates of this key will be erased. Use
* @ref ham_cursor_erase to erase a specific duplicate key.
*
* @param db A valid Database handle
* @param txn A Transaction handle, or NULL
* @param key The key to delete
* @param flags Optional flags for erasing; unused, set to 0
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_INV_PARAMETER if @a db or @a key is NULL
* @return @ref HAM_WRITE_PROTECTED if you tried to erase a key from a read-only
* Database
* @return @ref HAM_KEY_NOT_FOUND if @a key was not found
* @return @ref HAM_TXN_CONFLICT if the same key was inserted in another
* Transaction which was not yet committed or aborted
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_db_erase(ham_db_t *db, ham_txn_t *txn, ham_key_t *key, uint32_t flags);
/* internal flag for ham_db_erase() - do not use */
#define HAM_ERASE_ALL_DUPLICATES 1
/**
* Returns the number of keys stored in the Database
*
* You can specify the @ref HAM_SKIP_DUPLICATES if you do now want
* to include any duplicates in the count. This will also speed up the
* counting.
*
* @param db A valid Database handle
* @param txn A Transaction handle, or NULL
* @param flags Optional flags:
*
* - @ref HAM_SKIP_DUPLICATES. Excludes any duplicates from
* the count
*
* @param keycount A reference to a variable which will receive
* the calculated key count per page
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_INV_PARAMETER if @a db or @a keycount is NULL or when
* @a flags contains an invalid flag set
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_db_get_key_count(ham_db_t *db, ham_txn_t *txn, uint32_t flags,
uint64_t *keycount);
/**
* Retrieve the current value for a given Database setting
*
* Only those values requested by the parameter array will be stored.
*
* The following parameters are supported:
*
* - HAM_PARAM_FLAGS
returns the flags which were used to
* open or create this Database
* - HAM_PARAM_DATABASE_NAME
returns the Database name
* - HAM_PARAM_KEY_TYPE
returns the Btree key type
* - HAM_PARAM_KEY_SIZE
returns the Btree key size
* or @ref HAM_KEY_SIZE_UNLIMITED if there was no fixed key size
* specified.
* - HAM_PARAM_RECORD_SIZE
returns the record size,
* or @ref HAM_RECORD_SIZE_UNLIMITED if there was no fixed record size
* specified.
* - HAM_PARAM_MAX_KEYS_PER_PAGE
returns the maximum number
* of keys per page. This number is precise if the key size is fixed
* and duplicates are disabled; otherwise it's an estimate.
* - @ref HAM_PARAM_RECORD_COMPRESSION
Returns the
* selected algorithm for record compression, or 0 if compression
* is disabled
* - @ref HAM_PARAM_KEY_COMPRESSION
Returns the
* selected algorithm for key compression, or 0 if compression
* is disabled
*
*
* @param db A valid Database handle
* @param param An array of ham_parameter_t structures
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_INV_PARAMETER if the @a db pointer is NULL or
* @a param is NULL
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_db_get_parameters(ham_db_t *db, ham_parameter_t *param);
/** Parameter name for @ref ham_env_open, @ref ham_env_create;
* Journal files are switched whenever the number of new Transactions exceeds
* this threshold. */
#define HAM_PARAM_JOURNAL_SWITCH_THRESHOLD 0x00001
/** Parameter name for @ref ham_env_open, @ref ham_env_create;
* sets the cache size */
#define HAM_PARAM_CACHE_SIZE 0x00000100
/* deprecated */
#define HAM_PARAM_CACHESIZE HAM_PARAM_CACHE_SIZE
/** Parameter name for @ref ham_env_create; sets the page size */
#define HAM_PARAM_PAGE_SIZE 0x00000101
/* deprecated */
#define HAM_PARAM_PAGESIZE HAM_PARAM_PAGE_SIZE
/** Parameter name for @ref ham_env_create_db; sets the key size */
#define HAM_PARAM_KEY_SIZE 0x00000102
/* deprecated */
#define HAM_PARAM_KEYSIZE HAM_PARAM_KEY_SIZE
/** Parameter name for @ref ham_env_get_parameters; retrieves the number
* of maximum Databases */
#define HAM_PARAM_MAX_DATABASES 0x00000103
/** Parameter name for @ref ham_env_create_db; sets the key type */
#define HAM_PARAM_KEY_TYPE 0x00000104
/** Parameter name for @ref ham_env_open, @ref ham_env_create;
* sets the path of the log files */
#define HAM_PARAM_LOG_DIRECTORY 0x00000105
/** hamsterdb pro: Parameter name for @ref ham_env_open, @ref ham_env_create;
* sets the AES encryption key */
#define HAM_PARAM_ENCRYPTION_KEY 0x00000106
/** Parameter name for @ref ham_env_open, @ref ham_env_create;
* sets the network timeout (in seconds) */
#define HAM_PARAM_NETWORK_TIMEOUT_SEC 0x00000107
/** Parameter name for @ref ham_env_create_db; sets the key size */
#define HAM_PARAM_RECORD_SIZE 0x00000108
/** Parameter name for @ref ham_env_create, @ref ham_env_open; sets a
* limit for the file size (in bytes) */
#define HAM_PARAM_FILE_SIZE_LIMIT 0x00000109
/** Parameter name for @ref ham_env_create, @ref ham_env_open; sets the
* parameter for posix_fadvise() */
#define HAM_PARAM_POSIX_FADVISE 0x00000110
/** Value for @ref HAM_PARAM_POSIX_FADVISE */
#define HAM_POSIX_FADVICE_NORMAL 0
/** Value for @ref HAM_PARAM_POSIX_FADVISE */
#define HAM_POSIX_FADVICE_RANDOM 1
/** Value for unlimited record sizes */
#define HAM_RECORD_SIZE_UNLIMITED ((uint32_t)-1)
/** Value for unlimited key sizes */
#define HAM_KEY_SIZE_UNLIMITED ((uint16_t)-1)
/** Retrieves the Database/Environment flags as were specified at the time of
* @ref ham_env_create/@ref ham_env_open invocation. */
#define HAM_PARAM_FLAGS 0x00000200
/** Retrieves the filesystem file access mode as was specified at the time
* of @ref ham_env_create/@ref ham_env_open invocation. */
#define HAM_PARAM_FILEMODE 0x00000201
/**
* Return a const char *
pointer to the current
* Environment/Database file name in the @ref uint64_t value
* member, when the Database is actually stored on disc.
*
* In-memory Databases will return a NULL (0) pointer instead.
*/
#define HAM_PARAM_FILENAME 0x00000202
/**
* Retrieve the Database 'name' number of this @ref ham_db_t Database within
* the current @ref ham_env_t Environment.
*/
#define HAM_PARAM_DATABASE_NAME 0x00000203
/**
* Retrieve the maximum number of keys per page; this number depends on the
* currently active page and key sizes. Can be an estimate if keys do not
* have constant sizes or if duplicate keys are used.
*/
#define HAM_PARAM_MAX_KEYS_PER_PAGE 0x00000204
/**
* hamsterdb pro: Parameter name for @ref ham_env_create, @ref ham_env_open;
* enables compression for the journal.
*/
#define HAM_PARAM_JOURNAL_COMPRESSION 0x00001000
/**
* hamsterdb pro: Parameter name for @ref ham_env_create_db,
* @ref ham_env_open_db; enables compression for the records of
* a Database.
*/
#define HAM_PARAM_RECORD_COMPRESSION 0x00001001
/**
* hamsterdb pro: Parameter name for @ref ham_env_create_db,
* @ref ham_env_open_db; enables compression for the records of
* a Database.
*/
#define HAM_PARAM_KEY_COMPRESSION 0x00001002
/** hamsterdb pro: helper macro for disabling compression */
#define HAM_COMPRESSOR_NONE 0
/**
* hamsterdb pro: selects zlib compression
* http://www.zlib.net/
*/
#define HAM_COMPRESSOR_ZLIB 1
/**
* hamsterdb pro: selects google snappy compression
* http://code.google.com/p/snappy
*/
#define HAM_COMPRESSOR_SNAPPY 2
/**
* hamsterdb pro: selects lzf compression
* http://oldhome.schmorp.de/marc/liblzf.html
*/
#define HAM_COMPRESSOR_LZF 3
/**
* hamsterdb pro: selects lzo compression
* http://www.oberhumer.com/opensource/lzo
*/
#define HAM_COMPRESSOR_LZO 4
/**
* Retrieves the Environment handle of a Database
*
* @param db A valid Database handle
*
* @return The Environment handle
*/
HAM_EXPORT ham_env_t *HAM_CALLCONV
ham_db_get_env(ham_db_t *db);
/**
* Returns the kind of key match which produced this key as it was
* returned by one of the @ref ham_db_find() and @ref ham_cursor_find().
*
* This routine assumes the key was passed back by one of the @ref ham_db_find
* and @ref ham_cursor_find functions and not used by any other hamsterdb
* functions after that.
*
* As such, this function produces an answer akin to the 'sign' of the
* specified key as it was returned by the find operation.
*
* @param key A valid key
*
* @return 1 (greater than) or -1 (less than) when the given key is an
* approximate result / zero (0) otherwise. Specifically:
*
* - +1 when the key is greater than the item searched for (key
* was a GT match)
*
- -1 when the key is less than the item searched for (key was
* a LT match)
*
- zero (0) otherwise (key was an EQ (EXACT) match)
*
*/
HAM_EXPORT int HAM_CALLCONV
ham_key_get_approximate_match_type(ham_key_t *key);
/**
* Closes the Database
*
* This function flushes the Database and then closes the file handle.
* It also free the memory resources allocated in the @a db handle.
*
* If the flag @ref HAM_AUTO_CLEANUP is specified, hamsterdb automatically
* calls @ref ham_cursor_close on all open Cursors. This invalidates the
* ham_cursor_t handle!
*
* If the flag is not specified, the application must close all Database
* Cursors with @ref ham_cursor_close to prevent memory leaks.
*
* This function also aborts all Transactions which were not yet committed,
* and therefore renders all Transaction handles invalid. If the flag
* @ref HAM_TXN_AUTO_COMMIT is specified, all Transactions will be committed.
*
* @param db A valid Database handle
* @param flags Optional flags for closing the Database. Possible values are:
*
* - @ref HAM_AUTO_CLEANUP. Automatically closes all open Cursors
*
- @ref HAM_TXN_AUTO_COMMIT. Automatically commit all open
* Transactions
*
- @ref HAM_TXN_AUTO_ABORT. Automatically abort all open
* Transactions; this is the default behaviour
*
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_INV_PARAMETER if @a db is NULL
* @return @ref HAM_CURSOR_STILL_OPEN if not all Cursors of this Database
* were closed, and @ref HAM_AUTO_CLEANUP was not specified
* @return @ref HAM_TXN_STILL_OPEN if this Database is modified by a
* currently active Transaction
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_db_close(ham_db_t *db, uint32_t flags);
/** Flag for @ref ham_db_close, @ref ham_env_close */
#define HAM_AUTO_CLEANUP 1
/** @internal (Internal) flag for @ref ham_db_close, @ref ham_env_close */
#define HAM_DONT_CLEAR_LOG 2
/** Automatically abort all open Transactions (the default) */
#define HAM_TXN_AUTO_ABORT 4
/** Automatically commit all open Transactions */
#define HAM_TXN_AUTO_COMMIT 8
/**
* @}
*/
/**
* @defgroup ham_cursor hamsterdb Cursor Functions
* @{
*/
/**
* Creates a Database Cursor
*
* Creates a new Database Cursor. Cursors can be used to
* traverse the Database from start to end or vice versa. Cursors
* can also be used to insert, delete or search Database items.
*
* A newly created Cursor does not point to any item in the Database.
*
* The application should close all Cursors of a Database before closing
* the Database.
*
* If Transactions are enabled (@ref HAM_ENABLE_TRANSACTIONS), but @a txn
* is NULL, then each Cursor operation (i.e. @ref ham_cursor_insert,
* @ref ham_cursor_find etc) will create its own, temporary Transaction
* only for the lifetime of this operation and not for the lifetime
* of the whole Cursor!
*
* @param db A valid Database handle
* @param txn A Transaction handle, or NULL
* @param flags Optional flags for creating the Cursor; unused, set to 0
* @param cursor A pointer to a pointer which is allocated for the
* new Cursor handle
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_INV_PARAMETER if @a db or @a cursor is NULL
* @return @ref HAM_OUT_OF_MEMORY if the new structure could not be allocated
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_cursor_create(ham_cursor_t **cursor, ham_db_t *db, ham_txn_t *txn,
uint32_t flags);
/**
* Clones a Database Cursor
*
* Clones an existing Cursor. The new Cursor will point to
* exactly the same item as the old Cursor. If the old Cursor did not point
* to any item, so will the new Cursor.
*
* If the old Cursor is bound to a Transaction, then the new Cursor will
* also be bound to this Transaction.
*
* @param src The existing Cursor
* @param dest A pointer to a pointer, which is allocated for the
* cloned Cursor handle
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_INV_PARAMETER if @a src or @a dest is NULL
* @return @ref HAM_OUT_OF_MEMORY if the new structure could not be allocated
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_cursor_clone(ham_cursor_t *src, ham_cursor_t **dest);
/**
* Moves the Cursor
*
* Moves the Cursor. Use the @a flags to specify the direction.
* After the move, key and record of the item are returned, if @a key
* and/or @a record are valid pointers.
*
* If the direction is not specified, the Cursor will not move. Do not
* specify a direction if you want to fetch the key and/or record of
* the current item.
*
* When specifying @ref HAM_DIRECT_ACCESS, the @a data pointer will point
* directly to the record that is stored in hamsterdb; the data can be modified,
* but the pointer must not be reallocated or freed. The flag @ref
* HAM_DIRECT_ACCESS is only allowed in In-Memory Databases and not if
* Transactions are enabled.
*
* You can read only portions of the record by specifying the flag
* @ref HAM_PARTIAL. In this case, hamsterdb will read
* record->partial_size bytes of the record data at offset
* record->partial_offset. If necessary, the record data will
* be limited to the original record size. The number of actually read
* bytes is returned in record->partial_size. The original size of
* the record is stored in record->size.
*
* @ref HAM_PARTIAL is not allowed if record->size is <= 8 or if Transactions
* are enabled. In such a case, @ref HAM_INV_PARAMETER is returned.
*
* If Transactions are enabled (see @ref HAM_ENABLE_TRANSACTIONS), and
* the Cursor moves next or previous to a key which is currently modified
* in an active Transaction (one that is not yet committed or aborted), then
* hamsterdb will skip the modified key. (This behavior is different from i.e.
* @a ham_cursor_find, which would return the error @ref HAM_TXN_CONFLICT).
*
* If a key has duplicates and any of the duplicates is currently modified
* in another active Transaction, then ALL duplicate keys are skipped when
* moving to the next or previous key.
*
* If the first (@ref HAM_CURSOR_FIRST) or last (@ref HAM_CURSOR_LAST) key
* is requested, and the current key (or any of its duplicates) is currently
* modified in an active Transaction, then @ref HAM_TXN_CONFLICT is
* returned.
*
* If this Cursor is nil (i.e. because it was not yet used or the Cursor's
* item was erased) then the flag @a HAM_CURSOR_NEXT (or @a
* HAM_CURSOR_PREVIOUS) will be identical to @a HAM_CURSOR_FIRST (or
* @a HAM_CURSOR_LAST).
*
* @param cursor A valid Cursor handle
* @param key An optional pointer to a @ref ham_key_t structure. If this
* pointer is not NULL, the key of the new item is returned.
* Note that key->data will point to temporary data. This pointer
* will be invalidated by subsequent hamsterdb API calls. See
* @ref HAM_KEY_USER_ALLOC on how to change this behaviour.
* @param record An optional pointer to a @ref ham_record_t structure. If this
* pointer is not NULL, the record of the new item is returned.
* Note that record->data will point to temporary data. This pointer
* will be invalidated by subsequent hamsterdb API calls. See
* @ref HAM_RECORD_USER_ALLOC on how to change this behaviour.
* @param flags The flags for this operation. They are used to specify
* the direction for the "move". If you do not specify a direction,
* the Cursor will remain on the current position.
*
* - @ref HAM_CURSOR_FIRST
positions the Cursor on the first
* item in the Database
* - @ref HAM_CURSOR_LAST
positions the Cursor on the last
* item in the Database
* - @ref HAM_CURSOR_NEXT
positions the Cursor on the next
* item in the Database; if the Cursor does not point to any
* item, the function behaves as if direction was
* @ref HAM_CURSOR_FIRST.
* - @ref HAM_CURSOR_PREVIOUS
positions the Cursor on the
* previous item in the Database; if the Cursor does not point to
* any item, the function behaves as if direction was
* @ref HAM_CURSOR_LAST.
* - @ref HAM_SKIP_DUPLICATES
skips duplicate keys of the
* current key. Not allowed in combination with
* @ref HAM_ONLY_DUPLICATES.
* - @ref HAM_ONLY_DUPLICATES
only move through duplicate keys
* of the current key. Not allowed in combination with
* @ref HAM_SKIP_DUPLICATES.
* - @ref HAM_DIRECT_ACCESS
Only for In-Memory Databases and
* not if Transactions are enabled!
* Returns a direct pointer to the data blob stored by the
* hamsterdb engine. This pointer must not be resized or freed,
* but the data in this memory can be modified.
*
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_INV_PARAMETER if @a cursor is NULL, or if an invalid
* combination of flags was specified
* @return @ref HAM_INV_PARAMETER if @ref HAM_PARTIAL is set but record
* size is <= 8 or Transactions are enabled
* @return @ref HAM_CURSOR_IS_NIL if the Cursor does not point to an item, but
* key and/or record were requested
* @return @ref HAM_KEY_NOT_FOUND if @a cursor points to the first (or last)
* item, and a move to the previous (or next) item was
* requested
* @return @ref HAM_INV_PARAMETER if @a HAM_DIRECT_ACCESS is specified,
* but the Database is not an In-Memory Database.
* @return @ref HAM_INV_PARAMETER if @a HAM_DIRECT_ACCESS and
* @a HAM_ENABLE_TRANSACTIONS were both specified.
* @return @ref HAM_INV_PARAMETER if @ref HAM_PARTIAL is specified and
* record->partial_offset+record->partial_size exceeds the
* record->size
* @return @ref HAM_TXN_CONFLICT if @ref HAM_CURSOR_FIRST or @ref
* HAM_CURSOR_LAST is specified but the first (or last) key or
* any of its duplicates is currently modified in an active
* Transaction
*
* @sa HAM_RECORD_USER_ALLOC
* @sa HAM_KEY_USER_ALLOC
* @sa ham_record_t
* @sa ham_key_t
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_cursor_move(ham_cursor_t *cursor, ham_key_t *key,
ham_record_t *record, uint32_t flags);
/** Flag for @ref ham_cursor_move */
#define HAM_CURSOR_FIRST 0x0001
/** Flag for @ref ham_cursor_move */
#define HAM_CURSOR_LAST 0x0002
/** Flag for @ref ham_cursor_move */
#define HAM_CURSOR_NEXT 0x0004
/** Flag for @ref ham_cursor_move */
#define HAM_CURSOR_PREVIOUS 0x0008
/** Flag for @ref ham_cursor_move and @ref ham_db_get_key_count */
#define HAM_SKIP_DUPLICATES 0x0010
/** Flag for @ref ham_cursor_move */
#define HAM_ONLY_DUPLICATES 0x0020
/**
* Overwrites the current record
*
* This function overwrites the record of the current item.
*
* @param cursor A valid Cursor handle
* @param record A valid record structure
* @param flags Optional flags for overwriting the item; unused, set to 0
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_INV_PARAMETER if @a cursor or @a record is NULL
* @return @ref HAM_INV_PARAMETER if @a cursor points to an item with
* duplicates and duplicate sorting is enabled
* @return @ref HAM_INV_PARAMETER if duplicate sorting is enabled
* @return @ref HAM_CURSOR_IS_NIL if the Cursor does not point to an item
* @return @ref HAM_TXN_CONFLICT if the same key was inserted in another
* Transaction which was not yet committed or aborted
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_cursor_overwrite(ham_cursor_t *cursor, ham_record_t *record,
uint32_t flags);
/**
* Searches with a key and points the Cursor to the key found, retrieves
* the located record
*
* Searches for an item in the Database and points the Cursor to this item.
* If the item could not be found, the Cursor is not modified.
*
* Note that @ref ham_cursor_find can not search for duplicate keys. If @a key
* has multiple duplicates, only the first duplicate is returned.
*
* When specifying @ref HAM_DIRECT_ACCESS, the @a data pointer will point
* directly to the record that is stored in hamsterdb; the data can be modified,
* but the pointer must not be reallocated or freed. The flag @ref
* HAM_DIRECT_ACCESS is only allowed in In-Memory Databases and not if
* Transactions are enabled.
*
* You can read only portions of the record by specifying the flag
* @ref HAM_PARTIAL. In this case, hamsterdb will read
* record->partial_size bytes of the record data at offset
* record->partial_offset. If necessary, the record data will
* be limited to the original record size. The number of actually read
* bytes is returned in record->partial_size. The original size of
* the record is stored in record->size.
*
* @ref HAM_PARTIAL is not allowed if record->size is <= 8 or if Transactions
* are enabled. In such a case, @ref HAM_INV_PARAMETER is returned.
*
* When either or both @ref HAM_FIND_LT_MATCH and/or @ref HAM_FIND_GT_MATCH
* have been specified as flags, the @a key structure will be overwritten
* when an approximate match was found: the @a key and @a record
* structures will then point at the located @a key (and @a record).
* In this case the caller should ensure @a key points at a structure
* which must adhere to the same restrictions and conditions as specified
* for @ref ham_cursor_move(...,HAM_CURSOR_*):
* key->data will point to temporary data upon return. This pointer
* will be invalidated by subsequent hamsterdb API calls using the same
* Transaction (or the same Database, if Transactions are disabled). See
* @ref HAM_KEY_USER_ALLOC on how to change this behaviour.
*
* Further note that the @a key structure must be non-const at all times as its
* internal flag bits may be written to. This is done for your benefit, as
* you may pass the returned @a key structure to
* @ref ham_key_get_approximate_match_type() to retrieve additional info about
* the precise nature of the returned key: the sign value produced
* by @ref ham_key_get_approximate_match_type() tells you which kind of match
* (equal, less than, greater than) occurred. This is very useful to
* discern between the various possible successful answers produced by the
* combinations of @ref HAM_FIND_LT_MATCH and @ref HAM_FIND_GT_MATCH.
*
* @param cursor A valid Cursor handle
* @param key A pointer to a @ref ham_key_t structure. If this
* pointer is not NULL, the key of the new item is returned.
* Note that key->data will point to temporary data. This pointer
* will be invalidated by subsequent hamsterdb API calls. See
* @a HAM_KEY_USER_ALLOC on how to change this behaviour.
* @param record Optional pointer to a @ref ham_record_t structure. If this
* pointer is not NULL, the record of the new item is returned.
* Note that record->data will point to temporary data. This pointer
* will be invalidated by subsequent hamsterdb API calls. See
* @ref HAM_RECORD_USER_ALLOC on how to change this behaviour.
* @param flags Optional flags for searching, which can be combined with
* bitwise OR. Possible flags are:
*
* - @ref HAM_FIND_LT_MATCH
Cursor 'find' flag 'Less Than': the
* cursor is moved to point at the last record which' key
* is less than the specified key. When such a record cannot
* be located, an error is returned.
* - @ref HAM_FIND_GT_MATCH
Cursor 'find' flag 'Greater Than':
* the cursor is moved to point at the first record which' key is
* larger than the specified key. When such a record cannot be
* located, an error is returned.
* - @ref HAM_FIND_LEQ_MATCH
Cursor 'find' flag 'Less or EQual':
* the cursor is moved to point at the record which' key matches
* the specified key and when such a record is not available
* the cursor is moved to point at the last record which' key
* is less than the specified key. When such a record cannot be
* located, an error is returned.
* - @ref HAM_FIND_GEQ_MATCH
Cursor 'find' flag 'Greater or
* Equal': the cursor is moved to point at the record which' key
* matches the specified key and when such a record
* is not available the cursor is moved to point at the first
* record which' key is larger than the specified key.
* When such a record cannot be located, an error is returned.
* - @ref HAM_FIND_NEAR_MATCH
Cursor 'find' flag 'Any Near Or
* Equal': the cursor is moved to point at the record which'
* key matches the specified key and when such a record is
* not available the cursor is moved to point at either the
* last record which' key is less than the specified key or
* the first record which' key is larger than the specified
* key, whichever of these records is located first.
* When such records cannot be located, an error is returned.
* - @ref HAM_DIRECT_ACCESS
Only for In-Memory Databases and
* not if Transactions are enabled!
* Returns a direct pointer to the data blob stored by the
* hamsterdb engine. This pointer must not be resized or freed,
* but the data in this memory can be modified.
*
*
* Remark
* For Approximate Matching the returned match will either match the
* key exactly or is either the first key available above or below the
* given key when an exact match could not be found; 'find' does NOT
* spend any effort, in the sense of determining which of both is the
* 'nearest' to the given key, when both a key above and a key below the
* one given exist; 'find' will simply return the first of both found.
* As such, this flag is the simplest possible combination of the
* combined @ref HAM_FIND_LEQ_MATCH and @ref HAM_FIND_GEQ_MATCH flags.
*
* Note that these flags may be bitwise OR-ed to form functional combinations.
*
* @ref HAM_FIND_LEQ_MATCH, @ref HAM_FIND_GEQ_MATCH and
* @ref HAM_FIND_LT_MATCH, @ref HAM_FIND_GT_MATCH
*
* @return @ref HAM_SUCCESS upon success. Mind the remarks about the
* @a key flags being adjusted and the useful invocation of
* @ref ham_key_get_approximate_match_type() afterwards.
* @return @ref HAM_INV_PARAMETER if @a db, @a key or @a record is NULL
* @return @ref HAM_CURSOR_IS_NIL if the Cursor does not point to an item
* @return @ref HAM_KEY_NOT_FOUND if no suitable @a key (record) exists
* @return @ref HAM_INV_PARAMETER if @a HAM_DIRECT_ACCESS is specified,
* but the Database is not an In-Memory Database.
* @return @ref HAM_INV_PARAMETER if @a HAM_DIRECT_ACCESS and
* @a HAM_ENABLE_TRANSACTIONS were both specified.
* @return @ref HAM_INV_PARAMETER if @ref HAM_PARTIAL is set but record
* size is <= 8 or Transactions are enabled
* @return @ref HAM_TXN_CONFLICT if the same key was inserted in another
* Transaction which was not yet committed or aborted
*
* @sa HAM_KEY_USER_ALLOC
* @sa ham_key_t
* @sa HAM_RECORD_USER_ALLOC
* @sa ham_record_t
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_cursor_find(ham_cursor_t *cursor, ham_key_t *key,
ham_record_t *record, uint32_t flags);
/* internal flag */
#define HAM_FIND_EXACT_MATCH 0x4000
/**
* Cursor 'find' flag 'Less Than': return the nearest match below the
* given key, whether an exact match exists or not.
*/
#define HAM_FIND_LT_MATCH 0x1000
/**
* Cursor 'find' flag 'Greater Than': return the nearest match above the
* given key, whether an exact match exists or not.
*/
#define HAM_FIND_GT_MATCH 0x2000
/**
* Cursor 'find' flag 'Less or EQual': return the nearest match below the
* given key, when an exact match does not exist.
*
* May be combined with @ref HAM_FIND_GEQ_MATCH to accept any 'near' key, or
* you can use the @ref HAM_FIND_NEAR_MATCH constant as a shorthand for that.
*/
#define HAM_FIND_LEQ_MATCH (HAM_FIND_LT_MATCH | HAM_FIND_EXACT_MATCH)
/**
* Cursor 'find' flag 'Greater or Equal': return the nearest match above
* the given key, when an exact match does not exist.
*
* May be combined with @ref HAM_FIND_LEQ_MATCH to accept any 'near' key,
* or you can use the @ref HAM_FIND_NEAR_MATCH constant as a shorthand for that.
*/
#define HAM_FIND_GEQ_MATCH (HAM_FIND_GT_MATCH | HAM_FIND_EXACT_MATCH)
/**
* Cursor 'find' flag 'Any Near Or Equal': return a match directly below or
* above the given key, when an exact match does not exist.
*
* Be aware that the returned match will either match the key exactly or
* is either the first key available above or below the given key when an
* exact match could not be found; 'find' does NOT spend any effort, in the
* sense of determining which of both is the 'nearest' to the given key,
* when both a key above and a key below the one given exist; 'find' will
* simply return the first of both found. As such, this flag is the simplest
* possible combination of the combined @ref HAM_FIND_LEQ_MATCH and
* @ref HAM_FIND_GEQ_MATCH flags.
*/
#define HAM_FIND_NEAR_MATCH (HAM_FIND_LT_MATCH | HAM_FIND_GT_MATCH \
| HAM_FIND_EXACT_MATCH)
/**
* Inserts a Database item and points the Cursor to the inserted item
*
* This function inserts a key/record pair as a new Database item.
* If the key already exists in the Database, error @ref HAM_DUPLICATE_KEY
* is returned.
*
* If you wish to overwrite an existing entry specify the
* flag @ref HAM_OVERWRITE. The use of this flag is not allowed in combination
* with @ref HAM_DUPLICATE.
*
* If you wish to insert a duplicate key specify the flag @ref HAM_DUPLICATE.
* (In order to use duplicate keys, the Database has to be created with
* @ref HAM_ENABLE_DUPLICATE_KEYS.)
* By default, the duplicate key is inserted after all other duplicate keys
* (see @ref HAM_DUPLICATE_INSERT_LAST). This behaviour can be overwritten by
* specifying @ref HAM_DUPLICATE_INSERT_FIRST, @ref HAM_DUPLICATE_INSERT_BEFORE
* or @ref HAM_DUPLICATE_INSERT_AFTER.
*
* You can write only portions of the record by specifying the flag
* @ref HAM_PARTIAL. In this case, hamsterdb will write partial_size
* bytes of the record data at offset partial_offset. If necessary, the
* record data will grow. Gaps will be filled with null-bytes, if the record
* did not yet exist.
*
* @ref HAM_PARTIAL is not allowed if record->size is <= 8 or if Transactions
* are enabled. In such a case, @ref HAM_INV_PARAMETER is returned.
*
* Specify the flag @ref HAM_HINT_APPEND if you insert sequential data
* and the current @a key is greater than any other key in this Database.
* In this case hamsterdb will optimize the insert algorithm. hamsterdb will
* verify that this key is the greatest; if not, it will perform a normal
* insert. This flag is the default for Record Number Databases.
*
* Specify the flag @ref HAM_HINT_PREPEND if you insert sequential data
* and the current @a key is lower than any other key in this Database.
* In this case hamsterdb will optimize the insert algorithm. hamsterdb will
* verify that this key is the lowest; if not, it will perform a normal
* insert.
*
* After inserting, the Cursor will point to the new item. If inserting
* the item failed, the Cursor is not modified.
*
* Record Number Databases (created with @ref HAM_RECORD_NUMBER32 or
* @ref HAM_RECORD_NUMBER64) expect either an empty @a key (with a size of
* 0 and data pointing to NULL), or a user-supplied key (with key.flag
* @ref HAM_KEY_USER_ALLOC and a valid data pointer).
* If key.size is 0 and key.data is NULL, hamsterdb will temporarily
* allocate memory for key->data, which will then point to an 4-byte (or 8-byte)
* unsigned integer.
*
* @param cursor A valid Cursor handle
* @param key A valid key structure
* @param record A valid record structure
* @param flags Optional flags for inserting the item, combined with
* bitwise OR. Possible flags are:
*
* - @ref HAM_OVERWRITE. If the @a key already exists, the record is
* overwritten. Otherwise, the key is inserted. Not allowed in
* combination with @ref HAM_DUPLICATE.
*
- @ref HAM_DUPLICATE. If the @a key already exists, a duplicate
* key is inserted. Same as @ref HAM_DUPLICATE_INSERT_LAST. Not
* allowed in combination with @ref HAM_DUPLICATE.
*
- @ref HAM_DUPLICATE_INSERT_BEFORE. If the @a key already exists,
* a duplicate key is inserted before the duplicate pointed
* to by the Cursor. Not allowed if duplicate sorting is enabled.
*
- @ref HAM_DUPLICATE_INSERT_AFTER. If the @a key already exists,
* a duplicate key is inserted after the duplicate pointed
* to by the Cursor. Not allowed if duplicate sorting is enabled.
*
- @ref HAM_DUPLICATE_INSERT_FIRST. If the @a key already exists,
* a duplicate key is inserted as the first duplicate of
* the current key. Not allowed if duplicate sorting is enabled.
*
- @ref HAM_DUPLICATE_INSERT_LAST. If the @a key already exists,
* a duplicate key is inserted as the last duplicate of
* the current key. Not allowed if duplicate sorting is enabled.
*
- @ref HAM_HINT_APPEND. Hints the hamsterdb engine that the
* current key will compare as @e larger than any key already
* existing in the Database. The hamsterdb engine will verify
* this postulation and when found not to be true, will revert
* to a regular insert operation as if this flag was not
* specified. The incurred cost then is only one additional key
* comparison. Mutually exclusive with flag @ref HAM_HINT_PREPEND.
* This is the default for Record Number Databases.
*
- @ref HAM_HINT_PREPEND. Hints the hamsterdb engine that the
* current key will compare as @e lower than any key already
* existing in the Database. The hamsterdb engine will verify
* this postulation and when found not to be true, will revert
* to a regular insert operation as if this flag was not
* specified. The incurred cost then is only one additional key
* comparison. Mutually exclusive with flag @ref HAM_HINT_APPEND.
*
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_INV_PARAMETER if @a key or @a record is NULL
* @return @ref HAM_INV_PARAMETER if the Database is a Record Number Database
* and the key is invalid (see above)
* @return @ref HAM_INV_PARAMETER if @ref HAM_PARTIAL is set but record
* size is <= 8 or Transactions are enabled
* @return @ref HAM_INV_PARAMETER if the flags @ref HAM_OVERWRITE and
* @ref HAM_DUPLICATE were specified, or if @ref HAM_DUPLICATE
* was specified, but the Database was not created with
* flag @ref HAM_ENABLE_DUPLICATE_KEYS.
* @return @ref HAM_WRITE_PROTECTED if you tried to insert a key to a read-only
* Database.
* @return @ref HAM_INV_KEY_SIZE if the key size is different from
* the one specified with @a HAM_PARAM_KEY_SIZE
* @return @ref HAM_INV_RECORD_SIZE if the record size is different from
* the one specified with @a HAM_PARAM_RECORD_SIZE
* @return @ref HAM_CURSOR_IS_NIL if the Cursor does not point to an item
* @return @ref HAM_TXN_CONFLICT if the same key was inserted in another
* Transaction which was not yet committed or aborted
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_cursor_insert(ham_cursor_t *cursor, ham_key_t *key,
ham_record_t *record, uint32_t flags);
/**
* Erases the current key
*
* Erases a key from the Database. If the erase was
* successful, the Cursor is invalidated and does no longer point to
* any item. In case of an error, the Cursor is not modified.
*
* If the Database was opened with the flag @ref HAM_ENABLE_DUPLICATE_KEYS,
* this function erases only the duplicate item to which the Cursor refers.
*
* @param cursor A valid Cursor handle
* @param flags Unused, set to 0
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_INV_PARAMETER if @a cursor is NULL
* @return @ref HAM_WRITE_PROTECTED if you tried to erase a key from a read-only
* Database
* @return @ref HAM_CURSOR_IS_NIL if the Cursor does not point to an item
* @return @ref HAM_TXN_CONFLICT if the same key was inserted in another
* Transaction which was not yet committed or aborted
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_cursor_erase(ham_cursor_t *cursor, uint32_t flags);
/**
* Returns the number of duplicate keys
*
* Returns the number of duplicate keys of the item to which the
* Cursor currently refers.
* Returns 1 if the key has no duplicates.
*
* @param cursor A valid Cursor handle
* @param count Returns the number of duplicate keys
* @param flags Optional flags; unused, set to 0.
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_CURSOR_IS_NIL if the Cursor does not point to an item
* @return @ref HAM_INV_PARAMETER if @a cursor or @a count is NULL
* @return @ref HAM_TXN_CONFLICT if the same key was inserted in another
* Transaction which was not yet committed or aborted
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_cursor_get_duplicate_count(ham_cursor_t *cursor,
uint32_t *count, uint32_t flags);
/**
* Returns the current cursor position in the duplicate list
*
* Returns the position in the duplicate list of the current key. The position
* is 0-based.
*
* @param cursor A valid Cursor handle
* @param position Returns the duplicate position
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_CURSOR_IS_NIL if the Cursor does not point to an item
* @return @ref HAM_INV_PARAMETER if @a cursor or @a position is NULL
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_cursor_get_duplicate_position(ham_cursor_t *cursor,
uint32_t *position);
/**
* Returns the record size of the current key
*
* Returns the record size of the item to which the Cursor currently refers.
*
* @param cursor A valid Cursor handle
* @param size Returns the record size, in bytes
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_CURSOR_IS_NIL if the Cursor does not point to an item
* @return @ref HAM_INV_PARAMETER if @a cursor or @a size is NULL
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_cursor_get_record_size(ham_cursor_t *cursor, uint64_t *size);
/**
* Closes a Database Cursor
*
* Closes a Cursor and frees allocated memory. All Cursors
* should be closed before closing the Database (see @ref ham_db_close).
*
* @param cursor A valid Cursor handle
*
* @return @ref HAM_SUCCESS upon success
* @return @ref HAM_CURSOR_IS_NIL if the Cursor does not point to an item
* @return @ref HAM_INV_PARAMETER if @a cursor is NULL
*
* @sa ham_db_close
*/
HAM_EXPORT ham_status_t HAM_CALLCONV
ham_cursor_close(ham_cursor_t *cursor);
/**
* @}
*/
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* HAM_HAMSTERDB_H */