diff options
Diffstat (limited to 'plugins/Dbx_kyoto/src/kyotocabinet/kcdb.h')
-rw-r--r-- | plugins/Dbx_kyoto/src/kyotocabinet/kcdb.h | 2520 |
1 files changed, 0 insertions, 2520 deletions
diff --git a/plugins/Dbx_kyoto/src/kyotocabinet/kcdb.h b/plugins/Dbx_kyoto/src/kyotocabinet/kcdb.h deleted file mode 100644 index 8abffb4c6b..0000000000 --- a/plugins/Dbx_kyoto/src/kyotocabinet/kcdb.h +++ /dev/null @@ -1,2520 +0,0 @@ -/************************************************************************************************* - * Database interface - * Copyright (C) 2009-2012 FAL Labs - * This file is part of Kyoto Cabinet. - * This program is free software: you can redistribute it and/or modify it under the terms of - * the GNU General Public License as published by the Free Software Foundation, either version - * 3 of the License, or any later version. - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. - * You should have received a copy of the GNU General Public License along with this program. - * If not, see <http://www.gnu.org/licenses/>. - *************************************************************************************************/ - - -#ifndef _KCDB_H // duplication check -#define _KCDB_H - -#include <kccommon.h> -#include <kcutil.h> -#include <kcthread.h> -#include <kcfile.h> -#include <kccompress.h> -#include <kccompare.h> -#include <kcmap.h> - -#define KCDBSSMAGICDATA "KCSS\n" ///< The magic data of the snapshot file - -namespace kyotocabinet { // common namespace - - -/** - * Interface of database abstraction. - * @note This class is an abstract class to prescribe the interface of record access. - */ -class DB { - public: - /** - * Interface to access a record. - */ - class Visitor { - public: - /** Special pointer for no operation. */ - static const char* const NOP; - /** Special pointer to remove the record. */ - static const char* const REMOVE; - /** - * Destructor. - */ - virtual ~Visitor() { - _assert_(true); - } - /** - * Visit a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param vbuf the pointer to the value region. - * @param vsiz the size of the value region. - * @param sp the pointer to the variable into which the size of the region of the return - * value is assigned. - * @return If it is the pointer to a region, the value is replaced by the content. If it - * is Visitor::NOP, nothing is modified. If it is Visitor::REMOVE, the record is removed. - */ - virtual const char* visit_full(const char* kbuf, size_t ksiz, - const char* vbuf, size_t vsiz, size_t* sp) { - _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp); - return NOP; - } - /** - * Visit a empty record space. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param sp the pointer to the variable into which the size of the region of the return - * value is assigned. - * @return If it is the pointer to a region, the value is replaced by the content. If it - * is Visitor::NOP or Visitor::REMOVE, nothing is modified. - */ - virtual const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { - _assert_(kbuf && ksiz <= MEMMAXSIZ && sp); - return NOP; - } - /** - * Preprocess the main operations. - */ - virtual void visit_before() { - _assert_(true); - } - /** - * Postprocess the main operations. - */ - virtual void visit_after() { - _assert_(true); - } - }; - /** - * Interface of cursor to indicate a record. - */ - class Cursor { - public: - /** - * Destructor. - */ - virtual ~Cursor() { - _assert_(true); - } - /** - * Accept a visitor to the current record. - * @param visitor a visitor object. - * @param writable true for writable operation, or false for read-only operation. - * @param step true to move the cursor to the next record, or false for no move. - * @return true on success, or false on failure. - * @note The operation for each record is performed atomically and other threads accessing - * the same record are blocked. To avoid deadlock, any explicit database operation must not - * be performed in this function. - */ - virtual bool accept(Visitor* visitor, bool writable = true, bool step = false) = 0; - /** - * Set the value of the current record. - * @param vbuf the pointer to the value region. - * @param vsiz the size of the value region. - * @param step true to move the cursor to the next record, or false for no move. - * @return true on success, or false on failure. - */ - virtual bool set_value(const char* vbuf, size_t vsiz, bool step = false) = 0; - /** - * Set the value of the current record. - * @note Equal to the original Cursor::set_value method except that the parameter is - * std::string. - */ - virtual bool set_value_str(const std::string& value, bool step = false) = 0; - /** - * Remove the current record. - * @return true on success, or false on failure. - * @note If no record corresponds to the key, false is returned. The cursor is moved to the - * next record implicitly. - */ - virtual bool remove() = 0; - /** - * Get the key of the current record. - * @param sp the pointer to the variable into which the size of the region of the return - * value is assigned. - * @param step true to move the cursor to the next record, or false for no move. - * @return the pointer to the key region of the current record, or NULL on failure. - * @note If the cursor is invalidated, NULL is returned. Because an additional zero - * code is appended at the end of the region of the return value, the return value can be - * treated as a C-style string. Because the region of the return value is allocated with the - * the new[] operator, it should be released with the delete[] operator when it is no longer - * in use. - */ - virtual char* get_key(size_t* sp, bool step = false) = 0; - /** - * Get the key of the current record. - * @note Equal to the original Cursor::get_key method except that a parameter is a string to - * contain the result and the return value is bool for success. - */ - virtual bool get_key(std::string* key, bool step = false) = 0; - /** - * Get the value of the current record. - * @param sp the pointer to the variable into which the size of the region of the return - * value is assigned. - * @param step true to move the cursor to the next record, or false for no move. - * @return the pointer to the value region of the current record, or NULL on failure. - * @note If the cursor is invalidated, NULL is returned. Because an additional zero - * code is appended at the end of the region of the return value, the return value can be - * treated as a C-style string. Because the region of the return value is allocated with the - * the new[] operator, it should be released with the delete[] operator when it is no longer - * in use. - */ - virtual char* get_value(size_t* sp, bool step = false) = 0; - /** - * Get the value of the current record. - * @note Equal to the original Cursor::get_value method except that a parameter is a string - * to contain the result and the return value is bool for success. - */ - virtual bool get_value(std::string* value, bool step = false) = 0; - /** - * Get a pair of the key and the value of the current record. - * @param ksp the pointer to the variable into which the size of the region of the return - * value is assigned. - * @param vbp the pointer to the variable into which the pointer to the value region is - * assigned. - * @param vsp the pointer to the variable into which the size of the value region is - * assigned. - * @param step true to move the cursor to the next record, or false for no move. - * @return the pointer to the key region, or NULL on failure. - * @note If the cursor is invalidated, NULL is returned. Because an additional zero code is - * appended at the end of each region of the key and the value, each region can be treated - * as a C-style string. The return value should be deleted explicitly by the caller with - * the detele[] operator. - */ - virtual char* get(size_t* ksp, const char** vbp, size_t* vsp, bool step = false) = 0; - /** - * Get a pair of the key and the value of the current record. - * @note Equal to the original Cursor::get method except that parameters are strings - * to contain the result and the return value is bool for success. - */ - virtual bool get(std::string* key, std::string* value, bool step = false) = 0; - /** - * Jump the cursor to the first record for forward scan. - * @return true on success, or false on failure. - */ - virtual bool jump() = 0; - /** - * Jump the cursor to a record for forward scan. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @return true on success, or false on failure. - */ - virtual bool jump(const char* kbuf, size_t ksiz) = 0; - /** - * Jump the cursor to a record for forward scan. - * @note Equal to the original Cursor::jump method except that the parameter is std::string. - */ - virtual bool jump(const std::string& key) = 0; - /** - * Jump the cursor to the last record for backward scan. - * @return true on success, or false on failure. - * @note This method is dedicated to tree databases. Some database types, especially hash - * databases, will provide a dummy implementation. - */ - virtual bool jump_back() = 0; - /** - * Jump the cursor to a record for backward scan. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @return true on success, or false on failure. - * @note This method is dedicated to tree databases. Some database types, especially hash - * databases, will provide a dummy implementation. - */ - virtual bool jump_back(const char* kbuf, size_t ksiz) = 0; - /** - * Jump the cursor to a record for backward scan. - * @note Equal to the original Cursor::jump_back method except that the parameter is - * std::string. - */ - virtual bool jump_back(const std::string& key) = 0; - /** - * Step the cursor to the next record. - * @return true on success, or false on failure. - */ - virtual bool step() = 0; - /** - * Step the cursor to the previous record. - * @return true on success, or false on failure. - * @note This method is dedicated to tree databases. Some database types, especially hash - * databases, will provide a dummy implementation. - */ - virtual bool step_back() = 0; - /** - * Get the database object. - * @return the database object. - */ - virtual DB* db() = 0; - }; - /** - * Destructor. - */ - virtual ~DB() { - _assert_(true); - } - /** - * Accept a visitor to a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param visitor a visitor object. - * @param writable true for writable operation, or false for read-only operation. - * @return true on success, or false on failure. - * @note The operation for each record is performed atomically and other threads accessing the - * same record are blocked. To avoid deadlock, any explicit database operation must not be - * performed in this function. - */ - virtual bool accept(const char* kbuf, size_t ksiz, Visitor* visitor, bool writable = true) = 0; - /** - * Set the value of a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param vbuf the pointer to the value region. - * @param vsiz the size of the value region. - * @return true on success, or false on failure. - * @note If no record corresponds to the key, a new record is created. If the corresponding - * record exists, the value is overwritten. - */ - virtual bool set(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) = 0; - /** - * Set the value of a record. - * @note Equal to the original DB::set method except that the parameters are std::string. - */ - virtual bool set(const std::string& key, const std::string& value) = 0; - /** - * Add a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param vbuf the pointer to the value region. - * @param vsiz the size of the value region. - * @return true on success, or false on failure. - * @note If no record corresponds to the key, a new record is created. If the corresponding - * record exists, the record is not modified and false is returned. - */ - virtual bool add(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) = 0; - /** - * Set the value of a record. - * @note Equal to the original DB::add method except that the parameters are std::string. - */ - virtual bool add(const std::string& key, const std::string& value) = 0; - /** - * Replace the value of a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param vbuf the pointer to the value region. - * @param vsiz the size of the value region. - * @return true on success, or false on failure. - * @note If no record corresponds to the key, no new record is created and false is returned. - * If the corresponding record exists, the value is modified. - */ - virtual bool replace(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) = 0; - /** - * Replace the value of a record. - * @note Equal to the original DB::replace method except that the parameters are std::string. - */ - virtual bool replace(const std::string& key, const std::string& value) = 0; - /** - * Append the value of a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param vbuf the pointer to the value region. - * @param vsiz the size of the value region. - * @return true on success, or false on failure. - * @note If no record corresponds to the key, a new record is created. If the corresponding - * record exists, the given value is appended at the end of the existing value. - */ - virtual bool append(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) = 0; - /** - * Set the value of a record. - * @note Equal to the original DB::append method except that the parameters are std::string. - */ - virtual bool append(const std::string& key, const std::string& value) = 0; - /** - * Add a number to the numeric integer value of a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param num the additional number. - * @param orig the origin number if no record corresponds to the key. If it is INT64MIN and - * no record corresponds, this function fails. If it is INT64MAX, the value is set as the - * additional number regardless of the current value. - * @return the result value, or kyotocabinet::INT64MIN on failure. - * @note The value is serialized as an 8-byte binary integer in big-endian order, not a decimal - * string. If existing value is not 8-byte, this function fails. - */ - virtual int64_t increment(const char* kbuf, size_t ksiz, int64_t num, int64_t orig = 0) = 0; - /** - * Add a number to the numeric integer value of a record. - * @note Equal to the original DB::increment method except that the parameter is std::string. - */ - virtual int64_t increment(const std::string& key, int64_t num, int64_t orig = 0) = 0; - /** - * Add a number to the numeric double value of a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param num the additional number. - * @param orig the origin number if no record corresponds to the key. If it is negative - * infinity and no record corresponds, this function fails. If it is positive infinity, the - * value is set as the additional number regardless of the current value. - * @return the result value, or Not-a-number on failure. - * @note The value is serialized as an 16-byte binary fixed-point number in big-endian order, - * not a decimal string. If existing value is not 16-byte, this function fails. - */ - virtual double increment_double(const char* kbuf, size_t ksiz, double num, - double orig = 0) = 0; - /** - * Add a number to the numeric double value of a record. - * @note Equal to the original DB::increment_double method except that the parameter is - * std::string. - */ - virtual double increment_double(const std::string& key, double num, double orig = 0) = 0; - /** - * Perform compare-and-swap. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param ovbuf the pointer to the old value region. NULL means that no record corresponds. - * @param ovsiz the size of the old value region. - * @param nvbuf the pointer to the new value region. NULL means that the record is removed. - * @param nvsiz the size of new old value region. - * @return true on success, or false on failure. - */ - virtual bool cas(const char* kbuf, size_t ksiz, - const char* ovbuf, size_t ovsiz, const char* nvbuf, size_t nvsiz) = 0; - /** - * Perform compare-and-swap. - * @note Equal to the original DB::cas method except that the parameters are std::string. - */ - virtual bool cas(const std::string& key, - const std::string& ovalue, const std::string& nvalue) = 0; - /** - * Remove a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @return true on success, or false on failure. - * @note If no record corresponds to the key, false is returned. - */ - virtual bool remove(const char* kbuf, size_t ksiz) = 0; - /** - * Remove a record. - * @note Equal to the original DB::remove method except that the parameter is std::string. - */ - virtual bool remove(const std::string& key) = 0; - /** - * Retrieve the value of a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param sp the pointer to the variable into which the size of the region of the return - * value is assigned. - * @return the pointer to the value region of the corresponding record, or NULL on failure. - * @note If no record corresponds to the key, NULL is returned. Because an additional zero - * code is appended at the end of the region of the return value, the return value can be - * treated as a C-style string. Because the region of the return value is allocated with the - * the new[] operator, it should be released with the delete[] operator when it is no longer - * in use. - */ - virtual char* get(const char* kbuf, size_t ksiz, size_t* sp) = 0; - /** - * Retrieve the value of a record. - * @note Equal to the original DB::get method except that the first parameters is the key - * string and the second parameter is a string to contain the result and the return value is - * bool for success. - */ - virtual bool get(const std::string& key, std::string* value) = 0; - /** - * Retrieve the value of a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param vbuf the pointer to the buffer into which the value of the corresponding record is - * written. - * @param max the size of the buffer. - * @return the size of the value, or -1 on failure. - */ - virtual int32_t get(const char* kbuf, size_t ksiz, char* vbuf, size_t max) = 0; - /** - * Check the existence of a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @return the size of the value, or -1 on failure. - */ - virtual int32_t check(const char* kbuf, size_t ksiz) = 0; - /** - * Check the existence of a record. - * @note Equal to the original DB::check method except that the parameter is std::string. - */ - virtual int32_t check(const std::string& key) = 0; - /** - * Remove all records. - * @return true on success, or false on failure. - */ - virtual bool clear() = 0; - /** - * Get the number of records. - * @return the number of records, or -1 on failure. - */ - virtual int64_t count() = 0; - /** - * Create a cursor object. - * @return the return value is the created cursor object. - * @note Because the object of the return value is allocated by the constructor, it should be - * released with the delete operator when it is no longer in use. - */ - virtual Cursor* cursor() = 0; -}; - - -/** - * Basic implementation of database. - * @note This class is an abstract class to prescribe the interface of file operations and - * provide mix-in methods. This class can be inherited but overwriting methods is forbidden. - * Before every database operation, it is necessary to call the BasicDB::open method in order to - * open a database file and connect the database object to it. To avoid data missing or - * corruption, it is important to close every database file by the BasicDB::close method when the - * database is no longer in use. It is forbidden for multible database objects in a process to - * open the same database at the same time. It is forbidden to share a database object with - * child processes. - */ -class BasicDB : public DB { - public: - class Cursor; - class Error; - class ProgressChecker; - class FileProcessor; - class Logger; - class MetaTrigger; - private: - /** The size of the IO buffer. */ - static const size_t IOBUFSIZ = 8192; - public: - /** - * Database types. - */ - enum Type { - TYPEVOID = 0x00, ///< void database - TYPEPHASH = 0x10, ///< prototype hash database - TYPEPTREE = 0x11, ///< prototype tree database - TYPESTASH = 0x18, ///< stash database - TYPECACHE = 0x20, ///< cache hash database - TYPEGRASS = 0x21, ///< cache tree database - TYPEHASH = 0x30, ///< file hash database - TYPETREE = 0x31, ///< file tree database - TYPEDIR = 0x40, ///< directory hash database - TYPEFOREST = 0x41, ///< directory tree database - TYPETEXT = 0x50, ///< plain text database - TYPEMISC = 0x80 ///< miscellaneous database - }; - /** - * Interface of cursor to indicate a record. - */ - class Cursor : public DB::Cursor { - public: - /** - * Destructor. - */ - virtual ~Cursor() { - _assert_(true); - } - /** - * Set the value of the current record. - * @param vbuf the pointer to the value region. - * @param vsiz the size of the value region. - * @param step true to move the cursor to the next record, or false for no move. - * @return true on success, or false on failure. - */ - bool set_value(const char* vbuf, size_t vsiz, bool step = false) { - _assert_(vbuf && vsiz <= MEMMAXSIZ); - class VisitorImpl : public Visitor { - public: - explicit VisitorImpl(const char* vbuf, size_t vsiz) : - vbuf_(vbuf), vsiz_(vsiz), ok_(false) {} - bool ok() const { - return ok_; - } - private: - const char* visit_full(const char* kbuf, size_t ksiz, - const char* vbuf, size_t vsiz, size_t* sp) { - ok_ = true; - *sp = vsiz_; - return vbuf_; - } - const char* vbuf_; - size_t vsiz_; - bool ok_; - }; - VisitorImpl visitor(vbuf, vsiz); - if (!accept(&visitor, true, step)) return false; - if (!visitor.ok()) return false; - return true; - } - /** - * Set the value of the current record. - * @note Equal to the original Cursor::set_value method except that the parameter is - * std::string. - */ - bool set_value_str(const std::string& value, bool step = false) { - _assert_(true); - return set_value(value.c_str(), value.size(), step); - } - /** - * Remove the current record. - * @return true on success, or false on failure. - * @note If no record corresponds to the key, false is returned. The cursor is moved to the - * next record implicitly. - */ - bool remove() { - _assert_(true); - class VisitorImpl : public Visitor { - public: - explicit VisitorImpl() : ok_(false) {} - bool ok() const { - return ok_; - } - private: - const char* visit_full(const char* kbuf, size_t ksiz, - const char* vbuf, size_t vsiz, size_t* sp) { - ok_ = true; - return REMOVE; - } - bool ok_; - }; - VisitorImpl visitor; - if (!accept(&visitor, true, false)) return false; - if (!visitor.ok()) return false; - return true; - } - /** - * Get the key of the current record. - * @param sp the pointer to the variable into which the size of the region of the return - * value is assigned. - * @param step true to move the cursor to the next record, or false for no move. - * @return the pointer to the key region of the current record, or NULL on failure. - * @note If the cursor is invalidated, NULL is returned. Because an additional zero - * code is appended at the end of the region of the return value, the return value can be - * treated as a C-style string. Because the region of the return value is allocated with the - * the new[] operator, it should be released with the delete[] operator when it is no longer - * in use. - */ - char* get_key(size_t* sp, bool step = false) { - _assert_(sp); - class VisitorImpl : public Visitor { - public: - explicit VisitorImpl() : kbuf_(NULL), ksiz_(0) {} - char* pop(size_t* sp) { - *sp = ksiz_; - return kbuf_; - } - void clear() { - delete[] kbuf_; - } - private: - const char* visit_full(const char* kbuf, size_t ksiz, - const char* vbuf, size_t vsiz, size_t* sp) { - kbuf_ = new char[ksiz+1]; - std::memcpy(kbuf_, kbuf, ksiz); - kbuf_[ksiz] = '\0'; - ksiz_ = ksiz; - return NOP; - } - char* kbuf_; - size_t ksiz_; - }; - VisitorImpl visitor; - if (!accept(&visitor, false, step)) { - visitor.clear(); - *sp = 0; - return NULL; - } - size_t ksiz; - char* kbuf = visitor.pop(&ksiz); - if (!kbuf) { - *sp = 0; - return NULL; - } - *sp = ksiz; - return kbuf; - } - /** - * Get the key of the current record. - * @note Equal to the original Cursor::get_key method except that a parameter is a string to - * contain the result and the return value is bool for success. - */ - bool get_key(std::string* key, bool step = false) { - _assert_(key); - size_t ksiz; - char* kbuf = get_key(&ksiz, step); - if (!kbuf) return false; - key->clear(); - key->append(kbuf, ksiz); - delete[] kbuf; - return true; - } - /** - * Get the value of the current record. - * @param sp the pointer to the variable into which the size of the region of the return - * value is assigned. - * @param step true to move the cursor to the next record, or false for no move. - * @return the pointer to the value region of the current record, or NULL on failure. - * @note If the cursor is invalidated, NULL is returned. Because an additional zero - * code is appended at the end of the region of the return value, the return value can be - * treated as a C-style string. Because the region of the return value is allocated with the - * the new[] operator, it should be released with the delete[] operator when it is no longer - * in use. - */ - char* get_value(size_t* sp, bool step = false) { - _assert_(sp); - class VisitorImpl : public Visitor { - public: - explicit VisitorImpl() : vbuf_(NULL), vsiz_(0) {} - char* pop(size_t* sp) { - *sp = vsiz_; - return vbuf_; - } - void clear() { - delete[] vbuf_; - } - private: - const char* visit_full(const char* kbuf, size_t ksiz, - const char* vbuf, size_t vsiz, size_t* sp) { - vbuf_ = new char[vsiz+1]; - std::memcpy(vbuf_, vbuf, vsiz); - vbuf_[vsiz] = '\0'; - vsiz_ = vsiz; - return NOP; - } - char* vbuf_; - size_t vsiz_; - }; - VisitorImpl visitor; - if (!accept(&visitor, false, step)) { - visitor.clear(); - *sp = 0; - return NULL; - } - size_t vsiz; - char* vbuf = visitor.pop(&vsiz); - if (!vbuf) { - *sp = 0; - return NULL; - } - *sp = vsiz; - return vbuf; - } - /** - * Get the value of the current record. - * @note Equal to the original Cursor::get_value method except that a parameter is a string - * to contain the result and the return value is bool for success. - */ - bool get_value(std::string* value, bool step = false) { - _assert_(value); - size_t vsiz; - char* vbuf = get_value(&vsiz, step); - if (!vbuf) return false; - value->clear(); - value->append(vbuf, vsiz); - delete[] vbuf; - return true; - } - /** - * Get a pair of the key and the value of the current record. - * @param ksp the pointer to the variable into which the size of the region of the return - * value is assigned. - * @param vbp the pointer to the variable into which the pointer to the value region is - * assigned. - * @param vsp the pointer to the variable into which the size of the value region is - * assigned. - * @param step true to move the cursor to the next record, or false for no move. - * @return the pointer to the key region, or NULL on failure. - * @note If the cursor is invalidated, NULL is returned. Because an additional zero code is - * appended at the end of each region of the key and the value, each region can be treated - * as a C-style string. The return value should be deleted explicitly by the caller with - * the detele[] operator. - */ - char* get(size_t* ksp, const char** vbp, size_t* vsp, bool step = false) { - _assert_(ksp && vbp && vsp); - class VisitorImpl : public Visitor { - public: - explicit VisitorImpl() : kbuf_(NULL), ksiz_(0), vbuf_(NULL), vsiz_(0) {} - char* pop(size_t* ksp, const char** vbp, size_t* vsp) { - *ksp = ksiz_; - *vbp = vbuf_; - *vsp = vsiz_; - return kbuf_; - } - void clear() { - delete[] kbuf_; - } - private: - const char* visit_full(const char* kbuf, size_t ksiz, - const char* vbuf, size_t vsiz, size_t* sp) { - size_t rsiz = ksiz + 1 + vsiz + 1; - kbuf_ = new char[rsiz]; - std::memcpy(kbuf_, kbuf, ksiz); - kbuf_[ksiz] = '\0'; - ksiz_ = ksiz; - vbuf_ = kbuf_ + ksiz + 1; - std::memcpy(vbuf_, vbuf, vsiz); - vbuf_[vsiz] = '\0'; - vsiz_ = vsiz; - return NOP; - } - char* kbuf_; - size_t ksiz_; - char* vbuf_; - size_t vsiz_; - }; - VisitorImpl visitor; - if (!accept(&visitor, false, step)) { - visitor.clear(); - *ksp = 0; - *vbp = NULL; - *vsp = 0; - return NULL; - } - return visitor.pop(ksp, vbp, vsp); - } - /** - * Get a pair of the key and the value of the current record. - * @note Equal to the original Cursor::get method except that parameters are strings - * to contain the result and the return value is bool for success. - */ - bool get(std::string* key, std::string* value, bool step = false) { - _assert_(key && value); - class VisitorImpl : public Visitor { - public: - explicit VisitorImpl(std::string* key, std::string* value) : - key_(key), value_(value), ok_(false) {} - bool ok() { - return ok_; - } - private: - const char* visit_full(const char* kbuf, size_t ksiz, - const char* vbuf, size_t vsiz, size_t* sp) { - key_->clear(); - key_->append(kbuf, ksiz); - value_->clear(); - value_->append(vbuf, vsiz); - ok_ = true; - return NOP; - } - std::string* key_; - std::string* value_; - bool ok_; - }; - VisitorImpl visitor(key, value); - if (!accept(&visitor, false, step)) return false; - return visitor.ok(); - } - /** - * Get a pair of the key and the value of the current record and remove it atomically. - * @param ksp the pointer to the variable into which the size of the region of the return - * value is assigned. - * @param vbp the pointer to the variable into which the pointer to the value region is - * assigned. - * @param vsp the pointer to the variable into which the size of the value region is - * assigned. - * @return the pointer to the key region, or NULL on failure. - * @note If the cursor is invalidated, NULL is returned. Because an additional zero code is - * appended at the end of each region of the key and the value, each region can be treated - * as a C-style string. The return value should be deleted explicitly by the caller with - * the detele[] operator. The cursor is moved to the next record implicitly. - */ - char* seize(size_t* ksp, const char** vbp, size_t* vsp) { - _assert_(ksp && vbp && vsp); - class VisitorImpl : public Visitor { - public: - explicit VisitorImpl() : kbuf_(NULL), ksiz_(0), vbuf_(NULL), vsiz_(0) {} - char* pop(size_t* ksp, const char** vbp, size_t* vsp) { - *ksp = ksiz_; - *vbp = vbuf_; - *vsp = vsiz_; - return kbuf_; - } - void clear() { - delete[] kbuf_; - } - private: - const char* visit_full(const char* kbuf, size_t ksiz, - const char* vbuf, size_t vsiz, size_t* sp) { - size_t rsiz = ksiz + 1 + vsiz + 1; - kbuf_ = new char[rsiz]; - std::memcpy(kbuf_, kbuf, ksiz); - kbuf_[ksiz] = '\0'; - ksiz_ = ksiz; - vbuf_ = kbuf_ + ksiz + 1; - std::memcpy(vbuf_, vbuf, vsiz); - vbuf_[vsiz] = '\0'; - vsiz_ = vsiz; - return REMOVE; - } - char* kbuf_; - size_t ksiz_; - char* vbuf_; - size_t vsiz_; - }; - VisitorImpl visitor; - if (!accept(&visitor, true, false)) { - visitor.clear(); - *ksp = 0; - *vbp = NULL; - *vsp = 0; - return NULL; - } - return visitor.pop(ksp, vbp, vsp); - } - /** - * Get a pair of the key and the value of the current record and remove it atomically. - * @note Equal to the original Cursor::seize method except that parameters are strings - * to contain the result and the return value is bool for success. - */ - bool seize(std::string* key, std::string* value) { - _assert_(key && value); - class VisitorImpl : public Visitor { - public: - explicit VisitorImpl(std::string* key, std::string* value) : - key_(key), value_(value), ok_(false) {} - bool ok() { - return ok_; - } - private: - const char* visit_full(const char* kbuf, size_t ksiz, - const char* vbuf, size_t vsiz, size_t* sp) { - key_->clear(); - key_->append(kbuf, ksiz); - value_->clear(); - value_->append(vbuf, vsiz); - ok_ = true; - return REMOVE; - } - std::string* key_; - std::string* value_; - bool ok_; - }; - VisitorImpl visitor(key, value); - if (!accept(&visitor, true, false)) return false; - return visitor.ok(); - } - /** - * Get the database object. - * @return the database object. - */ - virtual BasicDB* db() = 0; - /** - * Get the last happened error. - * @return the last happened error. - */ - Error error() { - _assert_(true); - return db()->error(); - } - }; - /** - * Error data. - */ - class Error { - public: - /** - * Error codes. - */ - enum Code { - SUCCESS, ///< success - NOIMPL, ///< not implemented - INVALID, ///< invalid operation - NOREPOS, ///< no repository - NOPERM, ///< no permission - BROKEN, ///< broken file - DUPREC, ///< record duplication - NOREC, ///< no record - LOGIC, ///< logical inconsistency - SYSTEM, ///< system error - MISC = 15 ///< miscellaneous error - }; - /** - * Default constructor. - */ - explicit Error() : code_(SUCCESS), message_("no error") { - _assert_(true); - } - /** - * Copy constructor. - * @param src the source object. - */ - Error(const Error& src) : code_(src.code_), message_(src.message_) { - _assert_(true); - } - /** - * Constructor. - * @param code an error code. - * @param message a supplement message. - */ - explicit Error(Code code, const char* message) : code_(code), message_(message) { - _assert_(message); - } - /** - * Destructor. - */ - ~Error() { - _assert_(true); - } - /** - * Set the error information. - * @param code an error code. - * @param message a supplement message. - */ - void set(Code code, const char* message) { - _assert_(message); - code_ = code; - message_ = message; - } - /** - * Get the error code. - * @return the error code. - */ - Code code() const { - _assert_(true); - return code_; - } - /** - * Get the readable string of the code. - * @return the readable string of the code. - */ - const char* name() const { - _assert_(true); - return codename(code_); - } - /** - * Get the supplement message. - * @return the supplement message. - */ - const char* message() const { - _assert_(true); - return message_; - } - /** - * Get the readable string of an error code. - * @param code the error code. - * @return the readable string of the error code. - */ - static const char* codename(Code code) { - _assert_(true); - switch (code) { - case SUCCESS: return "success"; - case NOIMPL: return "not implemented"; - case INVALID: return "invalid operation"; - case NOREPOS: return "no repository"; - case NOPERM: return "no permission"; - case BROKEN: return "broken file"; - case DUPREC: return "record duplication"; - case NOREC: return "no record"; - case LOGIC: return "logical inconsistency"; - case SYSTEM: return "system error"; - default: break; - } - return "miscellaneous error"; - } - /** - * Assignment operator from the self type. - * @param right the right operand. - * @return the reference to itself. - */ - Error& operator =(const Error& right) { - _assert_(true); - if (&right == this) return *this; - code_ = right.code_; - message_ = right.message_; - return *this; - } - /** - * Cast operator to integer. - * @return the error code. - */ - operator int32_t() const { - return code_; - } - private: - /** The error code. */ - Code code_; - /** The supplement message. */ - const char* message_; - }; - /** - * Interface to check progress status of long process. - */ - class ProgressChecker { - public: - /** - * Destructor. - */ - virtual ~ProgressChecker() { - _assert_(true); - } - /** - * Check the progress status. - * @param name the name of the process. - * @param message a supplement message. - * @param curcnt the count of the current step of the progress, or -1 if not applicable. - * @param allcnt the estimation count of all steps of the progress, or -1 if not applicable. - * @return true to continue the process, or false to stop the process. - */ - virtual bool check(const char* name, const char* message, - int64_t curcnt, int64_t allcnt) = 0; - }; - /** - * Interface to process the database file. - */ - class FileProcessor { - public: - /** - * Destructor. - */ - virtual ~FileProcessor() { - _assert_(true); - } - /** - * Process the database file. - * @param path the path of the database file. - * @param count the number of records. A negative value means omission. - * @param size the size of the available region. A negative value means omission. - * @return true on success, or false on failure. - */ - virtual bool process(const std::string& path, int64_t count, int64_t size) = 0; - }; - /** - * Interface to log internal information and errors. - */ - class Logger { - public: - /** - * Event kinds. - */ - enum Kind { - DEBUG = 1 << 0, ///< debugging - INFO = 1 << 1, ///< normal information - WARN = 1 << 2, ///< warning - ERROR = 1 << 3 ///< error - }; - /** - * Destructor. - */ - virtual ~Logger() { - _assert_(true); - } - /** - * Process a log message. - * @param file the file name of the program source code. - * @param line the line number of the program source code. - * @param func the function name of the program source code. - * @param kind the kind of the event. Logger::DEBUG for debugging, Logger::INFO for normal - * information, Logger::WARN for warning, and Logger::ERROR for fatal error. - * @param message the supplement message. - */ - virtual void log(const char* file, int32_t line, const char* func, Kind kind, - const char* message) = 0; - }; - /** - * Interface to trigger meta database operations. - */ - class MetaTrigger { - public: - /** - * Event kinds. - */ - enum Kind { - OPEN, ///< opening - CLOSE, ///< closing - CLEAR, ///< clearing - ITERATE, ///< iteration - SYNCHRONIZE, ///< synchronization - OCCUPY, ///< occupation - BEGINTRAN, ///< beginning transaction - COMMITTRAN, ///< committing transaction - ABORTTRAN, ///< aborting transaction - MISC = 15 ///< miscellaneous operation - }; - /** - * Destructor. - */ - virtual ~MetaTrigger() { - _assert_(true); - } - /** - * Trigger a meta database operation. - * @param kind the kind of the event. MetaTrigger::OPEN for opening, MetaTrigger::CLOSE for - * closing, MetaTrigger::CLEAR for clearing, MetaTrigger::ITERATE for iteration, - * MetaTrigger::SYNCHRONIZE for synchronization, MetaTrigger::OCCUPY for occupation, - * MetaTrigger::BEGINTRAN for beginning transaction, MetaTrigger::COMMITTRAN for committing - * transaction, MetaTrigger::ABORTTRAN for aborting transaction, and MetaTrigger::MISC for - * miscellaneous operations. - * @param message the supplement message. - */ - virtual void trigger(Kind kind, const char* message) = 0; - }; - /** - * Open modes. - */ - enum OpenMode { - OREADER = 1 << 0, ///< open as a reader - OWRITER = 1 << 1, ///< open as a writer - OCREATE = 1 << 2, ///< writer creating - OTRUNCATE = 1 << 3, ///< writer truncating - OAUTOTRAN = 1 << 4, ///< auto transaction - OAUTOSYNC = 1 << 5, ///< auto synchronization - ONOLOCK = 1 << 6, ///< open without locking - OTRYLOCK = 1 << 7, ///< lock without blocking - ONOREPAIR = 1 << 8 ///< open without auto repair - }; - /** - * Destructor. - * @note If the database is not closed, it is closed implicitly. - */ - virtual ~BasicDB() { - _assert_(true); - } - /** - * Get the last happened error. - * @return the last happened error. - */ - virtual Error error() const = 0; - /** - * Set the error information. - * @param file the file name of the program source code. - * @param line the line number of the program source code. - * @param func the function name of the program source code. - * @param code an error code. - * @param message a supplement message. - */ - virtual void set_error(const char* file, int32_t line, const char* func, - Error::Code code, const char* message) = 0; - /** - * Open a database file. - * @param path the path of a database file. - * @param mode the connection mode. BasicDB::OWRITER as a writer, BasicDB::OREADER as a - * reader. The following may be added to the writer mode by bitwise-or: BasicDB::OCREATE, - * which means it creates a new database if the file does not exist, BasicDB::OTRUNCATE, which - * means it creates a new database regardless if the file exists, BasicDB::OAUTOTRAN, which - * means each updating operation is performed in implicit transaction, BasicDB::OAUTOSYNC, - * which means each updating operation is followed by implicit synchronization with the file - * system. The following may be added to both of the reader mode and the writer mode by - * bitwise-or: BasicDB::ONOLOCK, which means it opens the database file without file locking, - * BasicDB::OTRYLOCK, which means locking is performed without blocking, File::ONOREPAIR, which - * means the database file is not repaired implicitly even if file destruction is detected. - * @return true on success, or false on failure. - * @note Every opened database must be closed by the BasicDB::close method when it is no longer - * in use. It is not allowed for two or more database objects in the same process to keep - * their connections to the same database file at the same time. - */ - virtual bool open(const std::string& path, uint32_t mode = OWRITER | OCREATE) = 0; - /** - * Close the database file. - * @return true on success, or false on failure. - */ - virtual bool close() = 0; - /** - * Accept a visitor to multiple records at once. - * @param keys specifies a string vector of the keys. - * @param visitor a visitor object. - * @param writable true for writable operation, or false for read-only operation. - * @return true on success, or false on failure. - * @note The operations for specified records are performed atomically and other threads - * accessing the same records are blocked. To avoid deadlock, any explicit database operation - * must not be performed in this function. - */ - virtual bool accept_bulk(const std::vector<std::string>& keys, Visitor* visitor, - bool writable = true) = 0; - /** - * Iterate to accept a visitor for each record. - * @param visitor a visitor object. - * @param writable true for writable operation, or false for read-only operation. - * @param checker a progress checker object. If it is NULL, no checking is performed. - * @return true on success, or false on failure. - * @note The whole iteration is performed atomically and other threads are blocked. To avoid - * deadlock, any explicit database operation must not be performed in this function. - */ - virtual bool iterate(Visitor *visitor, bool writable = true, - ProgressChecker* checker = NULL) = 0; - /** - * Scan each record in parallel. - * @param visitor a visitor object. - * @param thnum the number of worker threads. - * @param checker a progress checker object. If it is NULL, no checking is performed. - * @return true on success, or false on failure. - * @note This function is for reading records and not for updating ones. The return value of - * the visitor is just ignored. To avoid deadlock, any explicit database operation must not - * be performed in this function. - */ - virtual bool scan_parallel(Visitor *visitor, size_t thnum, - ProgressChecker* checker = NULL) = 0; - /** - * Synchronize updated contents with the file and the device. - * @param hard true for physical synchronization with the device, or false for logical - * synchronization with the file system. - * @param proc a postprocessor object. If it is NULL, no postprocessing is performed. - * @param checker a progress checker object. If it is NULL, no checking is performed. - * @return true on success, or false on failure. - * @note The operation of the postprocessor is performed atomically and other threads accessing - * the same record are blocked. To avoid deadlock, any explicit database operation must not - * be performed in this function. - */ - virtual bool synchronize(bool hard = false, FileProcessor* proc = NULL, - ProgressChecker* checker = NULL) = 0; - /** - * Occupy database by locking and do something meanwhile. - * @param writable true to use writer lock, or false to use reader lock. - * @param proc a processor object. If it is NULL, no processing is performed. - * @return true on success, or false on failure. - * @note The operation of the processor is performed atomically and other threads accessing - * the same record are blocked. To avoid deadlock, any explicit database operation must not - * be performed in this function. - */ - virtual bool occupy(bool writable = true, FileProcessor* proc = NULL) = 0; - /** - * Create a copy of the database file. - * @param dest the path of the destination file. - * @param checker a progress checker object. If it is NULL, no checking is performed. - * @return true on success, or false on failure. - */ - bool copy(const std::string& dest, ProgressChecker* checker = NULL) { - _assert_(true); - class FileProcessorImpl : public FileProcessor { - public: - explicit FileProcessorImpl(const std::string& dest, ProgressChecker* checker, - BasicDB* db) : - dest_(dest), checker_(checker), db_(db) {} - private: - bool process(const std::string& path, int64_t count, int64_t size) { - File::Status sbuf; - if (!File::status(path, &sbuf)) return false; - if (sbuf.isdir) { - if (!File::make_directory(dest_)) return false; - bool err = false; - DirStream dir; - if (dir.open(path)) { - if (checker_ && !checker_->check("copy", "beginning", 0, -1)) { - db_->set_error(_KCCODELINE_, Error::LOGIC, "checker failed"); - err = true; - } - std::string name; - int64_t curcnt = 0; - while (!err && dir.read(&name)) { - const std::string& spath = path + File::PATHCHR + name; - const std::string& dpath = dest_ + File::PATHCHR + name; - int64_t dsiz; - char* dbuf = File::read_file(spath, &dsiz); - if (dbuf) { - if (!File::write_file(dpath, dbuf, dsiz)) err = true; - delete[] dbuf; - } else { - err = true; - } - curcnt++; - if (checker_ && !checker_->check("copy", "processing", curcnt, -1)) { - db_->set_error(_KCCODELINE_, Error::LOGIC, "checker failed"); - err = true; - break; - } - } - if (checker_ && !checker_->check("copy", "ending", -1, -1)) { - db_->set_error(_KCCODELINE_, Error::LOGIC, "checker failed"); - err = true; - } - if (!dir.close()) err = true; - } else { - err = true; - } - return !err; - } - std::ofstream ofs; - ofs.open(dest_.c_str(), - std::ios_base::out | std::ios_base::binary | std::ios_base::trunc); - if (!ofs) return false; - bool err = false; - std::ifstream ifs; - ifs.open(path.c_str(), std::ios_base::in | std::ios_base::binary); - if (checker_ && !checker_->check("copy", "beginning", 0, size)) { - db_->set_error(_KCCODELINE_, Error::LOGIC, "checker failed"); - err = true; - } - if (ifs) { - char buf[IOBUFSIZ]; - int64_t curcnt = 0; - while (!err && !ifs.eof()) { - size_t n = ifs.read(buf, sizeof(buf)).gcount(); - if (n > 0) { - ofs.write(buf, n); - if (!ofs) { - err = true; - break; - } - } - curcnt += n; - if (checker_ && !checker_->check("copy", "processing", curcnt, size)) { - db_->set_error(_KCCODELINE_, Error::LOGIC, "checker failed"); - err = true; - break; - } - } - ifs.close(); - if (ifs.bad()) err = true; - } else { - err = true; - } - if (checker_ && !checker_->check("copy", "ending", -1, size)) { - db_->set_error(_KCCODELINE_, Error::LOGIC, "checker failed"); - err = true; - } - ofs.close(); - if (!ofs) err = true; - return !err; - } - const std::string& dest_; - ProgressChecker* checker_; - BasicDB* db_; - }; - FileProcessorImpl proc(dest, checker, this); - return synchronize(false, &proc, checker); - } - /** - * Begin transaction. - * @param hard true for physical synchronization with the device, or false for logical - * synchronization with the file system. - * @return true on success, or false on failure. - */ - virtual bool begin_transaction(bool hard = false) = 0; - /** - * Try to begin transaction. - * @param hard true for physical synchronization with the device, or false for logical - * synchronization with the file system. - * @return true on success, or false on failure. - */ - virtual bool begin_transaction_try(bool hard = false) = 0; - /** - * End transaction. - * @param commit true to commit the transaction, or false to abort the transaction. - * @return true on success, or false on failure. - */ - virtual bool end_transaction(bool commit = true) = 0; - /** - * Get the size of the database file. - * @return the size of the database file in bytes, or -1 on failure. - */ - virtual int64_t size() = 0; - /** - * Get the path of the database file. - * @return the path of the database file, or an empty string on failure. - */ - virtual std::string path() = 0; - /** - * Get the miscellaneous status information. - * @param strmap a string map to contain the result. - * @return true on success, or false on failure. - */ - virtual bool status(std::map<std::string, std::string>* strmap) = 0; - /** - * Set the value of a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param vbuf the pointer to the value region. - * @param vsiz the size of the value region. - * @return true on success, or false on failure. - * @note If no record corresponds to the key, a new record is created. If the corresponding - * record exists, the value is overwritten. - */ - bool set(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) { - _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ); - class VisitorImpl : public Visitor { - public: - explicit VisitorImpl(const char* vbuf, size_t vsiz) : vbuf_(vbuf), vsiz_(vsiz) {} - private: - const char* visit_full(const char* kbuf, size_t ksiz, - const char* vbuf, size_t vsiz, size_t* sp) { - *sp = vsiz_; - return vbuf_; - } - const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { - *sp = vsiz_; - return vbuf_; - } - const char* vbuf_; - size_t vsiz_; - }; - VisitorImpl visitor(vbuf, vsiz); - if (!accept(kbuf, ksiz, &visitor, true)) return false; - return true; - } - /** - * Set the value of a record. - * @note Equal to the original DB::set method except that the parameters are std::string. - */ - bool set(const std::string& key, const std::string& value) { - _assert_(true); - return set(key.c_str(), key.size(), value.c_str(), value.size()); - } - /** - * Add a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param vbuf the pointer to the value region. - * @param vsiz the size of the value region. - * @return true on success, or false on failure. - * @note If no record corresponds to the key, a new record is created. If the corresponding - * record exists, the record is not modified and false is returned. - */ - bool add(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) { - _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ); - class VisitorImpl : public Visitor { - public: - explicit VisitorImpl(const char* vbuf, size_t vsiz) : - vbuf_(vbuf), vsiz_(vsiz), ok_(false) {} - bool ok() const { - return ok_; - } - private: - const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { - ok_ = true; - *sp = vsiz_; - return vbuf_; - } - const char* vbuf_; - size_t vsiz_; - bool ok_; - }; - VisitorImpl visitor(vbuf, vsiz); - if (!accept(kbuf, ksiz, &visitor, true)) return false; - if (!visitor.ok()) { - set_error(_KCCODELINE_, Error::DUPREC, "record duplication"); - return false; - } - return true; - } - /** - * Set the value of a record. - * @note Equal to the original DB::add method except that the parameters are std::string. - */ - bool add(const std::string& key, const std::string& value) { - _assert_(true); - return add(key.c_str(), key.size(), value.c_str(), value.size()); - } - /** - * Replace the value of a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param vbuf the pointer to the value region. - * @param vsiz the size of the value region. - * @return true on success, or false on failure. - * @note If no record corresponds to the key, no new record is created and false is returned. - * If the corresponding record exists, the value is modified. - */ - bool replace(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) { - _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ); - class VisitorImpl : public Visitor { - public: - explicit VisitorImpl(const char* vbuf, size_t vsiz) : - vbuf_(vbuf), vsiz_(vsiz), ok_(false) {} - bool ok() const { - return ok_; - } - private: - const char* visit_full(const char* kbuf, size_t ksiz, - const char* vbuf, size_t vsiz, size_t* sp) { - ok_ = true; - *sp = vsiz_; - return vbuf_; - } - const char* vbuf_; - size_t vsiz_; - bool ok_; - }; - VisitorImpl visitor(vbuf, vsiz); - if (!accept(kbuf, ksiz, &visitor, true)) return false; - if (!visitor.ok()) { - set_error(_KCCODELINE_, Error::NOREC, "no record"); - return false; - } - return true; - } - /** - * Replace the value of a record. - * @note Equal to the original DB::replace method except that the parameters are std::string. - */ - bool replace(const std::string& key, const std::string& value) { - _assert_(true); - return replace(key.c_str(), key.size(), value.c_str(), value.size()); - } - /** - * Append the value of a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param vbuf the pointer to the value region. - * @param vsiz the size of the value region. - * @return true on success, or false on failure. - * @note If no record corresponds to the key, a new record is created. If the corresponding - * record exists, the given value is appended at the end of the existing value. - */ - bool append(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) { - _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ); - class VisitorImpl : public Visitor { - public: - explicit VisitorImpl(const char* vbuf, size_t vsiz) : - vbuf_(vbuf), vsiz_(vsiz), nbuf_(NULL) {} - ~VisitorImpl() { - if (nbuf_) delete[] nbuf_; - } - private: - const char* visit_full(const char* kbuf, size_t ksiz, - const char* vbuf, size_t vsiz, size_t* sp) { - size_t nsiz = vsiz + vsiz_; - nbuf_ = new char[nsiz]; - std::memcpy(nbuf_, vbuf, vsiz); - std::memcpy(nbuf_ + vsiz, vbuf_, vsiz_); - *sp = nsiz; - return nbuf_; - } - const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { - *sp = vsiz_; - return vbuf_; - } - const char* vbuf_; - size_t vsiz_; - char* nbuf_; - }; - VisitorImpl visitor(vbuf, vsiz); - if (!accept(kbuf, ksiz, &visitor, true)) return false; - return true; - } - /** - * Set the value of a record. - * @note Equal to the original DB::append method except that the parameters are std::string. - */ - bool append(const std::string& key, const std::string& value) { - _assert_(true); - return append(key.c_str(), key.size(), value.c_str(), value.size()); - } - /** - * Add a number to the numeric value of a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param num the additional number. - * @param orig the origin number if no record corresponds to the key. If it is INT64MIN and - * no record corresponds, this function fails. If it is INT64MAX, the value is set as the - * additional number regardless of the current value. - * @return the result value, or kyotocabinet::INT64MIN on failure. - * @note The value is serialized as an 8-byte binary integer in big-endian order, not a decimal - * string. If existing value is not 8-byte, this function fails. - */ - int64_t increment(const char* kbuf, size_t ksiz, int64_t num, int64_t orig = 0) { - _assert_(kbuf && ksiz <= MEMMAXSIZ); - class VisitorImpl : public Visitor { - public: - explicit VisitorImpl(int64_t num, int64_t orig) : num_(num), orig_(orig), big_(0) {} - int64_t num() { - return num_; - } - private: - const char* visit_full(const char* kbuf, size_t ksiz, - const char* vbuf, size_t vsiz, size_t* sp) { - if (vsiz != sizeof(num_)) { - num_ = INT64MIN; - return NOP; - } - int64_t onum; - if (orig_ == INT64MAX) { - onum = 0; - } else { - std::memcpy(&onum, vbuf, vsiz); - onum = ntoh64(onum); - if (num_ == 0) { - num_ = onum; - return NOP; - } - } - num_ += onum; - big_ = hton64(num_); - *sp = sizeof(big_); - return (const char*)&big_; - } - const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { - if (orig_ == INT64MIN) { - num_ = INT64MIN; - return NOP; - } - if (orig_ != INT64MAX) num_ += orig_; - big_ = hton64(num_); - *sp = sizeof(big_); - return (const char*)&big_; - } - int64_t num_; - int64_t orig_; - uint64_t big_; - }; - VisitorImpl visitor(num, orig); - if (!accept(kbuf, ksiz, &visitor, num != 0 || orig != INT64MIN)) return INT64MIN; - num = visitor.num(); - if (num == INT64MIN) { - set_error(_KCCODELINE_, Error::LOGIC, "logical inconsistency"); - return num; - } - return num; - } - /** - * Add a number to the numeric value of a record. - * @note Equal to the original DB::increment method except that the parameter is std::string. - */ - int64_t increment(const std::string& key, int64_t num, int64_t orig = 0) { - _assert_(true); - return increment(key.c_str(), key.size(), num, orig); - } - /** - * Add a number to the numeric double value of a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param num the additional number. - * @param orig the origin number if no record corresponds to the key. If it is negative - * infinity and no record corresponds, this function fails. If it is positive infinity, the - * value is set as the additional number regardless of the current value. - * @return the result value, or Not-a-number on failure. - * @note The value is serialized as an 16-byte binary fixed-point number in big-endian order, - * not a decimal string. If existing value is not 16-byte, this function fails. - */ - double increment_double(const char* kbuf, size_t ksiz, double num, double orig = 0) { - _assert_(kbuf && ksiz <= MEMMAXSIZ); - class VisitorImpl : public Visitor { - public: - explicit VisitorImpl(double num, double orig) : - DECUNIT(1000000000000000LL), num_(num), orig_(orig), buf_() {} - double num() { - return num_; - } - private: - const char* visit_full(const char* kbuf, size_t ksiz, - const char* vbuf, size_t vsiz, size_t* sp) { - if (vsiz != sizeof(buf_)) { - num_ = nan(); - return NOP; - } - int64_t linteg, lfract; - if (chkinf(orig_) && orig_ >= 0) { - linteg = 0; - lfract = 0; - } else { - std::memcpy(&linteg, vbuf, sizeof(linteg)); - linteg = ntoh64(linteg); - std::memcpy(&lfract, vbuf + sizeof(linteg), sizeof(lfract)); - lfract = ntoh64(lfract); - } - if (lfract == INT64MIN && linteg == INT64MIN) { - num_ = nan(); - return NOP; - } else if (linteg == INT64MAX) { - num_ = HUGE_VAL; - return NOP; - } else if (linteg == INT64MIN) { - num_ = -HUGE_VAL; - return NOP; - } - if (num_ == 0.0 && !(chkinf(orig_) && orig_ >= 0)) { - num_ = linteg + (double)lfract / DECUNIT; - return NOP; - } - long double dinteg; - long double dfract = std::modfl(num_, &dinteg); - if (chknan(dinteg)) { - linteg = INT64MIN; - lfract = INT64MIN; - num_ = nan(); - } else if (chkinf(dinteg)) { - linteg = dinteg > 0 ? INT64MAX : INT64MIN; - lfract = 0; - num_ = dinteg; - } else { - linteg += (int64_t)dinteg; - lfract += (int64_t)(dfract * DECUNIT); - if (lfract >= DECUNIT) { - linteg += 1; - lfract -= DECUNIT; - } - num_ = linteg + (double)lfract / DECUNIT; - } - linteg = hton64(linteg); - std::memcpy(buf_, &linteg, sizeof(linteg)); - lfract = hton64(lfract); - std::memcpy(buf_ + sizeof(linteg), &lfract, sizeof(lfract)); - *sp = sizeof(buf_); - return buf_; - } - const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { - if (chknan(orig_) || (chkinf(orig_) && orig_ < 0)) { - num_ = nan(); - return NOP; - } - if (!chkinf(orig_)) num_ += orig_; - long double dinteg; - long double dfract = std::modfl(num_, &dinteg); - int64_t linteg, lfract; - if (chknan(dinteg)) { - linteg = INT64MIN; - lfract = INT64MIN; - } else if (chkinf(dinteg)) { - linteg = dinteg > 0 ? INT64MAX : INT64MIN; - lfract = 0; - } else { - linteg = (int64_t)dinteg; - lfract = (int64_t)(dfract * DECUNIT); - } - linteg = hton64(linteg); - std::memcpy(buf_, &linteg, sizeof(linteg)); - lfract = hton64(lfract); - std::memcpy(buf_ + sizeof(linteg), &lfract, sizeof(lfract)); - *sp = sizeof(buf_); - return buf_; - } - const int64_t DECUNIT; - double num_; - double orig_; - char buf_[sizeof(int64_t)*2]; - }; - VisitorImpl visitor(num, orig); - if (!accept(kbuf, ksiz, &visitor, true)) return nan(); - num = visitor.num(); - if (chknan(num)) { - set_error(_KCCODELINE_, Error::LOGIC, "logical inconsistency"); - return nan(); - } - return num; - } - /** - * Add a number to the numeric double value of a record. - * @note Equal to the original DB::increment_double method except that the parameter is - * std::string. - */ - double increment_double(const std::string& key, double num, double orig) { - _assert_(true); - return increment_double(key.c_str(), key.size(), num, orig); - } - /** - * Perform compare-and-swap. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param ovbuf the pointer to the old value region. NULL means that no record corresponds. - * @param ovsiz the size of the old value region. - * @param nvbuf the pointer to the new value region. NULL means that the record is removed. - * @param nvsiz the size of new old value region. - * @return true on success, or false on failure. - */ - bool cas(const char* kbuf, size_t ksiz, - const char* ovbuf, size_t ovsiz, const char* nvbuf, size_t nvsiz) { - _assert_(kbuf && ksiz <= MEMMAXSIZ); - class VisitorImpl : public Visitor { - public: - explicit VisitorImpl(const char* ovbuf, size_t ovsiz, const char* nvbuf, size_t nvsiz) : - ovbuf_(ovbuf), ovsiz_(ovsiz), nvbuf_(nvbuf), nvsiz_(nvsiz), ok_(false) {} - bool ok() const { - return ok_; - } - private: - const char* visit_full(const char* kbuf, size_t ksiz, - const char* vbuf, size_t vsiz, size_t* sp) { - if (!ovbuf_ || vsiz != ovsiz_ || std::memcmp(vbuf, ovbuf_, vsiz)) return NOP; - ok_ = true; - if (!nvbuf_) return REMOVE; - *sp = nvsiz_; - return nvbuf_; - } - const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { - if (ovbuf_) return NOP; - ok_ = true; - if (!nvbuf_) return NOP; - *sp = nvsiz_; - return nvbuf_; - } - const char* ovbuf_; - size_t ovsiz_; - const char* nvbuf_; - size_t nvsiz_; - bool ok_; - }; - VisitorImpl visitor(ovbuf, ovsiz, nvbuf, nvsiz); - if (!accept(kbuf, ksiz, &visitor, true)) return false; - if (!visitor.ok()) { - set_error(_KCCODELINE_, Error::LOGIC, "status conflict"); - return false; - } - return true; - } - /** - * Perform compare-and-swap. - * @note Equal to the original DB::cas method except that the parameters are std::string. - */ - bool cas(const std::string& key, - const std::string& ovalue, const std::string& nvalue) { - _assert_(true); - return cas(key.c_str(), key.size(), - ovalue.c_str(), ovalue.size(), nvalue.c_str(), nvalue.size()); - } - /** - * Remove a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @return true on success, or false on failure. - * @note If no record corresponds to the key, false is returned. - */ - bool remove(const char* kbuf, size_t ksiz) { - _assert_(kbuf && ksiz <= MEMMAXSIZ); - class VisitorImpl : public Visitor { - public: - explicit VisitorImpl() : ok_(false) {} - bool ok() const { - return ok_; - } - private: - const char* visit_full(const char* kbuf, size_t ksiz, - const char* vbuf, size_t vsiz, size_t* sp) { - ok_ = true; - return REMOVE; - } - bool ok_; - }; - VisitorImpl visitor; - if (!accept(kbuf, ksiz, &visitor, true)) return false; - if (!visitor.ok()) { - set_error(_KCCODELINE_, Error::NOREC, "no record"); - return false; - } - return true; - } - /** - * Remove a record. - * @note Equal to the original DB::remove method except that the parameter is std::string. - */ - bool remove(const std::string& key) { - _assert_(true); - return remove(key.c_str(), key.size()); - } - /** - * Retrieve the value of a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param sp the pointer to the variable into which the size of the region of the return - * value is assigned. - * @return the pointer to the value region of the corresponding record, or NULL on failure. - * @note If no record corresponds to the key, NULL is returned. Because an additional zero - * code is appended at the end of the region of the return value, the return value can be - * treated as a C-style string. Because the region of the return value is allocated with the - * the new[] operator, it should be released with the delete[] operator when it is no longer - * in use. - */ - char* get(const char* kbuf, size_t ksiz, size_t* sp) { - _assert_(kbuf && ksiz <= MEMMAXSIZ && sp); - class VisitorImpl : public Visitor { - public: - explicit VisitorImpl() : vbuf_(NULL), vsiz_(0) {} - char* pop(size_t* sp) { - *sp = vsiz_; - return vbuf_; - } - private: - const char* visit_full(const char* kbuf, size_t ksiz, - const char* vbuf, size_t vsiz, size_t* sp) { - vbuf_ = new char[vsiz+1]; - std::memcpy(vbuf_, vbuf, vsiz); - vbuf_[vsiz] = '\0'; - vsiz_ = vsiz; - return NOP; - } - char* vbuf_; - size_t vsiz_; - }; - VisitorImpl visitor; - if (!accept(kbuf, ksiz, &visitor, false)) { - *sp = 0; - return NULL; - } - size_t vsiz; - char* vbuf = visitor.pop(&vsiz); - if (!vbuf) { - set_error(_KCCODELINE_, Error::NOREC, "no record"); - *sp = 0; - return NULL; - } - *sp = vsiz; - return vbuf; - } - /** - * Retrieve the value of a record. - * @note Equal to the original DB::get method except that the first parameters is the key - * string and the second parameter is a string to contain the result and the return value is - * bool for success. - */ - bool get(const std::string& key, std::string* value) { - _assert_(value); - class VisitorImpl : public Visitor { - public: - explicit VisitorImpl(std::string* value) : value_(value), ok_(false) {} - bool ok() { - return ok_; - } - private: - const char* visit_full(const char* kbuf, size_t ksiz, - const char* vbuf, size_t vsiz, size_t* sp) { - value_->clear(); - value_->append(vbuf, vsiz); - ok_ = true; - return NOP; - } - std::string* value_; - bool ok_; - }; - VisitorImpl visitor(value); - if (!accept(key.data(), key.size(), &visitor, false)) return false; - if (!visitor.ok()) { - set_error(_KCCODELINE_, Error::NOREC, "no record"); - return false; - } - return true; - } - /** - * Retrieve the value of a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param vbuf the pointer to the buffer into which the value of the corresponding record is - * written. - * @param max the size of the buffer. - * @return the size of the value, or -1 on failure. - */ - int32_t get(const char* kbuf, size_t ksiz, char* vbuf, size_t max) { - _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf); - class VisitorImpl : public Visitor { - public: - explicit VisitorImpl(char* vbuf, size_t max) : vbuf_(vbuf), max_(max), vsiz_(-1) {} - int32_t vsiz() { - return vsiz_; - } - private: - const char* visit_full(const char* kbuf, size_t ksiz, - const char* vbuf, size_t vsiz, size_t* sp) { - vsiz_ = vsiz; - size_t max = vsiz < max_ ? vsiz : max_; - std::memcpy(vbuf_, vbuf, max); - return NOP; - } - char* vbuf_; - size_t max_; - int32_t vsiz_; - }; - VisitorImpl visitor(vbuf, max); - if (!accept(kbuf, ksiz, &visitor, false)) return -1; - int32_t vsiz = visitor.vsiz(); - if (vsiz < 0) { - set_error(_KCCODELINE_, Error::NOREC, "no record"); - return -1; - } - return vsiz; - } - /** - * Check the existence of a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @return the size of the value, or -1 on failure. - */ - int32_t check(const char* kbuf, size_t ksiz) { - class VisitorImpl : public Visitor { - public: - explicit VisitorImpl() : vsiz_(-1) {} - int32_t vsiz() { - return vsiz_; - } - private: - const char* visit_full(const char* kbuf, size_t ksiz, - const char* vbuf, size_t vsiz, size_t* sp) { - vsiz_ = vsiz; - return NOP; - } - size_t vsiz_; - }; - VisitorImpl visitor; - if (!accept(kbuf, ksiz, &visitor, false)) return -1; - int32_t vsiz = visitor.vsiz(); - if (vsiz < 0) { - set_error(_KCCODELINE_, Error::NOREC, "no record"); - return -1; - } - return vsiz; - } - /** - * Check the existence of a record. - * @note Equal to the original DB::check method except that the parameter is std::string. - */ - int32_t check(const std::string& key) { - return check(key.data(), key.size()); - } - /** - * Retrieve the value of a record and remove it atomically. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param sp the pointer to the variable into which the size of the region of the return - * value is assigned. - * @return the pointer to the value region of the corresponding record, or NULL on failure. - * @note If no record corresponds to the key, NULL is returned. Because an additional zero - * code is appended at the end of the region of the return value, the return value can be - * treated as a C-style string. Because the region of the return value is allocated with the - * the new[] operator, it should be released with the delete[] operator when it is no longer - * in use. - */ - char* seize(const char* kbuf, size_t ksiz, size_t* sp) { - _assert_(kbuf && ksiz <= MEMMAXSIZ && sp); - class VisitorImpl : public Visitor { - public: - explicit VisitorImpl() : vbuf_(NULL), vsiz_(0) {} - char* pop(size_t* sp) { - *sp = vsiz_; - return vbuf_; - } - private: - const char* visit_full(const char* kbuf, size_t ksiz, - const char* vbuf, size_t vsiz, size_t* sp) { - vbuf_ = new char[vsiz+1]; - std::memcpy(vbuf_, vbuf, vsiz); - vbuf_[vsiz] = '\0'; - vsiz_ = vsiz; - return REMOVE; - } - char* vbuf_; - size_t vsiz_; - }; - VisitorImpl visitor; - if (!accept(kbuf, ksiz, &visitor, true)) { - *sp = 0; - return NULL; - } - size_t vsiz; - char* vbuf = visitor.pop(&vsiz); - if (!vbuf) { - set_error(_KCCODELINE_, Error::NOREC, "no record"); - *sp = 0; - return NULL; - } - *sp = vsiz; - return vbuf; - } - /** - * Retrieve the value of a record and remove it atomically. - * @note Equal to the original DB::seize method except that the first parameters is the key - * string and the second parameter is a string to contain the result and the return value is - * bool for success. - */ - bool seize(const std::string& key, std::string* value) { - _assert_(value); - class VisitorImpl : public Visitor { - public: - explicit VisitorImpl(std::string* value) : value_(value), ok_(false) {} - bool ok() { - return ok_; - } - private: - const char* visit_full(const char* kbuf, size_t ksiz, - const char* vbuf, size_t vsiz, size_t* sp) { - value_->clear(); - value_->append(vbuf, vsiz); - ok_ = true; - return REMOVE; - } - std::string* value_; - bool ok_; - }; - VisitorImpl visitor(value); - if (!accept(key.data(), key.size(), &visitor, true)) return false; - if (!visitor.ok()) { - set_error(_KCCODELINE_, Error::NOREC, "no record"); - return false; - } - return true; - } - /** - * Store records at once. - * @param recs the records to store. - * @param atomic true to perform all operations atomically, or false for non-atomic operations. - * @return the number of stored records, or -1 on failure. - */ - int64_t set_bulk(const std::map<std::string, std::string>& recs, bool atomic = true) { - _assert_(true); - if (atomic) { - std::vector<std::string> keys; - keys.reserve(recs.size()); - std::map<std::string, std::string>::const_iterator rit = recs.begin(); - std::map<std::string, std::string>::const_iterator ritend = recs.end(); - while (rit != ritend) { - keys.push_back(rit->first); - ++rit; - } - class VisitorImpl : public Visitor { - public: - explicit VisitorImpl(const std::map<std::string, std::string>& recs) : recs_(recs) {} - private: - const char* visit_full(const char* kbuf, size_t ksiz, - const char* vbuf, size_t vsiz, size_t* sp) { - std::map<std::string, std::string>::const_iterator rit = - recs_.find(std::string(kbuf, ksiz)); - if (rit == recs_.end()) return NOP; - *sp = rit->second.size(); - return rit->second.data(); - } - const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { - std::map<std::string, std::string>::const_iterator rit = - recs_.find(std::string(kbuf, ksiz)); - if (rit == recs_.end()) return NOP; - *sp = rit->second.size(); - return rit->second.data(); - } - const std::map<std::string, std::string>& recs_; - }; - VisitorImpl visitor(recs); - if (!accept_bulk(keys, &visitor, true)) return -1; - return keys.size(); - } - std::map<std::string, std::string>::const_iterator rit = recs.begin(); - std::map<std::string, std::string>::const_iterator ritend = recs.end(); - while (rit != ritend) { - if (!set(rit->first.data(), rit->first.size(), rit->second.data(), rit->second.size())) - return -1; - ++rit; - } - return recs.size(); - } - /** - * Remove records at once. - * @param keys the keys of the records to remove. - * @param atomic true to perform all operations atomically, or false for non-atomic operations. - * @return the number of removed records, or -1 on failure. - */ - int64_t remove_bulk(const std::vector<std::string>& keys, bool atomic = true) { - _assert_(true); - if (atomic) { - class VisitorImpl : public Visitor { - public: - explicit VisitorImpl() : cnt_(0) {} - int64_t cnt() const { - return cnt_; - } - private: - const char* visit_full(const char* kbuf, size_t ksiz, - const char* vbuf, size_t vsiz, size_t* sp) { - cnt_++; - return REMOVE; - } - int64_t cnt_; - }; - VisitorImpl visitor; - if (!accept_bulk(keys, &visitor, true)) return -1; - return visitor.cnt(); - } - int64_t cnt = 0; - std::vector<std::string>::const_iterator kit = keys.begin(); - std::vector<std::string>::const_iterator kitend = keys.end(); - while (kit != kitend) { - if (remove(kit->data(), kit->size())) { - cnt++; - } else if (error() != Error::NOREC) { - return -1; - } - ++kit; - } - return cnt; - } - /** - * Retrieve records at once. - * @param keys the keys of the records to retrieve. - * @param recs a string map to contain the retrieved records. - * @param atomic true to perform all operations atomically, or false for non-atomic operations. - * @return the number of retrieved records, or -1 on failure. - */ - int64_t get_bulk(const std::vector<std::string>& keys, - std::map<std::string, std::string>* recs, bool atomic = true) { - _assert_(recs); - if (atomic) { - class VisitorImpl : public Visitor { - public: - explicit VisitorImpl(std::map<std::string, std::string>* recs) : recs_(recs) {} - private: - const char* visit_full(const char* kbuf, size_t ksiz, - const char* vbuf, size_t vsiz, size_t* sp) { - (*recs_)[std::string(kbuf, ksiz)] = std::string(vbuf, vsiz); - return NOP; - } - std::map<std::string, std::string>* recs_; - }; - VisitorImpl visitor(recs); - if (!accept_bulk(keys, &visitor, false)) return -1; - return recs->size(); - } - std::vector<std::string>::const_iterator kit = keys.begin(); - std::vector<std::string>::const_iterator kitend = keys.end(); - while (kit != kitend) { - size_t vsiz; - const char* vbuf = get(kit->data(), kit->size(), &vsiz); - if (vbuf) { - (*recs)[*kit] = std::string(vbuf, vsiz); - delete[] vbuf; - } else if (error() != Error::NOREC) { - return -1; - } - ++kit; - } - return recs->size(); - } - /** - * Dump records into a data stream. - * @param dest the destination stream. - * @param checker a progress checker object. If it is NULL, no checking is performed. - * @return true on success, or false on failure. - */ - bool dump_snapshot(std::ostream* dest, ProgressChecker* checker = NULL) { - _assert_(dest); - if (dest->fail()) { - set_error(_KCCODELINE_, Error::INVALID, "invalid stream"); - return false; - } - class VisitorImpl : public Visitor { - public: - explicit VisitorImpl(std::ostream* dest) : dest_(dest), stack_() {} - private: - const char* visit_full(const char* kbuf, size_t ksiz, - const char* vbuf, size_t vsiz, size_t* sp) { - char* wp = stack_; - *(wp++) = 0x00; - wp += writevarnum(wp, ksiz); - wp += writevarnum(wp, vsiz); - dest_->write(stack_, wp - stack_); - dest_->write(kbuf, ksiz); - dest_->write(vbuf, vsiz); - return NOP; - } - std::ostream* dest_; - char stack_[NUMBUFSIZ*2]; - }; - VisitorImpl visitor(dest); - bool err = false; - dest->write(KCDBSSMAGICDATA, sizeof(KCDBSSMAGICDATA)); - if (iterate(&visitor, false, checker)) { - unsigned char c = 0xff; - dest->write((char*)&c, 1); - if (dest->fail()) { - set_error(_KCCODELINE_, Error::SYSTEM, "stream output error"); - err = true; - } - } else { - err = true; - } - return !err; - } - /** - * Dump records into a file. - * @param dest the path of the destination file. - * @param checker a progress checker object. If it is NULL, no checking is performed. - * @return true on success, or false on failure. - */ - bool dump_snapshot(const std::string& dest, ProgressChecker* checker = NULL) { - _assert_(true); - std::ofstream ofs; - ofs.open(dest.c_str(), std::ios_base::out | std::ios_base::binary | std::ios_base::trunc); - if (!ofs) { - set_error(_KCCODELINE_, Error::NOREPOS, "open failed"); - return false; - } - bool err = false; - if (!dump_snapshot(&ofs, checker)) err = true; - ofs.close(); - if (!ofs) { - set_error(_KCCODELINE_, Error::SYSTEM, "close failed"); - err = true; - } - return !err; - } - /** - * Load records from a data stream. - * @param src the source stream. - * @param checker a progress checker object. If it is NULL, no checking is performed. - * @return true on success, or false on failure. - */ - bool load_snapshot(std::istream* src, ProgressChecker* checker = NULL) { - _assert_(src); - if (src->fail()) { - set_error(_KCCODELINE_, Error::INVALID, "invalid stream"); - return false; - } - char buf[IOBUFSIZ]; - src->read(buf, sizeof(KCDBSSMAGICDATA)); - if (src->fail()) { - set_error(_KCCODELINE_, Error::SYSTEM, "stream input error"); - return false; - } - if (std::memcmp(buf, KCDBSSMAGICDATA, sizeof(KCDBSSMAGICDATA))) { - set_error(_KCCODELINE_, Error::INVALID, "invalid magic data of input stream"); - return false; - } - bool err = false; - if (checker && !checker->check("load_snapshot", "beginning", 0, -1)) { - set_error(_KCCODELINE_, Error::LOGIC, "checker failed"); - err = true; - } - int64_t curcnt = 0; - while (!err) { - int32_t c = src->get(); - if (src->fail()) { - set_error(_KCCODELINE_, Error::SYSTEM, "stream input error"); - err = true; - break; - } - if (c == 0xff) break; - if (c == 0x00) { - size_t ksiz = 0; - do { - c = src->get(); - ksiz = (ksiz << 7) + (c & 0x7f); - } while (c >= 0x80); - size_t vsiz = 0; - do { - c = src->get(); - vsiz = (vsiz << 7) + (c & 0x7f); - } while (c >= 0x80); - size_t rsiz = ksiz + vsiz; - char* rbuf = rsiz > sizeof(buf) ? new char[rsiz] : buf; - src->read(rbuf, ksiz + vsiz); - if (src->fail()) { - set_error(_KCCODELINE_, Error::SYSTEM, "stream input error"); - err = true; - if (rbuf != buf) delete[] rbuf; - break; - } - if (!set(rbuf, ksiz, rbuf + ksiz, vsiz)) { - err = true; - if (rbuf != buf) delete[] rbuf; - break; - } - if (rbuf != buf) delete[] rbuf; - } else { - set_error(_KCCODELINE_, Error::INVALID, "invalid magic data of input stream"); - err = true; - break; - } - curcnt++; - if (checker && !checker->check("load_snapshot", "processing", curcnt, -1)) { - set_error(_KCCODELINE_, Error::LOGIC, "checker failed"); - err = true; - break; - } - } - if (checker && !checker->check("load_snapshot", "ending", -1, -1)) { - set_error(_KCCODELINE_, Error::LOGIC, "checker failed"); - err = true; - } - return !err; - } - /** - * Load records from a file. - * @param src the path of the source file. - * @param checker a progress checker object. If it is NULL, no checking is performed. - * @return true on success, or false on failure. - */ - bool load_snapshot(const std::string& src, ProgressChecker* checker = NULL) { - _assert_(true); - std::ifstream ifs; - ifs.open(src.c_str(), std::ios_base::in | std::ios_base::binary); - if (!ifs) { - set_error(_KCCODELINE_, Error::NOREPOS, "open failed"); - return false; - } - bool err = false; - if (!load_snapshot(&ifs, checker)) err = true; - ifs.close(); - if (ifs.bad()) { - set_error(_KCCODELINE_, Error::SYSTEM, "close failed"); - return false; - } - return !err; - } - /** - * Create a cursor object. - * @return the return value is the created cursor object. - * @note Because the object of the return value is allocated by the constructor, it should be - * released with the delete operator when it is no longer in use. - */ - virtual Cursor* cursor() = 0; - /** - * Write a log message. - * @param file the file name of the program source code. - * @param line the line number of the program source code. - * @param func the function name of the program source code. - * @param kind the kind of the event. Logger::DEBUG for debugging, Logger::INFO for normal - * information, Logger::WARN for warning, and Logger::ERROR for fatal error. - * @param message the supplement message. - */ - virtual void log(const char* file, int32_t line, const char* func, Logger::Kind kind, - const char* message) = 0; - /** - * Set the internal logger. - * @param logger the logger object. - * @param kinds kinds of logged messages by bitwise-or: Logger::DEBUG for debugging, - * Logger::INFO for normal information, Logger::WARN for warning, and Logger::ERROR for fatal - * error. - * @return true on success, or false on failure. - */ - virtual bool tune_logger(Logger* logger, uint32_t kinds = Logger::WARN | Logger::ERROR) = 0; - /** - * Set the internal meta operation trigger. - * @param trigger the trigger object. - * @return true on success, or false on failure. - */ - virtual bool tune_meta_trigger(MetaTrigger* trigger) = 0; - /** - * Get the class name of a database type. - * @param type the database type. - * @return the string of the type name. - */ - static const char* typecname(uint32_t type) { - _assert_(true); - switch (type) { - case TYPEVOID: return "void"; - case TYPEPHASH: return "ProtoHashDB"; - case TYPEPTREE: return "ProtoTreeDB"; - case TYPESTASH: return "StashDB"; - case TYPECACHE: return "CacheDB"; - case TYPEGRASS: return "GrassDB"; - case TYPEHASH: return "HashDB"; - case TYPETREE: return "TreeDB"; - case TYPEDIR: return "DirDB"; - case TYPEFOREST: return "ForestDB"; - case TYPEMISC: return "misc"; - } - return "unknown"; - } - /** - * Get the description string of a database type. - * @param type the database type. - * @return the string of the type name. - */ - static const char* typestring(uint32_t type) { - _assert_(true); - switch (type) { - case TYPEVOID: return "void"; - case TYPEPHASH: return "prototype hash database"; - case TYPEPTREE: return "prototype tree database"; - case TYPESTASH: return "stash database"; - case TYPECACHE: return "cache hash database"; - case TYPEGRASS: return "cache tree database"; - case TYPEHASH: return "file hash database"; - case TYPETREE: return "file tree database"; - case TYPEDIR: return "directory hash database"; - case TYPEFOREST: return "directory tree database"; - case TYPEMISC: return "miscellaneous database"; - } - return "unknown"; - } -}; - - -} // common namespace - -#endif // duplication check - -// END OF FILE |