Blame overview

Packit 807167
/**
Packit 807167
Packit 807167
@mainpage Kyoto Cabinet: a straightforward implementation of DBM
Packit 807167
Packit 807167
@section Introduction
Packit 807167
Packit 807167
Kyoto Cabinet is a library of routines for managing a database.  The database is a simple data file containing records, each is a pair of a key and a value.  Every key and value is serial bytes with variable length.  Both binary data and character string can be used as a key and a value.  Each key must be unique within a database.  There is neither concept of data tables nor data types.  Records are organized in hash table or B+ tree.
Packit 807167
Packit 807167
The following access methods are provided to the database: storing a record with a key and a value, deleting a record by a key, retrieving a record by a key.  Moreover, traversal access to every key are provided.  These access methods are similar to ones of the original DBM (and its followers: NDBM and GDBM) library defined in the UNIX standard.  Kyoto Cabinet is an alternative for the DBM because of its higher performance.
Packit 807167
Packit 807167
Each operation of the hash database has the time complexity of "O(1)".  Therefore, in theory, the performance is constant regardless of the scale of the database.  In practice, the performance is determined by the speed of the main memory or the storage device.  If the size of the database is less than the capacity of the main memory, the performance will seem on-memory speed, which is faster than std::map of STL.  Of course, the database size can be greater than the capacity of the main memory and the upper limit is 8 exabytes.  Even in that case, each operation needs only one or two seeking of the storage device.
Packit 807167
Packit 807167
Each operation of the B+ tree database has the time complexity of "O(log N)".  Therefore, in theory, the performance is logarithmic to the scale of the database.  Although the performance of random access of the B+ tree database is slower than that of the hash database, the B+ tree database supports sequential access in order of the keys, which realizes forward matching search for strings and range search for integers.  The performance of sequential access is much faster than that of random access.
Packit 807167
Packit 807167
As the API is based on object-oriented design, the hash database and the the B+ tree database have same methods which inherited from the upper abstract class.  Beside them, seven kinds of databases are provided under the same base class.  The prototype hash database is powered by the standard container of std::unordered_map.  The prototype tree database is powered by the standard container of std::map.  The stash database is powered by the original implementation of naive hash map saving memory.  The cache hash database is powered by the original implementation of doubly-linked hash map with LRU deletion algorithm.  The cache tree database is powered by the cache hash database and provides B+ tree mechanism.  The directory hash database is powered by the directory mechanism of the file system and stores records as respective files in a directory.  The directory tree database is powered by the directory hash database and provides B+ tree mechanism.  All databases have practical utility methods related to transaction and cursor.  Programs for command line interface are also included in the package.
Packit 807167
Packit 807167
All databases have practical utility methods related to transaction and cursor.  Programs for command line interface are also included in the package.
Packit 807167
Packit 807167
The following classes are most important.  If you are new to Kyoto Cabinet, learn the polymorphic database first.
Packit 807167
Packit 807167
@li kyotocabinet::BasicDB -- common interface of concrete databases
Packit 807167
@li kyotocabinet::ProtoHashDB -- on-memory hash database based on std::unordered_map
Packit 807167
@li kyotocabinet::ProtoTreeDB --  on-memory hash database based on std::map
Packit 807167
@li kyotocabinet::StashDB -- economical on-memory hash database for cache.
Packit 807167
@li kyotocabinet::CacheDB -- on-memory hash database for cache with LRU deletion
Packit 807167
@li kyotocabinet::GrassDB -- on-memory tree database for cache in order
Packit 807167
@li kyotocabinet::HashDB -- file hash database, which implements hash table on a file
Packit 807167
@li kyotocabinet::TreeDB -- file tree database, which implements B+ tree on a file
Packit 807167
@li kyotocabinet::DirDB -- directory hash database, which handles respective files in a directory
Packit 807167
@li kyotocabinet::ForestDB -- directory tree database, which implements B+ tree on a directory
Packit 807167
@li kyotocabinet::TextDB -- plain text database, which treats a text file as a database
Packit 807167
@li kyotocabinet::PolyDB -- polymorphic database, dynamic binding of the above databases
Packit 807167
Packit 807167
@li kyotocabinet::MapReduce -- MapReduce framework to process records in each database
Packit 807167
@li kyotocabinet::IndexDB -- wrapper for efficient appending operations to each database
Packit 807167
Packit 807167
@li kclangc.h -- C language binding of the polymorphic database
Packit 807167
Packit 807167
See the project homepage ( http://fallabs.com/kyotocabinet/ ) for details.
Packit 807167
Packit 807167
@section Example
Packit 807167
Packit 807167
The following code is an example to use a polymorphic database.
Packit 807167
Packit 807167
@code
Packit 807167
#include <kcpolydb.h>
Packit 807167
Packit 807167
using namespace std;
Packit 807167
using namespace kyotocabinet;
Packit 807167
Packit 807167
// main routine
Packit 807167
int main(int argc, char** argv) {
Packit 807167
Packit 807167
  // create the database object
Packit 807167
  PolyDB db;
Packit 807167
Packit 807167
  // open the database
Packit 807167
  if (!db.open("casket.kch", PolyDB::OWRITER | PolyDB::OCREATE)) {
Packit 807167
    cerr << "open error: " << db.error().name() << endl;
Packit 807167
  }
Packit 807167
Packit 807167
  // store records
Packit 807167
  if (!db.set("foo", "hop") ||
Packit 807167
      !db.set("bar", "step") ||
Packit 807167
      !db.set("baz", "jump")) {
Packit 807167
    cerr << "set error: " << db.error().name() << endl;
Packit 807167
  }
Packit 807167
Packit 807167
  // retrieve a record
Packit 807167
  string value;
Packit 807167
  if (db.get("foo", &value)) {
Packit 807167
    cout << value << endl;
Packit 807167
  } else {
Packit 807167
    cerr << "get error: " << db.error().name() << endl;
Packit 807167
  }
Packit 807167
Packit 807167
  // traverse records
Packit 807167
  DB::Cursor* cur = db.cursor();
Packit 807167
  cur->jump();
Packit 807167
  string ckey, cvalue;
Packit 807167
  while (cur->get(&ckey, &cvalue, true)) {
Packit 807167
    cout << ckey << ":" << cvalue << endl;
Packit 807167
  }
Packit 807167
  delete cur;
Packit 807167
Packit 807167
  // close the database
Packit 807167
  if (!db.close()) {
Packit 807167
    cerr << "close error: " << db.error().name() << endl;
Packit 807167
  }
Packit 807167
Packit 807167
  return 0;
Packit 807167
}
Packit 807167
@endcode
Packit 807167
Packit 807167
The following code is a more complex example, which uses the Visitor pattern.
Packit 807167
Packit 807167
@code
Packit 807167
#include <kcpolydb.h>
Packit 807167
Packit 807167
using namespace std;
Packit 807167
using namespace kyotocabinet;
Packit 807167
Packit 807167
// main routine
Packit 807167
int main(int argc, char** argv) {
Packit 807167
Packit 807167
  // create the database object
Packit 807167
  PolyDB db;
Packit 807167
Packit 807167
  // open the database
Packit 807167
  if (!db.open("casket.kch", PolyDB::OREADER)) {
Packit 807167
    cerr << "open error: " << db.error().name() << endl;
Packit 807167
  }
Packit 807167
Packit 807167
  // define the visitor
Packit 807167
  class VisitorImpl : public DB::Visitor {
Packit 807167
    // call back function for an existing record
Packit 807167
    const char* visit_full(const char* kbuf, size_t ksiz,
Packit 807167
                           const char* vbuf, size_t vsiz, size_t *sp) {
Packit 807167
      cout << string(kbuf, ksiz) << ":" << string(vbuf, vsiz) << endl;
Packit 807167
      return NOP;
Packit 807167
    }
Packit 807167
    // call back function for an empty record space
Packit 807167
    const char* visit_empty(const char* kbuf, size_t ksiz, size_t *sp) {
Packit 807167
      cerr << string(kbuf, ksiz) << " is missing" << endl;
Packit 807167
      return NOP;
Packit 807167
    }
Packit 807167
  } visitor;
Packit 807167
Packit 807167
  // retrieve a record with visitor
Packit 807167
  if (!db.accept("foo", 3, &visitor, false) ||
Packit 807167
      !db.accept("dummy", 5, &visitor, false)) {
Packit 807167
    cerr << "accept error: " << db.error().name() << endl;
Packit 807167
  }
Packit 807167
Packit 807167
  // traverse records with visitor
Packit 807167
  if (!db.iterate(&visitor, false)) {
Packit 807167
    cerr << "iterate error: " << db.error().name() << endl;
Packit 807167
  }
Packit 807167
Packit 807167
  // close the database
Packit 807167
  if (!db.close()) {
Packit 807167
    cerr << "close error: " << db.error().name() << endl;
Packit 807167
  }
Packit 807167
Packit 807167
  return 0;
Packit 807167
}
Packit 807167
@endcode
Packit 807167
Packit 807167
The following code is an example of word counting with the MapReduce framework.
Packit 807167
Packit 807167
@code
Packit 807167
#include <kcpolydb.h>
Packit 807167
#include <kcdbext.h>
Packit 807167
Packit 807167
using namespace std;
Packit 807167
using namespace kyotocabinet;
Packit 807167
Packit 807167
// main routine
Packit 807167
int main(int argc, char** argv) {
Packit 807167
Packit 807167
  // create the database object
Packit 807167
  PolyDB db;
Packit 807167
Packit 807167
  // open the database
Packit 807167
  if (!db.open()) {
Packit 807167
    cerr << "open error: " << db.error().name() << endl;
Packit 807167
  }
Packit 807167
Packit 807167
  // store records
Packit 807167
  db.set("1", "this is a pen");
Packit 807167
  db.set("2", "what a beautiful pen this is");
Packit 807167
  db.set("3", "she is beautiful");
Packit 807167
Packit 807167
  // define the mapper and the reducer
Packit 807167
  class MapReduceImpl : public MapReduce {
Packit 807167
    // call back function of the mapper
Packit 807167
    bool map(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) {
Packit 807167
      vector<string> words;
Packit 807167
      strsplit(string(vbuf, vsiz), ' ', &words);
Packit 807167
      for (vector<string>::iterator it = words.begin();
Packit 807167
           it != words.end(); it++) {
Packit 807167
        emit(it->data(), it->size(), "", 0);
Packit 807167
      }
Packit 807167
      return true;
Packit 807167
    }
Packit 807167
    // call back function of the reducer
Packit 807167
    bool reduce(const char* kbuf, size_t ksiz, ValueIterator* iter) {
Packit 807167
      size_t count = 0;
Packit 807167
      const char* vbuf;
Packit 807167
      size_t vsiz;
Packit 807167
      while ((vbuf = iter->next(&vsiz)) != NULL) {
Packit 807167
        count++;
Packit 807167
      }
Packit 807167
      cout << string(kbuf, ksiz) << ": " << count << endl;
Packit 807167
      return true;
Packit 807167
    }
Packit 807167
  } mr;
Packit 807167
Packit 807167
  // execute the MapReduce process
Packit 807167
  if (!mr.execute(&db)) {
Packit 807167
    cerr << "MapReduce error: " << db.error().name() << endl;
Packit 807167
  }
Packit 807167
Packit 807167
  // close the database
Packit 807167
  if (!db.close()) {
Packit 807167
    cerr << "close error: " << db.error().name() << endl;
Packit 807167
  }
Packit 807167
Packit 807167
  return 0;
Packit 807167
}
Packit 807167
@endcode
Packit 807167
Packit 807167
The C language binding is also provided as a wrapper of the polymorphic database API.  The following code is an example.
Packit 807167
Packit 807167
@code
Packit 807167
#include <kclangc.h>
Packit 807167
Packit 807167
/* call back function for an existing record */
Packit 807167
const char* visitfull(const char* kbuf, size_t ksiz,
Packit 807167
                      const char* vbuf, size_t vsiz, size_t *sp, void* opq) {
Packit 807167
  fwrite(kbuf, 1, ksiz, stdout);
Packit 807167
  printf(":");
Packit 807167
  fwrite(vbuf, 1, vsiz, stdout);
Packit 807167
  printf("\n");
Packit 807167
  return KCVISNOP;
Packit 807167
}
Packit 807167
Packit 807167
/* call back function for an empty record space */
Packit 807167
const char* visitempty(const char* kbuf, size_t ksiz, size_t *sp, void* opq) {
Packit 807167
  fwrite(kbuf, 1, ksiz, stdout);
Packit 807167
  printf(" is missing\n");
Packit 807167
  return KCVISNOP;
Packit 807167
}
Packit 807167
Packit 807167
/* main routine */
Packit 807167
int main(int argc, char** argv) {
Packit 807167
  KCDB* db;
Packit 807167
  KCCUR* cur;
Packit 807167
  char *kbuf, *vbuf;
Packit 807167
  size_t ksiz, vsiz;
Packit 807167
  const char *cvbuf;
Packit 807167
Packit 807167
  /* create the database object */
Packit 807167
  db = kcdbnew();
Packit 807167
Packit 807167
  /* open the database */
Packit 807167
  if (!kcdbopen(db, "casket.kch", KCOWRITER | KCOCREATE)) {
Packit 807167
    fprintf(stderr, "open error: %s\n", kcecodename(kcdbecode(db)));
Packit 807167
  }
Packit 807167
Packit 807167
  /* store records */
Packit 807167
  if (!kcdbset(db, "foo", 3, "hop", 3) ||
Packit 807167
      !kcdbset(db, "bar", 3, "step", 4) ||
Packit 807167
      !kcdbset(db, "baz", 3, "jump", 4)) {
Packit 807167
    fprintf(stderr, "set error: %s\n", kcecodename(kcdbecode(db)));
Packit 807167
  }
Packit 807167
Packit 807167
  /* retrieve a record */
Packit 807167
  vbuf = kcdbget(db, "foo", 3, &vsiz);
Packit 807167
  if (vbuf) {
Packit 807167
    printf("%s\n", vbuf);
Packit 807167
    kcfree(vbuf);
Packit 807167
  } else {
Packit 807167
    fprintf(stderr, "get error: %s\n", kcecodename(kcdbecode(db)));
Packit 807167
  }
Packit 807167
Packit 807167
  /* traverse records */
Packit 807167
  cur = kcdbcursor(db);
Packit 807167
  kccurjump(cur);
Packit 807167
  while ((kbuf = kccurget(cur, &ksiz, &cvbuf, &vsiz, 1)) != NULL) {
Packit 807167
    printf("%s:%s\n", kbuf, cvbuf);
Packit 807167
    kcfree(kbuf);
Packit 807167
  }
Packit 807167
  kccurdel(cur);
Packit 807167
Packit 807167
  /* retrieve a record with visitor */
Packit 807167
  if (!kcdbaccept(db, "foo", 3, visitfull, visitempty, NULL, 0) ||
Packit 807167
      !kcdbaccept(db, "dummy", 5, visitfull, visitempty, NULL, 0)) {
Packit 807167
    fprintf(stderr, "accept error: %s\n", kcecodename(kcdbecode(db)));
Packit 807167
  }
Packit 807167
Packit 807167
  /* traverse records with visitor */
Packit 807167
  if (!kcdbiterate(db, visitfull, NULL, 0)) {
Packit 807167
    fprintf(stderr, "iterate error: %s\n", kcecodename(kcdbecode(db)));
Packit 807167
  }
Packit 807167
Packit 807167
  /* close the database */
Packit 807167
  if (!kcdbclose(db)) {
Packit 807167
    fprintf(stderr, "close error: %s\n", kcecodename(kcdbecode(db)));
Packit 807167
  }
Packit 807167
Packit 807167
  /* delete the database object */
Packit 807167
  kcdbdel(db);
Packit 807167
Packit 807167
  return 0;
Packit 807167
}
Packit 807167
@endcode
Packit 807167
Packit 807167
*/
Packit 807167
Packit 807167
Packit 807167
/**
Packit 807167
 * Common namespace of Kyoto Cabinet.
Packit 807167
 */
Packit 807167
namespace kyotocabinet {}
Packit 807167
Packit 807167
Packit 807167
/**
Packit 807167
 * @file kccommon.h     common symbols for the library
Packit 807167
 * @file kcutil.h       utility functions
Packit 807167
 * @file kcdb.h         database interface
Packit 807167
 * @file kcthread.h     threading devices
Packit 807167
 * @file kcfile.h       filesystem abstraction
Packit 807167
 * @file kccompress.h   data compressor and decompressor
Packit 807167
 * @file kccompare.h    comparator functions
Packit 807167
 * @file kcmap.h        data mapping structures
Packit 807167
 * @file kcregex.h      regular expression
Packit 807167
 * @file kcplantdb.h    plant database
Packit 807167
 * @file kcprotodb.h    prototype database
Packit 807167
 * @file kccachedb.h    cache hash database
Packit 807167
 * @file kchashdb.h     file hash database
Packit 807167
 * @file kcdirdb.h      directory hash database
Packit 807167
 * @file kctextdb.h     plain text database
Packit 807167
 * @file kcpolydb.h     polymorphic database
Packit 807167
 * @file kcdbext.h      database extension
Packit 807167
 * @file kclangc.h      C language binding
Packit 807167
 */