[Contents]   [Back]   [Prev]   [Up]   [Next]   [Forward]  


C Interface

C Compile-Time Parameters

The C Preprocessor Constants in this section are defined in `wbdefs.h' which is derived from `wbdefs.scm'.

A segment is a self-contained collection of B-trees. Each is usually associated with its own (disk) file. WB functions refer to segments by integers between 0 and num_segs - 1.

C Preprocessor Constant: num_segs
The default value of num_segs is 10. The minimum value of num_segs is 1.

Each segment (file-based or not) maintains a freelist of disk blocks. In a newly created segment, nearly all of its block numbers are in the freelist.

C Preprocessor Constant: flc_len
flc_len must be larger than 2 times the maximum number of blocks which would ever be needed for a freelist split. The minimum for flc_len is 10.

C Status Codes

C Preprocessor Macro: err_P (x)
Return x if a valid error code (-1 ... MAXERR); else 0.

C Preprocessor Macro: success_P (x)
Not err_P.

C Preprocessor Constant: success
Successful execution (0).

Negative integers are used for errors according to increasingly severity, as follows:

C Preprocessor Constant: notpres
Successful execution; no data present or no change made.

C Preprocessor Constant: terminated
Failure; no damage; caller can retry operation.

C Preprocessor Constant: retryerr
Failure; no damage; caller can retry operation.

C Preprocessor Constant: argerr
Failure, no damage, call was in error.

C Preprocessor Constant: noroom
Failure, no damage, out of room in file.

C Preprocessor Constant: typerr
Failure, file or object was not of correct type.

C Preprocessor Constant: ioerr
I/O error, DB may be damaged.

C Preprocessor Constant: strangerr
Internal error, DB may be damaged.

C Preprocessor Constant: unkerr
Placeholder code.

