
<title>LSM API Reference</title>
<nowiki>
<br note="
  DO NOT EDIT!!! 
  DO NOT EDIT!!! 
  DO NOT EDIT!!! 
  This document is generated by script tools/updateapi.tcl.
  DO NOT EDIT!!! 
  DO NOT EDIT!!! 
  DO NOT EDIT!!! 
">

<p>
This page contains the LSM API Reference Manual. It is intended to complement
the <a href=lsmusr.wiki>LSM User Manual</a>.

<h1>LSM API Topics</h1>
<ol>
<li><a href="#database" style=text-decoration:none>Database Runtime Environment</a>
<li><a href="#lsm" style=text-decoration:none>LSM Error Codes</a>
<li><a href="#creating" style=text-decoration:none>Creating and Destroying Database Connection Handles</a>
<li><a href="#connecting" style=text-decoration:none>Connecting to a Database</a>
<li><a href="#obtaining" style=text-decoration:none>Obtaining pointers to database environments</a>
<li><a href="#configuring" style=text-decoration:none>Configuring a database connection.</a>
<li><a href="#compression" style=text-decoration:none>Compression and/or Encryption Hooks</a>
<li><a href="#allocating" style=text-decoration:none>Allocating and Freeing Memory</a>
<li><a href="#querying" style=text-decoration:none>Querying a Connection For Operational Data</a>
<li><a href="#opening" style=text-decoration:none>Opening and Closing Write Transactions</a>
<li><a href="#writing" style=text-decoration:none>Writing to a Database</a>
<li><a href="#explicit" style=text-decoration:none>Explicit Database Work and Checkpointing</a>
<li><a href="#opening" style=text-decoration:none>Opening and Closing Database Cursors</a>
<li><a href="#positioning" style=text-decoration:none>Positioning Database Cursors</a>
<li><a href="#extracting" style=text-decoration:none>Extracting Data From Database Cursors</a>
<li><a href="#change" style=text-decoration:none>Change these!!</a>

