Zero-Knowledge Database Library API

$Id: zkdbAPI.html,v 1.1 2000/05/23 14:14:41 sam Exp $
Revision Comments
1.1 Author(s): Sam Sanjabi (sam@zks.net),

Initial draft.

Contents

  1. Introduction
  2. User's Guide
  3. Function Reference
    1. Database Storage Object Functions
      1. zkDBTNew
      2. zkDBTCreate
      3. zkDBTFree
      4. zkDBSetKeyOrData
      5. zkDBGetKeyOrData
    2. Basic DB Functions
      1. zkDB_Open
      2. zkDB_Close
      3. zkDB_Fetch
      4. zkDB_Update
      5. zkDB_Store
      6. zkDB_Put
      7. zkDB_Replace
      8. zkDB_Delete
      9. zkDB_SetLog
      10. zkDB_GetLog
      11. zkDB_CheckPointsActivate
      12. zkDB_GetDataBaseName
    3. DB Iteration Functions
      1. zkDB_CursorOpen
      2. zkDB_CursorClose
      3. zkDB_CursorAbort
      4. zkDB_CursorGetNext
      5. zkDB_CursorDeleteCurrent
      6. zkDB_CursorUpdateCurrent
  4. Examples
  5. References

1 - Introduction

Goto : [top]

This document is intended as a user's guide to the Zero-Knowledge database library. It gives a high level description of the functions of the zkDB library, and includes a function reference

2 - User's Guide

Goto : [top]

Data Types

The data types exposed by the API are the following:

typedef struct T_ZkDB * ZkDB;
typedef struct DBT    * ZkDBT;

ZkDB

A pointer to a Zero-Knowledge database. The database can be manipulated using the basic functions zkDB_*.

ZkDBT

The type of the objects that are stored in the data base (playfully known as database thangs). These objects can be created, destroyed and generally pushed around using the storage object functions zkDBT*.

Using the API

