summaryrefslogtreecommitdiff
path: root/plugins/Dbx_kyoto/src/kyotocabinet/kcdb.h
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/Dbx_kyoto/src/kyotocabinet/kcdb.h')
-rw-r--r--plugins/Dbx_kyoto/src/kyotocabinet/kcdb.h2520
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