C Preprocessor Constant: maxerr
All error codes are between 0 and `maxerr'.

C Diagnostic Channel

The machine translated source utilizes dprintf as a platform-independent way to log diagnostic, warning, and error messages. tdprintf

C Preprocessor Macro: dprintf ((diagout, const char *template, ...))
The single argument to dprintf must be an argument list within parenthesis (eg. double parentheses). The first argument inside this list should be literally diagout. template is a printf style format string followed by the arguments for formatting, as with printf.

C SEGs

The bsiz of a segment (given in call to make_seg) is a parameter crucial for performance; balancing CPU time traversing blocks with file-system latency. bsiz should be an integer multiple of the file-system block size.

In the 1990s our nominal bsiz was 2.kiB; now it should probably be 4.kiB, 8.kiB, or 16.kiB.

Function: int open_seg ({int} seg, {unsigned char *} filename, {int} mode)

seg should be a non-negative number. Opens the database seg in filename and returns seg if successful, a status code otherwise. The database seg will be read-only if the mode argument is 0. It will be read-write if the mode argument is 2.

Function: int close_seg ({int} seg, {int} hammer_P)

Closes database segment seg and the file containing it. If hammer_P is NULL, then if there are any problems freeing buffers, then the close is aborted. A status code is returned.

Function: int make_seg ({int} seg, {unsigned char *} filename, {int} bsiz)

The integer seg must specify an unused segment. The integer bsiz specifies the size of B-tree blocks. bsiz should be an integer multiple of the file-system block size. Nominal value is 4096.

make_seg makes a new empty database named filename. A status code is returned. Call open_seg to use the new database.

The write-control-bits argument (wcb) to these functions controls the latency of updates to the file after various operations. These bits are defined as follows:
value C-name Meaning
1 wcb_sap save block after PUTs
2 wcb_sar save block after REMOVEs
4 wcb_sac force block save after cached block changes
8 wcb_fac flush buffer entirely after cached block changes (not currently implemented)

Function: int bt_open ({int} seg, {long} blk_num, {HAND *} han, {int} wcb)
Opens bt-handle han to seg number seg, block number blk_num, and returns the type of the block. If no such block exists or is not a root block, then a (negative) status code is returned.

Function: int bt_create ({int} seg, {int} typ, {HAND *} han, {int} wcb)
Creates a new root block in seg seg of type typ, opens bt-handle han to it, and returns a status code. If seg has insufficient room to create a new tree, then the noroom status code is returned.

bt_create can be used to create temporary b-trees. Temporary trees will be be reclaimed by check program after system crashes. In order to make a tree persistent, add it to a directory (tree).

Function: int bt_close ({HAND *} han)
Closes bt-handle han and returns SUCCESS.

Currently, bt_close has no effect other than to clear han.

C HANDs and Tree Operations

Note: most of the data-manipulating commands here can return notpres, with the followng meanings:
bt-get no such key.
bt-next no NEXT key (ie, key given was LAST key).
bt-prev no PREV key (ie, key given was FIRST key).
bt-rem KEY was not found.
bt-put NOT USED (could be symmetric w/WRITE).
bt-write key WAS found, so no write done.

Function: int bt_get ({HAND *} han, {unsigned char *} key_str, {int} k_len, {unsigned char *} ans_str)
key_str is a string of length k_len. bt_get stores into the string ans_str the value associated with key_str in tree han. bt_get returns the length of the string stored into ans_str or an error code.

Function: int bt_next ({HAND *} han, {unsigned char *} key_str, {int} k_len, {unsigned char *} ans_str)
key_str is a string of length k_len. bt_next stores into the string ans_str the next key after key_str in tree han. bt_next returns the length of the string stored into ans_str or an error code.

Function: int bt_prev ({HAND *} han, {unsigned char *} key_str, {int} k_len, {unsigned char *} ans_str)
key_str is a string of length k_len. bt_prev stores into the string ans_str the last key before key_str in tree han. bt_prev returns the length of the string stored into ans_str or an error code.

Function: int bt_rem ({HAND *} han, {unsigned char *} key_str, {int} k_len, {unsigned char *} ans_str)
key_str is a string of length k_len. bt_rem stores into the string ans_str the value associated with key_str in tree han; then removes that association from tree han. bt_rem returns the length of the string stored into ans_str or an error code.

If ans_str is 0, bt_rem removes the key_str association from tree han and returns SUCCESS if successful; an error code if not.

Function: int bt_rem_range ({HAND *} han, {unsigned char *} key_str, {int} k_len, {unsigned char *} key2_str, {int} k2_len)
key_str must be a maximum-length (256 byte) string containing a key k_len bytes long. key2_str is a string of length k2_len.

bt_rem_range removes [key_str ... key2_str) and their values. If key2_str <= key_str no deletion will occur (even if key_str is found). bt_rem_range returns SUCCESS if the operation is complete, an error status code if not.

Function: int bt_put ({HAND *} han, {unsigned char *} key_str, {int} k_len, {unsigned char *} val_str, {int} v_len)
key_str is a string of length k_len. val_str is a string of length v_len. bt_put makes the value associated with key_str be val_str in tree han. bt_put returns a status code for the operation.

Function: int bt_write ({HAND *} han, {unsigned char *} key_str, {int} k_len, {unsigned char *} val_str, {int} v_len)
key_str is a string of length k_len. val_str is a string of length v_len. If han currently contains an association for key_str, then bt_write does not modify the tree and returns the notpres status code.

Otherwise, bt_write makes the value associated with key_str be val_str in tree han. bt_write returns a status code for the operation.

C Scan

Function: int bt_scan ({HAND *} han, {int} operation, {unsigned char *} kstr1, {int} len1, {unsigned char *} kstr2, {int} len2, int_function func, {long *} long_tab, {int *} respkt, {int} blk_limit)
bt_scan scans all keys in the range [kstr1..kstr2), performing one of several functions:
operation func RESULT
COUNT-SCAN NIL counts all keys in range
COUNT-SCAN given counts all keys in range satisfying func
REM-SCAN NIL deletes all keys in range
REM-SCAN given deletes all keys in range satisfying func
MODIFY-SCAN NIL ARGERR
MODIFY-SCAN given updates values for keys in range satisfying func

bt_scan returns SUCCESS if scan completed; under any other result code the scan is resumable. The possible results are:

NOTPRES
meaning the blk_limit was exceeded;
RETRYERR
meaning func or delete got a RETRYERRR;
TERMINATED
meaning func asked to terminate the scan;
<other error>
means func or DELETE encountered this errror.

Each block of data is scanned/deleted/modified in a single operation that is, the block is found and locked only once, and only written after all modifications are made. Tho only exception is that MODIFY-SCANs that increase the size of values can cause block splits. Such cases are detected and converted to a PUT plus a NEXT. This has two consequences: data is written out each time a PUT occurs, and it is conceivable that func may be called more than once on the key value that caused the split if a RETRYERR occurs in the PUT. However, SCAN guarantees that only one modification will actually be made in this case (so that one can write INCREMENT-RANGE, for example).

func is passed pointers to (copies of) the key and value, plus one user argument:

func (keystr klen vstr vlen extra_arg);

func is expected to return either: SUCCESS for DELETE/COUNT, NOTPRES/NOTDONE for SKIP (ie, DONT DELETE/COUNT), or any other code to terminate the scan resumably at the current point. For MODIFY-SCAN, if changing the value, the new value length is returned. Except for the case mentioned above, the caller can depend on func being called exactly once for each key value in the specified range, and only on those values.

If kstr2 <= kstr1, then no scan will occur (even if kstr1 is found). To make possible bounded-time operation bt_scan will access at most blk_limit blocks at a time; if you dont care, give it -1 for blk_limit.

The number of keys deleted/counted/modified is returned in the skey-count field of respkt; the key to resume at is returned in kstr1 (which therefore needs to be 256 bytes long); and the new key length is returned in the skey-len field of respkt. If returns SUCCESS, skey-len is zero. NOTE that skey-count is cumulative, so the caller needs to initialize it to 0 when starting a new bt_scan.

WARNING: when bt_scan returns other than SUCCESS, it modifies the kstr1 string so that the string args are correctly set up for the next call (the returned value is the new length for kstr1). Therefore, kstr1 must be a maximum-length string!


[Contents]   [Back]   [Prev]   [Up]   [Next]   [Forward]