</ol>
<h1 style=clear:both>All LSM API Functions</h1>
<span style=display:block;float:left;width:35ex><a href=#lsm_begin>lsm_begin</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_checkpoint>lsm_checkpoint</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_close>lsm_close</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_commit>lsm_commit</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_config>lsm_config</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_config_log>lsm_config_log</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_config_work_hook>lsm_config_work_hook</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_csr_close>lsm_csr_close</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_csr_cmp>lsm_csr_cmp</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_csr_first>lsm_csr_first</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_csr_key>lsm_csr_key</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_csr_last>lsm_csr_last</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_csr_next>lsm_csr_next</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_csr_open>lsm_csr_open</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_csr_prev>lsm_csr_prev</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_csr_seek>lsm_csr_seek</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_csr_valid>lsm_csr_valid</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_csr_value>lsm_csr_value</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_delete>lsm_delete</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_delete_range>lsm_delete_range</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_flush>lsm_flush</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_free>lsm_free</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_info>lsm_info</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_insert>lsm_insert</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_new>lsm_new</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_open>lsm_open</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_rollback>lsm_rollback</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_work>lsm_work</a></span>
<br style=clear:both>
<h1 style=clear:both>All LSM API Types</h1>
<span style=display:block;float:left;width:35ex><a href=#lsm_compress>lsm_compress</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_compress>lsm_compress</a></span>
<span style=display:block;float:left;width:35ex><a href=#lsm_env>lsm_env</a></span>
<br style=clear:both>
<h1>All LSM API Constants</h1>
<span style=display:block;float:left;width:35ex><a href=#LSM_BUSY>LSM_BUSY</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_CANTOPEN>LSM_CANTOPEN</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_CONFIG_AUTOCHECKPOINT>LSM_CONFIG_AUTOCHECKPOINT</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_CONFIG_AUTOFLUSH>LSM_CONFIG_AUTOFLUSH</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_CONFIG_AUTOMERGE>LSM_CONFIG_AUTOMERGE</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_CONFIG_AUTOWORK>LSM_CONFIG_AUTOWORK</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_CONFIG_BLOCK_SIZE>LSM_CONFIG_BLOCK_SIZE</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_CONFIG_GET_COMPRESSION>LSM_CONFIG_GET_COMPRESSION</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_CONFIG_MAX_FREELIST>LSM_CONFIG_MAX_FREELIST</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_CONFIG_MMAP>LSM_CONFIG_MMAP</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_CONFIG_MULTIPLE_PROCESSES>LSM_CONFIG_MULTIPLE_PROCESSES</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_CONFIG_PAGE_SIZE>LSM_CONFIG_PAGE_SIZE</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_CONFIG_SAFETY>LSM_CONFIG_SAFETY</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_CONFIG_SET_COMPRESSION>LSM_CONFIG_SET_COMPRESSION</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_CONFIG_SET_COMPRESSION_FACTORY>LSM_CONFIG_SET_COMPRESSION_FACTORY</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_CONFIG_USE_LOG>LSM_CONFIG_USE_LOG</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_CORRUPT>LSM_CORRUPT</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_ERROR>LSM_ERROR</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_FULL>LSM_FULL</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_INFO_ARRAY_PAGES>LSM_INFO_ARRAY_PAGES</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_INFO_ARRAY_STRUCTURE>LSM_INFO_ARRAY_STRUCTURE</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_INFO_CHECKPOINT_SIZE>LSM_INFO_CHECKPOINT_SIZE</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_INFO_DB_STRUCTURE>LSM_INFO_DB_STRUCTURE</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_INFO_FREELIST>LSM_INFO_FREELIST</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_INFO_FREELIST_SIZE>LSM_INFO_FREELIST_SIZE</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_INFO_LOG_STRUCTURE>LSM_INFO_LOG_STRUCTURE</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_INFO_NREAD>LSM_INFO_NREAD</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_INFO_NWRITE>LSM_INFO_NWRITE</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_INFO_PAGE_ASCII_DUMP>LSM_INFO_PAGE_ASCII_DUMP</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_INFO_PAGE_HEX_DUMP>LSM_INFO_PAGE_HEX_DUMP</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_INFO_TREE_SIZE>LSM_INFO_TREE_SIZE</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_IOERR>LSM_IOERR</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_MISUSE>LSM_MISUSE</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_MUTEX_GLOBAL>LSM_MUTEX_GLOBAL</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_MUTEX_HEAP>LSM_MUTEX_HEAP</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_NOMEM>LSM_NOMEM</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_OK>LSM_OK</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_PROTOCOL>LSM_PROTOCOL</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_SAFETY_FULL>LSM_SAFETY_FULL</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_SAFETY_NORMAL>LSM_SAFETY_NORMAL</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_SAFETY_OFF>LSM_SAFETY_OFF</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_SEEK_EQ>LSM_SEEK_EQ</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_SEEK_GE>LSM_SEEK_GE</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_SEEK_LE>LSM_SEEK_LE</a></span>
<span style=display:block;float:left;width:35ex><a href=#LSM_SEEK_LEFAST>LSM_SEEK_LEFAST</a></span>
<br style=clear:both>
<h2 id=database>Database Runtime Environment<a id=lsm_env></a><a id=LSM_MUTEX_GLOBAL></a><a id=LSM_MUTEX_HEAP></a></h2>
<verbatim>struct lsm_env {
  int nByte;                 /* Size of this structure in bytes */
  int iVersion;              /* Version number of this structure (1) */
  /****** file i/o ***********************************************/
  void *pVfsCtx;
  int (*xFullpath)(lsm_env*, const char *, char *, int *);
  int (*xOpen)(lsm_env*, const char *, lsm_file **);
  int (*xRead)(lsm_file *, lsm_i64, void *, int);
  int (*xWrite)(lsm_file *, lsm_i64, void *, int);
  int (*xTruncate)(lsm_file *, lsm_i64);
  int (*xSync)(lsm_file *);
  int (*xSectorSize)(lsm_file *);
  int (*xRemap)(lsm_file *, lsm_i64, void **, lsm_i64*);
  int (*xFileid)(lsm_file *, void *pBuf, int *pnBuf);
  int (*xClose)(lsm_file *);
  int (*xUnlink)(lsm_env*, const char *);
  int (*xLock)(lsm_file*, int, int);
  int (*xShmMap)(lsm_file*, int, int, void **);
  void (*xShmBarrier)(void);
  int (*xShmUnmap)(lsm_file*, int);
  /****** memory allocation ****************************************/
  void *pMemCtx;
  void *(*xMalloc)(lsm_env*, int);            /* malloc(3) function */
  void *(*xRealloc)(lsm_env*, void *, int);   /* realloc(3) function */
  void (*xFree)(lsm_env*, void *);            /* free(3) function */
  sqlite4_size_t (*xSize)(lsm_env*, void *);  /* xSize function */
  /****** mutexes ****************************************************/
  void *pMutexCtx;
  int (*xMutexStatic)(lsm_env*,int,lsm_mutex**); /* Obtain a static mutex */
  int (*xMutexNew)(lsm_env*, lsm_mutex**);       /* Get a new dynamic mutex */
  void (*xMutexDel)(lsm_mutex *);           /* Delete an allocated mutex */
  void (*xMutexEnter)(lsm_mutex *);         /* Grab a mutex */
  int (*xMutexTry)(lsm_mutex *);            /* Attempt to obtain a mutex */
  void (*xMutexLeave)(lsm_mutex *);         /* Leave a mutex */
  int (*xMutexHeld)(lsm_mutex *);           /* Return true if mutex is held */
  int (*xMutexNotHeld)(lsm_mutex *);        /* Return true if mutex not held */
  /****** other ****************************************************/
  int (*xSleep)(lsm_env*, int microseconds);
  /* New fields may be added in future releases, in which case the
  ** iVersion value will increase. */
};
#define LSM_MUTEX_GLOBAL 1
#define LSM_MUTEX_HEAP   2
</verbatim>
<p>Run-time environment used by LSM
Values that may be passed as the second argument to xMutexStatic. 
<h2 id=lsm>LSM Error Codes<a id=LSM_OK></a><a id=LSM_ERROR></a><a id=LSM_BUSY></a><a id=LSM_NOMEM></a><a id=LSM_IOERR></a><a id=LSM_CORRUPT></a><a id=LSM_FULL></a><a id=LSM_CANTOPEN></a><a id=LSM_PROTOCOL></a><a id=LSM_MISUSE></a></h2>
<verbatim>#define LSM_OK         0
#define LSM_ERROR      1
#define LSM_BUSY       5
#define LSM_NOMEM      7
#define LSM_IOERR     10
#define LSM_CORRUPT   11
#define LSM_FULL      13
#define LSM_CANTOPEN  14
#define LSM_PROTOCOL  15
#define LSM_MISUSE    21
</verbatim>
<h2 id=creating>Creating and Destroying Database Connection Handles<a id=lsm_new></a><a id=lsm_close></a></h2>
<verbatim>int lsm_new(lsm_env*, lsm_db **ppDb);
int lsm_close(lsm_db *pDb);
</verbatim>
<p>Open and close a database connection handle.
<h2 id=connecting>Connecting to a Database<a id=lsm_open></a></h2>
<verbatim>int lsm_open(lsm_db *pDb, const char *zFilename);
</verbatim>
<h2 id=obtaining>Obtaining pointers to database environments</h2>
<verbatim>lsm_env *lsm_get_env(lsm_db *pDb);
lsm_env *lsm_default_env(void);
</verbatim>
<p>Return a pointer to the environment used by the database connection 
passed as the first argument. Assuming the argument is valid, this 
function always returns a valid environment pointer - it cannot fail.
The lsm_default_env() function returns a pointer to the default LSM
environment for the current platform.
<h2 id=configuring>Configuring a database connection.<a id=lsm_config></a><a id=LSM_CONFIG_AUTOFLUSH></a><a id=LSM_CONFIG_PAGE_SIZE></a><a id=LSM_CONFIG_SAFETY></a><a id=LSM_CONFIG_BLOCK_SIZE></a><a id=LSM_CONFIG_AUTOWORK></a><a id=LSM_CONFIG_MMAP></a><a id=LSM_CONFIG_USE_LOG></a><a id=LSM_CONFIG_AUTOMERGE></a><a id=LSM_CONFIG_MAX_FREELIST></a><a id=LSM_CONFIG_MULTIPLE_PROCESSES></a><a id=LSM_CONFIG_AUTOCHECKPOINT></a><a id=LSM_CONFIG_SET_COMPRESSION></a><a id=LSM_CONFIG_GET_COMPRESSION></a><a id=LSM_CONFIG_SET_COMPRESSION_FACTORY></a><a id=LSM_SAFETY_OFF></a><a id=LSM_SAFETY_NORMAL></a><a id=LSM_SAFETY_FULL></a></h2>
<verbatim>int lsm_config(lsm_db *, int, ...);
#define LSM_CONFIG_AUTOFLUSH                1
#define LSM_CONFIG_PAGE_SIZE                2
#define LSM_CONFIG_SAFETY                   3
#define LSM_CONFIG_BLOCK_SIZE               4
#define LSM_CONFIG_AUTOWORK                 5
#define LSM_CONFIG_MMAP                     7
#define LSM_CONFIG_USE_LOG                  8
#define LSM_CONFIG_AUTOMERGE                9
#define LSM_CONFIG_MAX_FREELIST            10
#define LSM_CONFIG_MULTIPLE_PROCESSES      11
#define LSM_CONFIG_AUTOCHECKPOINT          12
#define LSM_CONFIG_SET_COMPRESSION         13
#define LSM_CONFIG_GET_COMPRESSION         14
#define LSM_CONFIG_SET_COMPRESSION_FACTORY 15
#define LSM_SAFETY_OFF    0
#define LSM_SAFETY_NORMAL 1
#define LSM_SAFETY_FULL   2
</verbatim>
<p>The lsm_config() function is used to configure a database connection.
The following values may be passed as the second argument to lsm_config().
<p><dl><dt>LSM_CONFIG_AUTOFLUSH<dd>A read/write integer parameter. 
<p>This value determines the amount of data allowed to accumulate in a
live in-memory tree before it is marked as old. After committing a
transaction, a connection checks if the size of the live in-memory tree,
including data structure overhead, is greater than the value of this
option in KB. If it is, and there is not already an old in-memory tree,
the live in-memory tree is marked as old.
<p>The maximum allowable value is 1048576 (1GB). There is no minimum 
value. If this parameter is set to zero, then an attempt is made to
mark the live in-memory tree as old after each transaction is committed.
<p>The default value is 1024 (1MB).
<p><dt>LSM_CONFIG_PAGE_SIZE<dd>A read/write integer parameter. This parameter may only be set before
lsm_open() has been called.
<p><dt>LSM_CONFIG_BLOCK_SIZE<dd>A read/write integer parameter. 
<p>This parameter may only be set before lsm_open() has been called. It
must be set to a power of two between 64 and 65536, inclusive (block 
sizes between 64KB and 64MB).
<p>If the connection creates a new database, the block size of the new
database is set to the value of this option in KB. After lsm_open()
has been called, querying this parameter returns the actual block
size of the opened database.
<p>The default value is 1024 (1MB blocks).
<p><dt>LSM_CONFIG_SAFETY<dd>A read/write integer parameter. Valid values are 0, 1 (the default) 
and 2. This parameter determines how robust the database is in the
face of a system crash (e.g. a power failure or operating system 
crash). As follows:
<p>0 (off):    No robustness. A system crash may corrupt the database.
<p>1 (normal): Some robustness. A system crash may not corrupt the
database file, but recently committed transactions may
be lost following recovery.
<p>2 (full):   Full robustness. A system crash may not corrupt the
database file. Following recovery the database file
contains all successfully committed transactions.
<p><dt>LSM_CONFIG_AUTOWORK<dd>A read/write integer parameter.
<p><dt>LSM_CONFIG_AUTOCHECKPOINT<dd>A read/write integer parameter.
<p>If this option is set to non-zero value N, then a checkpoint is
automatically attempted after each N KB of data have been written to 
the database file.
<p>The amount of uncheckpointed data already written to the database file
is a global parameter. After performing database work (writing to the
database file), the process checks if the total amount of uncheckpointed 
data exceeds the value of this paramter. If so, a checkpoint is performed.
This means that this option may cause the connection to perform a 
checkpoint even if the current connection has itself written very little
data into the database file.
<p>The default value is 2048 (checkpoint every 2MB).
<p><dt>LSM_CONFIG_MMAP<dd>A read/write integer parameter. True to use mmap() to access the 
database file. False otherwise.
<p><dt>LSM_CONFIG_USE_LOG<dd>A read/write boolean parameter. True (the default) to use the log
file normally. False otherwise.
<p><dt>LSM_CONFIG_AUTOMERGE<dd>A read/write integer parameter. The minimum number of segments to
merge together at a time. Default value 4.
<p><dt>LSM_CONFIG_MAX_FREELIST<dd>A read/write integer parameter. The maximum number of free-list 
entries that are stored in a database checkpoint (the others are
stored elsewhere in the database).
<p>There is no reason for an application to configure or query this
parameter. It is only present because configuring a small value
makes certain parts of the lsm code easier to test.
<p><dt>LSM_CONFIG_MULTIPLE_PROCESSES<dd>A read/write boolean parameter. This parameter may only be set before
lsm_open() has been called. If true, the library uses shared-memory
and posix advisory locks to co-ordinate access by clients from within
multiple processes. Otherwise, if false, all database clients must be 
located in the same process. The default value is true.
<p><dt>LSM_CONFIG_SET_COMPRESSION<dd>Set the compression methods used to compress and decompress database
content. The argument to this option should be a pointer to a structure
of type lsm_compress. The lsm_config() method takes a copy of the 
structures contents.
<p>This option may only be used before lsm_open() is called. Invoking it
after lsm_open() has been called results in an LSM_MISUSE error.
<p><dt>LSM_CONFIG_GET_COMPRESSION<dd>Query the compression methods used to compress and decompress database
content.
<p><dt>LSM_CONFIG_SET_COMPRESSION_FACTORY<dd>Configure a factory method to be invoked in case of an LSM_MISMATCH
error.
</dl><h2 id=compression>Compression and/or Encryption Hooks<a id=lsm_compress></a><a id=lsm_compress></a></h2>
<verbatim>struct lsm_compress {
  void *pCtx;
  unsigned int iId;
  int (*xBound)(void *, int nSrc);
  int (*xCompress)(void *, char *, int *, const char *, int);
  int (*xUncompress)(void *, char *, int *, const char *, int);
  void (*xFree)(void *pCtx);
};
struct lsm_compress_factory {
  void *pCtx;
  int (*xFactory)(void *, lsm_db *, u32);
  void (*xFree)(void *pCtx);
};
</verbatim>
<h2 id=allocating>Allocating and Freeing Memory<a id=lsm_free></a></h2>
<verbatim>void *lsm_malloc(lsm_env*, size_t);
void *lsm_realloc(lsm_env*, void *, size_t);
void lsm_free(lsm_env*, void *);
</verbatim>
<p>Invoke the memory allocation functions that belong to environment
pEnv. Or the system defaults if no memory allocation functions have 
been registered.
<h2 id=querying>Querying a Connection For Operational Data<a id=lsm_info></a><a id=LSM_INFO_NWRITE></a><a id=LSM_INFO_NREAD></a><a id=LSM_INFO_DB_STRUCTURE></a><a id=LSM_INFO_LOG_STRUCTURE></a><a id=LSM_INFO_ARRAY_STRUCTURE></a><a id=LSM_INFO_PAGE_ASCII_DUMP></a><a id=LSM_INFO_PAGE_HEX_DUMP></a><a id=LSM_INFO_FREELIST></a><a id=LSM_INFO_ARRAY_PAGES></a><a id=LSM_INFO_CHECKPOINT_SIZE></a><a id=LSM_INFO_TREE_SIZE></a><a id=LSM_INFO_FREELIST_SIZE></a></h2>
<verbatim>int lsm_info(lsm_db *, int, ...);
#define LSM_INFO_NWRITE           1
#define LSM_INFO_NREAD            2
#define LSM_INFO_DB_STRUCTURE     3
#define LSM_INFO_LOG_STRUCTURE    4
#define LSM_INFO_ARRAY_STRUCTURE  5
#define LSM_INFO_PAGE_ASCII_DUMP  6
#define LSM_INFO_PAGE_HEX_DUMP    7
#define LSM_INFO_FREELIST         8
#define LSM_INFO_ARRAY_PAGES      9
#define LSM_INFO_CHECKPOINT_SIZE 10
#define LSM_INFO_TREE_SIZE       11
#define LSM_INFO_FREELIST_SIZE   12
</verbatim>
<p>Query a database connection for operational statistics or data.
The following values may be passed as the second argument to lsm_info().
<p><dl><dt>LSM_INFO_NWRITE<dd>The third parameter should be of type (int *). The location pointed
to by the third parameter is set to the number of 4KB pages written to
the database file during the lifetime of this connection. 
<p><dt>LSM_INFO_NREAD<dd>The third parameter should be of type (int *). The location pointed
to by the third parameter is set to the number of 4KB pages read from
the database file during the lifetime of this connection.
<p><dt>LSM_INFO_DB_STRUCTURE<dd>The third argument should be of type (char **). The location pointed
to is populated with a pointer to a nul-terminated string containing
the string representation of a Tcl data-structure reflecting the 
current structure of the database file. Specifically, the current state
of the worker snapshot. The returned string should be eventually freed 
by the caller using lsm_free().
<p>The returned list contains one element for each level in the database,
in order from most to least recent. Each element contains a 
single element for each segment comprising the corresponding level,
starting with the lhs segment, then each of the rhs segments (if any)
in order from most to least recent.
<p>Each segment element is itself a list of 4 integer values, as follows:
<p><ol><li> First page of segment
<li> Last page of segment
<li> Root page of segment (if applicable)
<li> Total number of pages in segment
</ol>
<p><dt>LSM_INFO_ARRAY_STRUCTURE<dd>There should be two arguments passed following this option (i.e. a 
total of four arguments passed to lsm_info()). The first argument 
should be the page number of the first page in a database array 
(perhaps obtained from an earlier INFO_DB_STRUCTURE call). The second 
trailing argument should be of type (char **). The location pointed 
to is populated with a pointer to a nul-terminated string that must 
be eventually freed using lsm_free() by the caller.
<p>The output string contains the text representation of a Tcl list of
integers. Each pair of integers represent a range of pages used by
the identified array. For example, if the array occupies database
pages 993 to 1024, then pages 2048 to 2777, then the returned string
will be "993 1024 2048 2777".
<p>If the specified integer argument does not correspond to the first
page of any database array, LSM_ERROR is returned and the output
pointer is set to a NULL value.
<p><dt>LSM_INFO_LOG_STRUCTURE<dd>The third argument should be of type (char **). The location pointed
to is populated with a pointer to a nul-terminated string containing
the string representation of a Tcl data-structure. The returned 
string should be eventually freed by the caller using lsm_free().
<p>The Tcl structure returned is a list of six integers that describe
the current structure of the log file.
<p><dt>LSM_INFO_ARRAY_PAGES<dd><p><dt>LSM_INFO_PAGE_ASCII_DUMP<dd>As with LSM_INFO_ARRAY_STRUCTURE, there should be two arguments passed
with calls that specify this option - an integer page number and a
(char **) used to return a nul-terminated string that must be later
freed using lsm_free(). In this case the output string is populated
with a human-readable description of the page content.
<p>If the page cannot be decoded, it is not an error. In this case the
human-readable output message will report the systems failure to 
interpret the page data.
<p><dt>LSM_INFO_PAGE_HEX_DUMP<dd>This argument is similar to PAGE_ASCII_DUMP, except that keys and
values are represented using hexadecimal notation instead of ascii.
<p><dt>LSM_INFO_FREELIST<dd>The third argument should be of type (char **). The location pointed
to is populated with a pointer to a nul-terminated string containing
the string representation of a Tcl data-structure. The returned 
string should be eventually freed by the caller using lsm_free().
<p>The Tcl structure returned is a list containing one element for each
free block in the database. The element itself consists of two 
integers - the block number and the id of the snapshot that freed it.
<p><dt>LSM_INFO_CHECKPOINT_SIZE<dd>The third argument should be of type (int *). The location pointed to
by this argument is populated with the number of KB written to the
database file since the most recent checkpoint.
<p><dt>LSM_INFO_TREE_SIZE<dd>If this value is passed as the second argument to an lsm_info() call, it
should be followed by two arguments of type (int *) (for a total of four
arguments).
<p>At any time, there are either one or two tree structures held in shared
memory that new database clients will access (there may also be additional
tree structures being used by older clients - this API does not provide
information on them). One tree structure - the current tree - is used to
accumulate new data written to the database. The other tree structure -
the old tree - is a read-only tree holding older data and may be flushed 
to disk at any time.
<p>Assuming no error occurs, the location pointed to by the first of the two
(int *) arguments is set to the size of the old in-memory tree in KB.
The second is set to the size of the current, or live in-memory tree.
</dl><h2 id=opening>Opening and Closing Write Transactions<a id=lsm_begin></a><a id=lsm_commit></a><a id=lsm_rollback></a></h2>
<verbatim>int lsm_begin(lsm_db *pDb, int iLevel);
int lsm_commit(lsm_db *pDb, int iLevel);
int lsm_rollback(lsm_db *pDb, int iLevel);
</verbatim>
<p>These functions are used to open and close transactions and nested 
sub-transactions.
<p>The lsm_begin() function is used to open transactions and sub-transactions. 
A successful call to lsm_begin() ensures that there are at least iLevel 
nested transactions open. To open a top-level transaction, pass iLevel=1. 
To open a sub-transaction within the top-level transaction, iLevel=2. 
Passing iLevel=0 is a no-op.
<p>lsm_commit() is used to commit transactions and sub-transactions. A
successful call to lsm_commit() ensures that there are at most iLevel 
nested transactions open. To commit a top-level transaction, pass iLevel=0. 
To commit all sub-transactions inside the main transaction, pass iLevel=1.
<p>Function lsm_rollback() is used to roll back transactions and
sub-transactions. A successful call to lsm_rollback() restores the database 
to the state it was in when the iLevel'th nested sub-transaction (if any) 
was first opened. And then closes transactions to ensure that there are 
at most iLevel nested transactions open. Passing iLevel=0 rolls back and 
closes the top-level transaction. iLevel=1 also rolls back the top-level 
transaction, but leaves it open. iLevel=2 rolls back the sub-transaction 
nested directly inside the top-level transaction (and leaves it open).
<h2 id=writing>Writing to a Database<a id=lsm_insert></a><a id=lsm_delete></a><a id=lsm_delete_range></a></h2>
<verbatim>int lsm_insert(lsm_db*, const void *pKey, int nKey, const void *pVal, int nVal);
int lsm_delete(lsm_db *, const void *pKey, int nKey);
int lsm_delete_range(lsm_db *, 
    const void *pKey1, int nKey1, const void *pKey2, int nKey2
);
</verbatim>
<p>Write a new value into the database. If a value with a duplicate key 
already exists it is replaced.
Delete a value from the database. No error is returned if the specified
key value does not exist in the database.
Delete all database entries with keys that are greater than (pKey1/nKey1) 
and smaller than (pKey2/nKey2). Note that keys (pKey1/nKey1) and
(pKey2/nKey2) themselves, if they exist in the database, are not deleted.
<p>Return LSM_OK if successful, or an LSM error code otherwise.
<h2 id=explicit>Explicit Database Work and Checkpointing<a id=lsm_work></a><a id=lsm_flush></a><a id=lsm_checkpoint></a></h2>
<verbatim>int lsm_work(lsm_db *pDb, int nMerge, int nKB, int *pnWrite);
int lsm_flush(lsm_db *pDb);
int lsm_checkpoint(lsm_db *pDb, int *pnKB);
</verbatim>
<p>This function is called by a thread to work on the database structure.
Attempt to checkpoint the current database snapshot. Return an LSM
error code if an error occurs or LSM_OK otherwise.
<p>If the current snapshot has already been checkpointed, calling this 
function is a no-op. In this case if pnKB is not NULL, *pnKB is
set to 0. Or, if the current snapshot is successfully checkpointed
by this function and pbKB is not NULL, *pnKB is set to the number
of bytes written to the database file since the previous checkpoint
(the same measure as returned by the LSM_INFO_CHECKPOINT_SIZE query).
<h2 id=opening>Opening and Closing Database Cursors<a id=lsm_csr_open></a><a id=lsm_csr_close></a></h2>
<verbatim>int lsm_csr_open(lsm_db *pDb, lsm_cursor **ppCsr);
int lsm_csr_close(lsm_cursor *pCsr);
</verbatim>
<p>Open and close a database cursor.
<h2 id=positioning>Positioning Database Cursors<a id=lsm_csr_seek></a><a id=lsm_csr_first></a><a id=lsm_csr_last></a><a id=lsm_csr_next></a><a id=lsm_csr_prev></a><a id=LSM_SEEK_LEFAST></a><a id=LSM_SEEK_LE></a><a id=LSM_SEEK_EQ></a><a id=LSM_SEEK_GE></a></h2>
<verbatim>int lsm_csr_seek(lsm_cursor *pCsr, const void *pKey, int nKey, int eSeek);
int lsm_csr_first(lsm_cursor *pCsr);
int lsm_csr_last(lsm_cursor *pCsr);
int lsm_csr_next(lsm_cursor *pCsr);
int lsm_csr_prev(lsm_cursor *pCsr);
#define LSM_SEEK_LEFAST   -2
#define LSM_SEEK_LE       -1
#define LSM_SEEK_EQ        0
#define LSM_SEEK_GE        1
</verbatim>
<p>If the fourth parameter is LSM_SEEK_EQ, LSM_SEEK_GE or LSM_SEEK_LE,
this function searches the database for an entry with key (pKey/nKey). 
If an error occurs, an LSM error code is returned. Otherwise, LSM_OK.
<p>If no error occurs and the requested key is present in the database, the
cursor is left pointing to the entry with the specified key. Or, if the 
specified key is not present in the database the state of the cursor 
depends on the value passed as the final parameter, as follows:
<p><dl><dt>LSM_SEEK_EQ<dd>The cursor is left at EOF (invalidated). A call to lsm_csr_valid()
returns non-zero.
<p><dt>LSM_SEEK_LE<dd>The cursor is left pointing to the largest key in the database that
is smaller than (pKey/nKey). If the database contains no keys smaller
than (pKey/nKey), the cursor is left at EOF.
<p><dt>LSM_SEEK_GE<dd>The cursor is left pointing to the smallest key in the database that
is larger than (pKey/nKey). If the database contains no keys larger
than (pKey/nKey), the cursor is left at EOF.
<p></dl><p>If the fourth parameter is LSM_SEEK_LEFAST, this function searches the
database in a similar manner to LSM_SEEK_LE, with two differences:
<p><ol><li>Even if a key can be found (the cursor is not left at EOF), the
lsm_csr_value() function may not be used (attempts to do so return
LSM_MISUSE).
<p><li>The key that the cursor is left pointing to may be one that has 
been recently deleted from the database. In this case it is
guaranteed that the returned key is larger than any key currently 
in the database that is less than or equal to (pKey/nKey).
</ol>
<p>LSM_SEEK_LEFAST requests are intended to be used to allocate database
keys.
Advance the specified cursor to the next or previous key in the database.
Return LSM_OK if successful, or an LSM error code otherwise.
<p>Functions lsm_csr_seek(), lsm_csr_first() and lsm_csr_last() are "seek"
functions. Whether or not lsm_csr_next and lsm_csr_prev may be called
successfully also depends on the most recent seek function called on
the cursor. Specifically:
<p><ul>
<li> At least one seek function must have been called on the cursor.
<li> To call lsm_csr_next(), the most recent call to a seek function must
have been either lsm_csr_first() or a call to lsm_csr_seek() specifying
LSM_SEEK_GE. 
<li> To call lsm_csr_prev(), the most recent call to a seek function must
have been either lsm_csr_first() or a call to lsm_csr_seek() specifying
LSM_SEEK_GE. 
</ul>
<p>Otherwise, if the above conditions are not met when lsm_csr_next or 
lsm_csr_prev is called, LSM_MISUSE is returned and the cursor position
remains unchanged.
Values that may be passed as the fourth argument to lsm_csr_seek().
<h2 id=extracting>Extracting Data From Database Cursors<a id=lsm_csr_valid></a><a id=lsm_csr_key></a><a id=lsm_csr_value></a><a id=lsm_csr_cmp></a></h2>
<verbatim>int lsm_csr_valid(lsm_cursor *pCsr);
int lsm_csr_key(lsm_cursor *pCsr, const void **ppKey, int *pnKey);
int lsm_csr_value(lsm_cursor *pCsr, const void **ppVal, int *pnVal);
int lsm_csr_cmp(lsm_cursor *pCsr, const void *pKey, int nKey, int *piRes);
</verbatim>
<p>Retrieve data from a database cursor.
If no error occurs, this function compares the database key passed via
the pKey/nKey arguments with the key that the cursor passed as the first
argument currently points to. If the cursors key is less than, equal to
or greater than pKey/nKey, *piRes is set to less than, equal to or greater
than zero before returning. LSM_OK is returned in this case.
<p>Or, if an error occurs, an LSM error code is returned and the final 
value of *piRes is undefined. If the cursor does not point to a valid
key when this function is called, LSM_MISUSE is returned.
<h2 id=change>Change these!!<a id=lsm_config_log></a><a id=lsm_config_work_hook></a></h2>
<verbatim>void lsm_config_log(lsm_db *, void (*)(void *, int, const char *), void *);
void lsm_config_work_hook(lsm_db *, void (*)(lsm_db *, void *), void *);
</verbatim>
<p>Configure a callback to which debugging and other messages should 
be directed. Only useful for debugging lsm.
Configure a callback that is invoked if the database connection ever
writes to the database file.