The zkDB API will give the user ability to query and update any Zero-Knowledge database managed by Berkeley DB. All the user needs is the location of the appropriate configuration file , and the API takes care of the rest (see http://caesar.zks.net/devnet/cvs/freedom/ndb/doc/zkdb-conf.html for the skinny on database configuration).

The API allows you to open an interaction with one of the databases, update and query the database as you please, and then close the interaction. In order to avoid any concurrencies when using the API, there are a few issues that the user should be aware of:

Essentially, many potential problems in user code can be avoided by following a few simple coding guidelines: See the examples below to see this process in code form.

3 - Function Reference

Goto : [top]

3.1 - Storage Object Functions


3.1.1 - zkDBTNew

Prototype:

int zkDBTNew(
        ZK_INOUT ZkError                    error,
        ZK_OUT   ZkDBT *                    dbt );

FUNCTIONALITY

Creates a new ZkDBT object and points dbt to it. The object will be empty (i.e. devoid of data, not null).

RETURN VALUE

The return value is 0 if an error occured, and non-zero otherwise.

NOTES


3.1.2 - zkDBTCreate

Prototype:

int zkDBTCreate(
        ZK_INOUT ZkError                    error,
        ZK_IN    const char *               buffer,
        ZK_IN    int                        size,
        ZK_OUT   ZkDBT *                    dbt );

FUNCTIONALITY

Creates a new ZkDBT object and points dbt to it. The buffer parameter specifies the string that will be used as this object's data. The size parameter should specify the number of bytes in this string.

RETURN VALUE

The return value is 0 if an error occured, and non-zero otherwise.

NOTES


3.1.3 - zkDBTFree

Prototype:

int zkDBTFree(
        ZK_INOUT ZkError                    error,
        ZK_OUT   ZkDBT *                    dbt );

FUNCTIONALITY

Destructor for ZkDBT objects. Frees the memory allocated to the object pointed at by dbt.

RETURN VALUE

The return value is 0 if an error occured, and non-zero otherwise.

NOTES


3.1.4 - zkDBSetKeyOrData

Prototype:

int zkDBSetKeyOrData(
        ZK_INOUT ZkError                    error,
        ZK_OUT   ZkDBT                      dbt,
        ZK_IN    void *                     data,
        ZK_IN    uint32_t                   size);

FUNCTIONALITY

Set the data field of the given ZkDBT object to the data pointed at by the data parameter, and its size field to size.

RETURN VALUE

The return value is 0 if an error occured, and non-zero otherwise.

NOTES


3.1.5 - zkDBGetKeyOrData

Prototype:

int zkDBGetKeyOrData(
        ZK_INOUT ZkError                    error,
        ZK_IN    ZkDBT                      dbt,
        ZK_OUT   void **                    data,
        ZK_OUT   uint32_t *                 size);

FUNCTIONALITY

Sets the data and size output parameters to be equal to the corresponding fields in the given ZkDBT object (dbt).

RETURN VALUE

The return value is 0 if an error occured, and non-zero otherwise.

NOTES


3.2 - Basic Database Functions


3.2.1 - zkDB_Open

Prototype:

int zkDB_Open(
        ZK_INOUT ZkError                    error,
        ZK_OUT   ZkDB *                     db,
        ZK_IN    const char *               configfile);

FUNCTIONALITY

Mounts a database into the db parameter. This must be done before modifying the database in any way during an interaction using the other functions in this system. This is the first function called when opening an interaction with a database. The configfile parameter is the name of the system database configuration file for the database. For more info on database configuration files read about Zero Knowledge Database Configuration.

RETURN VALUE

The return value is 0 if an error occured, and non-zero otherwise.

NOTES


3.2.2 - zkDB_Close

Prototype:

int zkDB_Close(
        ZK_INOUT ZkError                    error,
        ZK_OUT   ZkDB *                     db);

FUNCTIONALITY

Closes the interaction with the database pointed at by db, and frees the pointer. If there is an active cursor, this function will also close it and commit its transaction to the database.

RETURN VALUE

The return value is 0 if an error occured, and non-zero otherwise.

NOTES


3.2.3 - zkDB_Fetch

Prototype:

int zkDB_Fetch(
        ZK_INOUT ZkError                    error,
        ZK_IN    ZkDB                       db,
        ZK_IN    ZkDBT                      key,
        ZK_OUT   ZkDBT                      data,
        ZK_OUT   int *                      found);

FUNCTIONALITY

Searches the database db for a record with the specified key. If found, the found parameter is set to 1, and the data parameter is pointed to the record's data field within the internal database system. See NOTES below for repercursions and appropriate usage of this function.

RETURN VALUE

The return value is 1 if the operation is successful and 0 otherwise.

NOTES


3.2.4 - zkDB_Update

Prototype:

int zkDB_Update(
        ZK_INOUT ZkError                    error,
        ZK_IN    ZkDB                       db,
        ZK_IN    ZkDBT                      key,
        ZK_IN    ZkDBT                      data,
        ZK_OUT   int *                      exists,
        ZK_IN    int                        overwrite);

FUNCTIONALITY

Attempts to insert a record specified by key and data into database db. The output parameter exists will indicate if a record with the same key was already present in the database. If it was, the value of the overwrite parameter determines the behaviour of this operation as follows:

overwrite value Function Behaviour
0 Overwrites the already existing record (default value)
DB_APPEND Will append the record at the end of the database
DB_NOOVERWRITE Operation will not overwrite existing record, database remains unchanged

RETURN VALUE

The return value of the function is 1 if the update operation is successful, and 0 if an error occured.

NOTES


3.2.5 - zkDB_Store

Prototype:

int zkDB_Store(
        ZK_INOUT ZkError                    error,
        ZK_IN    ZkDB                       db,
        ZK_IN    ZkDBT                      key,
        ZK_IN    ZkDBT                      data,
        ZK_OUT   int *                      exists);

FUNCTIONALITY

Stores the item only if the key does not exists. This function is equivalent to zkDB_Update(error,db,key,data,exists,DB_NOOVERWRITE).


3.2.6 - zkDB_Put

Prototype:

int zkDB_Put(
        ZK_INOUT ZkError                    error,
        ZK_IN    ZkDB                       db,
        ZK_IN    ZkDBT                      key,
        ZK_IN    ZkDBT                      data);

FUNCTIONALITY

Puts the item in database db regardless of the existence of a previous occupant with the same key. This function is equivalent to zkDB_Update(error,db,key,data,NULL,0).


3.2.7 - zkDB_Replace

Prototype:

int zkDB_Replace(
        ZK_INOUT ZkError                    error,
        ZK_IN    ZkDB                       db,
        ZK_IN    ZkDBT                      key,
        ZK_IN    ZkDBT                      data);

FUNCTIONALITY

Replaces the data stored under key if it already exists. This function is equivalent to zkDB_Update(error,db,key,data,NULL,0).


3.2.8 - zkDB_Delete

Prototype:

int zkDB_Delete(
        ZK_INOUT ZkError                    error,
        ZK_IN    ZkDB                       db,
        ZK_IN    ZkDBT                      key,
        ZK_OUT   int *                      notfound);

FUNCTIONALITY

Removes the record stored under key key from the database. The output parameter notfound is set to 1 if no record was stored at that key previously.

RETURN VALUE

The return is non-zero for a successful operation, and 0 otherwise.

NOTES


3.2.9 - zkDB_SetLog

Prototype:

void zkDB_SetLog(
        ZK_IN    ZkLog                      log);

FUNCTIONALITY

Sets the database message log object (as defined in zkLog.h) to log.

NOTES


3.2.10 - zkDB_GetLog

Prototype:

void zkDB_GetLog(
        ZK_OUT    ZkLog *                   log);

FUNCTIONALITY

Retrieves the database log object and points log to it.

NOTES


3.2.11 - zkDB_CheckPointsActivate

Prototype:

void zkDB_CheckPointsActivate(
        ZK_INOUT ZkError                    err,
        ZK_IN    ZkDB                       db,
        ZK_IN    int                        checkpoint_stat);

FUNCTIONALITY

This function forces a flush of the underlying memory cache to the physical database disk, writes a checkpoint record to the Berkeley DB log, and then flushes the log.

RETURN VALUE

The return is non-zero for a successful operation, and 0 otherwise.

NOTES


3.2.12 - zkDB_GetDataBaseName

Prototype:

void zkDB_GetDataBaseName(
        ZK_INOUT ZkError                    err,
        ZK_IN    ZkDB                       db,
        ZK_OUT   const char **              name);

FUNCTIONALITY

Retrieves the string containing database db's name and points the name output parameter to it.

NOTES


3.3 - Database Iteration Functions


3.3.1 - zkDB_CursorOpen

Prototype:

int zkDB_CursorOpen(
        ZK_INOUT ZkError                    error,
        ZK_INOUT ZkDB                       db);

FUNCTIONALITY

Creates a cursor into the database mounted into db. A cursor is a structure used to offer sequential access to a database. Hence after calling this function you can use the functions zkDB_Cursor* to access the next element in the database, or delete/update the current element. Currently, only one cursor at a time can be active on a given database. Also, all commands given through cursors are protected from corruption via transaction functionality with roll back (see NOTES).

RETURN VALUE

The return value is 0 if an error occured, and non-zero otherwise.

NOTES


3.3.2 - zkDB_CursorClose

Prototype:

int zkDB_CursorClose(
        ZK_INOUT ZkError                    error,
        ZK_INOUT ZkDB                       db);

FUNCTIONALITY

Closes and discards the cursor currently accessing the database mounted into db. This discard is "clean" in that it commits the commands requested under this cursor's transaction to the database.

RETURN VALUE

The return value is 0 if an error occured, and non-zero otherwise.

NOTES


3.3.3 - zkDB_CursorAbort

Prototype:

int zkDB_CursorAbort(
        ZK_INOUT ZkError                    error,
        ZK_INOUT ZkDB                       db);

FUNCTIONALITY

Closes and discards the cursor currently accessing the database mounted into db. The commands requested under this cursor's transaction to the database are aborted (they will be undone).

RETURN VALUE

The return value is 0 if an error occured, and non-zero otherwise.

NOTES


3.3.4 - zkDB_CursorGetNext

Prototype:

int zkDB_CursorGetNext(
        ZK_INOUT ZkError                    error,
        ZK_IN    ZkDB                       db,
	ZK_OUT   ZkDBT                      key,
	ZK_OUT   ZkDBT			    data,
	ZK_OUT   int *			    found);

FUNCTIONALITY

Points the key and data parameters to the key and data fields of the next record in the database, and increments the cursor by one record (so that it now points to the currently returned key/data pair). If the end of the database is reached, the function will automatically close the cursor and commit the transaction.

RETURN VALUE

The return value is 0 if an error occured, and non-zero otherwise.

NOTES


3.3.5 - zkDB_CursorDeleteCurrent

Prototype:

int zkDB_CursorDeleteCurrent(
        ZK_INOUT ZkError                    error,
        ZK_IN    ZkDB                       db);

FUNCTIONALITY

Deletes the database record currently referenced by the cursor into db. This command isn't committed until the cursor is "cleanly" closed using zkDB_CursorClose. Hence it could be undone if the system crashes or the cursor transaction is aborted.

RETURN VALUE

The return value is 0 if an error occured, and non-zero otherwise.

NOTES


3.3.6 - zkDB_CursorUpdateCurrent

Prototype:

int zkDB_CursorUpdateCurrent(
        ZK_INOUT ZkError                    error,
        ZK_IN    ZkDB                       db,
	ZK_IN    ZkDBT                      key,
	ZK_IN    ZkDBT                      data);

FUNCTIONALITY

Replaces the data field of the database record currently referenced by the cursor into db with the data parameter. The key parameter is simply ignored. This command isn't committed until the cursor is "cleanly" closed using zkDB_CursorClose.

RETURN VALUE

The return value is 0 if an error occured, and non-zero otherwise.

NOTES


4 - Examples

Goto : [top]
The following are examples of how to mount and interact with a database. Note that for simplicity no error checking and handling is performed. The code in red represents the new database types and code.

4.1 - Example 1: Fetching a Record

This example mounts the nidb's topology database, fetches a record corresponding to key KEYVAL, makes a copy of the data, and prints the record to the screen.

void main(int argc, const char **argv)
{
  char * configFile = "/freedom/etc/db/nidb-topology.local.conf";
  ZkDB topoDB = NULL;
  ZkDBT key,data;
  void * p;     /* to store fetched data locally */
  int psize;    /* to store data's size locally */
  int eid_num = KEYVAL;
  int found;

  /* Mount the desired database into topoDB */
  zkDB_Open(err, &topoDB, configFile);

  /* Allocate memory for the key and data */
  zkDBTNew(err, &key);
  zkDBTNew(err, &data);

  /* BEGIN: Retrieve a piece of data from the database */

  /* Set the sought key to eid_num (its value is irrelevant) */
  zkDBSetKeyOrData(err, key, &eid_num, sizeof(eid_num));

  /* Fetch the record from the database */
  zkDB_Fetch(err, topoDB, key, data, &found);

  /* If found, copy the data for my use */
  if (found) {
      zkDBGetKeyOrData(err, data, &p, &psize);
      fprintf(stdout,"Record Retrieved: KEY=%d DATA=%d\n", eid_num, *((int *) p));
  } else {
      fprintf(stdout,"Record Not Found: KEY=%d\n", eid_num);
  }

  /* END: Retrieve a piece of data from the database */

  /* restore the memory used for the database thangs */
  if (key) zkDBTFree(err, &key);
  if (data)zkDBTFree(err, &data);

  /* close the database interaction */
  zkDB_Close(err, &topoDB);

}
Deleting and updating a record is done using essentially the same format. Note that all of the ZkDBT objects were freed before closing the database. This is generally good practice simply because after closing the database, the user's access to the ZkDBT's data buffers is no longer necessarily valid. Attempting to use these objects after dismounting the database with zkDB_Close could lead to some concurrency problems, and shouldn't be attempted.

4.2 - Example 2: Using the cursor

This example mounts the nidb's topology database, opens a cursor into it, and iterates over the whole database, printing each record to standard out (the fields of the records are interpreted as integers for the sake of convenience.

void main(int argc, const char **argv)
{
  char * configFile = "/freedom/etc/db/nidb-topology.local.conf";
  ZkDB topoDB = NULL;
  ZkDBT key,data;
  void * d;     /* to store fetched data locally */
  int dsize;    /* to store data's size locally */
  void * k;     /* to store fetched key locally */
  int ksize;    /* to store key's size locally */
  int found = 1;

  /* Mount the desired database into topoDB */
  zkDB_Open(err, &topoDB, configFile);

  /* Allocate memory for the key and data */
  zkDBTNew(err, &key);
  zkDBTNew(err, &data);

  /* Open a cursor into the database */
  zkDB_CursorOpen(err, topoDB);

  /* BEGIN: Iterate over the database */

  while (found) {
    /* Fetch the record from the database */
    zkDB_CursorGetNext(err, topoDB, key, data, &found);

    /* If found, copy the data and key for my use */
    if (found) {
        zkDBGetKeyOrData(err, data, &p, &psize);
        zkDBGetKeyOrData(err, key, &k, &ksize);
        fprintf(stdout,"KEY=%d DATA=%d\n", *((int *) k), *((int *) p));
    }
  }

  /* END: Iterate over the database */

  /* Close the cursor into the database */
  zkDB_CursorClose(err, topoDB);

  /* restore the memory used for the database thangs */
  if (key) zkDBTFree(err, &key);
  if (data)zkDBTFree(err, &data);

  /* close the database interaction */
  zkDB_Close(err, &topoDB);

}
Note that closing the cursor after the iteration is redundant (since zkDB_CursorGetNext does it automatically when it reaches the end of the database), but it makes for nicer code to have every "Open" paired with a "Close".

Copyright © 2000 Zero-Knowledge Systems Inc.
All rights reserved.