| kccachedb.h | | kccachedb.h | |
| | | | |
| skipping to change at line 43 | | skipping to change at line 43 | |
| * @note This class is a concrete class to operate a hash database on memor
y. This class can be | | * @note This class is a concrete class to operate a hash database on memor
y. This class can be | |
| * inherited but overwriting methods is forbidden. Before every database o
peration, it is | | * inherited but overwriting methods is forbidden. Before every database o
peration, it is | |
| * necessary to call the CacheDB::open method in order to open a database f
ile and connect the | | * necessary to call the CacheDB::open method in order to open a database f
ile and connect the | |
| * database object to it. To avoid data missing or corruption, it is impor
tant to close every | | * database object to it. To avoid data missing or corruption, it is impor
tant to close every | |
| * database file by the CacheDB::close method when the database is no longe
r in use. It is | | * database file by the CacheDB::close method when the database is no longe
r in use. It is | |
| * forbidden for multible database objects in a process to open the same da
tabase at the same | | * forbidden for multible database objects in a process to open the same da
tabase at the same | |
| * time. It is forbidden to share a database object with child processes. | | * time. It is forbidden to share a database object with child processes. | |
| */ | | */ | |
| class CacheDB : public BasicDB { | | class CacheDB : public BasicDB { | |
| friend class PlantDB<CacheDB, BasicDB::TYPEGRASS>; | | friend class PlantDB<CacheDB, BasicDB::TYPEGRASS>; | |
|
| public: | | public: | |
| class Cursor; | | class Cursor; | |
|
| private: | | private: | |
| struct Record; | | struct Record; | |
| struct TranLog; | | struct TranLog; | |
| struct Slot; | | struct Slot; | |
| class Repeater; | | class Repeater; | |
| class Setter; | | class Setter; | |
| class Remover; | | class Remover; | |
| class ScopedVisitor; | | class ScopedVisitor; | |
| /** An alias of list of cursors. */ | | /** An alias of list of cursors. */ | |
| typedef std::list<Cursor*> CursorList; | | typedef std::list<Cursor*> CursorList; | |
| /** An alias of list of transaction logs. */ | | /** An alias of list of transaction logs. */ | |
| | | | |
| skipping to change at line 71 | | skipping to change at line 71 | |
| /** The mininum number of buckets to use mmap. */ | | /** The mininum number of buckets to use mmap. */ | |
| static const size_t ZMAPBNUM = 32768; | | static const size_t ZMAPBNUM = 32768; | |
| /** The maximum size of each key. */ | | /** The maximum size of each key. */ | |
| static const uint32_t KSIZMAX = 0xfffff; | | static const uint32_t KSIZMAX = 0xfffff; | |
| /** The size of the record buffer. */ | | /** The size of the record buffer. */ | |
| static const size_t RECBUFSIZ = 48; | | static const size_t RECBUFSIZ = 48; | |
| /** The size of the opaque buffer. */ | | /** The size of the opaque buffer. */ | |
| static const size_t OPAQUESIZ = 16; | | static const size_t OPAQUESIZ = 16; | |
| /** The threshold of busy loop and sleep for locking. */ | | /** The threshold of busy loop and sleep for locking. */ | |
| static const uint32_t LOCKBUSYLOOP = 8192; | | static const uint32_t LOCKBUSYLOOP = 8192; | |
|
| public: | | public: | |
| /** | | /** | |
| * Cursor to indicate a record. | | * Cursor to indicate a record. | |
| */ | | */ | |
| class Cursor : public BasicDB::Cursor { | | class Cursor : public BasicDB::Cursor { | |
| friend class CacheDB; | | friend class CacheDB; | |
|
| public: | | public: | |
| /** | | /** | |
| * Constructor. | | * Constructor. | |
| * @param db the container database object. | | * @param db the container database object. | |
| */ | | */ | |
| explicit Cursor(CacheDB* db) : db_(db), sidx_(-1), rec_(NULL) { | | explicit Cursor(CacheDB* db) : db_(db), sidx_(-1), rec_(NULL) { | |
| _assert_(db); | | _assert_(db); | |
| ScopedSpinRWLock lock(&db_->mlock_, true); | | ScopedSpinRWLock lock(&db_->mlock_, true); | |
| db_->curs_.push_back(this); | | db_->curs_.push_back(this); | |
| } | | } | |
| /** | | /** | |
| | | | |
| skipping to change at line 320 | | skipping to change at line 320 | |
| return false; | | return false; | |
| } | | } | |
| /** | | /** | |
| * Get the database object. | | * Get the database object. | |
| * @return the database object. | | * @return the database object. | |
| */ | | */ | |
| CacheDB* db() { | | CacheDB* db() { | |
| _assert_(true); | | _assert_(true); | |
| return db_; | | return db_; | |
| } | | } | |
|
| private: | | private: | |
| /** | | /** | |
| * Step the cursor to the next record. | | * Step the cursor to the next record. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool step_impl() { | | bool step_impl() { | |
| _assert_(true); | | _assert_(true); | |
| rec_ = rec_->next; | | rec_ = rec_->next; | |
| if (!rec_) { | | if (!rec_) { | |
| for (int32_t i = sidx_ + 1; i < SLOTNUM; i++) { | | for (int32_t i = sidx_ + 1; i < SLOTNUM; i++) { | |
| Slot* slot = db_->slots_ + i; | | Slot* slot = db_->slots_ + i; | |
| | | | |
| skipping to change at line 374 | | skipping to change at line 374 | |
| * Status flags. | | * Status flags. | |
| */ | | */ | |
| enum Flag { | | enum Flag { | |
| FOPEN = 1 << 0, ///< dummy for compatibility | | FOPEN = 1 << 0, ///< dummy for compatibility | |
| FFATAL = 1 << 1 ///< dummy for compatibility | | FFATAL = 1 << 1 ///< dummy for compatibility | |
| }; | | }; | |
| /** | | /** | |
| * Default constructor. | | * Default constructor. | |
| */ | | */ | |
| explicit CacheDB() : | | explicit CacheDB() : | |
|
| mlock_(), flock_(), error_(), logger_(NULL), logkinds_(0), mtrigger_(NU | | mlock_(), flock_(), error_(), logger_(NULL), logkinds_(0), mtrigger_( | |
| LL), | | NULL), | |
| omode_(0), curs_(), path_(""), type_(TYPECACHE), | | omode_(0), curs_(), path_(""), type_(TYPECACHE), | |
| opts_(0), bnum_(DEFBNUM), capcnt_(-1), capsiz_(-1), | | opts_(0), bnum_(DEFBNUM), capcnt_(-1), capsiz_(-1), | |
| opaque_(), embcomp_(ZLIBRAWCOMP), comp_(NULL), slots_(), tran_(false) { | | opaque_(), embcomp_(ZLIBRAWCOMP), comp_(NULL), slots_(), tran_(false) | |
| | | { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| * @note If the database is not closed, it is closed implicitly. | | * @note If the database is not closed, it is closed implicitly. | |
| */ | | */ | |
| virtual ~CacheDB() { | | virtual ~CacheDB() { | |
| _assert_(true); | | _assert_(true); | |
| if (omode_ != 0) close(); | | if (omode_ != 0) close(); | |
| if (!curs_.empty()) { | | if (!curs_.empty()) { | |
| | | | |
| skipping to change at line 589 | | skipping to change at line 589 | |
| * @param func the function name of the program source code. | | * @param func the function name of the program source code. | |
| * @param code an error code. | | * @param code an error code. | |
| * @param message a supplement message. | | * @param message a supplement message. | |
| */ | | */ | |
| void set_error(const char* file, int32_t line, const char* func, | | void set_error(const char* file, int32_t line, const char* func, | |
| Error::Code code, const char* message) { | | Error::Code code, const char* message) { | |
| _assert_(file && line > 0 && func && message); | | _assert_(file && line > 0 && func && message); | |
| error_->set(code, message); | | error_->set(code, message); | |
| if (logger_) { | | if (logger_) { | |
| Logger::Kind kind = code == Error::BROKEN || code == Error::SYSTEM ? | | Logger::Kind kind = code == Error::BROKEN || code == Error::SYSTEM ? | |
|
| Logger::ERROR : Logger::INFO; | | Logger::ERROR : Logger::INFO; | |
| if (kind & logkinds_) | | if (kind & logkinds_) | |
| report(file, line, func, kind, "%d: %s: %s", code, Error::codename(
code), message); | | report(file, line, func, kind, "%d: %s: %s", code, Error::codename(
code), message); | |
| } | | } | |
| } | | } | |
| /** | | /** | |
| * Open a database file. | | * Open a database file. | |
| * @param path the path of a database file. | | * @param path the path of a database file. | |
| * @param mode the connection mode. CacheDB::OWRITER as a writer, CacheD
B::OREADER as a | | * @param mode the connection mode. CacheDB::OWRITER as a writer, CacheD
B::OREADER as a | |
| * reader. The following may be added to the writer mode by bitwise-or:
CacheDB::OCREATE, | | * reader. The following may be added to the writer mode by bitwise-or:
CacheDB::OCREATE, | |
| * which means it creates a new database if the file does not exist, Cach
eDB::OTRUNCATE, which | | * which means it creates a new database if the file does not exist, Cach
eDB::OTRUNCATE, which | |
| | | | |
| skipping to change at line 1056 | | skipping to change at line 1056 | |
| if (omode_ == 0) { | | if (omode_ == 0) { | |
| set_error(_KCCODELINE_, Error::INVALID, "not opened"); | | set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |
| return false; | | return false; | |
| } | | } | |
| if (!(omode_ & OWRITER)) { | | if (!(omode_ & OWRITER)) { | |
| set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | | set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | |
| return false; | | return false; | |
| } | | } | |
| return true; | | return true; | |
| } | | } | |
|
| protected: | | protected: | |
| /** | | /** | |
| * Report a message for debugging. | | * Report a message for debugging. | |
| * @param file the file name of the program source code. | | * @param file the file name of the program source code. | |
| * @param line the line number 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 func the function name of the program source code. | |
| * @param kind the kind of the event. Logger::DEBUG for debugging, Logge
r::INFO for normal | | * @param kind the kind of the event. Logger::DEBUG for debugging, Logge
r::INFO for normal | |
| * information, Logger::WARN for warning, and Logger::ERROR for fatal err
or. | | * information, Logger::WARN for warning, and Logger::ERROR for fatal err
or. | |
| * @param format the printf-like format string. | | * @param format the printf-like format string. | |
| * @param ... used according to the format string. | | * @param ... used according to the format string. | |
| */ | | */ | |
| | | | |
| skipping to change at line 1262 | | skipping to change at line 1262 | |
| */ | | */ | |
| bool reorganized() { | | bool reorganized() { | |
| _assert_(true); | | _assert_(true); | |
| ScopedSpinRWLock lock(&mlock_, false); | | ScopedSpinRWLock lock(&mlock_, false); | |
| if (omode_ == 0) { | | if (omode_ == 0) { | |
| set_error(_KCCODELINE_, Error::INVALID, "not opened"); | | set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |
| return false; | | return false; | |
| } | | } | |
| return false; | | return false; | |
| } | | } | |
|
| private: | | private: | |
| /** | | /** | |
| * Set the power of the alignment of record size. | | * Set the power of the alignment of record size. | |
| * @note This is a dummy implementation for compatibility. | | * @note This is a dummy implementation for compatibility. | |
| */ | | */ | |
| bool tune_alignment(int8_t apow) { | | bool tune_alignment(int8_t apow) { | |
| return true; | | return true; | |
| } | | } | |
| /** | | /** | |
| * Set the power of the capacity of the free block pool. | | * Set the power of the capacity of the free block pool. | |
| * @note This is a dummy implementation for compatibility. | | * @note This is a dummy implementation for compatibility. | |
| | | | |
| skipping to change at line 1340 | | skipping to change at line 1340 | |
| int64_t msiz() { | | int64_t msiz() { | |
| return 0; | | return 0; | |
| } | | } | |
| /** | | /** | |
| * Get the unit step number of auto defragmentation. | | * Get the unit step number of auto defragmentation. | |
| * @note This is a dummy implementation for compatibility. | | * @note This is a dummy implementation for compatibility. | |
| */ | | */ | |
| int64_t dfunit() { | | int64_t dfunit() { | |
| return 0; | | return 0; | |
| } | | } | |
|
| private: | | private: | |
| /** | | /** | |
| * Record data. | | * Record data. | |
| */ | | */ | |
| struct Record { | | struct Record { | |
| uint32_t ksiz; ///< size of the key | | uint32_t ksiz; ///< size of the key | |
| uint32_t vsiz; ///< size of the value | | uint32_t vsiz; ///< size of the value | |
| Record* left; ///< left child record | | Record* left; ///< left child record | |
| Record* right; ///< right child record | | Record* right; ///< right child record | |
| Record* prev; ///< privious record | | Record* prev; ///< privious record | |
| Record* next; ///< next record | | Record* next; ///< next record | |
| }; | | }; | |
| /** | | /** | |
| * Transaction log. | | * Transaction log. | |
| */ | | */ | |
| struct TranLog { | | struct TranLog { | |
| bool full; ///< flag whether full | | bool full; ///< flag whether full | |
| std::string key; ///< old key | | std::string key; ///< old key | |
| std::string value; ///< old value | | std::string value; ///< old value | |
| /** constructor for a full record */ | | /** constructor for a full record */ | |
| explicit TranLog(const char* kbuf, size_t ksiz, const char* vbuf, size_
t vsiz) : | | explicit TranLog(const char* kbuf, size_t ksiz, const char* vbuf, size_
t vsiz) : | |
|
| full(true), key(kbuf, ksiz), value(vbuf, vsiz) { | | full(true), key(kbuf, ksiz), value(vbuf, vsiz) { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| /** constructor for an empty record */ | | /** constructor for an empty record */ | |
| explicit TranLog(const char* kbuf, size_t ksiz) : full(false), key(kbuf
, ksiz) { | | explicit TranLog(const char* kbuf, size_t ksiz) : full(false), key(kbuf
, ksiz) { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| }; | | }; | |
| /** | | /** | |
| * Slot table. | | * Slot table. | |
| */ | | */ | |
| | | | |
| skipping to change at line 1389 | | skipping to change at line 1389 | |
| Record* last; ///< last record | | Record* last; ///< last record | |
| size_t count; ///< number of records | | size_t count; ///< number of records | |
| size_t size; ///< total size of records | | size_t size; ///< total size of records | |
| TranLogList trlogs; ///< transaction logs | | TranLogList trlogs; ///< transaction logs | |
| size_t trsize; ///< size before transaction | | size_t trsize; ///< size before transaction | |
| }; | | }; | |
| /** | | /** | |
| * Repeating visitor. | | * Repeating visitor. | |
| */ | | */ | |
| class Repeater : public Visitor { | | class Repeater : public Visitor { | |
|
| public: | | public: | |
| /** constructor */ | | /** constructor */ | |
| explicit Repeater(const char* vbuf, size_t vsiz) : vbuf_(vbuf), vsiz_(v
siz) {} | | explicit Repeater(const char* vbuf, size_t vsiz) : vbuf_(vbuf), vsiz_(v
siz) {} | |
|
| private: | | private: | |
| /** process a full record */ | | /** process a full record */ | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp
); | | _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp
); | |
| *sp = vsiz_; | | *sp = vsiz_; | |
| return vbuf_; | | return vbuf_; | |
| } | | } | |
| const char* vbuf_; ///< region of the value | | const char* vbuf_; ///< region of the value | |
| size_t vsiz_; ///< size of the value | | size_t vsiz_; ///< size of the value | |
| }; | | }; | |
| /** | | /** | |
| * Setting visitor. | | * Setting visitor. | |
| */ | | */ | |
| class Setter : public Visitor { | | class Setter : public Visitor { | |
|
| public: | | public: | |
| /** constructor */ | | /** constructor */ | |
| explicit Setter(const char* vbuf, size_t vsiz) : vbuf_(vbuf), vsiz_(vsi
z) {} | | explicit Setter(const char* vbuf, size_t vsiz) : vbuf_(vbuf), vsiz_(vsi
z) {} | |
|
| private: | | private: | |
| /** process a full record */ | | /** process a full record */ | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp
); | | _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp
); | |
| *sp = vsiz_; | | *sp = vsiz_; | |
| return vbuf_; | | return vbuf_; | |
| } | | } | |
| /** process an empty record */ | | /** process an empty record */ | |
| const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { | | const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { | |
| _assert_(kbuf && ksiz <= MEMMAXSIZ && sp); | | _assert_(kbuf && ksiz <= MEMMAXSIZ && sp); | |
| *sp = vsiz_; | | *sp = vsiz_; | |
| return vbuf_; | | return vbuf_; | |
| } | | } | |
| const char* vbuf_; ///< region of the value | | const char* vbuf_; ///< region of the value | |
| size_t vsiz_; ///< size of the value | | size_t vsiz_; ///< size of the value | |
| }; | | }; | |
| /** | | /** | |
| * Removing visitor. | | * Removing visitor. | |
| */ | | */ | |
| class Remover : public Visitor { | | class Remover : public Visitor { | |
|
| private: | | private: | |
| /** visit a record */ | | /** visit a record */ | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp
); | | _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp
); | |
| return REMOVE; | | return REMOVE; | |
| } | | } | |
| }; | | }; | |
| /** | | /** | |
| * Scoped visitor. | | * Scoped visitor. | |
| */ | | */ | |
| class ScopedVisitor { | | class ScopedVisitor { | |
|
| public: | | public: | |
| /** constructor */ | | /** constructor */ | |
| explicit ScopedVisitor(Visitor* visitor) : visitor_(visitor) { | | explicit ScopedVisitor(Visitor* visitor) : visitor_(visitor) { | |
| _assert_(visitor); | | _assert_(visitor); | |
| visitor_->visit_before(); | | visitor_->visit_before(); | |
| } | | } | |
| /** destructor */ | | /** destructor */ | |
| ~ScopedVisitor() { | | ~ScopedVisitor() { | |
| _assert_(true); | | _assert_(true); | |
| visitor_->visit_after(); | | visitor_->visit_after(); | |
| } | | } | |
|
| private: | | private: | |
| Visitor* visitor_; ///< visitor | | Visitor* visitor_; ///< visitor | |
| }; | | }; | |
| /** | | /** | |
| * Accept a visitor to a record. | | * Accept a visitor to a record. | |
| * @param slot the slot of the record. | | * @param slot the slot of the record. | |
| * @param hash the hash value of the key. | | * @param hash the hash value of the key. | |
| * @param kbuf the pointer to the key region. | | * @param kbuf the pointer to the key region. | |
| * @param ksiz the size of the key region. | | * @param ksiz the size of the key region. | |
| * @param visitor a visitor object. | | * @param visitor a visitor object. | |
| * @param comp the data compressor. | | * @param comp the data compressor. | |
| | | | |
| skipping to change at line 1798 | | skipping to change at line 1798 | |
| return hashmurmur(kbuf, ksiz); | | return hashmurmur(kbuf, ksiz); | |
| } | | } | |
| /** | | /** | |
| * Fold a hash value into a small number. | | * Fold a hash value into a small number. | |
| * @param hash the hash number. | | * @param hash the hash number. | |
| * @return the result number. | | * @return the result number. | |
| */ | | */ | |
| uint32_t fold_hash(uint64_t hash) { | | uint32_t fold_hash(uint64_t hash) { | |
| _assert_(true); | | _assert_(true); | |
| return ((hash & 0xffffffff00000000ULL) >> 32) ^ ((hash & 0x0000ffffffff
0000ULL) >> 16) ^ | | return ((hash & 0xffffffff00000000ULL) >> 32) ^ ((hash & 0x0000ffffffff
0000ULL) >> 16) ^ | |
|
| ((hash & 0x000000000000ffffULL) << 16) ^ ((hash & 0x00000000ffff0000U
LL) >> 0); | | ((hash & 0x000000000000ffffULL) << 16) ^ ((hash & 0x00000000ffff000
0ULL) >> 0); | |
| } | | } | |
| /** | | /** | |
| * Compare two keys in lexical order. | | * Compare two keys in lexical order. | |
| * @param abuf one key. | | * @param abuf one key. | |
| * @param asiz the size of the one key. | | * @param asiz the size of the one key. | |
| * @param bbuf the other key. | | * @param bbuf the other key. | |
| * @param bsiz the size of the other key. | | * @param bsiz the size of the other key. | |
| * @return positive if the former is big, or negative if the latter is bi
g, or 0 if both are | | * @return positive if the former is big, or negative if the latter is bi
g, or 0 if both are | |
| * equivalent. | | * equivalent. | |
| */ | | */ | |
| | | | |
End of changes. 19 change blocks. |
| 23 lines changed or deleted | | 24 lines changed or added | |
|
| kcdb.h | | kcdb.h | |
| | | | |
| skipping to change at line 35 | | skipping to change at line 35 | |
| | | | |
| #define KCDBSSMAGICDATA "KCSS\n" ///< The magic data of the snapsho
t file | | #define KCDBSSMAGICDATA "KCSS\n" ///< The magic data of the snapsho
t file | |
| | | | |
| namespace kyotocabinet { // common namespace | | namespace kyotocabinet { // common namespace | |
| | | | |
| /** | | /** | |
| * Interface of database abstraction. | | * Interface of database abstraction. | |
| * @note This class is an abstract class to prescribe the interface of reco
rd access. | | * @note This class is an abstract class to prescribe the interface of reco
rd access. | |
| */ | | */ | |
| class DB { | | class DB { | |
|
| public: | | public: | |
| /** | | /** | |
| * Interface to access a record. | | * Interface to access a record. | |
| */ | | */ | |
| class Visitor { | | class Visitor { | |
|
| public: | | public: | |
| /** Special pointer for no operation. */ | | /** Special pointer for no operation. */ | |
| static const char* const NOP; | | static const char* const NOP; | |
| /** Special pointer to remove the record. */ | | /** Special pointer to remove the record. */ | |
| static const char* const REMOVE; | | static const char* const REMOVE; | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| */ | | */ | |
| virtual ~Visitor() { | | virtual ~Visitor() { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| | | | |
| skipping to change at line 97 | | skipping to change at line 97 | |
| * Postprocess the main operations. | | * Postprocess the main operations. | |
| */ | | */ | |
| virtual void visit_after() { | | virtual void visit_after() { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| }; | | }; | |
| /** | | /** | |
| * Interface of cursor to indicate a record. | | * Interface of cursor to indicate a record. | |
| */ | | */ | |
| class Cursor { | | class Cursor { | |
|
| public: | | public: | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| */ | | */ | |
| virtual ~Cursor() { | | virtual ~Cursor() { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| /** | | /** | |
| * Accept a visitor to the current record. | | * Accept a visitor to the current record. | |
| * @param visitor a visitor object. | | * @param visitor a visitor object. | |
| * @param writable true for writable operation, or false for read-only
operation. | | * @param writable true for writable operation, or false for read-only
operation. | |
| | | | |
| skipping to change at line 463 | | skipping to change at line 463 | |
| * @note This class is an abstract class to prescribe the interface of file
operations and | | * @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 met
hods is forbidden. | | * provide mix-in methods. This class can be inherited but overwriting met
hods is forbidden. | |
| * Before every database operation, it is necessary to call the BasicDB::op
en method in order to | | * Before every database operation, it is necessary to call the BasicDB::op
en method in order to | |
| * open a database file and connect the database object to it. To avoid da
ta missing or | | * open a database file and connect the database object to it. To avoid da
ta missing or | |
| * corruption, it is important to close every database file by the BasicDB:
:close method when the | | * 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 obj
ects in a process to | | * database is no longer in use. It is forbidden for multible database obj
ects in a process to | |
| * open the same database at the same time. It is forbidden to share a dat
abase object with | | * open the same database at the same time. It is forbidden to share a dat
abase object with | |
| * child processes. | | * child processes. | |
| */ | | */ | |
| class BasicDB : public DB { | | class BasicDB : public DB { | |
|
| public: | | public: | |
| class Cursor; | | class Cursor; | |
| class Error; | | class Error; | |
| class ProgressChecker; | | class ProgressChecker; | |
| class FileProcessor; | | class FileProcessor; | |
| class Logger; | | class Logger; | |
| class MetaTrigger; | | class MetaTrigger; | |
|
| private: | | private: | |
| /** The size of the IO buffer. */ | | /** The size of the IO buffer. */ | |
| static const size_t IOBUFSIZ = 8192; | | static const size_t IOBUFSIZ = 8192; | |
|
| public: | | public: | |
| /** | | /** | |
| * Database types. | | * Database types. | |
| */ | | */ | |
| enum Type { | | enum Type { | |
| TYPEVOID = 0x00, ///< void database | | TYPEVOID = 0x00, ///< void database | |
| TYPEPHASH = 0x10, ///< prototype hash database | | TYPEPHASH = 0x10, ///< prototype hash database | |
| TYPEPTREE = 0x11, ///< prototype tree database | | TYPEPTREE = 0x11, ///< prototype tree database | |
| TYPESTASH = 0x18, ///< stash database | | TYPESTASH = 0x18, ///< stash database | |
| TYPECACHE = 0x20, ///< cache hash database | | TYPECACHE = 0x20, ///< cache hash database | |
| TYPEGRASS = 0x21, ///< cache tree database | | TYPEGRASS = 0x21, ///< cache tree database | |
| TYPEHASH = 0x30, ///< file hash database | | TYPEHASH = 0x30, ///< file hash database | |
| TYPETREE = 0x31, ///< file tree database | | TYPETREE = 0x31, ///< file tree database | |
| TYPEDIR = 0x40, ///< directory hash database | | TYPEDIR = 0x40, ///< directory hash database | |
| TYPEFOREST = 0x41, ///< directory tree database | | TYPEFOREST = 0x41, ///< directory tree database | |
| TYPEMISC = 0x80 ///< miscellaneous database | | TYPEMISC = 0x80 ///< miscellaneous database | |
| }; | | }; | |
| /** | | /** | |
| * Interface of cursor to indicate a record. | | * Interface of cursor to indicate a record. | |
| */ | | */ | |
| class Cursor : public DB::Cursor { | | class Cursor : public DB::Cursor { | |
|
| public: | | public: | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| */ | | */ | |
| virtual ~Cursor() { | | virtual ~Cursor() { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| /** | | /** | |
| * Set the value of the current record. | | * Set the value of the current record. | |
| * @param vbuf the pointer to the value region. | | * @param vbuf the pointer to the value region. | |
| * @param vsiz the size of 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. | | * @param step true to move the cursor to the next record, or false for
no move. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool set_value(const char* vbuf, size_t vsiz, bool step = false) { | | bool set_value(const char* vbuf, size_t vsiz, bool step = false) { | |
| _assert_(vbuf && vsiz <= MEMMAXSIZ); | | _assert_(vbuf && vsiz <= MEMMAXSIZ); | |
| class VisitorImpl : public Visitor { | | class VisitorImpl : public Visitor { | |
|
| public: | | public: | |
| explicit VisitorImpl(const char* vbuf, size_t vsiz) : | | explicit VisitorImpl(const char* vbuf, size_t vsiz) : | |
|
| vbuf_(vbuf), vsiz_(vsiz), ok_(false) {} | | vbuf_(vbuf), vsiz_(vsiz), ok_(false) {} | |
| bool ok() const { | | bool ok() const { | |
| return ok_; | | return ok_; | |
| } | | } | |
|
| private: | | private: | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| ok_ = true; | | ok_ = true; | |
| *sp = vsiz_; | | *sp = vsiz_; | |
| return vbuf_; | | return vbuf_; | |
| } | | } | |
| const char* vbuf_; | | const char* vbuf_; | |
| size_t vsiz_; | | size_t vsiz_; | |
| bool ok_; | | bool ok_; | |
| }; | | }; | |
| | | | |
| skipping to change at line 551 | | skipping to change at line 551 | |
| } | | } | |
| /** | | /** | |
| * Remove the current record. | | * Remove the current record. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| * @note If no record corresponds to the key, false is returned. The c
ursor is moved to the | | * @note If no record corresponds to the key, false is returned. The c
ursor is moved to the | |
| * next record implicitly. | | * next record implicitly. | |
| */ | | */ | |
| bool remove() { | | bool remove() { | |
| _assert_(true); | | _assert_(true); | |
| class VisitorImpl : public Visitor { | | class VisitorImpl : public Visitor { | |
|
| public: | | public: | |
| explicit VisitorImpl() : ok_(false) {} | | explicit VisitorImpl() : ok_(false) {} | |
| bool ok() const { | | bool ok() const { | |
| return ok_; | | return ok_; | |
| } | | } | |
|
| private: | | private: | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| ok_ = true; | | ok_ = true; | |
| return REMOVE; | | return REMOVE; | |
| } | | } | |
| bool ok_; | | bool ok_; | |
| }; | | }; | |
| VisitorImpl visitor; | | VisitorImpl visitor; | |
| if (!accept(&visitor, true, false)) return false; | | if (!accept(&visitor, true, false)) return false; | |
| if (!visitor.ok()) return false; | | if (!visitor.ok()) return false; | |
| | | | |
| skipping to change at line 584 | | skipping to change at line 584 | |
| * @return the pointer to the key region of the current record, or NULL
on failure. | | * @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 ad
ditional zero | | * @note If the cursor is invalidated, NULL is returned. Because an ad
ditional zero | |
| * code is appended at the end of the region of the return value, the r
eturn value can be | | * code is appended at the end of the region of the return value, the r
eturn value can be | |
| * treated as a C-style string. Because the region of the return value
is allocated with the | | * 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 | | * the new[] operator, it should be released with the delete[] operator
when it is no longer | |
| * in use. | | * in use. | |
| */ | | */ | |
| char* get_key(size_t* sp, bool step = false) { | | char* get_key(size_t* sp, bool step = false) { | |
| _assert_(sp); | | _assert_(sp); | |
| class VisitorImpl : public Visitor { | | class VisitorImpl : public Visitor { | |
|
| public: | | public: | |
| explicit VisitorImpl() : kbuf_(NULL), ksiz_(0) {} | | explicit VisitorImpl() : kbuf_(NULL), ksiz_(0) {} | |
| char* pop(size_t* sp) { | | char* pop(size_t* sp) { | |
| *sp = ksiz_; | | *sp = ksiz_; | |
| return kbuf_; | | return kbuf_; | |
| } | | } | |
| void clear() { | | void clear() { | |
| delete[] kbuf_; | | delete[] kbuf_; | |
| } | | } | |
|
| private: | | private: | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| kbuf_ = new char[ksiz+1]; | | kbuf_ = new char[ksiz+1]; | |
| std::memcpy(kbuf_, kbuf, ksiz); | | std::memcpy(kbuf_, kbuf, ksiz); | |
| kbuf_[ksiz] = '\0'; | | kbuf_[ksiz] = '\0'; | |
| ksiz_ = ksiz; | | ksiz_ = ksiz; | |
| return NOP; | | return NOP; | |
| } | | } | |
| char* kbuf_; | | char* kbuf_; | |
| size_t ksiz_; | | size_t ksiz_; | |
| | | | |
| skipping to change at line 650 | | skipping to change at line 650 | |
| * @return the pointer to the value region of the current record, or NU
LL on failure. | | * @return the pointer to the value region of the current record, or NU
LL on failure. | |
| * @note If the cursor is invalidated, NULL is returned. Because an ad
ditional zero | | * @note If the cursor is invalidated, NULL is returned. Because an ad
ditional zero | |
| * code is appended at the end of the region of the return value, the r
eturn value can be | | * code is appended at the end of the region of the return value, the r
eturn value can be | |
| * treated as a C-style string. Because the region of the return value
is allocated with the | | * 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 | | * the new[] operator, it should be released with the delete[] operator
when it is no longer | |
| * in use. | | * in use. | |
| */ | | */ | |
| char* get_value(size_t* sp, bool step = false) { | | char* get_value(size_t* sp, bool step = false) { | |
| _assert_(sp); | | _assert_(sp); | |
| class VisitorImpl : public Visitor { | | class VisitorImpl : public Visitor { | |
|
| public: | | public: | |
| explicit VisitorImpl() : vbuf_(NULL), vsiz_(0) {} | | explicit VisitorImpl() : vbuf_(NULL), vsiz_(0) {} | |
| char* pop(size_t* sp) { | | char* pop(size_t* sp) { | |
| *sp = vsiz_; | | *sp = vsiz_; | |
| return vbuf_; | | return vbuf_; | |
| } | | } | |
| void clear() { | | void clear() { | |
| delete[] vbuf_; | | delete[] vbuf_; | |
| } | | } | |
|
| private: | | private: | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| vbuf_ = new char[vsiz+1]; | | vbuf_ = new char[vsiz+1]; | |
| std::memcpy(vbuf_, vbuf, vsiz); | | std::memcpy(vbuf_, vbuf, vsiz); | |
| vbuf_[vsiz] = '\0'; | | vbuf_[vsiz] = '\0'; | |
| vsiz_ = vsiz; | | vsiz_ = vsiz; | |
| return NOP; | | return NOP; | |
| } | | } | |
| char* vbuf_; | | char* vbuf_; | |
| size_t vsiz_; | | size_t vsiz_; | |
| | | | |
| skipping to change at line 719 | | skipping to change at line 719 | |
| * @param step true to move the cursor to the next record, or false for
no move. | | * @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. | | * @return the pointer to the key region, or NULL on failure. | |
| * @note If the cursor is invalidated, NULL is returned. Because an ad
ditional zero code is | | * @note If the cursor is invalidated, NULL is returned. Because an ad
ditional zero code is | |
| * appended at the end of each region of the key and the value, each re
gion can be treated | | * appended at the end of each region of the key and the value, each re
gion can be treated | |
| * as a C-style string. The return value should be deleted explicitly
by the caller with | | * as a C-style string. The return value should be deleted explicitly
by the caller with | |
| * the detele[] operator. | | * the detele[] operator. | |
| */ | | */ | |
| char* get(size_t* ksp, const char** vbp, size_t* vsp, bool step = false
) { | | char* get(size_t* ksp, const char** vbp, size_t* vsp, bool step = false
) { | |
| _assert_(ksp && vbp && vsp); | | _assert_(ksp && vbp && vsp); | |
| class VisitorImpl : public Visitor { | | class VisitorImpl : public Visitor { | |
|
| public: | | public: | |
| explicit VisitorImpl() : kbuf_(NULL), ksiz_(0), vbuf_(NULL), vsiz_(
0) {} | | explicit VisitorImpl() : kbuf_(NULL), ksiz_(0), vbuf_(NULL), vsiz_(
0) {} | |
| char* pop(size_t* ksp, const char** vbp, size_t* vsp) { | | char* pop(size_t* ksp, const char** vbp, size_t* vsp) { | |
| *ksp = ksiz_; | | *ksp = ksiz_; | |
| *vbp = vbuf_; | | *vbp = vbuf_; | |
| *vsp = vsiz_; | | *vsp = vsiz_; | |
| return kbuf_; | | return kbuf_; | |
| } | | } | |
| void clear() { | | void clear() { | |
| delete[] kbuf_; | | delete[] kbuf_; | |
| } | | } | |
|
| private: | | private: | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| size_t rsiz = ksiz + 1 + vsiz + 1; | | size_t rsiz = ksiz + 1 + vsiz + 1; | |
| kbuf_ = new char[rsiz]; | | kbuf_ = new char[rsiz]; | |
| std::memcpy(kbuf_, kbuf, ksiz); | | std::memcpy(kbuf_, kbuf, ksiz); | |
| kbuf_[ksiz] = '\0'; | | kbuf_[ksiz] = '\0'; | |
| ksiz_ = ksiz; | | ksiz_ = ksiz; | |
| vbuf_ = kbuf_ + ksiz + 1; | | vbuf_ = kbuf_ + ksiz + 1; | |
| std::memcpy(vbuf_, vbuf, vsiz); | | std::memcpy(vbuf_, vbuf, vsiz); | |
| vbuf_[vsiz] = '\0'; | | vbuf_[vsiz] = '\0'; | |
| | | | |
| skipping to change at line 767 | | skipping to change at line 767 | |
| return visitor.pop(ksp, vbp, vsp); | | return visitor.pop(ksp, vbp, vsp); | |
| } | | } | |
| /** | | /** | |
| * Get a pair of the key and the value of the current record. | | * Get a pair of the key and the value of the current record. | |
| * @note Equal to the original Cursor::get method except that parameter
s are strings | | * @note Equal to the original Cursor::get method except that parameter
s are strings | |
| * to contain the result and the return value is bool for success. | | * to contain the result and the return value is bool for success. | |
| */ | | */ | |
| bool get(std::string* key, std::string* value, bool step = false) { | | bool get(std::string* key, std::string* value, bool step = false) { | |
| _assert_(key && value); | | _assert_(key && value); | |
| class VisitorImpl : public Visitor { | | class VisitorImpl : public Visitor { | |
|
| public: | | public: | |
| explicit VisitorImpl(std::string* key, std::string* value) : | | explicit VisitorImpl(std::string* key, std::string* value) : | |
|
| key_(key), value_(value), ok_(false) {} | | key_(key), value_(value), ok_(false) {} | |
| bool ok() { | | bool ok() { | |
| return ok_; | | return ok_; | |
| } | | } | |
|
| private: | | private: | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| key_->clear(); | | key_->clear(); | |
| key_->append(kbuf, ksiz); | | key_->append(kbuf, ksiz); | |
| value_->clear(); | | value_->clear(); | |
| value_->append(vbuf, vsiz); | | value_->append(vbuf, vsiz); | |
| ok_ = true; | | ok_ = true; | |
| return NOP; | | return NOP; | |
| } | | } | |
| std::string* key_; | | std::string* key_; | |
| | | | |
| skipping to change at line 809 | | skipping to change at line 809 | |
| */ | | */ | |
| Error error() { | | Error error() { | |
| _assert_(true); | | _assert_(true); | |
| return db()->error(); | | return db()->error(); | |
| } | | } | |
| }; | | }; | |
| /** | | /** | |
| * Error data. | | * Error data. | |
| */ | | */ | |
| class Error { | | class Error { | |
|
| public: | | public: | |
| /** | | /** | |
| * Error codes. | | * Error codes. | |
| */ | | */ | |
| enum Code { | | enum Code { | |
| SUCCESS, ///< success | | SUCCESS, ///< success | |
| NOIMPL, ///< not implemented | | NOIMPL, ///< not implemented | |
| INVALID, ///< invalid operation | | INVALID, ///< invalid operation | |
| NOREPOS, ///< no repository | | NOREPOS, ///< no repository | |
| NOPERM, ///< no permission | | NOPERM, ///< no permission | |
| BROKEN, ///< broken file | | BROKEN, ///< broken file | |
| | | | |
| skipping to change at line 928 | | skipping to change at line 928 | |
| message_ = right.message_; | | message_ = right.message_; | |
| return *this; | | return *this; | |
| } | | } | |
| /** | | /** | |
| * Cast operator to integer. | | * Cast operator to integer. | |
| * @return the error code. | | * @return the error code. | |
| */ | | */ | |
| operator int32_t() const { | | operator int32_t() const { | |
| return code_; | | return code_; | |
| } | | } | |
|
| private: | | private: | |
| /** The error code. */ | | /** The error code. */ | |
| Code code_; | | Code code_; | |
| /** The supplement message. */ | | /** The supplement message. */ | |
| const char* message_; | | const char* message_; | |
| }; | | }; | |
| /** | | /** | |
| * Interface to check progress status of long process. | | * Interface to check progress status of long process. | |
| */ | | */ | |
| class ProgressChecker { | | class ProgressChecker { | |
|
| public: | | public: | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| */ | | */ | |
| virtual ~ProgressChecker() { | | virtual ~ProgressChecker() { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| /** | | /** | |
| * Check the progress status. | | * Check the progress status. | |
| * @param name the name of the process. | | * @param name the name of the process. | |
| * @param message a supplement message. | | * @param message a supplement message. | |
| | | | |
| skipping to change at line 960 | | skipping to change at line 960 | |
| * @param allcnt the estimation count of all steps 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. | | * @return true to continue the process, or false to stop the process. | |
| */ | | */ | |
| virtual bool check(const char* name, const char* message, | | virtual bool check(const char* name, const char* message, | |
| int64_t curcnt, int64_t allcnt) = 0; | | int64_t curcnt, int64_t allcnt) = 0; | |
| }; | | }; | |
| /** | | /** | |
| * Interface to process the database file. | | * Interface to process the database file. | |
| */ | | */ | |
| class FileProcessor { | | class FileProcessor { | |
|
| public: | | public: | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| */ | | */ | |
| virtual ~FileProcessor() { | | virtual ~FileProcessor() { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| /** | | /** | |
| * Process the database file. | | * Process the database file. | |
| * @param path the path of the database file. | | * @param path the path of the database file. | |
| * @param count the number of records. A negative value means omission
. | | * @param count the number of records. A negative value means omission
. | |
| * @param size the size of the available region. A negative value mean
s omission. | | * @param size the size of the available region. A negative value mean
s omission. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| virtual bool process(const std::string& path, int64_t count, int64_t si
ze) = 0; | | virtual bool process(const std::string& path, int64_t count, int64_t si
ze) = 0; | |
| }; | | }; | |
| /** | | /** | |
| * Interface to log internal information and errors. | | * Interface to log internal information and errors. | |
| */ | | */ | |
| class Logger { | | class Logger { | |
|
| public: | | public: | |
| /** | | /** | |
| * Event kinds. | | * Event kinds. | |
| */ | | */ | |
| enum Kind { | | enum Kind { | |
| DEBUG = 1 << 0, ///< debugging | | DEBUG = 1 << 0, ///< debugging | |
| INFO = 1 << 1, ///< normal information | | INFO = 1 << 1, ///< normal information | |
| WARN = 1 << 2, ///< warning | | WARN = 1 << 2, ///< warning | |
| ERROR = 1 << 3 ///< error | | ERROR = 1 << 3 ///< error | |
| }; | | }; | |
| /** | | /** | |
| | | | |
| skipping to change at line 1012 | | skipping to change at line 1012 | |
| * information, Logger::WARN for warning, and Logger::ERROR for fatal e
rror. | | * information, Logger::WARN for warning, and Logger::ERROR for fatal e
rror. | |
| * @param message the supplement message. | | * @param message the supplement message. | |
| */ | | */ | |
| virtual void log(const char* file, int32_t line, const char* func, Kind
kind, | | virtual void log(const char* file, int32_t line, const char* func, Kind
kind, | |
| const char* message) = 0; | | const char* message) = 0; | |
| }; | | }; | |
| /** | | /** | |
| * Interface to trigger meta database operations. | | * Interface to trigger meta database operations. | |
| */ | | */ | |
| class MetaTrigger { | | class MetaTrigger { | |
|
| public: | | public: | |
| /** | | /** | |
| * Event kinds. | | * Event kinds. | |
| */ | | */ | |
| enum Kind { | | enum Kind { | |
| OPEN, ///< opening | | OPEN, ///< opening | |
| CLOSE, ///< closing | | CLOSE, ///< closing | |
| CLEAR, ///< clearing | | CLEAR, ///< clearing | |
| ITERATE, ///< iteration | | ITERATE, ///< iteration | |
| SYNCHRONIZE, ///< synchronization | | SYNCHRONIZE, ///< synchronization | |
| OCCUPY, ///< occupation | | OCCUPY, ///< occupation | |
| | | | |
| skipping to change at line 1161 | | skipping to change at line 1161 | |
| virtual bool occupy(bool writable = true, FileProcessor* proc = NULL) = 0
; | | virtual bool occupy(bool writable = true, FileProcessor* proc = NULL) = 0
; | |
| /** | | /** | |
| * Create a copy of the database file. | | * Create a copy of the database file. | |
| * @param dest the path of the destination file. | | * @param dest the path of the destination file. | |
| * @param checker a progress checker object. If it is NULL, no checking
is performed. | | * @param checker a progress checker object. If it is NULL, no checking
is performed. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool copy(const std::string& dest, ProgressChecker* checker = NULL) { | | bool copy(const std::string& dest, ProgressChecker* checker = NULL) { | |
| _assert_(true); | | _assert_(true); | |
| class FileProcessorImpl : public FileProcessor { | | class FileProcessorImpl : public FileProcessor { | |
|
| public: | | public: | |
| explicit FileProcessorImpl(const std::string& dest, ProgressChecker*
checker, | | explicit FileProcessorImpl(const std::string& dest, ProgressChecker*
checker, | |
| BasicDB* db) : | | BasicDB* db) : | |
|
| dest_(dest), checker_(checker), db_(db) {} | | dest_(dest), checker_(checker), db_(db) {} | |
| private: | | private: | |
| bool process(const std::string& path, int64_t count, int64_t size) { | | bool process(const std::string& path, int64_t count, int64_t size) { | |
| File::Status sbuf; | | File::Status sbuf; | |
| if (!File::status(path, &sbuf)) return false; | | if (!File::status(path, &sbuf)) return false; | |
| if (sbuf.isdir) { | | if (sbuf.isdir) { | |
| if (!File::make_directory(dest_)) return false; | | if (!File::make_directory(dest_)) return false; | |
| bool err = false; | | bool err = false; | |
| DirStream dir; | | DirStream dir; | |
| if (dir.open(path)) { | | if (dir.open(path)) { | |
| if (checker_ && !checker_->check("copy", "beginning", 0, -1)) { | | if (checker_ && !checker_->check("copy", "beginning", 0, -1)) { | |
| db_->set_error(_KCCODELINE_, Error::LOGIC, "checker failed"); | | db_->set_error(_KCCODELINE_, Error::LOGIC, "checker failed"); | |
| | | | |
| skipping to change at line 1307 | | skipping to change at line 1307 | |
| * @param ksiz the size of the key region. | | * @param ksiz the size of the key region. | |
| * @param vbuf the pointer to the value region. | | * @param vbuf the pointer to the value region. | |
| * @param vsiz the size of the value region. | | * @param vsiz the size of the value region. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| * @note If no record corresponds to the key, a new record is created. I
f the corresponding | | * @note If no record corresponds to the key, a new record is created. I
f the corresponding | |
| * record exists, the value is overwritten. | | * record exists, the value is overwritten. | |
| */ | | */ | |
| bool set(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) { | | bool set(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) { | |
| _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ); | | _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ); | |
| class VisitorImpl : public Visitor { | | class VisitorImpl : public Visitor { | |
|
| public: | | public: | |
| explicit VisitorImpl(const char* vbuf, size_t vsiz) : vbuf_(vbuf), vs
iz_(vsiz) {} | | explicit VisitorImpl(const char* vbuf, size_t vsiz) : vbuf_(vbuf), vs
iz_(vsiz) {} | |
|
| private: | | private: | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| *sp = vsiz_; | | *sp = vsiz_; | |
| return vbuf_; | | return vbuf_; | |
| } | | } | |
| const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { | | const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { | |
| *sp = vsiz_; | | *sp = vsiz_; | |
| return vbuf_; | | return vbuf_; | |
| } | | } | |
| const char* vbuf_; | | const char* vbuf_; | |
| | | | |
| skipping to change at line 1347 | | skipping to change at line 1347 | |
| * @param ksiz the size of the key region. | | * @param ksiz the size of the key region. | |
| * @param vbuf the pointer to the value region. | | * @param vbuf the pointer to the value region. | |
| * @param vsiz the size of the value region. | | * @param vsiz the size of the value region. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| * @note If no record corresponds to the key, a new record is created. I
f the corresponding | | * @note If no record corresponds to the key, a new record is created. I
f the corresponding | |
| * record exists, the record is not modified and false is returned. | | * 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) { | | bool add(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) { | |
| _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ); | | _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ); | |
| class VisitorImpl : public Visitor { | | class VisitorImpl : public Visitor { | |
|
| public: | | public: | |
| explicit VisitorImpl(const char* vbuf, size_t vsiz) : | | explicit VisitorImpl(const char* vbuf, size_t vsiz) : | |
|
| vbuf_(vbuf), vsiz_(vsiz), ok_(false) {} | | vbuf_(vbuf), vsiz_(vsiz), ok_(false) {} | |
| bool ok() const { | | bool ok() const { | |
| return ok_; | | return ok_; | |
| } | | } | |
|
| private: | | private: | |
| const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { | | const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { | |
| ok_ = true; | | ok_ = true; | |
| *sp = vsiz_; | | *sp = vsiz_; | |
| return vbuf_; | | return vbuf_; | |
| } | | } | |
| const char* vbuf_; | | const char* vbuf_; | |
| size_t vsiz_; | | size_t vsiz_; | |
| bool ok_; | | bool ok_; | |
| }; | | }; | |
| VisitorImpl visitor(vbuf, vsiz); | | VisitorImpl visitor(vbuf, vsiz); | |
| | | | |
| skipping to change at line 1392 | | skipping to change at line 1392 | |
| * @param ksiz the size of the key region. | | * @param ksiz the size of the key region. | |
| * @param vbuf the pointer to the value region. | | * @param vbuf the pointer to the value region. | |
| * @param vsiz the size of the value region. | | * @param vsiz the size of the value region. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| * @note If no record corresponds to the key, no new record is created an
d false is returned. | | * @note If no record corresponds to the key, no new record is created an
d false is returned. | |
| * If the corresponding record exists, the value is modified. | | * If the corresponding record exists, the value is modified. | |
| */ | | */ | |
| bool replace(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz
) { | | bool replace(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz
) { | |
| _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ); | | _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ); | |
| class VisitorImpl : public Visitor { | | class VisitorImpl : public Visitor { | |
|
| public: | | public: | |
| explicit VisitorImpl(const char* vbuf, size_t vsiz) : | | explicit VisitorImpl(const char* vbuf, size_t vsiz) : | |
|
| vbuf_(vbuf), vsiz_(vsiz), ok_(false) {} | | vbuf_(vbuf), vsiz_(vsiz), ok_(false) {} | |
| bool ok() const { | | bool ok() const { | |
| return ok_; | | return ok_; | |
| } | | } | |
|
| private: | | private: | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| ok_ = true; | | ok_ = true; | |
| *sp = vsiz_; | | *sp = vsiz_; | |
| return vbuf_; | | return vbuf_; | |
| } | | } | |
| const char* vbuf_; | | const char* vbuf_; | |
| size_t vsiz_; | | size_t vsiz_; | |
| bool ok_; | | bool ok_; | |
| }; | | }; | |
| | | | |
| skipping to change at line 1438 | | skipping to change at line 1438 | |
| * @param ksiz the size of the key region. | | * @param ksiz the size of the key region. | |
| * @param vbuf the pointer to the value region. | | * @param vbuf the pointer to the value region. | |
| * @param vsiz the size of the value region. | | * @param vsiz the size of the value region. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| * @note If no record corresponds to the key, a new record is created. I
f the corresponding | | * @note If no record corresponds to the key, a new record is created. I
f the corresponding | |
| * record exists, the given value is appended at the end of the existing
value. | | * 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)
{ | | bool append(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz)
{ | |
| _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ); | | _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ); | |
| class VisitorImpl : public Visitor { | | class VisitorImpl : public Visitor { | |
|
| public: | | public: | |
| explicit VisitorImpl(const char* vbuf, size_t vsiz) : | | explicit VisitorImpl(const char* vbuf, size_t vsiz) : | |
|
| vbuf_(vbuf), vsiz_(vsiz), nbuf_(NULL) {} | | vbuf_(vbuf), vsiz_(vsiz), nbuf_(NULL) {} | |
| ~VisitorImpl() { | | ~VisitorImpl() { | |
| if (nbuf_) delete[] nbuf_; | | if (nbuf_) delete[] nbuf_; | |
| } | | } | |
|
| private: | | private: | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| size_t nsiz = vsiz + vsiz_; | | size_t nsiz = vsiz + vsiz_; | |
| nbuf_ = new char[nsiz]; | | nbuf_ = new char[nsiz]; | |
| std::memcpy(nbuf_, vbuf, vsiz); | | std::memcpy(nbuf_, vbuf, vsiz); | |
| std::memcpy(nbuf_ + vsiz, vbuf_, vsiz_); | | std::memcpy(nbuf_ + vsiz, vbuf_, vsiz_); | |
| *sp = nsiz; | | *sp = nsiz; | |
| return nbuf_; | | return nbuf_; | |
| } | | } | |
| const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { | | const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { | |
| | | | |
| skipping to change at line 1488 | | skipping to change at line 1488 | |
| * @param num the additional number. | | * @param num the additional number. | |
| * @return the result value, or kyotocabinet::INT64MIN on failure. | | * @return the result value, or kyotocabinet::INT64MIN on failure. | |
| * @note If no record corresponds to the key, a new record is created wit
h the initial value | | * @note If no record corresponds to the key, a new record is created wit
h the initial value | |
| * set by the additional value. The value is serialized as an 8-byte bin
ary integer in | | * set by the additional value. The value is serialized as an 8-byte bin
ary integer in | |
| * big-endian order, not a decimal string. If existing value is not 8-by
te, this function | | * big-endian order, not a decimal string. If existing value is not 8-by
te, this function | |
| * fails. | | * fails. | |
| */ | | */ | |
| int64_t increment(const char* kbuf, size_t ksiz, int64_t num) { | | int64_t increment(const char* kbuf, size_t ksiz, int64_t num) { | |
| _assert_(kbuf && ksiz <= MEMMAXSIZ); | | _assert_(kbuf && ksiz <= MEMMAXSIZ); | |
| class VisitorImpl : public Visitor { | | class VisitorImpl : public Visitor { | |
|
| public: | | public: | |
| explicit VisitorImpl(int64_t num) : num_(num), big_(0) {} | | explicit VisitorImpl(int64_t num) : num_(num), big_(0) {} | |
| int64_t num() { | | int64_t num() { | |
| return num_; | | return num_; | |
| } | | } | |
|
| private: | | private: | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| if (vsiz != sizeof(num_)) { | | if (vsiz != sizeof(num_)) { | |
| num_ = INT64MIN; | | num_ = INT64MIN; | |
| return NOP; | | return NOP; | |
| } | | } | |
| int64_t onum; | | int64_t onum; | |
| std::memcpy(&onum, vbuf, vsiz); | | std::memcpy(&onum, vbuf, vsiz); | |
| onum = ntoh64(onum); | | onum = ntoh64(onum); | |
| if (num_ == 0) { | | if (num_ == 0) { | |
| | | | |
| skipping to change at line 1551 | | skipping to change at line 1551 | |
| * @param num the additional number. | | * @param num the additional number. | |
| * @return the result value, or Not-a-number on failure. | | * @return the result value, or Not-a-number on failure. | |
| * @note If no record corresponds to the key, a new record is created wit
h the initial value | | * @note If no record corresponds to the key, a new record is created wit
h the initial value | |
| * set by the additional value. The value is serialized as an 16-byte bi
nary fixed-point | | * set by the additional value. The value is serialized as an 16-byte bi
nary fixed-point | |
| * number in big-endian order, not a decimal string. If existing value i
s not 16-byte, this | | * number in big-endian order, not a decimal string. If existing value i
s not 16-byte, this | |
| * function fails. | | * function fails. | |
| */ | | */ | |
| double increment_double(const char* kbuf, size_t ksiz, double num) { | | double increment_double(const char* kbuf, size_t ksiz, double num) { | |
| _assert_(kbuf && ksiz <= MEMMAXSIZ); | | _assert_(kbuf && ksiz <= MEMMAXSIZ); | |
| class VisitorImpl : public Visitor { | | class VisitorImpl : public Visitor { | |
|
| public: | | public: | |
| explicit VisitorImpl(double num) : DECUNIT(1000000000000000LL), num_(
num), buf_() {} | | explicit VisitorImpl(double num) : DECUNIT(1000000000000000LL), num_(
num), buf_() {} | |
| double num() { | | double num() { | |
| return num_; | | return num_; | |
| } | | } | |
|
| private: | | private: | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| if (vsiz != sizeof(buf_)) { | | if (vsiz != sizeof(buf_)) { | |
| num_ = nan(); | | num_ = nan(); | |
| return NOP; | | return NOP; | |
| } | | } | |
| int64_t linteg, lfract; | | int64_t linteg, lfract; | |
| std::memcpy(&linteg, vbuf, sizeof(linteg)); | | std::memcpy(&linteg, vbuf, sizeof(linteg)); | |
| linteg = ntoh64(linteg); | | linteg = ntoh64(linteg); | |
| std::memcpy(&lfract, vbuf + sizeof(linteg), sizeof(lfract)); | | std::memcpy(&lfract, vbuf + sizeof(linteg), sizeof(lfract)); | |
| | | | |
| skipping to change at line 1665 | | skipping to change at line 1665 | |
| * @param ovbuf the pointer to the old value region. NULL means that no
record corresponds. | | * @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 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 nvbuf the pointer to the new value region. NULL means that the
record is removed. | |
| * @param nvsiz the size of new old value region. | | * @param nvsiz the size of new old value region. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool cas(const char* kbuf, size_t ksiz, | | bool cas(const char* kbuf, size_t ksiz, | |
| const char* ovbuf, size_t ovsiz, const char* nvbuf, size_t nvsiz
) { | | const char* ovbuf, size_t ovsiz, const char* nvbuf, size_t nvsiz
) { | |
| _assert_(kbuf && ksiz <= MEMMAXSIZ); | | _assert_(kbuf && ksiz <= MEMMAXSIZ); | |
| class VisitorImpl : public Visitor { | | class VisitorImpl : public Visitor { | |
|
| public: | | public: | |
| explicit VisitorImpl(const char* ovbuf, size_t ovsiz, const char* nvb
uf, size_t nvsiz) : | | explicit VisitorImpl(const char* ovbuf, size_t ovsiz, const char* nvb
uf, size_t nvsiz) : | |
|
| ovbuf_(ovbuf), ovsiz_(ovsiz), nvbuf_(nvbuf), nvsiz_(nvsiz), ok_(fal
se) {} | | ovbuf_(ovbuf), ovsiz_(ovsiz), nvbuf_(nvbuf), nvsiz_(nvsiz), ok_(f
alse) {} | |
| bool ok() const { | | bool ok() const { | |
| return ok_; | | return ok_; | |
| } | | } | |
|
| private: | | private: | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| if (!ovbuf_ || vsiz != ovsiz_ || std::memcmp(vbuf, ovbuf_, vsiz)) r
eturn NOP; | | if (!ovbuf_ || vsiz != ovsiz_ || std::memcmp(vbuf, ovbuf_, vsiz)) r
eturn NOP; | |
| ok_ = true; | | ok_ = true; | |
| if (!nvbuf_) return REMOVE; | | if (!nvbuf_) return REMOVE; | |
| *sp = nvsiz_; | | *sp = nvsiz_; | |
| return nvbuf_; | | return nvbuf_; | |
| } | | } | |
| const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { | | const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { | |
| if (ovbuf_) return NOP; | | if (ovbuf_) return NOP; | |
| | | | |
| skipping to change at line 1721 | | skipping to change at line 1721 | |
| /** | | /** | |
| * Remove a record. | | * Remove a record. | |
| * @param kbuf the pointer to the key region. | | * @param kbuf the pointer to the key region. | |
| * @param ksiz the size of the key region. | | * @param ksiz the size of the key region. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| * @note If no record corresponds to the key, false is returned. | | * @note If no record corresponds to the key, false is returned. | |
| */ | | */ | |
| bool remove(const char* kbuf, size_t ksiz) { | | bool remove(const char* kbuf, size_t ksiz) { | |
| _assert_(kbuf && ksiz <= MEMMAXSIZ); | | _assert_(kbuf && ksiz <= MEMMAXSIZ); | |
| class VisitorImpl : public Visitor { | | class VisitorImpl : public Visitor { | |
|
| public: | | public: | |
| explicit VisitorImpl() : ok_(false) {} | | explicit VisitorImpl() : ok_(false) {} | |
| bool ok() const { | | bool ok() const { | |
| return ok_; | | return ok_; | |
| } | | } | |
|
| private: | | private: | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| ok_ = true; | | ok_ = true; | |
| return REMOVE; | | return REMOVE; | |
| } | | } | |
| bool ok_; | | bool ok_; | |
| }; | | }; | |
| VisitorImpl visitor; | | VisitorImpl visitor; | |
| if (!accept(kbuf, ksiz, &visitor, true)) return false; | | if (!accept(kbuf, ksiz, &visitor, true)) return false; | |
| if (!visitor.ok()) { | | if (!visitor.ok()) { | |
| | | | |
| skipping to change at line 1766 | | skipping to change at line 1766 | |
| * @return the pointer to the value region of the corresponding record, o
r NULL on failure. | | * @return the pointer to the value region of the corresponding record, o
r NULL on failure. | |
| * @note If no record corresponds to the key, NULL is returned. Because
an additional zero | | * @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 ret
urn value can be | | * code is appended at the end of the region of the return value, the ret
urn value can be | |
| * treated as a C-style string. Because the region of the return value i
s allocated with the | | * treated as a C-style string. Because the region of the return value i
s allocated with the | |
| * the new[] operator, it should be released with the delete[] operator w
hen it is no longer | | * the new[] operator, it should be released with the delete[] operator w
hen it is no longer | |
| * in use. | | * in use. | |
| */ | | */ | |
| char* get(const char* kbuf, size_t ksiz, size_t* sp) { | | char* get(const char* kbuf, size_t ksiz, size_t* sp) { | |
| _assert_(kbuf && ksiz <= MEMMAXSIZ && sp); | | _assert_(kbuf && ksiz <= MEMMAXSIZ && sp); | |
| class VisitorImpl : public Visitor { | | class VisitorImpl : public Visitor { | |
|
| public: | | public: | |
| explicit VisitorImpl() : vbuf_(NULL), vsiz_(0) {} | | explicit VisitorImpl() : vbuf_(NULL), vsiz_(0) {} | |
| char* pop(size_t* sp) { | | char* pop(size_t* sp) { | |
| *sp = vsiz_; | | *sp = vsiz_; | |
| return vbuf_; | | return vbuf_; | |
| } | | } | |
|
| private: | | private: | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| vbuf_ = new char[vsiz+1]; | | vbuf_ = new char[vsiz+1]; | |
| std::memcpy(vbuf_, vbuf, vsiz); | | std::memcpy(vbuf_, vbuf, vsiz); | |
| vbuf_[vsiz] = '\0'; | | vbuf_[vsiz] = '\0'; | |
| vsiz_ = vsiz; | | vsiz_ = vsiz; | |
| return NOP; | | return NOP; | |
| } | | } | |
| char* vbuf_; | | char* vbuf_; | |
| size_t vsiz_; | | size_t vsiz_; | |
| | | | |
| skipping to change at line 1827 | | skipping to change at line 1827 | |
| * @param kbuf the pointer to the key region. | | * @param kbuf the pointer to the key region. | |
| * @param ksiz the size of the key region. | | * @param ksiz the size of the key region. | |
| * @param vbuf the pointer to the buffer into which the value of the corr
esponding record is | | * @param vbuf the pointer to the buffer into which the value of the corr
esponding record is | |
| * written. | | * written. | |
| * @param max the size of the buffer. | | * @param max the size of the buffer. | |
| * @return the size of the value, or -1 on failure. | | * @return the size of the value, or -1 on failure. | |
| */ | | */ | |
| int32_t get(const char* kbuf, size_t ksiz, char* vbuf, size_t max) { | | int32_t get(const char* kbuf, size_t ksiz, char* vbuf, size_t max) { | |
| _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf); | | _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf); | |
| class VisitorImpl : public Visitor { | | class VisitorImpl : public Visitor { | |
|
| public: | | public: | |
| explicit VisitorImpl(char* vbuf, size_t max) : vbuf_(vbuf), max_(max)
, vsiz_(-1) {} | | explicit VisitorImpl(char* vbuf, size_t max) : vbuf_(vbuf), max_(max)
, vsiz_(-1) {} | |
| int32_t vsiz() { | | int32_t vsiz() { | |
| return vsiz_; | | return vsiz_; | |
| } | | } | |
|
| private: | | private: | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| vsiz_ = vsiz; | | vsiz_ = vsiz; | |
| size_t max = vsiz < max_ ? vsiz : max_; | | size_t max = vsiz < max_ ? vsiz : max_; | |
| std::memcpy(vbuf_, vbuf, max); | | std::memcpy(vbuf_, vbuf, max); | |
| return NOP; | | return NOP; | |
| } | | } | |
| char* vbuf_; | | char* vbuf_; | |
| size_t max_; | | size_t max_; | |
| int32_t vsiz_; | | int32_t vsiz_; | |
| | | | |
| skipping to change at line 1871 | | skipping to change at line 1871 | |
| if (atomic) { | | if (atomic) { | |
| std::vector<std::string> keys; | | std::vector<std::string> keys; | |
| keys.reserve(recs.size()); | | keys.reserve(recs.size()); | |
| std::map<std::string, std::string>::const_iterator rit = recs.begin()
; | | std::map<std::string, std::string>::const_iterator rit = recs.begin()
; | |
| std::map<std::string, std::string>::const_iterator ritend = recs.end(
); | | std::map<std::string, std::string>::const_iterator ritend = recs.end(
); | |
| while (rit != ritend) { | | while (rit != ritend) { | |
| keys.push_back(rit->first); | | keys.push_back(rit->first); | |
| ++rit; | | ++rit; | |
| } | | } | |
| class VisitorImpl : public Visitor { | | class VisitorImpl : public Visitor { | |
|
| public: | | public: | |
| explicit VisitorImpl(const std::map<std::string, std::string>& recs
) : recs_(recs) {} | | explicit VisitorImpl(const std::map<std::string, std::string>& recs
) : recs_(recs) {} | |
|
| private: | | private: | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| std::map<std::string, std::string>::const_iterator rit = | | std::map<std::string, std::string>::const_iterator rit = | |
|
| recs_.find(std::string(kbuf, ksiz)); | | recs_.find(std::string(kbuf, ksiz)); | |
| if (rit == recs_.end()) return NOP; | | if (rit == recs_.end()) return NOP; | |
| *sp = rit->second.size(); | | *sp = rit->second.size(); | |
| return rit->second.data(); | | return rit->second.data(); | |
| } | | } | |
| const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp)
{ | | const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp)
{ | |
| std::map<std::string, std::string>::const_iterator rit = | | std::map<std::string, std::string>::const_iterator rit = | |
|
| recs_.find(std::string(kbuf, ksiz)); | | recs_.find(std::string(kbuf, ksiz)); | |
| if (rit == recs_.end()) return NOP; | | if (rit == recs_.end()) return NOP; | |
| *sp = rit->second.size(); | | *sp = rit->second.size(); | |
| return rit->second.data(); | | return rit->second.data(); | |
| } | | } | |
| const std::map<std::string, std::string>& recs_; | | const std::map<std::string, std::string>& recs_; | |
| }; | | }; | |
| VisitorImpl visitor(recs); | | VisitorImpl visitor(recs); | |
| if (!accept_bulk(keys, &visitor, true)) return -1; | | if (!accept_bulk(keys, &visitor, true)) return -1; | |
| return keys.size(); | | return keys.size(); | |
| } | | } | |
| | | | |
| skipping to change at line 1914 | | skipping to change at line 1914 | |
| /** | | /** | |
| * Remove records at once. | | * Remove records at once. | |
| * @param keys the keys of the records to remove. | | * @param keys the keys of the records to remove. | |
| * @param atomic true to perform all operations atomically, or false for
non-atomic operations. | | * @param atomic true to perform all operations atomically, or false for
non-atomic operations. | |
| * @return the number of removed records, or -1 on failure. | | * @return the number of removed records, or -1 on failure. | |
| */ | | */ | |
| int64_t remove_bulk(const std::vector<std::string>& keys, bool atomic = t
rue) { | | int64_t remove_bulk(const std::vector<std::string>& keys, bool atomic = t
rue) { | |
| _assert_(true); | | _assert_(true); | |
| if (atomic) { | | if (atomic) { | |
| class VisitorImpl : public Visitor { | | class VisitorImpl : public Visitor { | |
|
| public: | | public: | |
| explicit VisitorImpl() : cnt_(0) {} | | explicit VisitorImpl() : cnt_(0) {} | |
| int64_t cnt() const { | | int64_t cnt() const { | |
| return cnt_; | | return cnt_; | |
| } | | } | |
|
| private: | | private: | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| cnt_++; | | cnt_++; | |
| return REMOVE; | | return REMOVE; | |
| } | | } | |
| int64_t cnt_; | | int64_t cnt_; | |
| }; | | }; | |
| VisitorImpl visitor; | | VisitorImpl visitor; | |
| if (!accept_bulk(keys, &visitor, true)) return -1; | | if (!accept_bulk(keys, &visitor, true)) return -1; | |
| return visitor.cnt(); | | return visitor.cnt(); | |
| | | | |
| skipping to change at line 1956 | | skipping to change at line 1956 | |
| * @param keys the keys of the records to retrieve. | | * @param keys the keys of the records to retrieve. | |
| * @param recs a string map to contain the retrieved records. | | * @param recs a string map to contain the retrieved records. | |
| * @param atomic true to perform all operations atomically, or false for
non-atomic operations. | | * @param atomic true to perform all operations atomically, or false for
non-atomic operations. | |
| * @return the number of retrieved records, or -1 on failure. | | * @return the number of retrieved records, or -1 on failure. | |
| */ | | */ | |
| int64_t get_bulk(const std::vector<std::string>& keys, | | int64_t get_bulk(const std::vector<std::string>& keys, | |
| std::map<std::string, std::string>* recs, bool atomic =
true) { | | std::map<std::string, std::string>* recs, bool atomic =
true) { | |
| _assert_(recs); | | _assert_(recs); | |
| if (atomic) { | | if (atomic) { | |
| class VisitorImpl : public Visitor { | | class VisitorImpl : public Visitor { | |
|
| public: | | public: | |
| explicit VisitorImpl(std::map<std::string, std::string>* recs) : re
cs_(recs) {} | | explicit VisitorImpl(std::map<std::string, std::string>* recs) : re
cs_(recs) {} | |
|
| private: | | private: | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| (*recs_)[std::string(kbuf, ksiz)] = std::string(vbuf, vsiz); | | (*recs_)[std::string(kbuf, ksiz)] = std::string(vbuf, vsiz); | |
| return NOP; | | return NOP; | |
| } | | } | |
| std::map<std::string, std::string>* recs_; | | std::map<std::string, std::string>* recs_; | |
| }; | | }; | |
| VisitorImpl visitor(recs); | | VisitorImpl visitor(recs); | |
| if (!accept_bulk(keys, &visitor, false)) return -1; | | if (!accept_bulk(keys, &visitor, false)) return -1; | |
| return recs->size(); | | return recs->size(); | |
| | | | |
| skipping to change at line 1998 | | skipping to change at line 1998 | |
| * @param checker a progress checker object. If it is NULL, no checking
is performed. | | * @param checker a progress checker object. If it is NULL, no checking
is performed. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool dump_snapshot(std::ostream* dest, ProgressChecker* checker = NULL) { | | bool dump_snapshot(std::ostream* dest, ProgressChecker* checker = NULL) { | |
| _assert_(dest); | | _assert_(dest); | |
| if (dest->fail()) { | | if (dest->fail()) { | |
| set_error(_KCCODELINE_, Error::INVALID, "invalid stream"); | | set_error(_KCCODELINE_, Error::INVALID, "invalid stream"); | |
| return false; | | return false; | |
| } | | } | |
| class VisitorImpl : public Visitor { | | class VisitorImpl : public Visitor { | |
|
| public: | | public: | |
| explicit VisitorImpl(std::ostream* dest) : dest_(dest), stack_() {} | | explicit VisitorImpl(std::ostream* dest) : dest_(dest), stack_() {} | |
|
| private: | | private: | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| char* wp = stack_; | | char* wp = stack_; | |
| *(wp++) = 0x00; | | *(wp++) = 0x00; | |
| wp += writevarnum(wp, ksiz); | | wp += writevarnum(wp, ksiz); | |
| wp += writevarnum(wp, vsiz); | | wp += writevarnum(wp, vsiz); | |
| dest_->write(stack_, wp - stack_); | | dest_->write(stack_, wp - stack_); | |
| dest_->write(kbuf, ksiz); | | dest_->write(kbuf, ksiz); | |
| dest_->write(vbuf, vsiz); | | dest_->write(vbuf, vsiz); | |
| return NOP; | | return NOP; | |
| | | | |
End of changes. 63 change blocks. |
| 64 lines changed or deleted | | 64 lines changed or added | |
|
| kcdbext.h | | kcdbext.h | |
| | | | |
| skipping to change at line 43 | | skipping to change at line 43 | |
| #include <kcpolydb.h> | | #include <kcpolydb.h> | |
| | | | |
| namespace kyotocabinet { // common namespace | | namespace kyotocabinet { // common namespace | |
| | | | |
| /** | | /** | |
| * MapReduce framework. | | * MapReduce framework. | |
| * @note Although this framework is not distributed or concurrent, it is us
eful for aggregate | | * @note Although this framework is not distributed or concurrent, it is us
eful for aggregate | |
| * calculation with less CPU loading and less memory usage. | | * calculation with less CPU loading and less memory usage. | |
| */ | | */ | |
| class MapReduce { | | class MapReduce { | |
|
| public: | | public: | |
| class MapEmitter; | | class MapEmitter; | |
| class ValueIterator; | | class ValueIterator; | |
|
| private: | | private: | |
| class MapVisitor; | | class MapVisitor; | |
| struct MergeLine; | | struct MergeLine; | |
| /** An alias of vector of loaded values. */ | | /** An alias of vector of loaded values. */ | |
| typedef std::vector<std::string> Values; | | typedef std::vector<std::string> Values; | |
| /** The default number of temporary databases. */ | | /** The default number of temporary databases. */ | |
| static const size_t MRDEFDBNUM = 8; | | static const size_t MRDEFDBNUM = 8; | |
| /** The maxinum number of temporary databases. */ | | /** The maxinum number of temporary databases. */ | |
| static const size_t MRMAXDBNUM = 256; | | static const size_t MRMAXDBNUM = 256; | |
| /** The default cache limit. */ | | /** The default cache limit. */ | |
| static const int64_t MRDEFCLIM = 512LL << 20; | | static const int64_t MRDEFCLIM = 512LL << 20; | |
| /** The default cache bucket numer. */ | | /** The default cache bucket numer. */ | |
| static const int64_t MRDEFCBNUM = 1048583LL; | | static const int64_t MRDEFCBNUM = 1048583LL; | |
| /** The bucket number of temprary databases. */ | | /** The bucket number of temprary databases. */ | |
| static const int64_t MRDBBNUM = 512LL << 10; | | static const int64_t MRDBBNUM = 512LL << 10; | |
| /** The page size of temprary databases. */ | | /** The page size of temprary databases. */ | |
| static const int32_t MRDBPSIZ = 32768; | | static const int32_t MRDBPSIZ = 32768; | |
| /** The mapped size of temprary databases. */ | | /** The mapped size of temprary databases. */ | |
| static const int64_t MRDBMSIZ = 516LL * 4096; | | static const int64_t MRDBMSIZ = 516LL * 4096; | |
| /** The page cache capacity of temprary databases. */ | | /** The page cache capacity of temprary databases. */ | |
| static const int64_t MRDBPCCAP = 16LL << 20; | | static const int64_t MRDBPCCAP = 16LL << 20; | |
|
| public: | | public: | |
| /** | | /** | |
| * Data emitter for the mapper. | | * Data emitter for the mapper. | |
| */ | | */ | |
| class MapEmitter { | | class MapEmitter { | |
| friend class MapReduce; | | friend class MapReduce; | |
| friend class MapReduce::MapVisitor; | | friend class MapReduce::MapVisitor; | |
|
| public: | | public: | |
| /** | | /** | |
| * Emit a record from the mapper. | | * Emit a record from the mapper. | |
| * @param kbuf the pointer to the key region. | | * @param kbuf the pointer to the key region. | |
| * @param ksiz the size of the key region. | | * @param ksiz the size of the key region. | |
| * @param vbuf the pointer to the value region. | | * @param vbuf the pointer to the value region. | |
| * @param vsiz the size of the value region. | | * @param vsiz the size of the value region. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool emit(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz)
{ | | bool emit(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz)
{ | |
| _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ); | | _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ); | |
| | | | |
| skipping to change at line 97 | | skipping to change at line 97 | |
| char stack[NUMBUFSIZ*4]; | | char stack[NUMBUFSIZ*4]; | |
| char* rbuf = rsiz > sizeof(stack) ? new char[rsiz] : stack; | | char* rbuf = rsiz > sizeof(stack) ? new char[rsiz] : stack; | |
| char* wp = rbuf; | | char* wp = rbuf; | |
| wp += writevarnum(rbuf, vsiz); | | wp += writevarnum(rbuf, vsiz); | |
| std::memcpy(wp, vbuf, vsiz); | | std::memcpy(wp, vbuf, vsiz); | |
| mr_->cache_->append(kbuf, ksiz, rbuf, rsiz); | | mr_->cache_->append(kbuf, ksiz, rbuf, rsiz); | |
| if (rbuf != stack) delete[] rbuf; | | if (rbuf != stack) delete[] rbuf; | |
| mr_->csiz_ += rsiz; | | mr_->csiz_ += rsiz; | |
| return !err; | | return !err; | |
| } | | } | |
|
| private: | | private: | |
| /** | | /** | |
| * Default constructor. | | * Default constructor. | |
| */ | | */ | |
| explicit MapEmitter(MapReduce* mr) : mr_(mr) { | | explicit MapEmitter(MapReduce* mr) : mr_(mr) { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| */ | | */ | |
| ~MapEmitter() { | | ~MapEmitter() { | |
| | | | |
| skipping to change at line 122 | | skipping to change at line 122 | |
| /** Dummy Operator to forbid the use. */ | | /** Dummy Operator to forbid the use. */ | |
| MapEmitter& operator =(const MapEmitter&); | | MapEmitter& operator =(const MapEmitter&); | |
| /** The owner object. */ | | /** The owner object. */ | |
| MapReduce* mr_; | | MapReduce* mr_; | |
| }; | | }; | |
| /** | | /** | |
| * Value iterator for the reducer. | | * Value iterator for the reducer. | |
| */ | | */ | |
| class ValueIterator { | | class ValueIterator { | |
| friend class MapReduce; | | friend class MapReduce; | |
|
| public: | | public: | |
| /** | | /** | |
| * Get the next value. | | * Get the next value. | |
| * @param sp the pointer to the variable into which the size of the reg
ion of the return | | * @param sp the pointer to the variable into which the size of the reg
ion of the return | |
| * value is assigned. | | * value is assigned. | |
| * @return the pointer to the next value region, or NULL if no value re
mains. | | * @return the pointer to the next value region, or NULL if no value re
mains. | |
| */ | | */ | |
| const char* next(size_t* sp) { | | const char* next(size_t* sp) { | |
| _assert_(sp); | | _assert_(sp); | |
| if (!vptr_) { | | if (!vptr_) { | |
| if (vit_ == vend_) return NULL; | | if (vit_ == vend_) return NULL; | |
| | | | |
| skipping to change at line 148 | | skipping to change at line 148 | |
| size_t step = readvarnum(vptr_, vsiz_, &vsiz); | | size_t step = readvarnum(vptr_, vsiz_, &vsiz); | |
| vptr_ += step; | | vptr_ += step; | |
| vsiz_ -= step; | | vsiz_ -= step; | |
| const char* vbuf = vptr_; | | const char* vbuf = vptr_; | |
| *sp = vsiz; | | *sp = vsiz; | |
| vptr_ += vsiz; | | vptr_ += vsiz; | |
| vsiz_ -= vsiz; | | vsiz_ -= vsiz; | |
| if (vsiz_ < 1) vptr_ = NULL; | | if (vsiz_ < 1) vptr_ = NULL; | |
| return vbuf; | | return vbuf; | |
| } | | } | |
|
| private: | | private: | |
| /** | | /** | |
| * Default constructor. | | * Default constructor. | |
| */ | | */ | |
| explicit ValueIterator(Values::const_iterator vit, Values::const_iterat
or vend) : | | explicit ValueIterator(Values::const_iterator vit, Values::const_iterat
or vend) : | |
|
| vit_(vit), vend_(vend), vptr_(NULL), vsiz_(0) { | | vit_(vit), vend_(vend), vptr_(NULL), vsiz_(0) { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| */ | | */ | |
| ~ValueIterator() { | | ~ValueIterator() { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| /** Dummy constructor to forbid the use. */ | | /** Dummy constructor to forbid the use. */ | |
| ValueIterator(const ValueIterator&); | | ValueIterator(const ValueIterator&); | |
| | | | |
| skipping to change at line 186 | | skipping to change at line 186 | |
| * Execution options. | | * Execution options. | |
| */ | | */ | |
| enum Option { | | enum Option { | |
| XNOLOCK = 1 << 0, ///< avoid locking against update
operations | | XNOLOCK = 1 << 0, ///< avoid locking against update
operations | |
| XNOCOMP = 1 << 1 ///< avoid compression of temporar
y databases | | XNOCOMP = 1 << 1 ///< avoid compression of temporar
y databases | |
| }; | | }; | |
| /** | | /** | |
| * Default constructor. | | * Default constructor. | |
| */ | | */ | |
| explicit MapReduce() : | | explicit MapReduce() : | |
|
| rcomp_(NULL), tmpdbs_(NULL), dbnum_(MRDEFDBNUM), dbclock_(0), keyclock_ | | rcomp_(NULL), tmpdbs_(NULL), dbnum_(MRDEFDBNUM), dbclock_(0), keycloc | |
| (0), | | k_(0), | |
| cache_(NULL), csiz_(0), clim_(MRDEFCLIM), cbnum_(MRDEFCBNUM) { | | cache_(NULL), csiz_(0), clim_(MRDEFCLIM), cbnum_(MRDEFCBNUM) { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| */ | | */ | |
| virtual ~MapReduce() { | | virtual ~MapReduce() { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| /** | | /** | |
| * Map a record data. | | * Map a record data. | |
| | | | |
| skipping to change at line 323 | | skipping to change at line 323 | |
| return false; | | return false; | |
| } | | } | |
| if (!logf("prepare", "started to open temporary databases under %s",
tmppath.c_str())) | | if (!logf("prepare", "started to open temporary databases under %s",
tmppath.c_str())) | |
| err = true; | | err = true; | |
| stime = time(); | | stime = time(); | |
| uint32_t pid = getpid() & UINT16MAX; | | uint32_t pid = getpid() & UINT16MAX; | |
| uint32_t tid = Thread::hash() & UINT16MAX; | | uint32_t tid = Thread::hash() & UINT16MAX; | |
| uint32_t ts = time() * 1000; | | uint32_t ts = time() * 1000; | |
| for (size_t i = 0; i < dbnum_; i++) { | | for (size_t i = 0; i < dbnum_; i++) { | |
| std::string childpath = | | std::string childpath = | |
|
| strprintf("%s%cmr-%04x-%04x-%08x-%03d%ckct", | | strprintf("%s%cmr-%04x-%04x-%08x-%03d%ckct", | |
| tmppath.c_str(), File::PATHCHR, pid, tid, ts, (int)(i + | | tmppath.c_str(), File::PATHCHR, pid, tid, ts, (int)(i | |
| 1), File::EXTCHR); | | + 1), File::EXTCHR); | |
| TreeDB* tdb = new TreeDB; | | TreeDB* tdb = new TreeDB; | |
| int32_t myopts = TreeDB::TSMALL | TreeDB::TLINEAR; | | int32_t myopts = TreeDB::TSMALL | TreeDB::TLINEAR; | |
| if (!(opts & XNOCOMP)) myopts |= TreeDB::TCOMPRESS; | | if (!(opts & XNOCOMP)) myopts |= TreeDB::TCOMPRESS; | |
| tdb->tune_options(myopts); | | tdb->tune_options(myopts); | |
| tdb->tune_buckets(MRDBBNUM); | | tdb->tune_buckets(MRDBBNUM); | |
| tdb->tune_page(MRDBPSIZ); | | tdb->tune_page(MRDBPSIZ); | |
| tdb->tune_map(MRDBMSIZ); | | tdb->tune_map(MRDBMSIZ); | |
| tdb->tune_page_cache(MRDBPCCAP); | | tdb->tune_page_cache(MRDBPCCAP); | |
| tdb->tune_comparator(rcomp_); | | tdb->tune_comparator(rcomp_); | |
| if (!tdb->open(childpath, TreeDB::OWRITER | TreeDB::OCREATE | TreeD
B::OTRUNCATE)) { | | if (!tdb->open(childpath, TreeDB::OWRITER | TreeDB::OCREATE | TreeD
B::OTRUNCATE)) { | |
| | | | |
| skipping to change at line 413 | | skipping to change at line 413 | |
| * @param cbnum the bucket number of the internal cache. | | * @param cbnum the bucket number of the internal cache. | |
| */ | | */ | |
| void tune_storage(int32_t dbnum, int64_t clim, int64_t cbnum) { | | void tune_storage(int32_t dbnum, int64_t clim, int64_t cbnum) { | |
| _assert_(true); | | _assert_(true); | |
| dbnum_ = dbnum > 0 ? dbnum : MRDEFDBNUM; | | dbnum_ = dbnum > 0 ? dbnum : MRDEFDBNUM; | |
| if (dbnum_ > MRMAXDBNUM) dbnum_ = MRMAXDBNUM; | | if (dbnum_ > MRMAXDBNUM) dbnum_ = MRMAXDBNUM; | |
| clim_ = clim > 0 ? clim : MRDEFCLIM; | | clim_ = clim > 0 ? clim : MRDEFCLIM; | |
| cbnum_ = cbnum > 0 ? cbnum : MRDEFCBNUM; | | cbnum_ = cbnum > 0 ? cbnum : MRDEFCBNUM; | |
| if (cbnum_ > INT16MAX) cbnum_ = nearbyprime(cbnum_); | | if (cbnum_ > INT16MAX) cbnum_ = nearbyprime(cbnum_); | |
| } | | } | |
|
| private: | | private: | |
| /** | | /** | |
| * Checker for the map process. | | * Checker for the map process. | |
| */ | | */ | |
| class MapChecker : public BasicDB::ProgressChecker { | | class MapChecker : public BasicDB::ProgressChecker { | |
|
| public: | | public: | |
| /** constructor */ | | /** constructor */ | |
| explicit MapChecker() : stop_(false) {} | | explicit MapChecker() : stop_(false) {} | |
| /** stop the process */ | | /** stop the process */ | |
| void stop() { | | void stop() { | |
| stop_ = true; | | stop_ = true; | |
| } | | } | |
| /** check whether stopped */ | | /** check whether stopped */ | |
| bool stopped() { | | bool stopped() { | |
| return stop_; | | return stop_; | |
| } | | } | |
|
| private: | | private: | |
| /** check whether stopped */ | | /** check whether stopped */ | |
| bool check(const char* name, const char* message, int64_t curcnt, int64
_t allcnt) { | | bool check(const char* name, const char* message, int64_t curcnt, int64
_t allcnt) { | |
| return !stop_; | | return !stop_; | |
| } | | } | |
| bool stop_; ///< flag for stop | | bool stop_; ///< flag for stop | |
| }; | | }; | |
| /** | | /** | |
| * Visitor for the map process. | | * Visitor for the map process. | |
| */ | | */ | |
| class MapVisitor : public BasicDB::Visitor { | | class MapVisitor : public BasicDB::Visitor { | |
|
| public: | | public: | |
| /** constructor */ | | /** constructor */ | |
| explicit MapVisitor(MapReduce* mr, MapChecker* checker, int64_t scale)
: | | explicit MapVisitor(MapReduce* mr, MapChecker* checker, int64_t scale)
: | |
|
| mr_(mr), checker_(checker), emitter_(mr), scale_(scale), | | mr_(mr), checker_(checker), emitter_(mr), scale_(scale), | |
| stime_(0), err_(false) {} | | stime_(0), err_(false) {} | |
| /** get the error flag */ | | /** get the error flag */ | |
| bool error() { | | bool error() { | |
| return err_; | | return err_; | |
| } | | } | |
| /** preprocess the mappter */ | | /** preprocess the mappter */ | |
| void visit_before() { | | void visit_before() { | |
| if (!mr_->preprocess()) err_ = true; | | if (!mr_->preprocess()) err_ = true; | |
| stime_ = time(); | | stime_ = time(); | |
| mr_->dbclock_ = 0; | | mr_->dbclock_ = 0; | |
| mr_->keyclock_ = 0; | | mr_->keyclock_ = 0; | |
| | | | |
| skipping to change at line 471 | | skipping to change at line 471 | |
| void visit_after() { | | void visit_after() { | |
| if (mr_->cache_->count() > 0 && !mr_->flush_cache()) err_ = true; | | if (mr_->cache_->count() > 0 && !mr_->flush_cache()) err_ = true; | |
| delete mr_->cache_; | | delete mr_->cache_; | |
| if (!mr_->midprocess()) err_ = true; | | if (!mr_->midprocess()) err_ = true; | |
| double etime = time(); | | double etime = time(); | |
| if (!mr_->logf("map", "the map process finished: time=%.6f", etime -
stime_)) | | if (!mr_->logf("map", "the map process finished: time=%.6f", etime -
stime_)) | |
| err_ = true; | | err_ = true; | |
| if (!err_ && !mr_->execute_reduce()) err_ = true; | | if (!err_ && !mr_->execute_reduce()) err_ = true; | |
| if (!mr_->postprocess()) err_ = true; | | if (!mr_->postprocess()) err_ = true; | |
| } | | } | |
|
| private: | | private: | |
| /** visit a record */ | | /** visit a record */ | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| if (!mr_->map(kbuf, ksiz, vbuf, vsiz, &emitter_)) { | | if (!mr_->map(kbuf, ksiz, vbuf, vsiz, &emitter_)) { | |
| checker_->stop(); | | checker_->stop(); | |
| err_ = true; | | err_ = true; | |
| } | | } | |
| if (mr_->csiz_ >= mr_->clim_ && !mr_->flush_cache()) { | | if (mr_->csiz_ >= mr_->clim_ && !mr_->flush_cache()) { | |
| checker_->stop(); | | checker_->stop(); | |
| err_ = true; | | err_ = true; | |
| | | | |
End of changes. 16 change blocks. |
| 21 lines changed or deleted | | 21 lines changed or added | |
|
| kcdirdb.h | | kcdirdb.h | |
| | | | |
| skipping to change at line 52 | | skipping to change at line 52 | |
| * @note This class is a concrete class to operate a hash database in a dir
ectory. This class | | * @note This class is a concrete class to operate a hash database in a dir
ectory. This class | |
| * can be inherited but overwriting methods is forbidden. Before every dat
abase operation, it is | | * can be inherited but overwriting methods is forbidden. Before every dat
abase operation, it is | |
| * necessary to call the TreeDB::open method in order to open a database fi
le and connect the | | * necessary to call the TreeDB::open method in order to open a database fi
le and connect the | |
| * database object to it. To avoid data missing or corruption, it is impor
tant to close every | | * database object to it. To avoid data missing or corruption, it is impor
tant to close every | |
| * database file by the TreeDB::close method when the database is no longer
in use. It is | | * database file by the TreeDB::close method when the database is no longer
in use. It is | |
| * forbidden for multible database objects in a process to open the same da
tabase at the same | | * forbidden for multible database objects in a process to open the same da
tabase at the same | |
| * time. It is forbidden to share a database object with child processes. | | * time. It is forbidden to share a database object with child processes. | |
| */ | | */ | |
| class DirDB : public BasicDB { | | class DirDB : public BasicDB { | |
| friend class PlantDB<DirDB, BasicDB::TYPEFOREST>; | | friend class PlantDB<DirDB, BasicDB::TYPEFOREST>; | |
|
| public: | | public: | |
| class Cursor; | | class Cursor; | |
|
| private: | | private: | |
| struct Record; | | struct Record; | |
| class ScopedVisitor; | | class ScopedVisitor; | |
| /** An alias of list of cursors. */ | | /** An alias of list of cursors. */ | |
| typedef std::list<Cursor*> CursorList; | | typedef std::list<Cursor*> CursorList; | |
| /** An alias of vector of strings. */ | | /** An alias of vector of strings. */ | |
| typedef std::vector<std::string> StringVector; | | typedef std::vector<std::string> StringVector; | |
| /** The size of the meta data buffer. */ | | /** The size of the meta data buffer. */ | |
| static const int64_t METABUFSIZ = 128; | | static const int64_t METABUFSIZ = 128; | |
| /** The magic data for record. */ | | /** The magic data for record. */ | |
| static const uint8_t RECMAGIC = 0xcc; | | static const uint8_t RECMAGIC = 0xcc; | |
| /** The number of slots of the record lock. */ | | /** The number of slots of the record lock. */ | |
| static const int32_t RLOCKSLOT = 2048; | | static const int32_t RLOCKSLOT = 2048; | |
| /** The unit size of a record. */ | | /** The unit size of a record. */ | |
| static const int32_t RECUNITSIZ = 32; | | static const int32_t RECUNITSIZ = 32; | |
| /** The size of the opaque buffer. */ | | /** The size of the opaque buffer. */ | |
| static const size_t OPAQUESIZ = 16; | | static const size_t OPAQUESIZ = 16; | |
| /** The threshold of busy loop and sleep for locking. */ | | /** The threshold of busy loop and sleep for locking. */ | |
| static const uint32_t LOCKBUSYLOOP = 8192; | | static const uint32_t LOCKBUSYLOOP = 8192; | |
|
| public: | | public: | |
| /** | | /** | |
| * Cursor to indicate a record. | | * Cursor to indicate a record. | |
| */ | | */ | |
| class Cursor : public BasicDB::Cursor { | | class Cursor : public BasicDB::Cursor { | |
| friend class DirDB; | | friend class DirDB; | |
|
| public: | | public: | |
| /** | | /** | |
| * Constructor. | | * Constructor. | |
| * @param db the container database object. | | * @param db the container database object. | |
| */ | | */ | |
| explicit Cursor(DirDB* db) : db_(db), dir_(), alive_(false), name_("")
{ | | explicit Cursor(DirDB* db) : db_(db), dir_(), alive_(false), name_("")
{ | |
| _assert_(db); | | _assert_(db); | |
| ScopedSpinRWLock lock(&db_->mlock_, true); | | ScopedSpinRWLock lock(&db_->mlock_, true); | |
| db_->curs_.push_back(this); | | db_->curs_.push_back(this); | |
| } | | } | |
| /** | | /** | |
| | | | |
| skipping to change at line 330 | | skipping to change at line 330 | |
| return false; | | return false; | |
| } | | } | |
| /** | | /** | |
| * Get the database object. | | * Get the database object. | |
| * @return the database object. | | * @return the database object. | |
| */ | | */ | |
| DirDB* db() { | | DirDB* db() { | |
| _assert_(true); | | _assert_(true); | |
| return db_; | | return db_; | |
| } | | } | |
|
| private: | | private: | |
| /** | | /** | |
| * Disable the cursor. | | * Disable the cursor. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool disable() { | | bool disable() { | |
| bool err = false; | | bool err = false; | |
| if (!dir_.close()) { | | if (!dir_.close()) { | |
| db_->set_error(_KCCODELINE_, Error::SYSTEM, "closing a directory fa
iled"); | | db_->set_error(_KCCODELINE_, Error::SYSTEM, "closing a directory fa
iled"); | |
| err = true; | | err = true; | |
| } | | } | |
| | | | |
| skipping to change at line 376 | | skipping to change at line 376 | |
| * Status flags. | | * Status flags. | |
| */ | | */ | |
| enum Flag { | | enum Flag { | |
| FOPEN = 1 << 0, ///< dummy for compatibility | | FOPEN = 1 << 0, ///< dummy for compatibility | |
| FFATAL = 1 << 1 ///< dummy for compatibility | | FFATAL = 1 << 1 ///< dummy for compatibility | |
| }; | | }; | |
| /** | | /** | |
| * Default constructor. | | * Default constructor. | |
| */ | | */ | |
| explicit DirDB() : | | explicit DirDB() : | |
|
| mlock_(), rlock_(RLOCKSLOT), error_(), logger_(NULL), logkinds_(0), mtr | | mlock_(), rlock_(RLOCKSLOT), error_(), | |
| igger_(NULL), | | logger_(NULL), logkinds_(0), mtrigger_(NULL), | |
| omode_(0), writer_(false), autotran_(false), autosync_(false), recov_(f | | omode_(0), writer_(false), autotran_(false), autosync_(false), | |
| alse), reorg_(false), | | recov_(false), reorg_(false), | |
| file_(), curs_(), path_(""), | | file_(), curs_(), path_(""), | |
| libver_(LIBVER), librev_(LIBREV), fmtver_(FMTVER), chksum_(0), type_(TY | | libver_(LIBVER), librev_(LIBREV), fmtver_(FMTVER), chksum_(0), type_( | |
| PEDIR), | | TYPEDIR), | |
| flags_(0), opts_(0), count_(0), size_(0), opaque_(), embcomp_(ZLIBRAWCO | | flags_(0), opts_(0), count_(0), size_(0), opaque_(), embcomp_(ZLIBRAW | |
| MP), comp_(NULL), | | COMP), comp_(NULL), | |
| tran_(false), trhard_(false), trcount_(0), trsize_(0), walpath_(""), tm | | tran_(false), trhard_(false), trcount_(0), trsize_(0), walpath_(""), | |
| ppath_("") { | | tmppath_("") { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| * @note If the database is not closed, it is closed implicitly. | | * @note If the database is not closed, it is closed implicitly. | |
| */ | | */ | |
| virtual ~DirDB() { | | virtual ~DirDB() { | |
| _assert_(true); | | _assert_(true); | |
| if (omode_ != 0) close(); | | if (omode_ != 0) close(); | |
| if (!curs_.empty()) { | | if (!curs_.empty()) { | |
| | | | |
| skipping to change at line 550 | | skipping to change at line 552 | |
| * @param code an error code. | | * @param code an error code. | |
| * @param message a supplement message. | | * @param message a supplement message. | |
| */ | | */ | |
| void set_error(const char* file, int32_t line, const char* func, | | void set_error(const char* file, int32_t line, const char* func, | |
| Error::Code code, const char* message) { | | Error::Code code, const char* message) { | |
| _assert_(file && line > 0 && func && message); | | _assert_(file && line > 0 && func && message); | |
| error_->set(code, message); | | error_->set(code, message); | |
| if (code == Error::BROKEN || code == Error::SYSTEM) flags_ |= FFATAL; | | if (code == Error::BROKEN || code == Error::SYSTEM) flags_ |= FFATAL; | |
| if (logger_) { | | if (logger_) { | |
| Logger::Kind kind = code == Error::BROKEN || code == Error::SYSTEM ? | | Logger::Kind kind = code == Error::BROKEN || code == Error::SYSTEM ? | |
|
| Logger::ERROR : Logger::INFO; | | Logger::ERROR : Logger::INFO; | |
| if (kind & logkinds_) | | if (kind & logkinds_) | |
| report(file, line, func, kind, "%d: %s: %s", code, Error::codename(
code), message); | | report(file, line, func, kind, "%d: %s: %s", code, Error::codename(
code), message); | |
| } | | } | |
| } | | } | |
| /** | | /** | |
| * Open a database file. | | * Open a database file. | |
| * @param path the path of a database file. | | * @param path the path of a database file. | |
| * @param mode the connection mode. DirDB::OWRITER as a writer, DirDB::O
READER as a | | * @param mode the connection mode. DirDB::OWRITER as a writer, DirDB::O
READER as a | |
| * reader. The following may be added to the writer mode by bitwise-or:
DirDB::OCREATE, | | * reader. The following may be added to the writer mode by bitwise-or:
DirDB::OCREATE, | |
| * which means it creates a new database if the file does not exist, DirD
B::OTRUNCATE, which | | * which means it creates a new database if the file does not exist, DirD
B::OTRUNCATE, which | |
| | | | |
| skipping to change at line 1188 | | skipping to change at line 1190 | |
| */ | | */ | |
| uint8_t flags() { | | uint8_t flags() { | |
| _assert_(true); | | _assert_(true); | |
| ScopedSpinRWLock lock(&mlock_, false); | | ScopedSpinRWLock lock(&mlock_, false); | |
| if (omode_ == 0) { | | if (omode_ == 0) { | |
| set_error(_KCCODELINE_, Error::INVALID, "not opened"); | | set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |
| return 0; | | return 0; | |
| } | | } | |
| return 0; | | return 0; | |
| } | | } | |
|
| protected: | | protected: | |
| /** | | /** | |
| * Report a message for debugging. | | * Report a message for debugging. | |
| * @param file the file name of the program source code. | | * @param file the file name of the program source code. | |
| * @param line the line number 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 func the function name of the program source code. | |
| * @param kind the kind of the event. Logger::DEBUG for debugging, Logge
r::INFO for normal | | * @param kind the kind of the event. Logger::DEBUG for debugging, Logge
r::INFO for normal | |
| * information, Logger::WARN for warning, and Logger::ERROR for fatal err
or. | | * information, Logger::WARN for warning, and Logger::ERROR for fatal err
or. | |
| * @param format the printf-like format string. | | * @param format the printf-like format string. | |
| * @param ... used according to the format string. | | * @param ... used according to the format string. | |
| */ | | */ | |
| | | | |
| skipping to change at line 1394 | | skipping to change at line 1396 | |
| */ | | */ | |
| bool reorganized() { | | bool reorganized() { | |
| _assert_(true); | | _assert_(true); | |
| ScopedSpinRWLock lock(&mlock_, false); | | ScopedSpinRWLock lock(&mlock_, false); | |
| if (omode_ == 0) { | | if (omode_ == 0) { | |
| set_error(_KCCODELINE_, Error::INVALID, "not opened"); | | set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |
| return false; | | return false; | |
| } | | } | |
| return reorg_; | | return reorg_; | |
| } | | } | |
|
| private: | | private: | |
| /** | | /** | |
| * Set the power of the alignment of record size. | | * Set the power of the alignment of record size. | |
| * @note This is a dummy implementation for compatibility. | | * @note This is a dummy implementation for compatibility. | |
| */ | | */ | |
| bool tune_alignment(int8_t apow) { | | bool tune_alignment(int8_t apow) { | |
| return true; | | return true; | |
| } | | } | |
| /** | | /** | |
| * Set the power of the capacity of the free block pool. | | * Set the power of the capacity of the free block pool. | |
| * @note This is a dummy implementation for compatibility. | | * @note This is a dummy implementation for compatibility. | |
| | | | |
| skipping to change at line 1472 | | skipping to change at line 1474 | |
| int64_t msiz() { | | int64_t msiz() { | |
| return 0; | | return 0; | |
| } | | } | |
| /** | | /** | |
| * Get the unit step number of auto defragmentation. | | * Get the unit step number of auto defragmentation. | |
| * @note This is a dummy implementation for compatibility. | | * @note This is a dummy implementation for compatibility. | |
| */ | | */ | |
| int64_t dfunit() { | | int64_t dfunit() { | |
| return 0; | | return 0; | |
| } | | } | |
|
| private: | | private: | |
| /** | | /** | |
| * Record data. | | * Record data. | |
| */ | | */ | |
| struct Record { | | struct Record { | |
| char* rbuf; ///< record buffer | | char* rbuf; ///< record buffer | |
| size_t rsiz; ///< record size | | size_t rsiz; ///< record size | |
| const char* kbuf; ///< key buffer | | const char* kbuf; ///< key buffer | |
| size_t ksiz; ///< key size | | size_t ksiz; ///< key size | |
| const char* vbuf; ///< value buffer | | const char* vbuf; ///< value buffer | |
| size_t vsiz; ///< value size | | size_t vsiz; ///< value size | |
| }; | | }; | |
| /** | | /** | |
| * Scoped visitor. | | * Scoped visitor. | |
| */ | | */ | |
| class ScopedVisitor { | | class ScopedVisitor { | |
|
| public: | | public: | |
| /** constructor */ | | /** constructor */ | |
| explicit ScopedVisitor(Visitor* visitor) : visitor_(visitor) { | | explicit ScopedVisitor(Visitor* visitor) : visitor_(visitor) { | |
| _assert_(visitor); | | _assert_(visitor); | |
| visitor_->visit_before(); | | visitor_->visit_before(); | |
| } | | } | |
| /** destructor */ | | /** destructor */ | |
| ~ScopedVisitor() { | | ~ScopedVisitor() { | |
| _assert_(true); | | _assert_(true); | |
| visitor_->visit_after(); | | visitor_->visit_after(); | |
| } | | } | |
|
| private: | | private: | |
| Visitor* visitor_; ///< visitor | | Visitor* visitor_; ///< visitor | |
| }; | | }; | |
| /** | | /** | |
| * Dump the magic data into the file. | | * Dump the magic data into the file. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool dump_magic() { | | bool dump_magic() { | |
| _assert_(true); | | _assert_(true); | |
| const std::string& buf = format_magic(count_, size_); | | const std::string& buf = format_magic(count_, size_); | |
| if (!file_.write(0, buf.c_str(), buf.size())) { | | if (!file_.write(0, buf.c_str(), buf.size())) { | |
| | | | |
End of changes. 12 change blocks. |
| 22 lines changed or deleted | | 22 lines changed or added | |
|
| kchashdb.h | | kchashdb.h | |
| | | | |
| skipping to change at line 47 | | skipping to change at line 47 | |
| * @note This class is a concrete class to operate a hash database on a fil
e. This class can be | | * @note This class is a concrete class to operate a hash database on a fil
e. This class can be | |
| * inherited but overwriting methods is forbidden. Before every database o
peration, it is | | * inherited but overwriting methods is forbidden. Before every database o
peration, it is | |
| * necessary to call the HashDB::open method in order to open a database fi
le and connect the | | * necessary to call the HashDB::open method in order to open a database fi
le and connect the | |
| * database object to it. To avoid data missing or corruption, it is impor
tant to close every | | * database object to it. To avoid data missing or corruption, it is impor
tant to close every | |
| * database file by the HashDB::close method when the database is no longer
in use. It is | | * database file by the HashDB::close method when the database is no longer
in use. It is | |
| * forbidden for multible database objects in a process to open the same da
tabase at the same | | * forbidden for multible database objects in a process to open the same da
tabase at the same | |
| * time. It is forbidden to share a database object with child processes. | | * time. It is forbidden to share a database object with child processes. | |
| */ | | */ | |
| class HashDB : public BasicDB { | | class HashDB : public BasicDB { | |
| friend class PlantDB<HashDB, BasicDB::TYPETREE>; | | friend class PlantDB<HashDB, BasicDB::TYPETREE>; | |
|
| public: | | public: | |
| class Cursor; | | class Cursor; | |
|
| private: | | private: | |
| struct Record; | | struct Record; | |
| struct FreeBlock; | | struct FreeBlock; | |
| struct FreeBlockComparator; | | struct FreeBlockComparator; | |
| class Repeater; | | class Repeater; | |
| class ScopedVisitor; | | class ScopedVisitor; | |
| /** An alias of set of free blocks. */ | | /** An alias of set of free blocks. */ | |
| typedef std::set<FreeBlock> FBP; | | typedef std::set<FreeBlock> FBP; | |
| /** An alias of list of cursors. */ | | /** An alias of list of cursors. */ | |
| typedef std::list<Cursor*> CursorList; | | typedef std::list<Cursor*> CursorList; | |
| /** The offset of the library version. */ | | /** The offset of the library version. */ | |
| | | | |
| skipping to change at line 125 | | skipping to change at line 125 | |
| /** The magic data for free block. */ | | /** The magic data for free block. */ | |
| static const uint8_t FBMAGIC = 0xdd; | | static const uint8_t FBMAGIC = 0xdd; | |
| /** The maximum unit of auto defragmentation. */ | | /** The maximum unit of auto defragmentation. */ | |
| static const int32_t DFRGMAX = 512; | | static const int32_t DFRGMAX = 512; | |
| /** The coefficient of auto defragmentation. */ | | /** The coefficient of auto defragmentation. */ | |
| static const int32_t DFRGCEF = 2; | | static const int32_t DFRGCEF = 2; | |
| /** The checking width for record salvage. */ | | /** The checking width for record salvage. */ | |
| static const int64_t SLVGWIDTH = 1LL << 20; | | static const int64_t SLVGWIDTH = 1LL << 20; | |
| /** The threshold of busy loop and sleep for locking. */ | | /** The threshold of busy loop and sleep for locking. */ | |
| static const uint32_t LOCKBUSYLOOP = 8192; | | static const uint32_t LOCKBUSYLOOP = 8192; | |
|
| public: | | public: | |
| /** | | /** | |
| * Cursor to indicate a record. | | * Cursor to indicate a record. | |
| */ | | */ | |
| class Cursor : public BasicDB::Cursor { | | class Cursor : public BasicDB::Cursor { | |
| friend class HashDB; | | friend class HashDB; | |
|
| public: | | public: | |
| /** | | /** | |
| * Constructor. | | * Constructor. | |
| * @param db the container database object. | | * @param db the container database object. | |
| */ | | */ | |
| explicit Cursor(HashDB* db) : db_(db), off_(0), end_(0) { | | explicit Cursor(HashDB* db) : db_(db), off_(0), end_(0) { | |
| _assert_(db); | | _assert_(db); | |
| ScopedSpinRWLock lock(&db_->mlock_, true); | | ScopedSpinRWLock lock(&db_->mlock_, true); | |
| db_->curs_.push_back(this); | | db_->curs_.push_back(this); | |
| } | | } | |
| /** | | /** | |
| | | | |
| skipping to change at line 326 | | skipping to change at line 326 | |
| while (off > 0) { | | while (off > 0) { | |
| rec.off = off; | | rec.off = off; | |
| if (!db_->read_record(&rec, rbuf)) return false; | | if (!db_->read_record(&rec, rbuf)) return false; | |
| if (rec.psiz == UINT16MAX) { | | if (rec.psiz == UINT16MAX) { | |
| db_->set_error(_KCCODELINE_, Error::BROKEN, "free block in the ch
ain"); | | db_->set_error(_KCCODELINE_, Error::BROKEN, "free block in the ch
ain"); | |
| db_->report(_KCCODELINE_, Logger::WARN, "psiz=%lld off=%lld fsiz=
%lld", | | db_->report(_KCCODELINE_, Logger::WARN, "psiz=%lld off=%lld fsiz=
%lld", | |
| (long long)db_->psiz_, (long long)rec.off, (long long
)db_->file_.size()); | | (long long)db_->psiz_, (long long)rec.off, (long long
)db_->file_.size()); | |
| return false; | | return false; | |
| } | | } | |
| uint32_t tpivot = db_->linear_ ? pivot : | | uint32_t tpivot = db_->linear_ ? pivot : | |
|
| db_->fold_hash(db_->hash_record(rec.kbuf, rec.ksiz)); | | db_->fold_hash(db_->hash_record(rec.kbuf, rec.ksiz)); | |
| if (pivot > tpivot) { | | if (pivot > tpivot) { | |
| delete[] rec.bbuf; | | delete[] rec.bbuf; | |
| off = rec.left; | | off = rec.left; | |
| } else if (pivot < tpivot) { | | } else if (pivot < tpivot) { | |
| delete[] rec.bbuf; | | delete[] rec.bbuf; | |
| off = rec.right; | | off = rec.right; | |
| } else { | | } else { | |
| int32_t kcmp = db_->compare_keys(kbuf, ksiz, rec.kbuf, rec.ksiz); | | int32_t kcmp = db_->compare_keys(kbuf, ksiz, rec.kbuf, rec.ksiz); | |
| if (db_->linear_ && kcmp != 0) kcmp = 1; | | if (db_->linear_ && kcmp != 0) kcmp = 1; | |
| if (kcmp > 0) { | | if (kcmp > 0) { | |
| | | | |
| skipping to change at line 450 | | skipping to change at line 450 | |
| return false; | | return false; | |
| } | | } | |
| /** | | /** | |
| * Get the database object. | | * Get the database object. | |
| * @return the database object. | | * @return the database object. | |
| */ | | */ | |
| HashDB* db() { | | HashDB* db() { | |
| _assert_(true); | | _assert_(true); | |
| return db_; | | return db_; | |
| } | | } | |
|
| private: | | private: | |
| /** | | /** | |
| * Step the cursor to the next record. | | * Step the cursor to the next record. | |
| * @param rec the record structure. | | * @param rec the record structure. | |
| * @param rbuf the working buffer. | | * @param rbuf the working buffer. | |
| * @param skip the number of skipping blocks. | | * @param skip the number of skipping blocks. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool step_impl(Record* rec, char* rbuf, int64_t skip) { | | bool step_impl(Record* rec, char* rbuf, int64_t skip) { | |
| _assert_(rec && rbuf && skip >= 0); | | _assert_(rec && rbuf && skip >= 0); | |
| if (off_ >= end_) { | | if (off_ >= end_) { | |
| | | | |
| skipping to change at line 512 | | skipping to change at line 512 | |
| * Status flags. | | * Status flags. | |
| */ | | */ | |
| enum Flag { | | enum Flag { | |
| FOPEN = 1 << 0, ///< whether opened | | FOPEN = 1 << 0, ///< whether opened | |
| FFATAL = 1 << 1 ///< whether with fatal error | | FFATAL = 1 << 1 ///< whether with fatal error | |
| }; | | }; | |
| /** | | /** | |
| * Default constructor. | | * Default constructor. | |
| */ | | */ | |
| explicit HashDB() : | | explicit HashDB() : | |
|
| mlock_(), rlock_(RLOCKSLOT), flock_(), atlock_(), error_(), | | mlock_(), rlock_(RLOCKSLOT), flock_(), atlock_(), error_(), | |
| logger_(NULL), logkinds_(0), mtrigger_(NULL), | | logger_(NULL), logkinds_(0), mtrigger_(NULL), | |
| omode_(0), writer_(false), autotran_(false), autosync_(false), reorg_(f | | omode_(0), writer_(false), autotran_(false), autosync_(false), | |
| alse), trim_(false), | | reorg_(false), trim_(false), | |
| file_(), fbp_(), curs_(), path_(""), | | file_(), fbp_(), curs_(), path_(""), | |
| libver_(0), librev_(0), fmtver_(0), chksum_(0), type_(TYPEHASH), | | libver_(0), librev_(0), fmtver_(0), chksum_(0), type_(TYPEHASH), | |
| apow_(DEFAPOW), fpow_(DEFFPOW), opts_(0), bnum_(DEFBNUM), | | apow_(DEFAPOW), fpow_(DEFFPOW), opts_(0), bnum_(DEFBNUM), | |
| flags_(0), flagopen_(false), count_(0), lsiz_(0), psiz_(0), opaque_(), | | flags_(0), flagopen_(false), count_(0), lsiz_(0), psiz_(0), opaque_() | |
| msiz_(DEFMSIZ), dfunit_(0), embcomp_(ZLIBRAWCOMP), | | , | |
| align_(0), fbpnum_(0), width_(0), linear_(false), | | msiz_(DEFMSIZ), dfunit_(0), embcomp_(ZLIBRAWCOMP), | |
| comp_(NULL), rhsiz_(0), boff_(0), roff_(0), dfcur_(0), frgcnt_(0), | | align_(0), fbpnum_(0), width_(0), linear_(false), | |
| tran_(false), trhard_(false), trfbp_(), trcount_(0), trsize_(0) { | | comp_(NULL), rhsiz_(0), boff_(0), roff_(0), dfcur_(0), frgcnt_(0), | |
| | | tran_(false), trhard_(false), trfbp_(), trcount_(0), trsize_(0) { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| * @note If the database is not closed, it is closed implicitly. | | * @note If the database is not closed, it is closed implicitly. | |
| */ | | */ | |
| virtual ~HashDB() { | | virtual ~HashDB() { | |
| _assert_(true); | | _assert_(true); | |
| if (omode_ != 0) close(); | | if (omode_ != 0) close(); | |
| if (!curs_.empty()) { | | if (!curs_.empty()) { | |
| | | | |
| skipping to change at line 742 | | skipping to change at line 743 | |
| * @param code an error code. | | * @param code an error code. | |
| * @param message a supplement message. | | * @param message a supplement message. | |
| */ | | */ | |
| void set_error(const char* file, int32_t line, const char* func, | | void set_error(const char* file, int32_t line, const char* func, | |
| Error::Code code, const char* message) { | | Error::Code code, const char* message) { | |
| _assert_(file && line > 0 && func && message); | | _assert_(file && line > 0 && func && message); | |
| error_->set(code, message); | | error_->set(code, message); | |
| if (code == Error::BROKEN || code == Error::SYSTEM) flags_ |= FFATAL; | | if (code == Error::BROKEN || code == Error::SYSTEM) flags_ |= FFATAL; | |
| if (logger_) { | | if (logger_) { | |
| Logger::Kind kind = code == Error::BROKEN || code == Error::SYSTEM ? | | Logger::Kind kind = code == Error::BROKEN || code == Error::SYSTEM ? | |
|
| Logger::ERROR : Logger::INFO; | | Logger::ERROR : Logger::INFO; | |
| if (kind & logkinds_) | | if (kind & logkinds_) | |
| report(file, line, func, kind, "%d: %s: %s", code, Error::codename(
code), message); | | report(file, line, func, kind, "%d: %s: %s", code, Error::codename(
code), message); | |
| } | | } | |
| } | | } | |
| /** | | /** | |
| * Open a database file. | | * Open a database file. | |
| * @param path the path of a database file. | | * @param path the path of a database file. | |
| * @param mode the connection mode. HashDB::OWRITER as a writer, HashDB:
:OREADER as a | | * @param mode the connection mode. HashDB::OWRITER as a writer, HashDB:
:OREADER as a | |
| * reader. The following may be added to the writer mode by bitwise-or:
HashDB::OCREATE, | | * reader. The following may be added to the writer mode by bitwise-or:
HashDB::OCREATE, | |
| * which means it creates a new database if the file does not exist, Hash
DB::OTRUNCATE, which | | * which means it creates a new database if the file does not exist, Hash
DB::OTRUNCATE, which | |
| | | | |
| skipping to change at line 1427 | | skipping to change at line 1428 | |
| */ | | */ | |
| uint8_t flags() { | | uint8_t flags() { | |
| _assert_(true); | | _assert_(true); | |
| ScopedSpinRWLock lock(&mlock_, false); | | ScopedSpinRWLock lock(&mlock_, false); | |
| if (omode_ == 0) { | | if (omode_ == 0) { | |
| set_error(_KCCODELINE_, Error::INVALID, "not opened"); | | set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |
| return 0; | | return 0; | |
| } | | } | |
| return flags_; | | return flags_; | |
| } | | } | |
|
| protected: | | protected: | |
| /** | | /** | |
| * Report a message for debugging. | | * Report a message for debugging. | |
| * @param file the file name of the program source code. | | * @param file the file name of the program source code. | |
| * @param line the line number 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 func the function name of the program source code. | |
| * @param kind the kind of the event. Logger::DEBUG for debugging, Logge
r::INFO for normal | | * @param kind the kind of the event. Logger::DEBUG for debugging, Logge
r::INFO for normal | |
| * information, Logger::WARN for warning, and Logger::ERROR for fatal err
or. | | * information, Logger::WARN for warning, and Logger::ERROR for fatal err
or. | |
| * @param format the printf-like format string. | | * @param format the printf-like format string. | |
| * @param ... used according to the format string. | | * @param ... used according to the format string. | |
| */ | | */ | |
| | | | |
| skipping to change at line 1698 | | skipping to change at line 1699 | |
| */ | | */ | |
| bool reorganized() { | | bool reorganized() { | |
| _assert_(true); | | _assert_(true); | |
| ScopedSpinRWLock lock(&mlock_, false); | | ScopedSpinRWLock lock(&mlock_, false); | |
| if (omode_ == 0) { | | if (omode_ == 0) { | |
| set_error(_KCCODELINE_, Error::INVALID, "not opened"); | | set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |
| return false; | | return false; | |
| } | | } | |
| return reorg_; | | return reorg_; | |
| } | | } | |
|
| private: | | private: | |
| /** | | /** | |
| * Record data. | | * Record data. | |
| */ | | */ | |
| struct Record { | | struct Record { | |
| int64_t off; ///< offset | | int64_t off; ///< offset | |
| size_t rsiz; ///< whole size | | size_t rsiz; ///< whole size | |
| size_t psiz; ///< size of the padding | | size_t psiz; ///< size of the padding | |
| size_t ksiz; ///< size of the key | | size_t ksiz; ///< size of the key | |
| size_t vsiz; ///< size of the value | | size_t vsiz; ///< size of the value | |
| int64_t left; ///< address of the left child rec
ord | | int64_t left; ///< address of the left child rec
ord | |
| | | | |
| skipping to change at line 1743 | | skipping to change at line 1744 | |
| /** comparing operator */ | | /** comparing operator */ | |
| bool operator ()(const FreeBlock& a, const FreeBlock& b) const { | | bool operator ()(const FreeBlock& a, const FreeBlock& b) const { | |
| _assert_(true); | | _assert_(true); | |
| return a.off < b.off; | | return a.off < b.off; | |
| } | | } | |
| }; | | }; | |
| /** | | /** | |
| * Repeating visitor. | | * Repeating visitor. | |
| */ | | */ | |
| class Repeater : public Visitor { | | class Repeater : public Visitor { | |
|
| public: | | public: | |
| /** constructor */ | | /** constructor */ | |
| explicit Repeater(const char* vbuf, size_t vsiz) : vbuf_(vbuf), vsiz_(v
siz) { | | explicit Repeater(const char* vbuf, size_t vsiz) : vbuf_(vbuf), vsiz_(v
siz) { | |
| _assert_(vbuf); | | _assert_(vbuf); | |
| } | | } | |
|
| private: | | private: | |
| /** visit a record */ | | /** visit a record */ | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp
); | | _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp
); | |
| *sp = vsiz_; | | *sp = vsiz_; | |
| return vbuf_; | | return vbuf_; | |
| } | | } | |
| const char* vbuf_; | | const char* vbuf_; | |
| size_t vsiz_; | | size_t vsiz_; | |
| }; | | }; | |
| /** | | /** | |
| * Scoped visitor. | | * Scoped visitor. | |
| */ | | */ | |
| class ScopedVisitor { | | class ScopedVisitor { | |
|
| public: | | public: | |
| /** constructor */ | | /** constructor */ | |
| explicit ScopedVisitor(Visitor* visitor) : visitor_(visitor) { | | explicit ScopedVisitor(Visitor* visitor) : visitor_(visitor) { | |
| _assert_(visitor); | | _assert_(visitor); | |
| visitor_->visit_before(); | | visitor_->visit_before(); | |
| } | | } | |
| /** destructor */ | | /** destructor */ | |
| ~ScopedVisitor() { | | ~ScopedVisitor() { | |
| _assert_(true); | | _assert_(true); | |
| visitor_->visit_after(); | | visitor_->visit_after(); | |
| } | | } | |
|
| private: | | private: | |
| Visitor* visitor_; ///< visitor | | Visitor* visitor_; ///< visitor | |
| }; | | }; | |
| /** | | /** | |
| * Accept a visitor to a record. | | * Accept a visitor to a record. | |
| * @param kbuf the pointer to the key region. | | * @param kbuf the pointer to the key region. | |
| * @param ksiz the size of the key region. | | * @param ksiz the size of the key region. | |
| * @param visitor a visitor object. | | * @param visitor a visitor object. | |
| * @param bidx the bucket index. | | * @param bidx the bucket index. | |
| * @param pivot the second hash value. | | * @param pivot the second hash value. | |
| @ @param isiter true for iterator use, or false for direct use. | | @ @param isiter true for iterator use, or false for direct use. | |
| | | | |
| skipping to change at line 2346 | | skipping to change at line 2347 | |
| } | | } | |
| return true; | | return true; | |
| } | | } | |
| /** | | /** | |
| * Calculate meta data with saved ones. | | * Calculate meta data with saved ones. | |
| */ | | */ | |
| void calc_meta() { | | void calc_meta() { | |
| _assert_(true); | | _assert_(true); | |
| align_ = 1 << apow_; | | align_ = 1 << apow_; | |
| fbpnum_ = fpow_ > 0 ? 1 << fpow_ : 0; | | fbpnum_ = fpow_ > 0 ? 1 << fpow_ : 0; | |
|
| //width_ = (opts_ & TSMALL) ? WIDTHSMALL : WIDTHLARGE; | | | |
| width_ = (opts_ & TSMALL) ? sizeof(uint32_t) : sizeof(uint32_t) + 2; | | width_ = (opts_ & TSMALL) ? sizeof(uint32_t) : sizeof(uint32_t) + 2; | |
|
| | | | |
| linear_ = (opts_ & TLINEAR) ? true : false; | | linear_ = (opts_ & TLINEAR) ? true : false; | |
| comp_ = (opts_ & TCOMPRESS) ? embcomp_ : NULL; | | comp_ = (opts_ & TCOMPRESS) ? embcomp_ : NULL; | |
| rhsiz_ = sizeof(uint16_t) + sizeof(uint8_t) * 2; | | rhsiz_ = sizeof(uint16_t) + sizeof(uint8_t) * 2; | |
| rhsiz_ += linear_ ? width_ : width_ * 2; | | rhsiz_ += linear_ ? width_ : width_ * 2; | |
| boff_ = HEADSIZ + FBPWIDTH * fbpnum_; | | boff_ = HEADSIZ + FBPWIDTH * fbpnum_; | |
| if (fbpnum_ > 0) boff_ += width_ * 2 + sizeof(uint8_t) * 2; | | if (fbpnum_ > 0) boff_ += width_ * 2 + sizeof(uint8_t) * 2; | |
| roff_ = boff_ + width_ * bnum_; | | roff_ = boff_ + width_ * bnum_; | |
| int64_t rem = roff_ % align_; | | int64_t rem = roff_ % align_; | |
| if (rem > 0) roff_ += align_ - rem; | | if (rem > 0) roff_ += align_ - rem; | |
| dfcur_ = roff_; | | dfcur_ = roff_; | |
| | | | |
| skipping to change at line 2713 | | skipping to change at line 2712 | |
| return hashmurmur(kbuf, ksiz); | | return hashmurmur(kbuf, ksiz); | |
| } | | } | |
| /** | | /** | |
| * Fold a hash value into a small number. | | * Fold a hash value into a small number. | |
| * @param hash the hash number. | | * @param hash the hash number. | |
| * @return the result number. | | * @return the result number. | |
| */ | | */ | |
| uint32_t fold_hash(uint64_t hash) { | | uint32_t fold_hash(uint64_t hash) { | |
| _assert_(true); | | _assert_(true); | |
| return (((hash & 0xffff000000000000ULL) >> 48) | ((hash & 0x0000ffff000
00000ULL) >> 16)) ^ | | return (((hash & 0xffff000000000000ULL) >> 48) | ((hash & 0x0000ffff000
00000ULL) >> 16)) ^ | |
|
| (((hash & 0x000000000000ffffULL) << 16) | ((hash & 0x00000000ffff0000
ULL) >> 16)); | | (((hash & 0x000000000000ffffULL) << 16) | ((hash & 0x00000000ffff00
00ULL) >> 16)); | |
| } | | } | |
| /** | | /** | |
| * Compare two keys in lexical order. | | * Compare two keys in lexical order. | |
| * @param abuf one key. | | * @param abuf one key. | |
| * @param asiz the size of the one key. | | * @param asiz the size of the one key. | |
| * @param bbuf the other key. | | * @param bbuf the other key. | |
| * @param bsiz the size of the other key. | | * @param bsiz the size of the other key. | |
| * @return positive if the former is big, or negative if the latter is bi
g, or 0 if both are | | * @return positive if the former is big, or negative if the latter is bi
g, or 0 if both are | |
| * equivalent. | | * equivalent. | |
| */ | | */ | |
| | | | |
End of changes. 17 change blocks. |
| 28 lines changed or deleted | | 27 lines changed or added | |
|
| kclangc.h | | kclangc.h | |
| | | | |
| skipping to change at line 51 | | skipping to change at line 51 | |
| #include <stdint.h> | | #include <stdint.h> | |
| | | | |
| /** | | /** | |
| * C wrapper of polymorphic database. | | * C wrapper of polymorphic database. | |
| */ | | */ | |
| typedef union { | | typedef union { | |
| void* db; /**< dummy member */ | | void* db; /**< dummy member */ | |
| } KCDB; | | } KCDB; | |
| | | | |
| /** | | /** | |
|
| | | * C wrapper of polymorphic cursor. | |
| | | */ | |
| | | typedef union { | |
| | | void* cur; /**< dummy member */ | |
| | | } KCCUR; | |
| | | | |
| | | /** | |
| * Binary string of byte array. | | * Binary string of byte array. | |
| */ | | */ | |
| typedef struct { | | typedef struct { | |
| char* buf; /**< pointer to the data region */ | | char* buf; /**< pointer to the data region */ | |
| size_t size; /**< size of the data region */ | | size_t size; /**< size of the data region */ | |
| } KCSTR; | | } KCSTR; | |
| | | | |
| /** | | /** | |
| * Key-Value record. | | * Key-Value record. | |
| */ | | */ | |
| | | | |
| skipping to change at line 155 | | skipping to change at line 162 | |
| * Call back function to process the database file. | | * Call back function to process the database file. | |
| * @param path the path of the database file. | | * @param path the path of the database file. | |
| * @param count the number of records. | | * @param count the number of records. | |
| * @param size the size of the available region. | | * @param size the size of the available region. | |
| * @param opq an opaque pointer. | | * @param opq an opaque pointer. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| typedef int32_t (*KCFILEPROC)(const char* path, int64_t count, int64_t size
, void* opq); | | typedef int32_t (*KCFILEPROC)(const char* path, int64_t count, int64_t size
, void* opq); | |
| | | | |
| /** | | /** | |
|
| * C wrapper of polymorphic cursor. | | | |
| */ | | | |
| typedef union { | | | |
| void* cur; /**< dummy member */ | | | |
| } KCCUR; | | | |
| | | | |
| /** | | | |
| * Allocate a region on memory. | | * Allocate a region on memory. | |
| * @param size the size of the region. | | * @param size the size of the region. | |
| * @return the pointer to the allocated region. The region of the return v
alue should be | | * @return the pointer to the allocated region. The region of the return v
alue should be | |
| * released with the kcfree function when it is no longer in use. | | * released with the kcfree function when it is no longer in use. | |
| */ | | */ | |
| void* kcmalloc(size_t size); | | void* kcmalloc(size_t size); | |
| | | | |
| /** | | /** | |
| * Release a region allocated in the library. | | * Release a region allocated in the library. | |
| * @param ptr the pointer to the region. | | * @param ptr the pointer to the region. | |
| | | | |
| skipping to change at line 254 | | skipping to change at line 254 | |
| int32_t kcchkinf(double num); | | int32_t kcchkinf(double num); | |
| | | | |
| /** | | /** | |
| * Get the readable string of an error code. | | * Get the readable string of an error code. | |
| * @param code the error code. | | * @param code the error code. | |
| * @return the readable string of the error code. | | * @return the readable string of the error code. | |
| */ | | */ | |
| const char* kcecodename(int32_t code); | | const char* kcecodename(int32_t code); | |
| | | | |
| /** | | /** | |
|
| * Create a database object. | | * Create a polymorphic database object. | |
| * @return the created database object. | | * @return the created database object. | |
| * @note The object of the return value should be released with the kcdbdel
function when it is | | * @note The object of the return value should be released with the kcdbdel
function when it is | |
| * no longer in use. | | * no longer in use. | |
| */ | | */ | |
| KCDB* kcdbnew(void); | | KCDB* kcdbnew(void); | |
| | | | |
| /** | | /** | |
| * Destroy a database object. | | * Destroy a database object. | |
| * @param db the database object. | | * @param db the database object. | |
| */ | | */ | |
| | | | |
| skipping to change at line 698 | | skipping to change at line 698 | |
| * @param srcary an array of the source detabase objects. | | * @param srcary an array of the source detabase objects. | |
| * @param srcnum the number of the elements of the source array. | | * @param srcnum the number of the elements of the source array. | |
| * @param mode the merge mode. KCMSET to overwrite the existing value, KCM
ADD to keep the | | * @param mode the merge mode. KCMSET to overwrite the existing value, KCM
ADD to keep the | |
| * existing value, KCMREPLACE to modify the existing record only, KCMAPPEND
to append the new | | * existing value, KCMREPLACE to modify the existing record only, KCMAPPEND
to append the new | |
| * value. | | * value. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| int32_t kcdbmerge(KCDB* db, KCDB** srcary, size_t srcnum, uint32_t mode); | | int32_t kcdbmerge(KCDB* db, KCDB** srcary, size_t srcnum, uint32_t mode); | |
| | | | |
| /** | | /** | |
|
| * Create a cursor object. | | * Create a polymorphic cursor object. | |
| * @param db a database object. | | * @param db a database object. | |
| * @return the return value is the created cursor object. | | * @return the return value is the created cursor object. | |
| * @note The object of the return value should be released with the kccurde
l function when it is | | * @note The object of the return value should be released with the kccurde
l function when it is | |
| * no longer in use. | | * no longer in use. | |
| */ | | */ | |
| KCCUR* kcdbcursor(KCDB* db); | | KCCUR* kcdbcursor(KCDB* db); | |
| | | | |
| /** | | /** | |
| * Destroy a cursor object. | | * Destroy a cursor object. | |
| * @param cur the cursor object. | | * @param cur the cursor object. | |
| | | | |
| skipping to change at line 865 | | skipping to change at line 865 | |
| */ | | */ | |
| int32_t kccurecode(KCCUR* cur); | | int32_t kccurecode(KCCUR* cur); | |
| | | | |
| /** | | /** | |
| * Get the supplement message of the last happened error. | | * Get the supplement message of the last happened error. | |
| * @param cur a cursor object. | | * @param cur a cursor object. | |
| * @return the supplement message of the last happened error. | | * @return the supplement message of the last happened error. | |
| */ | | */ | |
| const char* kccuremsg(KCCUR* cur); | | const char* kccuremsg(KCCUR* cur); | |
| | | | |
|
| | | /** | |
| | | * C wrapper of memory-saving string hash map. | |
| | | */ | |
| | | typedef union { | |
| | | void* map; /**< dummy member */ | |
| | | } KCMAP; | |
| | | | |
| | | /** | |
| | | * C wrapper of iterator of memory-saving string hash map. | |
| | | */ | |
| | | typedef union { | |
| | | void* iter; /**< dummy member */ | |
| | | } KCMAPITER; | |
| | | | |
| | | /** | |
| | | * C wrapper of sorter of memory-saving string hash map. | |
| | | */ | |
| | | typedef union { | |
| | | void* iter; /**< dummy member */ | |
| | | } KCMAPSORT; | |
| | | | |
| | | /** | |
| | | * Create a string hash map object. | |
| | | * @param bnum the number of buckets of the hash table. If it is not more | |
| | | than 0, the default | |
| | | * setting 31 is specified. | |
| | | * @return the created map object. | |
| | | * @note The object of the return value should be released with the kcmapde | |
| | | l function when it is | |
| | | * no longer in use. | |
| | | */ | |
| | | KCMAP* kcmapnew(size_t bnum); | |
| | | | |
| | | /** | |
| | | * Destroy a map object. | |
| | | * @param map the map object. | |
| | | */ | |
| | | void kcmapdel(KCMAP* map); | |
| | | | |
| | | /** | |
| | | * Set the value of a record. | |
| | | * @param map the map object. | |
| | | * @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. | |
| | | * @note If no record corresponds to the key, a new record is created. If | |
| | | the corresponding | |
| | | * record exists, the value is overwritten. | |
| | | */ | |
| | | void kcmapset(KCMAP* map, const char* kbuf, size_t ksiz, const char* vbuf, | |
| | | size_t vsiz); | |
| | | | |
| | | /** | |
| | | * Add a record. | |
| | | * @param map the map object. | |
| | | * @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. | |
| | | */ | |
| | | int32_t kcmapadd(KCMAP* map, const char* kbuf, size_t ksiz, const char* vbu | |
| | | f, size_t vsiz); | |
| | | | |
| | | /** | |
| | | * Replace the value of a record. | |
| | | * @param map the map object. | |
| | | * @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. | |
| | | */ | |
| | | int32_t kcmapreplace(KCMAP* map, const char* kbuf, size_t ksiz, const char* | |
| | | vbuf, size_t vsiz); | |
| | | | |
| | | /** | |
| | | * Append the value of a record. | |
| | | * @param map the map object. | |
| | | * @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. | |
| | | * @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 va | |
| | | lue. | |
| | | */ | |
| | | void kcmapappend(KCMAP* map, const char* kbuf, size_t ksiz, const char* vbu | |
| | | f, size_t vsiz); | |
| | | | |
| | | /** | |
| | | * Remove a record. | |
| | | * @param map the map object. | |
| | | * @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. | |
| | | */ | |
| | | int32_t kcmapremove(KCMAP* map, const char* kbuf, size_t ksiz); | |
| | | | |
| | | /** | |
| | | * Retrieve the value of a record. | |
| | | * @param map the map object. | |
| | | * @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. | |
| | | */ | |
| | | const char* kcmapget(KCMAP* map, const char* kbuf, size_t ksiz, size_t* sp) | |
| | | ; | |
| | | | |
| | | /** | |
| | | * Remove all records. | |
| | | * @param map the map object. | |
| | | */ | |
| | | void kcmapclear(KCMAP* map); | |
| | | | |
| | | /** | |
| | | * Get the number of records. | |
| | | * @param map the map object. | |
| | | * @return the number of records. | |
| | | */ | |
| | | size_t kcmapcount(KCMAP* map); | |
| | | | |
| | | /** | |
| | | * Create a string hash map iterator object. | |
| | | * @param map a map object. | |
| | | * @return the return value is the created iterator object. | |
| | | * @note The object of the return value should be released with the kcmapit | |
| | | erdel function when | |
| | | * it is no longer in use. | |
| | | * @note This object will not be invalidated even when the map object is up | |
| | | dated once. | |
| | | * However, phantom records may be retrieved if they are removed after crea | |
| | | tion of each iterator. | |
| | | */ | |
| | | KCMAPITER* kcmapiterator(KCMAP* map); | |
| | | | |
| | | /** | |
| | | * Destroy an iterator object. | |
| | | * @param iter the iterator object. | |
| | | */ | |
| | | void kcmapiterdel(KCMAPITER* iter); | |
| | | | |
| | | /** | |
| | | * Get the key of the current record. | |
| | | * @param iter the iterator object. | |
| | | * @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 key region of the current record, or NULL on | |
| | | failure. | |
| | | */ | |
| | | const char* kcmapitergetkey(KCMAPITER* iter, size_t* sp); | |
| | | | |
| | | /** | |
| | | * Get the value of the current record. | |
| | | * @param iter the iterator object. | |
| | | * @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 current record, or NULL o | |
| | | n failure. | |
| | | */ | |
| | | const char* kcmapitergetvalue(KCMAPITER* iter, size_t* sp); | |
| | | | |
| | | /** | |
| | | * Get a pair of the key and the value of the current record. | |
| | | * @param iter the iterator object. | |
| | | * @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 val | |
| | | ue 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. | |
| | | */ | |
| | | const char* kcmapiterget(KCMAPITER* iter, size_t* ksp, const char** vbp, si | |
| | | ze_t* vsp); | |
| | | | |
| | | /** | |
| | | * Step the cursor to the next record. | |
| | | * @param iter the iterator object. | |
| | | */ | |
| | | void kcmapiterstep(KCMAPITER* iter); | |
| | | | |
| | | /** | |
| | | * Create a string hash map sorter object. | |
| | | * @param map a map object. | |
| | | * @return the return value is the created sorter object. | |
| | | * @note The object of the return value should be released with the kcmapso | |
| | | rtdel function when | |
| | | * it is no longer in use. | |
| | | * @note This object will not be invalidated even when the map object is up | |
| | | dated once. | |
| | | * However, phantom records may be retrieved if they are removed after crea | |
| | | tion of each sorter. | |
| | | */ | |
| | | KCMAPSORT* kcmapsorter(KCMAP* map); | |
| | | | |
| | | /** | |
| | | * Destroy an sorter object. | |
| | | * @param sort the sorter object. | |
| | | */ | |
| | | void kcmapsortdel(KCMAPSORT* sort); | |
| | | | |
| | | /** | |
| | | * Get the key of the current record. | |
| | | * @param sort the sorter object. | |
| | | * @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 key region of the current record, or NULL on | |
| | | failure. | |
| | | */ | |
| | | const char* kcmapsortgetkey(KCMAPSORT* sort, size_t* sp); | |
| | | | |
| | | /** | |
| | | * Get the value of the current record. | |
| | | * @param sort the sorter object. | |
| | | * @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 current record, or NULL o | |
| | | n failure. | |
| | | */ | |
| | | const char* kcmapsortgetvalue(KCMAPSORT* sort, size_t* sp); | |
| | | | |
| | | /** | |
| | | * Get a pair of the key and the value of the current record. | |
| | | * @param sort the sorter object. | |
| | | * @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 val | |
| | | ue 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. | |
| | | */ | |
| | | const char* kcmapsortget(KCMAPSORT* sort, size_t* ksp, const char** vbp, si | |
| | | ze_t* vsp); | |
| | | | |
| | | /** | |
| | | * Step the cursor to the next record. | |
| | | * @param sort the sorter object. | |
| | | */ | |
| | | void kcmapsortstep(KCMAPSORT* sort); | |
| | | | |
| #if defined(__cplusplus) | | #if defined(__cplusplus) | |
| } | | } | |
| #endif | | #endif | |
| | | | |
| #endif /* duplication check */ | | #endif /* duplication check */ | |
| | | | |
| /* END OF FILE */ | | /* END OF FILE */ | |
| | | | |
End of changes. 5 change blocks. |
| 9 lines changed or deleted | | 274 lines changed or added | |
|
| kcmap.h | | kcmap.h | |
| | | | |
| skipping to change at line 24 | | skipping to change at line 24 | |
| | | | |
| #ifndef _KCMAP_H // duplication check | | #ifndef _KCMAP_H // duplication check | |
| #define _KCMAP_H | | #define _KCMAP_H | |
| | | | |
| #include <kccommon.h> | | #include <kccommon.h> | |
| #include <kcutil.h> | | #include <kcutil.h> | |
| | | | |
| namespace kyotocabinet { // common namespace | | namespace kyotocabinet { // common namespace | |
| | | | |
| /** | | /** | |
|
| * Memory-saving hash map. | | * Memory-saving string hash map. | |
| */ | | */ | |
| class TinyHashMap { | | class TinyHashMap { | |
|
| public: | | public: | |
| class Iterator; | | class Iterator; | |
|
| private: | | private: | |
| struct Record; | | struct Record; | |
| struct RecordComparator; | | struct RecordComparator; | |
| /** The default bucket number of hash table. */ | | /** The default bucket number of hash table. */ | |
| static const size_t MAPDEFBNUM = 31; | | static const size_t MAPDEFBNUM = 31; | |
| /** The mininum number of buckets to use mmap. */ | | /** The mininum number of buckets to use mmap. */ | |
| static const size_t MAPZMAPBNUM = 32768; | | static const size_t MAPZMAPBNUM = 32768; | |
|
| public: | | public: | |
| /** | | /** | |
| * Iterator of records. | | * Iterator of records. | |
| */ | | */ | |
| class Iterator { | | class Iterator { | |
| friend class TinyHashMap; | | friend class TinyHashMap; | |
|
| public: | | public: | |
| /** | | /** | |
| * Constructor. | | * Constructor. | |
| * @param map the container. | | * @param map the container. | |
|
| | | * @note This object will not be invalidated even when the map object i | |
| | | s updated once. | |
| | | * However, phantom records may be retrieved if they are removed after | |
| | | creation of each | |
| | | * iterator. | |
| */ | | */ | |
| explicit Iterator(TinyHashMap* map) : map_(map), bidx_(-1), ridx_(0), r
ecs_() { | | explicit Iterator(TinyHashMap* map) : map_(map), bidx_(-1), ridx_(0), r
ecs_() { | |
| _assert_(map); | | _assert_(map); | |
| step(); | | step(); | |
| } | | } | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| */ | | */ | |
| ~Iterator() { | | ~Iterator() { | |
| _assert_(true); | | _assert_(true); | |
| | | | |
| skipping to change at line 119 | | skipping to change at line 122 | |
| ridx_ = 0; | | ridx_ = 0; | |
| free_records(); | | free_records(); | |
| while (true) { | | while (true) { | |
| bidx_++; | | bidx_++; | |
| if (bidx_ >= (int64_t)map_->bnum_) return; | | if (bidx_ >= (int64_t)map_->bnum_) return; | |
| read_records(); | | read_records(); | |
| if (recs_.size() > 0) break; | | if (recs_.size() > 0) break; | |
| } | | } | |
| } | | } | |
| } | | } | |
|
| private: | | private: | |
| /** | | /** | |
| * Read records of the current bucket. | | * Read records of the current bucket. | |
| */ | | */ | |
| void read_records() { | | void read_records() { | |
| char* rbuf = map_->buckets_[bidx_]; | | char* rbuf = map_->buckets_[bidx_]; | |
| while (rbuf) { | | while (rbuf) { | |
| Record rec(rbuf); | | Record rec(rbuf); | |
| size_t rsiz = sizeof(rec.child_) + sizevarnum(rec.ksiz_) + rec.ksiz
_ + | | size_t rsiz = sizeof(rec.child_) + sizevarnum(rec.ksiz_) + rec.ksiz
_ + | |
|
| sizevarnum(rec.vsiz_) + rec.vsiz_ + sizevarnum(rec.psiz_); | | sizevarnum(rec.vsiz_) + rec.vsiz_ + sizevarnum(rec.psiz_); | |
| char* nbuf = new char[rsiz]; | | char* nbuf = new char[rsiz]; | |
| std::memcpy(nbuf, rbuf, rsiz); | | std::memcpy(nbuf, rbuf, rsiz); | |
| recs_.push_back(nbuf); | | recs_.push_back(nbuf); | |
| rbuf = rec.child_; | | rbuf = rec.child_; | |
| } | | } | |
| } | | } | |
| /** | | /** | |
| * Release recources of the current records. | | * Release recources of the current records. | |
| */ | | */ | |
| void free_records() { | | void free_records() { | |
| | | | |
| skipping to change at line 165 | | skipping to change at line 168 | |
| int64_t bidx_; | | int64_t bidx_; | |
| /** The current record index. */ | | /** The current record index. */ | |
| size_t ridx_; | | size_t ridx_; | |
| /** The current records. */ | | /** The current records. */ | |
| std::vector<char*> recs_; | | std::vector<char*> recs_; | |
| }; | | }; | |
| /** | | /** | |
| * Sorter of records. | | * Sorter of records. | |
| */ | | */ | |
| class Sorter { | | class Sorter { | |
|
| public: | | public: | |
| /** | | /** | |
| * Constructor. | | * Constructor. | |
| * @param map the container. | | * @param map the container. | |
|
| | | * @note This object will be invalidated when the map object is updated
once. | |
| */ | | */ | |
| explicit Sorter(TinyHashMap* map) : map_(map), ridx_(0), recs_() { | | explicit Sorter(TinyHashMap* map) : map_(map), ridx_(0), recs_() { | |
| _assert_(map); | | _assert_(map); | |
| recs_.reserve(map->count_); | | recs_.reserve(map->count_); | |
| char** buckets = map_->buckets_; | | char** buckets = map_->buckets_; | |
| size_t bnum = map_->bnum_; | | size_t bnum = map_->bnum_; | |
| for (size_t i = 0; i < bnum; i++) { | | for (size_t i = 0; i < bnum; i++) { | |
| char* rbuf = buckets[i]; | | char* rbuf = buckets[i]; | |
| while (rbuf) { | | while (rbuf) { | |
| Record rec(rbuf); | | Record rec(rbuf); | |
| | | | |
| skipping to change at line 482 | | skipping to change at line 486 | |
| count_ = 0; | | count_ = 0; | |
| } | | } | |
| /** | | /** | |
| * Get the number of records. | | * Get the number of records. | |
| * @return the number of records. | | * @return the number of records. | |
| */ | | */ | |
| size_t count() { | | size_t count() { | |
| _assert_(true); | | _assert_(true); | |
| return count_; | | return count_; | |
| } | | } | |
|
| private: | | private: | |
| /** | | /** | |
| * Record data. | | * Record data. | |
| */ | | */ | |
| struct Record { | | struct Record { | |
| /** constructor */ | | /** constructor */ | |
| Record(char* child, const char* kbuf, uint64_t ksiz, | | Record(char* child, const char* kbuf, uint64_t ksiz, | |
| const char* vbuf, uint64_t vsiz, uint64_t psiz) : | | const char* vbuf, uint64_t vsiz, uint64_t psiz) : | |
|
| child_(child), kbuf_(kbuf), ksiz_(ksiz), vbuf_(vbuf), vsiz_(vsiz), ps
iz_(psiz) { | | child_(child), kbuf_(kbuf), ksiz_(ksiz), vbuf_(vbuf), vsiz_(vsiz),
psiz_(psiz) { | |
| _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && ps
iz <= MEMMAXSIZ); | | _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && ps
iz <= MEMMAXSIZ); | |
| } | | } | |
| /** constructor */ | | /** constructor */ | |
| Record(const char* rbuf) : | | Record(const char* rbuf) : | |
|
| child_(NULL), kbuf_(NULL), ksiz_(0), vbuf_(NULL), vsiz_(0), psiz_(0)
{ | | child_(NULL), kbuf_(NULL), ksiz_(0), vbuf_(NULL), vsiz_(0), psiz_(0
) { | |
| _assert_(rbuf); | | _assert_(rbuf); | |
| deserialize(rbuf); | | deserialize(rbuf); | |
| } | | } | |
| /** overwrite the buffer */ | | /** overwrite the buffer */ | |
| void overwrite(char* rbuf, const char* vbuf, size_t vsiz, size_t psiz)
{ | | void overwrite(char* rbuf, const char* vbuf, size_t vsiz, size_t psiz)
{ | |
| _assert_(rbuf && vbuf && vsiz <= MEMMAXSIZ && psiz <= MEMMAXSIZ); | | _assert_(rbuf && vbuf && vsiz <= MEMMAXSIZ && psiz <= MEMMAXSIZ); | |
| char* wp = rbuf + sizeof(child_) + sizevarnum(ksiz_) + ksiz_; | | char* wp = rbuf + sizeof(child_) + sizevarnum(ksiz_) + ksiz_; | |
| wp += writevarnum(wp, vsiz); | | wp += writevarnum(wp, vsiz); | |
| std::memcpy(wp, vbuf, vsiz); | | std::memcpy(wp, vbuf, vsiz); | |
| wp += vsiz; | | wp += vsiz; | |
| | | | |
| skipping to change at line 541 | | skipping to change at line 545 | |
| std::memcpy(wp, ovbuf, ovsiz); | | std::memcpy(wp, ovbuf, ovsiz); | |
| wp += ovsiz; | | wp += ovsiz; | |
| std::memcpy(wp, nvbuf, nvsiz); | | std::memcpy(wp, nvbuf, nvsiz); | |
| wp += nvsiz; | | wp += nvsiz; | |
| writevarnum(wp, psiz); | | writevarnum(wp, psiz); | |
| } | | } | |
| /** serialize data into a buffer */ | | /** serialize data into a buffer */ | |
| char* serialize() { | | char* serialize() { | |
| _assert_(true); | | _assert_(true); | |
| uint64_t rsiz = sizeof(child_) + sizevarnum(ksiz_) + ksiz_ + sizevarn
um(vsiz_) + vsiz_ + | | uint64_t rsiz = sizeof(child_) + sizevarnum(ksiz_) + ksiz_ + sizevarn
um(vsiz_) + vsiz_ + | |
|
| sizevarnum(psiz_) + psiz_; | | sizevarnum(psiz_) + psiz_; | |
| char* rbuf = new char[rsiz]; | | char* rbuf = new char[rsiz]; | |
| char* wp = rbuf; | | char* wp = rbuf; | |
| *(char**)wp = child_; | | *(char**)wp = child_; | |
| wp += sizeof(child_); | | wp += sizeof(child_); | |
| wp += writevarnum(wp, ksiz_); | | wp += writevarnum(wp, ksiz_); | |
| std::memcpy(wp, kbuf_, ksiz_); | | std::memcpy(wp, kbuf_, ksiz_); | |
| wp += ksiz_; | | wp += ksiz_; | |
| wp += writevarnum(wp, vsiz_); | | wp += writevarnum(wp, vsiz_); | |
| std::memcpy(wp, vbuf_, vsiz_); | | std::memcpy(wp, vbuf_, vsiz_); | |
| wp += vsiz_; | | wp += vsiz_; | |
| | | | |
| skipping to change at line 662 | | skipping to change at line 666 | |
| /** | | /** | |
| * Doubly-linked hash map. | | * Doubly-linked hash map. | |
| * @param KEY the key type. | | * @param KEY the key type. | |
| * @param VALUE the value type. | | * @param VALUE the value type. | |
| * @param HASH the hash functor. | | * @param HASH the hash functor. | |
| * @param EQUALTO the equality checking functor. | | * @param EQUALTO the equality checking functor. | |
| */ | | */ | |
| template <class KEY, class VALUE, | | template <class KEY, class VALUE, | |
| class HASH = std::hash<KEY>, class EQUALTO = std::equal_to<KEY> > | | class HASH = std::hash<KEY>, class EQUALTO = std::equal_to<KEY> > | |
| class LinkedHashMap { | | class LinkedHashMap { | |
|
| public: | | public: | |
| class Iterator; | | class Iterator; | |
|
| private: | | private: | |
| struct Record; | | struct Record; | |
| /** The default bucket number of hash table. */ | | /** The default bucket number of hash table. */ | |
| static const size_t MAPDEFBNUM = 31; | | static const size_t MAPDEFBNUM = 31; | |
| /** The mininum number of buckets to use mmap. */ | | /** The mininum number of buckets to use mmap. */ | |
| static const size_t MAPZMAPBNUM = 32768; | | static const size_t MAPZMAPBNUM = 32768; | |
|
| public: | | public: | |
| /** | | /** | |
| * Iterator of records. | | * Iterator of records. | |
| */ | | */ | |
| class Iterator { | | class Iterator { | |
| friend class LinkedHashMap; | | friend class LinkedHashMap; | |
|
| public: | | public: | |
| /** | | /** | |
| * Copy constructor. | | * Copy constructor. | |
| * @param src the source object. | | * @param src the source object. | |
| */ | | */ | |
| Iterator(const Iterator& src) : map_(src.map_), rec_(src.rec_) { | | Iterator(const Iterator& src) : map_(src.map_), rec_(src.rec_) { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| /** | | /** | |
| * Get the key. | | * Get the key. | |
| */ | | */ | |
| | | | |
| skipping to change at line 774 | | skipping to change at line 778 | |
| Iterator operator --(int) { | | Iterator operator --(int) { | |
| _assert_(true); | | _assert_(true); | |
| Iterator old(*this); | | Iterator old(*this); | |
| if (rec_) { | | if (rec_) { | |
| rec_ = rec_->prev; | | rec_ = rec_->prev; | |
| } else { | | } else { | |
| rec_ = map_->last_; | | rec_ = map_->last_; | |
| } | | } | |
| return old; | | return old; | |
| } | | } | |
|
| private: | | private: | |
| /** | | /** | |
| * Constructor. | | * Constructor. | |
| * @param map the container. | | * @param map the container. | |
| * @param rec the pointer to the current record. | | * @param rec the pointer to the current record. | |
| */ | | */ | |
| explicit Iterator(LinkedHashMap* map, Record* rec) : map_(map), rec_(re
c) { | | explicit Iterator(LinkedHashMap* map, Record* rec) : map_(map), rec_(re
c) { | |
| _assert_(map); | | _assert_(map); | |
| } | | } | |
| /** The container. */ | | /** The container. */ | |
| LinkedHashMap* map_; | | LinkedHashMap* map_; | |
| | | | |
| skipping to change at line 800 | | skipping to change at line 804 | |
| */ | | */ | |
| enum MoveMode { | | enum MoveMode { | |
| MCURRENT, ///< keep the current position | | MCURRENT, ///< keep the current position | |
| MFIRST, ///< move to the first | | MFIRST, ///< move to the first | |
| MLAST ///< move to the last | | MLAST ///< move to the last | |
| }; | | }; | |
| /** | | /** | |
| * Default constructor. | | * Default constructor. | |
| */ | | */ | |
| explicit LinkedHashMap() : | | explicit LinkedHashMap() : | |
|
| buckets_(NULL), bnum_(MAPDEFBNUM), first_(NULL), last_(NULL), count_(0)
{ | | buckets_(NULL), bnum_(MAPDEFBNUM), first_(NULL), last_(NULL), count_(
0) { | |
| _assert_(true); | | _assert_(true); | |
| initialize(); | | initialize(); | |
| } | | } | |
| /** | | /** | |
| * Constructor. | | * Constructor. | |
| * @param bnum the number of buckets of the hash table. | | * @param bnum the number of buckets of the hash table. | |
| */ | | */ | |
| explicit LinkedHashMap(size_t bnum) : | | explicit LinkedHashMap(size_t bnum) : | |
|
| buckets_(NULL), bnum_(bnum), first_(NULL), last_(NULL), count_(0) { | | buckets_(NULL), bnum_(bnum), first_(NULL), last_(NULL), count_(0) { | |
| _assert_(true); | | _assert_(true); | |
| if (bnum_ < 1) bnum_ = MAPDEFBNUM; | | if (bnum_ < 1) bnum_ = MAPDEFBNUM; | |
| initialize(); | | initialize(); | |
| } | | } | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| */ | | */ | |
| ~LinkedHashMap() { | | ~LinkedHashMap() { | |
| _assert_(true); | | _assert_(true); | |
| destroy(); | | destroy(); | |
| | | | |
| skipping to change at line 1160 | | skipping to change at line 1164 | |
| return last_->key; | | return last_->key; | |
| } | | } | |
| /** | | /** | |
| * Get the reference of the value of the last record. | | * Get the reference of the value of the last record. | |
| * @return the reference of the value of the last record. | | * @return the reference of the value of the last record. | |
| */ | | */ | |
| VALUE& last_value() { | | VALUE& last_value() { | |
| _assert_(true); | | _assert_(true); | |
| return last_->value; | | return last_->value; | |
| } | | } | |
|
| private: | | private: | |
| /** | | /** | |
| * Record data. | | * Record data. | |
| */ | | */ | |
| struct Record { | | struct Record { | |
| KEY key; ///< key | | KEY key; ///< key | |
| VALUE value; ///< value | | VALUE value; ///< value | |
| Record* child; ///< child record | | Record* child; ///< child record | |
| Record* prev; ///< previous record | | Record* prev; ///< previous record | |
| Record* next; ///< next record | | Record* next; ///< next record | |
| /** constructor */ | | /** constructor */ | |
| explicit Record(const KEY& k, const VALUE& v) : | | explicit Record(const KEY& k, const VALUE& v) : | |
|
| key(k), value(v), child(NULL), prev(NULL), next(NULL) { | | key(k), value(v), child(NULL), prev(NULL), next(NULL) { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| }; | | }; | |
| /** | | /** | |
| * Initialize fields. | | * Initialize fields. | |
| */ | | */ | |
| void initialize() { | | void initialize() { | |
| _assert_(true); | | _assert_(true); | |
| if (bnum_ >= MAPZMAPBNUM) { | | if (bnum_ >= MAPZMAPBNUM) { | |
| buckets_ = (Record**)mapalloc(sizeof(*buckets_) * bnum_); | | buckets_ = (Record**)mapalloc(sizeof(*buckets_) * bnum_); | |
| | | | |
End of changes. 23 change blocks. |
| 21 lines changed or deleted | | 27 lines changed or added | |
|
| kcplantdb.h | | kcplantdb.h | |
| | | | |
| skipping to change at line 50 | | skipping to change at line 50 | |
| * TreeDB is the instance of the file tree database. The class ForestDB is
the instance of the | | * TreeDB is the instance of the file tree database. The class ForestDB is
the instance of the | |
| * directory tree database. Before every database operation, it is necessa
ry to call the | | * directory tree database. Before every database operation, it is necessa
ry to call the | |
| * BasicDB::open method in order to open a database file and connect the da
tabase object to it. | | * BasicDB::open method in order to open a database file and connect the da
tabase object to it. | |
| * To avoid data missing or corruption, it is important to close every data
base file by the | | * To avoid data missing or corruption, it is important to close every data
base file by the | |
| * BasicDB::close method when the database is no longer in use. It is forb
idden for multible | | * BasicDB::close method when the database is no longer in use. It is forb
idden for multible | |
| * database objects in a process to open the same database at the same time
. It is forbidden to | | * 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. | | * share a database object with child processes. | |
| */ | | */ | |
| template <class BASEDB, uint8_t DBTYPE> | | template <class BASEDB, uint8_t DBTYPE> | |
| class PlantDB : public BasicDB { | | class PlantDB : public BasicDB { | |
|
| public: | | public: | |
| class Cursor; | | class Cursor; | |
|
| private: | | private: | |
| struct Record; | | struct Record; | |
| struct RecordComparator; | | struct RecordComparator; | |
| struct LeafNode; | | struct LeafNode; | |
| struct Link; | | struct Link; | |
| struct LinkComparator; | | struct LinkComparator; | |
| struct InnerNode; | | struct InnerNode; | |
| struct LeafSlot; | | struct LeafSlot; | |
| struct InnerSlot; | | struct InnerSlot; | |
| class ScopedVisitor; | | class ScopedVisitor; | |
| /** An alias of array of records. */ | | /** An alias of array of records. */ | |
| | | | |
| skipping to change at line 112 | | skipping to change at line 112 | |
| /** The base ID number for inner nodes. */ | | /** The base ID number for inner nodes. */ | |
| static const int64_t INIDBASE = 1LL << 48; | | static const int64_t INIDBASE = 1LL << 48; | |
| /** The minimum number of links in each inner node. */ | | /** The minimum number of links in each inner node. */ | |
| static const size_t INLINKMIN = 8; | | static const size_t INLINKMIN = 8; | |
| /** The maximum level of B+ tree. */ | | /** The maximum level of B+ tree. */ | |
| static const int32_t LEVELMAX = 16; | | static const int32_t LEVELMAX = 16; | |
| /** The number of cached nodes for auto transaction. */ | | /** The number of cached nodes for auto transaction. */ | |
| static const int32_t ATRANCNUM = 256; | | static const int32_t ATRANCNUM = 256; | |
| /** The threshold of busy loop and sleep for locking. */ | | /** The threshold of busy loop and sleep for locking. */ | |
| static const uint32_t LOCKBUSYLOOP = 8192; | | static const uint32_t LOCKBUSYLOOP = 8192; | |
|
| public: | | public: | |
| /** | | /** | |
| * Cursor to indicate a record. | | * Cursor to indicate a record. | |
| */ | | */ | |
| class Cursor : public BasicDB::Cursor { | | class Cursor : public BasicDB::Cursor { | |
| friend class PlantDB; | | friend class PlantDB; | |
|
| public: | | public: | |
| /** | | /** | |
| * Constructor. | | * Constructor. | |
| * @param db the container database object. | | * @param db the container database object. | |
| */ | | */ | |
| explicit Cursor(PlantDB* db) : db_(db), stack_(), kbuf_(NULL), ksiz_(0)
, lid_(0) { | | explicit Cursor(PlantDB* db) : db_(db), stack_(), kbuf_(NULL), ksiz_(0)
, lid_(0) { | |
| _assert_(db); | | _assert_(db); | |
| ScopedSpinRWLock lock(&db_->mlock_, true); | | ScopedSpinRWLock lock(&db_->mlock_, true); | |
| db_->curs_.push_back(this); | | db_->curs_.push_back(this); | |
| } | | } | |
| /** | | /** | |
| | | | |
| skipping to change at line 356 | | skipping to change at line 356 | |
| return !err; | | return !err; | |
| } | | } | |
| /** | | /** | |
| * Get the database object. | | * Get the database object. | |
| * @return the database object. | | * @return the database object. | |
| */ | | */ | |
| PlantDB* db() { | | PlantDB* db() { | |
| _assert_(true); | | _assert_(true); | |
| return db_; | | return db_; | |
| } | | } | |
|
| private: | | private: | |
| /** | | /** | |
| * Clear the position. | | * Clear the position. | |
| */ | | */ | |
| void clear_position() { | | void clear_position() { | |
| _assert_(true); | | _assert_(true); | |
| if (kbuf_ != stack_) delete[] kbuf_; | | if (kbuf_ != stack_) delete[] kbuf_; | |
| kbuf_ = NULL; | | kbuf_ = NULL; | |
| lid_ = 0; | | lid_ = 0; | |
| } | | } | |
| /** | | /** | |
| | | | |
| skipping to change at line 935 | | skipping to change at line 935 | |
| * Status flags. | | * Status flags. | |
| */ | | */ | |
| enum Flag { | | enum Flag { | |
| FOPEN = BASEDB::FOPEN, ///< whether opened | | FOPEN = BASEDB::FOPEN, ///< whether opened | |
| FFATAL = BASEDB::FFATAL ///< whether with fatal error | | FFATAL = BASEDB::FFATAL ///< whether with fatal error | |
| }; | | }; | |
| /** | | /** | |
| * Default constructor. | | * Default constructor. | |
| */ | | */ | |
| explicit PlantDB() : | | explicit PlantDB() : | |
|
| mlock_(), mtrigger_(NULL), omode_(0), writer_(false), autotran_(false), | | mlock_(), mtrigger_(NULL), omode_(0), writer_(false), autotran_(false | |
| autosync_(false), | | ), autosync_(false), | |
| db_(), curs_(), apow_(DEFAPOW), fpow_(DEFFPOW), opts_(0), bnum_(DEFBNUM | | db_(), curs_(), apow_(DEFAPOW), fpow_(DEFFPOW), opts_(0), bnum_(DEFBN | |
| ), | | UM), | |
| psiz_(DEFPSIZ), pccap_(DEFPCCAP), | | psiz_(DEFPSIZ), pccap_(DEFPCCAP), | |
| root_(0), first_(0), last_(0), lcnt_(0), icnt_(0), count_(0), cusage_(0 | | root_(0), first_(0), last_(0), lcnt_(0), icnt_(0), count_(0), cusage_ | |
| ), | | (0), | |
| lslots_(), islots_(), reccomp_(), linkcomp_(), | | lslots_(), islots_(), reccomp_(), linkcomp_(), | |
| tran_(false), trclock_(0), trlcnt_(0), trcount_(0) { | | tran_(false), trclock_(0), trlcnt_(0), trcount_(0) { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| * @note If the database is not closed, it is closed implicitly. | | * @note If the database is not closed, it is closed implicitly. | |
| */ | | */ | |
| virtual ~PlantDB() { | | virtual ~PlantDB() { | |
| _assert_(true); | | _assert_(true); | |
| if (omode_ != 0) close(); | | if (omode_ != 0) close(); | |
| if (!curs_.empty()) { | | if (!curs_.empty()) { | |
| | | | |
| skipping to change at line 1498 | | skipping to change at line 1498 | |
| } | | } | |
| if (!flush_inner_cache(true)) err = true; | | if (!flush_inner_cache(true)) err = true; | |
| if (checker && !checker->check("synchronize", "dumping the meta data"
, -1, -1)) { | | if (checker && !checker->check("synchronize", "dumping the meta data"
, -1, -1)) { | |
| set_error(_KCCODELINE_, Error::LOGIC, "checker failed"); | | set_error(_KCCODELINE_, Error::LOGIC, "checker failed"); | |
| mlock_.unlock(); | | mlock_.unlock(); | |
| return false; | | return false; | |
| } | | } | |
| if (!dump_meta()) err = true; | | if (!dump_meta()) err = true; | |
| } | | } | |
| class Wrapper : public FileProcessor { | | class Wrapper : public FileProcessor { | |
|
| public: | | public: | |
| Wrapper(FileProcessor* proc, int64_t count) : proc_(proc), count_(cou
nt) {} | | Wrapper(FileProcessor* proc, int64_t count) : proc_(proc), count_(cou
nt) {} | |
|
| private: | | private: | |
| bool process(const std::string& path, int64_t count, int64_t size) { | | bool process(const std::string& path, int64_t count, int64_t size) { | |
| if (proc_) return proc_->process(path, count_, size); | | if (proc_) return proc_->process(path, count_, size); | |
| return true; | | return true; | |
| } | | } | |
| FileProcessor* proc_; | | FileProcessor* proc_; | |
| int64_t count_; | | int64_t count_; | |
| } wrapper(proc, count_); | | } wrapper(proc, count_); | |
| if (!db_.synchronize(hard, &wrapper, checker)) err = true; | | if (!db_.synchronize(hard, &wrapper, checker)) err = true; | |
| trigger_meta(MetaTrigger::SYNCHRONIZE, "synchronize"); | | trigger_meta(MetaTrigger::SYNCHRONIZE, "synchronize"); | |
| mlock_.unlock(); | | mlock_.unlock(); | |
| | | | |
| skipping to change at line 2018 | | skipping to change at line 2018 | |
| */ | | */ | |
| Comparator* rcomp() { | | Comparator* rcomp() { | |
| _assert_(true); | | _assert_(true); | |
| ScopedSpinRWLock lock(&mlock_, true); | | ScopedSpinRWLock lock(&mlock_, true); | |
| if (omode_ == 0) { | | if (omode_ == 0) { | |
| set_error(_KCCODELINE_, Error::INVALID, "not opened"); | | set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |
| return 0; | | return 0; | |
| } | | } | |
| return reccomp_.comp; | | return reccomp_.comp; | |
| } | | } | |
|
| protected: | | protected: | |
| /** | | /** | |
| * Report a message for debugging. | | * Report a message for debugging. | |
| * @param file the file name of the program source code. | | * @param file the file name of the program source code. | |
| * @param line the line number 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 func the function name of the program source code. | |
| * @param kind the kind of the event. Logger::DEBUG for debugging, Logge
r::INFO for normal | | * @param kind the kind of the event. Logger::DEBUG for debugging, Logge
r::INFO for normal | |
| * information, Logger::WARN for warning, and Logger::ERROR for fatal err
or. | | * information, Logger::WARN for warning, and Logger::ERROR for fatal err
or. | |
| * @param format the printf-like format string. | | * @param format the printf-like format string. | |
| * @param ... used according to the format string. | | * @param ... used according to the format string. | |
| */ | | */ | |
| | | | |
| skipping to change at line 2081 | | skipping to change at line 2081 | |
| * closing, MetaTrigger::CLEAR for clearing, MetaTrigger::ITERATE for ite
ration, | | * closing, MetaTrigger::CLEAR for clearing, MetaTrigger::ITERATE for ite
ration, | |
| * MetaTrigger::SYNCHRONIZE for synchronization, MetaTrigger::BEGINTRAN f
or beginning | | * MetaTrigger::SYNCHRONIZE for synchronization, MetaTrigger::BEGINTRAN f
or beginning | |
| * transaction, MetaTrigger::COMMITTRAN for committing transaction, MetaT
rigger::ABORTTRAN | | * transaction, MetaTrigger::COMMITTRAN for committing transaction, MetaT
rigger::ABORTTRAN | |
| * for aborting transaction, and MetaTrigger::MISC for miscellaneous oper
ations. | | * for aborting transaction, and MetaTrigger::MISC for miscellaneous oper
ations. | |
| * @param message the supplement message. | | * @param message the supplement message. | |
| */ | | */ | |
| void trigger_meta(MetaTrigger::Kind kind, const char* message) { | | void trigger_meta(MetaTrigger::Kind kind, const char* message) { | |
| _assert_(message); | | _assert_(message); | |
| if (mtrigger_) mtrigger_->trigger(kind, message); | | if (mtrigger_) mtrigger_->trigger(kind, message); | |
| } | | } | |
|
| private: | | private: | |
| /** | | /** | |
| * Record data. | | * Record data. | |
| */ | | */ | |
| struct Record { | | struct Record { | |
| uint32_t ksiz; ///< size of the key | | uint32_t ksiz; ///< size of the key | |
| uint32_t vsiz; ///< size of the value | | uint32_t vsiz; ///< size of the value | |
| }; | | }; | |
| /** | | /** | |
| * Comparator for records. | | * Comparator for records. | |
| */ | | */ | |
| | | | |
| skipping to change at line 2173 | | skipping to change at line 2173 | |
| * Slot cache of inner nodes. | | * Slot cache of inner nodes. | |
| */ | | */ | |
| struct InnerSlot { | | struct InnerSlot { | |
| SpinLock lock; ///< lock | | SpinLock lock; ///< lock | |
| InnerCache* warm; ///< warm cache | | InnerCache* warm; ///< warm cache | |
| }; | | }; | |
| /** | | /** | |
| * Scoped visitor. | | * Scoped visitor. | |
| */ | | */ | |
| class ScopedVisitor { | | class ScopedVisitor { | |
|
| public: | | public: | |
| /** constructor */ | | /** constructor */ | |
| explicit ScopedVisitor(Visitor* visitor) : visitor_(visitor) { | | explicit ScopedVisitor(Visitor* visitor) : visitor_(visitor) { | |
| _assert_(visitor); | | _assert_(visitor); | |
| visitor_->visit_before(); | | visitor_->visit_before(); | |
| } | | } | |
| /** destructor */ | | /** destructor */ | |
| ~ScopedVisitor() { | | ~ScopedVisitor() { | |
| _assert_(true); | | _assert_(true); | |
| visitor_->visit_after(); | | visitor_->visit_after(); | |
| } | | } | |
|
| private: | | private: | |
| Visitor* visitor_; ///< visitor | | Visitor* visitor_; ///< visitor | |
| }; | | }; | |
| /** | | /** | |
| * Open the leaf cache. | | * Open the leaf cache. | |
| */ | | */ | |
| void create_leaf_cache() { | | void create_leaf_cache() { | |
| _assert_(true); | | _assert_(true); | |
| int64_t bnum = bnum_ / SLOTNUM + 1; | | int64_t bnum = bnum_ / SLOTNUM + 1; | |
| if (bnum < INT8MAX) bnum = INT8MAX; | | if (bnum < INT8MAX) bnum = INT8MAX; | |
| bnum = nearbyprime(bnum); | | bnum = nearbyprime(bnum); | |
| | | | |
| skipping to change at line 2419 | | skipping to change at line 2419 | |
| (*np)->hot = true; | | (*np)->hot = true; | |
| return *np; | | return *np; | |
| } | | } | |
| } else { | | } else { | |
| LeafNode** np = slot->warm->get(id, LeafCache::MLAST); | | LeafNode** np = slot->warm->get(id, LeafCache::MLAST); | |
| if (np) return *np; | | if (np) return *np; | |
| } | | } | |
| char hbuf[NUMBUFSIZ]; | | char hbuf[NUMBUFSIZ]; | |
| size_t hsiz = std::sprintf(hbuf, "%c%llX", LNPREFIX, (long long)id); | | size_t hsiz = std::sprintf(hbuf, "%c%llX", LNPREFIX, (long long)id); | |
| class VisitorImpl : public DB::Visitor { | | class VisitorImpl : public DB::Visitor { | |
|
| public: | | public: | |
| explicit VisitorImpl() : node_(NULL) {} | | explicit VisitorImpl() : node_(NULL) {} | |
| LeafNode* pop() { | | LeafNode* pop() { | |
| return node_; | | return node_; | |
| } | | } | |
|
| private: | | private: | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| uint64_t prev; | | uint64_t prev; | |
| size_t step = readvarnum(vbuf, vsiz, &prev); | | size_t step = readvarnum(vbuf, vsiz, &prev); | |
| if (step < 1) return NOP; | | if (step < 1) return NOP; | |
| vbuf += step; | | vbuf += step; | |
| vsiz -= step; | | vsiz -= step; | |
| uint64_t next; | | uint64_t next; | |
| step = readvarnum(vbuf, vsiz, &next); | | step = readvarnum(vbuf, vsiz, &next); | |
| if (step < 1) return NOP; | | if (step < 1) return NOP; | |
| | | | |
| skipping to change at line 2780 | | skipping to change at line 2780 | |
| InnerNode* load_inner_node(int64_t id) { | | InnerNode* load_inner_node(int64_t id) { | |
| _assert_(id > 0); | | _assert_(id > 0); | |
| int32_t sidx = id % SLOTNUM; | | int32_t sidx = id % SLOTNUM; | |
| InnerSlot* slot = islots_ + sidx; | | InnerSlot* slot = islots_ + sidx; | |
| ScopedSpinLock lock(&slot->lock); | | ScopedSpinLock lock(&slot->lock); | |
| InnerNode** np = slot->warm->get(id, InnerCache::MLAST); | | InnerNode** np = slot->warm->get(id, InnerCache::MLAST); | |
| if (np) return *np; | | if (np) return *np; | |
| char hbuf[NUMBUFSIZ]; | | char hbuf[NUMBUFSIZ]; | |
| size_t hsiz = std::sprintf(hbuf, "%c%llX", INPREFIX, (long long)(id - I
NIDBASE)); | | size_t hsiz = std::sprintf(hbuf, "%c%llX", INPREFIX, (long long)(id - I
NIDBASE)); | |
| class VisitorImpl : public DB::Visitor { | | class VisitorImpl : public DB::Visitor { | |
|
| public: | | public: | |
| explicit VisitorImpl() : node_(NULL) {} | | explicit VisitorImpl() : node_(NULL) {} | |
| InnerNode* pop() { | | InnerNode* pop() { | |
| return node_; | | return node_; | |
| } | | } | |
|
| private: | | private: | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| uint64_t heir; | | uint64_t heir; | |
| size_t step = readvarnum(vbuf, vsiz, &heir); | | size_t step = readvarnum(vbuf, vsiz, &heir); | |
| if (step < 1) return NOP; | | if (step < 1) return NOP; | |
| vbuf += step; | | vbuf += step; | |
| vsiz -= step; | | vsiz -= step; | |
| InnerNode* node = new InnerNode; | | InnerNode* node = new InnerNode; | |
| node->size = sizeof(int64_t); | | node->size = sizeof(int64_t); | |
| node->heir = heir; | | node->heir = heir; | |
| | | | |
| skipping to change at line 3326 | | skipping to change at line 3326 | |
| } | | } | |
| /** | | /** | |
| * Recalculate the count data. | | * Recalculate the count data. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool recalc_count() { | | bool recalc_count() { | |
| _assert_(true); | | _assert_(true); | |
| if (!load_meta()) return false; | | if (!load_meta()) return false; | |
| bool err = false; | | bool err = false; | |
| class VisitorImpl : public DB::Visitor { | | class VisitorImpl : public DB::Visitor { | |
|
| public: | | public: | |
| explicit VisitorImpl() : count_(0) {} | | explicit VisitorImpl() : count_(0) {} | |
| int64_t count() { | | int64_t count() { | |
| return count_; | | return count_; | |
| } | | } | |
|
| private: | | private: | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| if (ksiz < 2 || kbuf[0] != LNPREFIX) return NOP; | | if (ksiz < 2 || kbuf[0] != LNPREFIX) return NOP; | |
| uint64_t prev; | | uint64_t prev; | |
| size_t step = readvarnum(vbuf, vsiz, &prev); | | size_t step = readvarnum(vbuf, vsiz, &prev); | |
| if (step < 1) return NOP; | | if (step < 1) return NOP; | |
| vbuf += step; | | vbuf += step; | |
| vsiz -= step; | | vsiz -= step; | |
| uint64_t next; | | uint64_t next; | |
| step = readvarnum(vbuf, vsiz, &next); | | step = readvarnum(vbuf, vsiz, &next); | |
| | | | |
End of changes. 18 change blocks. |
| 26 lines changed or deleted | | 26 lines changed or added | |
|
| kcprotodb.h | | kcprotodb.h | |
| | | | |
| skipping to change at line 47 | | skipping to change at line 47 | |
| * is forbidden. The class ProtoHashDB is the instance using std::unordere
d_map. The class | | * is forbidden. The class ProtoHashDB is the instance using std::unordere
d_map. The class | |
| * ProtoTreeDB is the instance using std::map. Before every database opera
tion, it is necessary | | * ProtoTreeDB is the instance using std::map. Before every database opera
tion, it is necessary | |
| * to call the BasicDB::open method in order to open a database file and co
nnect the database | | * to call the BasicDB::open method in order to open a database file and co
nnect the database | |
| * object to it. To avoid data missing or corruption, it is important to c
lose every database | | * object to it. To avoid data missing or corruption, it is important to c
lose every database | |
| * file by the BasicDB::close method when the database is no longer in use.
It is forbidden for | | * 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 | | * 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. | | * forbidden to share a database object with child processes. | |
| */ | | */ | |
| template <class STRMAP, uint8_t DBTYPE> | | template <class STRMAP, uint8_t DBTYPE> | |
| class ProtoDB : public BasicDB { | | class ProtoDB : public BasicDB { | |
|
| public: | | public: | |
| class Cursor; | | class Cursor; | |
|
| private: | | private: | |
| struct TranLog; | | struct TranLog; | |
| class ScopedVisitor; | | class ScopedVisitor; | |
| /** An alias of list of cursors. */ | | /** An alias of list of cursors. */ | |
| typedef std::list<Cursor*> CursorList; | | typedef std::list<Cursor*> CursorList; | |
| /** An alias of list of transaction logs. */ | | /** An alias of list of transaction logs. */ | |
| typedef std::list<TranLog> TranLogList; | | typedef std::list<TranLog> TranLogList; | |
| /** The size of the opaque buffer. */ | | /** The size of the opaque buffer. */ | |
| static const size_t OPAQUESIZ = 16; | | static const size_t OPAQUESIZ = 16; | |
| /** The threshold of busy loop and sleep for locking. */ | | /** The threshold of busy loop and sleep for locking. */ | |
| static const uint32_t LOCKBUSYLOOP = 8192; | | static const uint32_t LOCKBUSYLOOP = 8192; | |
|
| public: | | public: | |
| /** | | /** | |
| * Cursor to indicate a record. | | * Cursor to indicate a record. | |
| */ | | */ | |
| class Cursor : public BasicDB::Cursor { | | class Cursor : public BasicDB::Cursor { | |
| friend class ProtoDB; | | friend class ProtoDB; | |
|
| public: | | public: | |
| /** | | /** | |
| * Constructor. | | * Constructor. | |
| * @param db the container database object. | | * @param db the container database object. | |
| */ | | */ | |
| explicit Cursor(ProtoDB* db) : db_(db), it_(db->recs_.end()) { | | explicit Cursor(ProtoDB* db) : db_(db), it_(db->recs_.end()) { | |
| _assert_(db); | | _assert_(db); | |
| ScopedSpinRWLock lock(&db_->mlock_, true); | | ScopedSpinRWLock lock(&db_->mlock_, true); | |
| db_->curs_.push_back(this); | | db_->curs_.push_back(this); | |
| } | | } | |
| /** | | /** | |
| | | | |
| skipping to change at line 317 | | skipping to change at line 317 | |
| return true; | | return true; | |
| } | | } | |
| /** | | /** | |
| * Get the database object. | | * Get the database object. | |
| * @return the database object. | | * @return the database object. | |
| */ | | */ | |
| ProtoDB* db() { | | ProtoDB* db() { | |
| _assert_(true); | | _assert_(true); | |
| return db_; | | return db_; | |
| } | | } | |
|
| private: | | private: | |
| /** | | /** | |
| * Search for a record. | | * Search for a record. | |
| */ | | */ | |
| void search(const std::string& key); | | void search(const std::string& key); | |
| /** | | /** | |
| * Place back the inner iterator. | | * Place back the inner iterator. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool iter_back(); | | bool iter_back(); | |
| /** Dummy constructor to forbid the use. */ | | /** Dummy constructor to forbid the use. */ | |
| | | | |
| skipping to change at line 340 | | skipping to change at line 340 | |
| Cursor& operator =(const Cursor&); | | Cursor& operator =(const Cursor&); | |
| /** The inner database. */ | | /** The inner database. */ | |
| ProtoDB* db_; | | ProtoDB* db_; | |
| /** The inner iterator. */ | | /** The inner iterator. */ | |
| typename STRMAP::iterator it_; | | typename STRMAP::iterator it_; | |
| }; | | }; | |
| /** | | /** | |
| * Default constructor. | | * Default constructor. | |
| */ | | */ | |
| explicit ProtoDB() : | | explicit ProtoDB() : | |
|
| mlock_(), error_(), logger_(NULL), logkinds_(0), mtrigger_(NULL), | | mlock_(), error_(), logger_(NULL), logkinds_(0), mtrigger_(NULL), | |
| omode_(0), recs_(), curs_(), path_(""), size_(0), opaque_(), | | omode_(0), recs_(), curs_(), path_(""), size_(0), opaque_(), | |
| tran_(false), trlogs_(), trsize_(0) { | | tran_(false), trlogs_(), trsize_(0) { | |
| _assert_(true); | | _assert_(true); | |
| map_tune(); | | map_tune(); | |
| } | | } | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| * @note If the database is not closed, it is closed implicitly. | | * @note If the database is not closed, it is closed implicitly. | |
| */ | | */ | |
| virtual ~ProtoDB() { | | virtual ~ProtoDB() { | |
| _assert_(true); | | _assert_(true); | |
| if (omode_ != 0) close(); | | if (omode_ != 0) close(); | |
| | | | |
| skipping to change at line 613 | | skipping to change at line 613 | |
| * @param func the function name of the program source code. | | * @param func the function name of the program source code. | |
| * @param code an error code. | | * @param code an error code. | |
| * @param message a supplement message. | | * @param message a supplement message. | |
| */ | | */ | |
| void set_error(const char* file, int32_t line, const char* func, | | void set_error(const char* file, int32_t line, const char* func, | |
| Error::Code code, const char* message) { | | Error::Code code, const char* message) { | |
| _assert_(file && line > 0 && func && message); | | _assert_(file && line > 0 && func && message); | |
| error_->set(code, message); | | error_->set(code, message); | |
| if (logger_) { | | if (logger_) { | |
| Logger::Kind kind = code == Error::BROKEN || code == Error::SYSTEM ? | | Logger::Kind kind = code == Error::BROKEN || code == Error::SYSTEM ? | |
|
| Logger::ERROR : Logger::INFO; | | Logger::ERROR : Logger::INFO; | |
| if (kind & logkinds_) | | if (kind & logkinds_) | |
| report(file, line, func, kind, "%d: %s: %s", code, Error::codename(
code), message); | | report(file, line, func, kind, "%d: %s: %s", code, Error::codename(
code), message); | |
| } | | } | |
| } | | } | |
| /** | | /** | |
| * Open a database file. | | * Open a database file. | |
| * @param path the path of a database file. | | * @param path the path of a database file. | |
| * @param mode the connection mode. BasicDB::OWRITER as a writer, BasicD
B::OREADER as a | | * @param mode the connection mode. BasicDB::OWRITER as a writer, BasicD
B::OREADER as a | |
| * reader. The following may be added to the writer mode by bitwise-or:
BasicDB::OCREATE, | | * 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, Basi
cDB::OTRUNCATE, which | | * which means it creates a new database if the file does not exist, Basi
cDB::OTRUNCATE, which | |
| | | | |
| skipping to change at line 1007 | | skipping to change at line 1007 | |
| if (omode_ == 0) { | | if (omode_ == 0) { | |
| set_error(_KCCODELINE_, Error::INVALID, "not opened"); | | set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |
| return false; | | return false; | |
| } | | } | |
| if (!(omode_ & OWRITER)) { | | if (!(omode_ & OWRITER)) { | |
| set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | | set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | |
| return false; | | return false; | |
| } | | } | |
| return true; | | return true; | |
| } | | } | |
|
| protected: | | protected: | |
| /** | | /** | |
| * Report a message for debugging. | | * Report a message for debugging. | |
| * @param file the file name of the program source code. | | * @param file the file name of the program source code. | |
| * @param line the line number 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 func the function name of the program source code. | |
| * @param kind the kind of the event. Logger::DEBUG for debugging, Logge
r::INFO for normal | | * @param kind the kind of the event. Logger::DEBUG for debugging, Logge
r::INFO for normal | |
| * information, Logger::WARN for warning, and Logger::ERROR for fatal err
or. | | * information, Logger::WARN for warning, and Logger::ERROR for fatal err
or. | |
| * @param format the printf-like format string. | | * @param format the printf-like format string. | |
| * @param ... used according to the format string. | | * @param ... used according to the format string. | |
| */ | | */ | |
| | | | |
| skipping to change at line 1081 | | skipping to change at line 1081 | |
| * closing, MetaTrigger::CLEAR for clearing, MetaTrigger::ITERATE for ite
ration, | | * closing, MetaTrigger::CLEAR for clearing, MetaTrigger::ITERATE for ite
ration, | |
| * MetaTrigger::SYNCHRONIZE for synchronization, MetaTrigger::BEGINTRAN f
or beginning | | * MetaTrigger::SYNCHRONIZE for synchronization, MetaTrigger::BEGINTRAN f
or beginning | |
| * transaction, MetaTrigger::COMMITTRAN for committing transaction, MetaT
rigger::ABORTTRAN | | * transaction, MetaTrigger::COMMITTRAN for committing transaction, MetaT
rigger::ABORTTRAN | |
| * for aborting transaction, and MetaTrigger::MISC for miscellaneous oper
ations. | | * for aborting transaction, and MetaTrigger::MISC for miscellaneous oper
ations. | |
| * @param message the supplement message. | | * @param message the supplement message. | |
| */ | | */ | |
| void trigger_meta(MetaTrigger::Kind kind, const char* message) { | | void trigger_meta(MetaTrigger::Kind kind, const char* message) { | |
| _assert_(message); | | _assert_(message); | |
| if (mtrigger_) mtrigger_->trigger(kind, message); | | if (mtrigger_) mtrigger_->trigger(kind, message); | |
| } | | } | |
|
| private: | | private: | |
| /** | | /** | |
| * Transaction log. | | * Transaction log. | |
| */ | | */ | |
| struct TranLog { | | struct TranLog { | |
| bool full; ///< flag whether full | | bool full; ///< flag whether full | |
| std::string key; ///< old key | | std::string key; ///< old key | |
| std::string value; ///< old value | | std::string value; ///< old value | |
| /** constructor for a full record */ | | /** constructor for a full record */ | |
| explicit TranLog(const std::string& pkey, const std::string& pvalue) : | | explicit TranLog(const std::string& pkey, const std::string& pvalue) : | |
|
| full(true), key(pkey), value(pvalue) { | | full(true), key(pkey), value(pvalue) { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| /** constructor for an empty record */ | | /** constructor for an empty record */ | |
| explicit TranLog(const std::string& pkey) : full(false), key(pkey) { | | explicit TranLog(const std::string& pkey) : full(false), key(pkey) { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| }; | | }; | |
| /** | | /** | |
| * Scoped visitor. | | * Scoped visitor. | |
| */ | | */ | |
| class ScopedVisitor { | | class ScopedVisitor { | |
|
| public: | | public: | |
| /** constructor */ | | /** constructor */ | |
| explicit ScopedVisitor(Visitor* visitor) : visitor_(visitor) { | | explicit ScopedVisitor(Visitor* visitor) : visitor_(visitor) { | |
| _assert_(visitor); | | _assert_(visitor); | |
| visitor_->visit_before(); | | visitor_->visit_before(); | |
| } | | } | |
| /** destructor */ | | /** destructor */ | |
| ~ScopedVisitor() { | | ~ScopedVisitor() { | |
| _assert_(true); | | _assert_(true); | |
| visitor_->visit_after(); | | visitor_->visit_after(); | |
| } | | } | |
|
| private: | | private: | |
| Visitor* visitor_; ///< visitor | | Visitor* visitor_; ///< visitor | |
| }; | | }; | |
| /** | | /** | |
| * Tune the internal map object. | | * Tune the internal map object. | |
| */ | | */ | |
| void map_tune(); | | void map_tune(); | |
| /** Dummy constructor to forbid the use. */ | | /** Dummy constructor to forbid the use. */ | |
| ProtoDB(const ProtoDB&); | | ProtoDB(const ProtoDB&); | |
| /** Dummy Operator to forbid the use. */ | | /** Dummy Operator to forbid the use. */ | |
| ProtoDB& operator =(const ProtoDB&); | | ProtoDB& operator =(const ProtoDB&); | |
| | | | |
End of changes. 12 change blocks. |
| 14 lines changed or deleted | | 14 lines changed or added | |
|
| kcstashdb.h | | kcstashdb.h | |
| | | | |
| skipping to change at line 42 | | skipping to change at line 42 | |
| * Economical on-memory hash database. | | * Economical on-memory hash database. | |
| * @note This class is a concrete class to operate a hash database on memor
y. This class can be | | * @note This class is a concrete class to operate a hash database on memor
y. This class can be | |
| * inherited but overwriting methods is forbidden. Before every database o
peration, it is | | * inherited but overwriting methods is forbidden. Before every database o
peration, it is | |
| * necessary to call the StashDB::open method in order to open a database f
ile and connect the | | * necessary to call the StashDB::open method in order to open a database f
ile and connect the | |
| * database object to it. To avoid data missing or corruption, it is impor
tant to close every | | * database object to it. To avoid data missing or corruption, it is impor
tant to close every | |
| * database file by the StashDB::close method when the database is no longe
r in use. It is | | * database file by the StashDB::close method when the database is no longe
r in use. It is | |
| * forbidden for multible database objects in a process to open the same da
tabase at the same | | * forbidden for multible database objects in a process to open the same da
tabase at the same | |
| * time. It is forbidden to share a database object with child processes. | | * time. It is forbidden to share a database object with child processes. | |
| */ | | */ | |
| class StashDB : public BasicDB { | | class StashDB : public BasicDB { | |
|
| public: | | public: | |
| class Cursor; | | class Cursor; | |
|
| private: | | private: | |
| struct Record; | | struct Record; | |
| struct TranLog; | | struct TranLog; | |
| class Repeater; | | class Repeater; | |
| class Setter; | | class Setter; | |
| class Remover; | | class Remover; | |
| class ScopedVisitor; | | class ScopedVisitor; | |
| /** An alias of list of cursors. */ | | /** An alias of list of cursors. */ | |
| typedef std::list<Cursor*> CursorList; | | typedef std::list<Cursor*> CursorList; | |
| /** An alias of list of transaction logs. */ | | /** An alias of list of transaction logs. */ | |
| typedef std::list<TranLog> TranLogList; | | typedef std::list<TranLog> TranLogList; | |
| /** The number of slots of the record lock. */ | | /** The number of slots of the record lock. */ | |
| static const int32_t RLOCKSLOT = 1024; | | static const int32_t RLOCKSLOT = 1024; | |
| /** The default bucket number. */ | | /** The default bucket number. */ | |
| static const size_t DEFBNUM = 1048583LL; | | static const size_t DEFBNUM = 1048583LL; | |
| /** The size of the opaque buffer. */ | | /** The size of the opaque buffer. */ | |
| static const size_t OPAQUESIZ = 16; | | static const size_t OPAQUESIZ = 16; | |
| /** The threshold of busy loop and sleep for locking. */ | | /** The threshold of busy loop and sleep for locking. */ | |
| static const uint32_t LOCKBUSYLOOP = 8192; | | static const uint32_t LOCKBUSYLOOP = 8192; | |
| /** The mininum number of buckets to use mmap. */ | | /** The mininum number of buckets to use mmap. */ | |
| static const size_t MAPZMAPBNUM = 32768; | | static const size_t MAPZMAPBNUM = 32768; | |
|
| public: | | public: | |
| /** | | /** | |
| * Cursor to indicate a record. | | * Cursor to indicate a record. | |
| */ | | */ | |
| class Cursor : public BasicDB::Cursor { | | class Cursor : public BasicDB::Cursor { | |
| friend class StashDB; | | friend class StashDB; | |
|
| public: | | public: | |
| /** | | /** | |
| * Constructor. | | * Constructor. | |
| * @param db the container database object. | | * @param db the container database object. | |
| */ | | */ | |
| explicit Cursor(StashDB* db) : db_(db), bidx_(-1), rbuf_(NULL) { | | explicit Cursor(StashDB* db) : db_(db), bidx_(-1), rbuf_(NULL) { | |
| _assert_(db); | | _assert_(db); | |
| ScopedSpinRWLock lock(&db_->mlock_, true); | | ScopedSpinRWLock lock(&db_->mlock_, true); | |
| db_->curs_.push_back(this); | | db_->curs_.push_back(this); | |
| } | | } | |
| /** | | /** | |
| | | | |
| skipping to change at line 274 | | skipping to change at line 274 | |
| return false; | | return false; | |
| } | | } | |
| /** | | /** | |
| * Get the database object. | | * Get the database object. | |
| * @return the database object. | | * @return the database object. | |
| */ | | */ | |
| StashDB* db() { | | StashDB* db() { | |
| _assert_(true); | | _assert_(true); | |
| return db_; | | return db_; | |
| } | | } | |
|
| private: | | private: | |
| /** | | /** | |
| * Step the cursor to the next record. | | * Step the cursor to the next record. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool step_impl() { | | bool step_impl() { | |
| _assert_(true); | | _assert_(true); | |
| Record rec(rbuf_); | | Record rec(rbuf_); | |
| rbuf_ = rec.child_; | | rbuf_ = rec.child_; | |
| if (!rbuf_) { | | if (!rbuf_) { | |
| while (++bidx_ < (int64_t)db_->bnum_) { | | while (++bidx_ < (int64_t)db_->bnum_) { | |
| | | | |
| skipping to change at line 311 | | skipping to change at line 311 | |
| StashDB* db_; | | StashDB* db_; | |
| /** The index of the current bucket. */ | | /** The index of the current bucket. */ | |
| int64_t bidx_; | | int64_t bidx_; | |
| /** The buffer of the current record. */ | | /** The buffer of the current record. */ | |
| char* rbuf_; | | char* rbuf_; | |
| }; | | }; | |
| /** | | /** | |
| * Default constructor. | | * Default constructor. | |
| */ | | */ | |
| explicit StashDB() : | | explicit StashDB() : | |
|
| mlock_(), rlock_(RLOCKSLOT), flock_(), error_(), | | mlock_(), rlock_(RLOCKSLOT), flock_(), error_(), | |
| logger_(NULL), logkinds_(0), mtrigger_(NULL), | | logger_(NULL), logkinds_(0), mtrigger_(NULL), | |
| omode_(0), curs_(), path_(""), bnum_(DEFBNUM), opaque_(), | | omode_(0), curs_(), path_(""), bnum_(DEFBNUM), opaque_(), | |
| count_(0), size_(0), buckets_(NULL), | | count_(0), size_(0), buckets_(NULL), | |
| tran_(false), trlogs_(), trcount_(0), trsize_(0) { | | tran_(false), trlogs_(), trcount_(0), trsize_(0) { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| * @note If the database is not closed, it is closed implicitly. | | * @note If the database is not closed, it is closed implicitly. | |
| */ | | */ | |
| ~StashDB() { | | ~StashDB() { | |
| _assert_(true); | | _assert_(true); | |
| if (omode_ != 0) close(); | | if (omode_ != 0) close(); | |
| if (!curs_.empty()) { | | if (!curs_.empty()) { | |
| | | | |
| skipping to change at line 509 | | skipping to change at line 509 | |
| * @param func the function name of the program source code. | | * @param func the function name of the program source code. | |
| * @param code an error code. | | * @param code an error code. | |
| * @param message a supplement message. | | * @param message a supplement message. | |
| */ | | */ | |
| void set_error(const char* file, int32_t line, const char* func, | | void set_error(const char* file, int32_t line, const char* func, | |
| Error::Code code, const char* message) { | | Error::Code code, const char* message) { | |
| _assert_(file && line > 0 && func && message); | | _assert_(file && line > 0 && func && message); | |
| error_->set(code, message); | | error_->set(code, message); | |
| if (logger_) { | | if (logger_) { | |
| Logger::Kind kind = code == Error::BROKEN || code == Error::SYSTEM ? | | Logger::Kind kind = code == Error::BROKEN || code == Error::SYSTEM ? | |
|
| Logger::ERROR : Logger::INFO; | | Logger::ERROR : Logger::INFO; | |
| if (kind & logkinds_) | | if (kind & logkinds_) | |
| report(file, line, func, kind, "%d: %s: %s", code, Error::codename(
code), message); | | report(file, line, func, kind, "%d: %s: %s", code, Error::codename(
code), message); | |
| } | | } | |
| } | | } | |
| /** | | /** | |
| * Open a database file. | | * Open a database file. | |
| * @param path the path of a database file. | | * @param path the path of a database file. | |
| * @param mode the connection mode. StashDB::OWRITER as a writer, StashD
B::OREADER as a | | * @param mode the connection mode. StashDB::OWRITER as a writer, StashD
B::OREADER as a | |
| * reader. The following may be added to the writer mode by bitwise-or:
StashDB::OCREATE, | | * reader. The following may be added to the writer mode by bitwise-or:
StashDB::OCREATE, | |
| * which means it creates a new database if the file does not exist, Stas
hDB::OTRUNCATE, which | | * which means it creates a new database if the file does not exist, Stas
hDB::OTRUNCATE, which | |
| | | | |
| skipping to change at line 928 | | skipping to change at line 928 | |
| if (omode_ == 0) { | | if (omode_ == 0) { | |
| set_error(_KCCODELINE_, Error::INVALID, "not opened"); | | set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |
| return false; | | return false; | |
| } | | } | |
| if (!(omode_ & OWRITER)) { | | if (!(omode_ & OWRITER)) { | |
| set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | | set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | |
| return false; | | return false; | |
| } | | } | |
| return true; | | return true; | |
| } | | } | |
|
| protected: | | protected: | |
| /** | | /** | |
| * Report a message for debugging. | | * Report a message for debugging. | |
| * @param file the file name of the program source code. | | * @param file the file name of the program source code. | |
| * @param line the line number 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 func the function name of the program source code. | |
| * @param kind the kind of the event. Logger::DEBUG for debugging, Logge
r::INFO for normal | | * @param kind the kind of the event. Logger::DEBUG for debugging, Logge
r::INFO for normal | |
| * information, Logger::WARN for warning, and Logger::ERROR for fatal err
or. | | * information, Logger::WARN for warning, and Logger::ERROR for fatal err
or. | |
| * @param format the printf-like format string. | | * @param format the printf-like format string. | |
| * @param ... used according to the format string. | | * @param ... used according to the format string. | |
| */ | | */ | |
| | | | |
| skipping to change at line 1002 | | skipping to change at line 1002 | |
| * closing, MetaTrigger::CLEAR for clearing, MetaTrigger::ITERATE for ite
ration, | | * closing, MetaTrigger::CLEAR for clearing, MetaTrigger::ITERATE for ite
ration, | |
| * MetaTrigger::SYNCHRONIZE for synchronization, MetaTrigger::BEGINTRAN f
or beginning | | * MetaTrigger::SYNCHRONIZE for synchronization, MetaTrigger::BEGINTRAN f
or beginning | |
| * transaction, MetaTrigger::COMMITTRAN for committing transaction, MetaT
rigger::ABORTTRAN | | * transaction, MetaTrigger::COMMITTRAN for committing transaction, MetaT
rigger::ABORTTRAN | |
| * for aborting transaction, and MetaTrigger::MISC for miscellaneous oper
ations. | | * for aborting transaction, and MetaTrigger::MISC for miscellaneous oper
ations. | |
| * @param message the supplement message. | | * @param message the supplement message. | |
| */ | | */ | |
| void trigger_meta(MetaTrigger::Kind kind, const char* message) { | | void trigger_meta(MetaTrigger::Kind kind, const char* message) { | |
| _assert_(message); | | _assert_(message); | |
| if (mtrigger_) mtrigger_->trigger(kind, message); | | if (mtrigger_) mtrigger_->trigger(kind, message); | |
| } | | } | |
|
| private: | | private: | |
| /** | | /** | |
| * Record data. | | * Record data. | |
| */ | | */ | |
| struct Record { | | struct Record { | |
| /** constructor */ | | /** constructor */ | |
| Record(char* child, const char* kbuf, uint64_t ksiz, const char* vbuf,
uint64_t vsiz) : | | Record(char* child, const char* kbuf, uint64_t ksiz, const char* vbuf,
uint64_t vsiz) : | |
|
| child_(child), kbuf_(kbuf), ksiz_(ksiz), vbuf_(vbuf), vsiz_(vsiz) { | | child_(child), kbuf_(kbuf), ksiz_(ksiz), vbuf_(vbuf), vsiz_(vsiz) { | |
| _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ); | | _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ); | |
| } | | } | |
| /** constructor */ | | /** constructor */ | |
| Record(const char* rbuf) : | | Record(const char* rbuf) : | |
|
| child_(NULL), kbuf_(NULL), ksiz_(0), vbuf_(NULL), vsiz_(0) { | | child_(NULL), kbuf_(NULL), ksiz_(0), vbuf_(NULL), vsiz_(0) { | |
| _assert_(rbuf); | | _assert_(rbuf); | |
| deserialize(rbuf); | | deserialize(rbuf); | |
| } | | } | |
| /** overwrite the buffer */ | | /** overwrite the buffer */ | |
| void overwrite(char* rbuf, const char* vbuf, size_t vsiz) { | | void overwrite(char* rbuf, const char* vbuf, size_t vsiz) { | |
| _assert_(rbuf && vbuf && vsiz <= MEMMAXSIZ); | | _assert_(rbuf && vbuf && vsiz <= MEMMAXSIZ); | |
| char* wp = rbuf + sizeof(child_) + sizevarnum(ksiz_) + ksiz_; | | char* wp = rbuf + sizeof(child_) + sizevarnum(ksiz_) + ksiz_; | |
| wp += writevarnum(wp, vsiz); | | wp += writevarnum(wp, vsiz); | |
| std::memcpy(wp, vbuf, vsiz); | | std::memcpy(wp, vbuf, vsiz); | |
| } | | } | |
| | | | |
| skipping to change at line 1075 | | skipping to change at line 1075 | |
| }; | | }; | |
| /** | | /** | |
| * Transaction log. | | * Transaction log. | |
| */ | | */ | |
| struct TranLog { | | struct TranLog { | |
| bool full; ///< flag whether full | | bool full; ///< flag whether full | |
| std::string key; ///< old key | | std::string key; ///< old key | |
| std::string value; ///< old value | | std::string value; ///< old value | |
| /** constructor for a full record */ | | /** constructor for a full record */ | |
| explicit TranLog(const char* kbuf, size_t ksiz, const char* vbuf, size_
t vsiz) : | | explicit TranLog(const char* kbuf, size_t ksiz, const char* vbuf, size_
t vsiz) : | |
|
| full(true), key(kbuf, ksiz), value(vbuf, vsiz) { | | full(true), key(kbuf, ksiz), value(vbuf, vsiz) { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| /** constructor for an empty record */ | | /** constructor for an empty record */ | |
| explicit TranLog(const char* kbuf, size_t ksiz) : full(false), key(kbuf
, ksiz) { | | explicit TranLog(const char* kbuf, size_t ksiz) : full(false), key(kbuf
, ksiz) { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| }; | | }; | |
| /** | | /** | |
| * Repeating visitor. | | * Repeating visitor. | |
| */ | | */ | |
| class Repeater : public Visitor { | | class Repeater : public Visitor { | |
|
| public: | | public: | |
| /** constructor */ | | /** constructor */ | |
| explicit Repeater(const char* vbuf, size_t vsiz) : vbuf_(vbuf), vsiz_(v
siz) {} | | explicit Repeater(const char* vbuf, size_t vsiz) : vbuf_(vbuf), vsiz_(v
siz) {} | |
|
| private: | | private: | |
| /** process a full record */ | | /** process a full record */ | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp
); | | _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp
); | |
| *sp = vsiz_; | | *sp = vsiz_; | |
| return vbuf_; | | return vbuf_; | |
| } | | } | |
| const char* vbuf_; ///< region of the value | | const char* vbuf_; ///< region of the value | |
| size_t vsiz_; ///< size of the value | | size_t vsiz_; ///< size of the value | |
| }; | | }; | |
| /** | | /** | |
| * Setting visitor. | | * Setting visitor. | |
| */ | | */ | |
| class Setter : public Visitor { | | class Setter : public Visitor { | |
|
| public: | | public: | |
| /** constructor */ | | /** constructor */ | |
| explicit Setter(const char* vbuf, size_t vsiz) : vbuf_(vbuf), vsiz_(vsi
z) {} | | explicit Setter(const char* vbuf, size_t vsiz) : vbuf_(vbuf), vsiz_(vsi
z) {} | |
|
| private: | | private: | |
| /** process a full record */ | | /** process a full record */ | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp
); | | _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp
); | |
| *sp = vsiz_; | | *sp = vsiz_; | |
| return vbuf_; | | return vbuf_; | |
| } | | } | |
| /** process an empty record */ | | /** process an empty record */ | |
| const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { | | const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { | |
| _assert_(kbuf && ksiz <= MEMMAXSIZ && sp); | | _assert_(kbuf && ksiz <= MEMMAXSIZ && sp); | |
| *sp = vsiz_; | | *sp = vsiz_; | |
| return vbuf_; | | return vbuf_; | |
| } | | } | |
| const char* vbuf_; ///< region of the value | | const char* vbuf_; ///< region of the value | |
| size_t vsiz_; ///< size of the value | | size_t vsiz_; ///< size of the value | |
| }; | | }; | |
| /** | | /** | |
| * Removing visitor. | | * Removing visitor. | |
| */ | | */ | |
| class Remover : public Visitor { | | class Remover : public Visitor { | |
|
| private: | | private: | |
| /** visit a record */ | | /** visit a record */ | |
| const char* visit_full(const char* kbuf, size_t ksiz, | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| const char* vbuf, size_t vsiz, size_t* sp) { | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp
); | | _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp
); | |
| return REMOVE; | | return REMOVE; | |
| } | | } | |
| }; | | }; | |
| /** | | /** | |
| * Scoped visitor. | | * Scoped visitor. | |
| */ | | */ | |
| class ScopedVisitor { | | class ScopedVisitor { | |
|
| public: | | public: | |
| /** constructor */ | | /** constructor */ | |
| explicit ScopedVisitor(Visitor* visitor) : visitor_(visitor) { | | explicit ScopedVisitor(Visitor* visitor) : visitor_(visitor) { | |
| _assert_(visitor); | | _assert_(visitor); | |
| visitor_->visit_before(); | | visitor_->visit_before(); | |
| } | | } | |
| /** destructor */ | | /** destructor */ | |
| ~ScopedVisitor() { | | ~ScopedVisitor() { | |
| _assert_(true); | | _assert_(true); | |
| visitor_->visit_after(); | | visitor_->visit_after(); | |
| } | | } | |
|
| private: | | private: | |
| Visitor* visitor_; ///< visitor | | Visitor* visitor_; ///< visitor | |
| }; | | }; | |
| /** | | /** | |
| * Accept a visitor to a record. | | * Accept a visitor to a record. | |
| * @param kbuf the pointer to the key region. | | * @param kbuf the pointer to the key region. | |
| * @param ksiz the size of the key region. | | * @param ksiz the size of the key region. | |
| * @param visitor a visitor object. | | * @param visitor a visitor object. | |
| * @param bidx the bucket index. | | * @param bidx the bucket index. | |
| */ | | */ | |
| void accept_impl(const char* kbuf, size_t ksiz, Visitor* visitor, size_t
bidx) { | | void accept_impl(const char* kbuf, size_t ksiz, Visitor* visitor, size_t
bidx) { | |
| | | | |
End of changes. 19 change blocks. |
| 23 lines changed or deleted | | 23 lines changed or added | |
|
| kcthread.h | | kcthread.h | |
| | | | |
| skipping to change at line 27 | | skipping to change at line 27 | |
| | | | |
| #include <kccommon.h> | | #include <kccommon.h> | |
| #include <kcutil.h> | | #include <kcutil.h> | |
| | | | |
| namespace kyotocabinet { // common namespace | | namespace kyotocabinet { // common namespace | |
| | | | |
| /** | | /** | |
| * Threading device. | | * Threading device. | |
| */ | | */ | |
| class Thread { | | class Thread { | |
|
| public: | | public: | |
| /** | | /** | |
| * Default constructor. | | * Default constructor. | |
| */ | | */ | |
| explicit Thread(); | | explicit Thread(); | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| */ | | */ | |
| virtual ~Thread(); | | virtual ~Thread(); | |
| /** | | /** | |
| * Perform the concrete process. | | * Perform the concrete process. | |
| | | | |
| skipping to change at line 75 | | skipping to change at line 75 | |
| * Suspend execution of the current thread. | | * Suspend execution of the current thread. | |
| * @param sec the interval of the suspension in seconds. | | * @param sec the interval of the suspension in seconds. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| static bool sleep(double sec); | | static bool sleep(double sec); | |
| /** | | /** | |
| * Get the hash value of the current thread. | | * Get the hash value of the current thread. | |
| * @return the hash value of the current thread. | | * @return the hash value of the current thread. | |
| */ | | */ | |
| static int64_t hash(); | | static int64_t hash(); | |
|
| private: | | private: | |
| /** Dummy constructor to forbid the use. */ | | /** Dummy constructor to forbid the use. */ | |
| Thread(const Thread&); | | Thread(const Thread&); | |
| /** Dummy Operator to forbid the use. */ | | /** Dummy Operator to forbid the use. */ | |
| Thread& operator =(const Thread&); | | Thread& operator =(const Thread&); | |
| /** Opaque pointer. */ | | /** Opaque pointer. */ | |
| void* opq_; | | void* opq_; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Basic mutual exclusion device. | | * Basic mutual exclusion device. | |
| */ | | */ | |
| class Mutex { | | class Mutex { | |
| friend class CondVar; | | friend class CondVar; | |
|
| public: | | public: | |
| /** | | /** | |
| * Type of the behavior for double locking. | | * Type of the behavior for double locking. | |
| */ | | */ | |
| enum Type { | | enum Type { | |
| FAST, ///< no operation | | FAST, ///< no operation | |
| ERRORCHECK, ///< check error | | ERRORCHECK, ///< check error | |
| RECURSIVE ///< allow recursive locking | | RECURSIVE ///< allow recursive locking | |
| }; | | }; | |
| /** | | /** | |
| * Default constructor. | | * Default constructor. | |
| | | | |
| skipping to change at line 130 | | skipping to change at line 130 | |
| /** | | /** | |
| * Try to get the lock. | | * Try to get the lock. | |
| * @param sec the interval of the suspension in seconds. | | * @param sec the interval of the suspension in seconds. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool lock_try(double sec); | | bool lock_try(double sec); | |
| /** | | /** | |
| * Release the lock. | | * Release the lock. | |
| */ | | */ | |
| void unlock(); | | void unlock(); | |
|
| private: | | private: | |
| /** Dummy constructor to forbid the use. */ | | /** Dummy constructor to forbid the use. */ | |
| Mutex(const Mutex&); | | Mutex(const Mutex&); | |
| /** Dummy Operator to forbid the use. */ | | /** Dummy Operator to forbid the use. */ | |
| Mutex& operator =(const Mutex&); | | Mutex& operator =(const Mutex&); | |
| /** Opaque pointer. */ | | /** Opaque pointer. */ | |
| void* opq_; | | void* opq_; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Scoped mutex device. | | * Scoped mutex device. | |
| */ | | */ | |
| class ScopedMutex { | | class ScopedMutex { | |
|
| public: | | public: | |
| /** | | /** | |
| * Constructor. | | * Constructor. | |
| * @param mutex a mutex to lock the block. | | * @param mutex a mutex to lock the block. | |
| */ | | */ | |
| explicit ScopedMutex(Mutex* mutex) : mutex_(mutex) { | | explicit ScopedMutex(Mutex* mutex) : mutex_(mutex) { | |
| _assert_(mutex); | | _assert_(mutex); | |
| mutex_->lock(); | | mutex_->lock(); | |
| } | | } | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| */ | | */ | |
| ~ScopedMutex() { | | ~ScopedMutex() { | |
| _assert_(true); | | _assert_(true); | |
| mutex_->unlock(); | | mutex_->unlock(); | |
| } | | } | |
|
| private: | | private: | |
| /** Dummy constructor to forbid the use. */ | | /** Dummy constructor to forbid the use. */ | |
| ScopedMutex(const ScopedMutex&); | | ScopedMutex(const ScopedMutex&); | |
| /** Dummy Operator to forbid the use. */ | | /** Dummy Operator to forbid the use. */ | |
| ScopedMutex& operator =(const ScopedMutex&); | | ScopedMutex& operator =(const ScopedMutex&); | |
| /** The inner device. */ | | /** The inner device. */ | |
| Mutex* mutex_; | | Mutex* mutex_; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Slotted mutex device. | | * Slotted mutex device. | |
| */ | | */ | |
| class SlottedMutex { | | class SlottedMutex { | |
|
| public: | | public: | |
| /** | | /** | |
| * Constructor. | | * Constructor. | |
| * @param slotnum the number of slots. | | * @param slotnum the number of slots. | |
| */ | | */ | |
| explicit SlottedMutex(size_t slotnum); | | explicit SlottedMutex(size_t slotnum); | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| */ | | */ | |
| ~SlottedMutex(); | | ~SlottedMutex(); | |
| /** | | /** | |
| | | | |
| skipping to change at line 200 | | skipping to change at line 200 | |
| */ | | */ | |
| void unlock(size_t idx); | | void unlock(size_t idx); | |
| /** | | /** | |
| * Get the locks of all slots. | | * Get the locks of all slots. | |
| */ | | */ | |
| void lock_all(); | | void lock_all(); | |
| /** | | /** | |
| * Release the locks of all slots. | | * Release the locks of all slots. | |
| */ | | */ | |
| void unlock_all(); | | void unlock_all(); | |
|
| private: | | private: | |
| /** Opaque pointer. */ | | /** Opaque pointer. */ | |
| void* opq_; | | void* opq_; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Lightweight mutual exclusion device. | | * Lightweight mutual exclusion device. | |
| */ | | */ | |
| class SpinLock { | | class SpinLock { | |
|
| public: | | public: | |
| /** | | /** | |
| * Default constructor. | | * Default constructor. | |
| */ | | */ | |
| explicit SpinLock(); | | explicit SpinLock(); | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| */ | | */ | |
| ~SpinLock(); | | ~SpinLock(); | |
| /** | | /** | |
| * Get the lock. | | * Get the lock. | |
| | | | |
| skipping to change at line 231 | | skipping to change at line 231 | |
| void lock(); | | void lock(); | |
| /** | | /** | |
| * Try to get the lock. | | * Try to get the lock. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool lock_try(); | | bool lock_try(); | |
| /** | | /** | |
| * Release the lock. | | * Release the lock. | |
| */ | | */ | |
| void unlock(); | | void unlock(); | |
|
| private: | | private: | |
| /** Dummy constructor to forbid the use. */ | | /** Dummy constructor to forbid the use. */ | |
| SpinLock(const SpinLock&); | | SpinLock(const SpinLock&); | |
| /** Dummy Operator to forbid the use. */ | | /** Dummy Operator to forbid the use. */ | |
| SpinLock& operator =(const SpinLock&); | | SpinLock& operator =(const SpinLock&); | |
| /** Opaque pointer. */ | | /** Opaque pointer. */ | |
| void* opq_; | | void* opq_; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Scoped spin lock device. | | * Scoped spin lock device. | |
| */ | | */ | |
| class ScopedSpinLock { | | class ScopedSpinLock { | |
|
| public: | | public: | |
| /** | | /** | |
| * Constructor. | | * Constructor. | |
| * @param spinlock a spin lock to lock the block. | | * @param spinlock a spin lock to lock the block. | |
| */ | | */ | |
| explicit ScopedSpinLock(SpinLock* spinlock) : spinlock_(spinlock) { | | explicit ScopedSpinLock(SpinLock* spinlock) : spinlock_(spinlock) { | |
| _assert_(spinlock); | | _assert_(spinlock); | |
| spinlock_->lock(); | | spinlock_->lock(); | |
| } | | } | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| */ | | */ | |
| ~ScopedSpinLock() { | | ~ScopedSpinLock() { | |
| _assert_(true); | | _assert_(true); | |
| spinlock_->unlock(); | | spinlock_->unlock(); | |
| } | | } | |
|
| private: | | private: | |
| /** Dummy constructor to forbid the use. */ | | /** Dummy constructor to forbid the use. */ | |
| ScopedSpinLock(const ScopedSpinLock&); | | ScopedSpinLock(const ScopedSpinLock&); | |
| /** Dummy Operator to forbid the use. */ | | /** Dummy Operator to forbid the use. */ | |
| ScopedSpinLock& operator =(const ScopedSpinLock&); | | ScopedSpinLock& operator =(const ScopedSpinLock&); | |
| /** The inner device. */ | | /** The inner device. */ | |
| SpinLock* spinlock_; | | SpinLock* spinlock_; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Slotted spin lock devices. | | * Slotted spin lock devices. | |
| */ | | */ | |
| class SlottedSpinLock { | | class SlottedSpinLock { | |
|
| public: | | public: | |
| /** | | /** | |
| * Constructor. | | * Constructor. | |
| * @param slotnum the number of slots. | | * @param slotnum the number of slots. | |
| */ | | */ | |
| explicit SlottedSpinLock(size_t slotnum); | | explicit SlottedSpinLock(size_t slotnum); | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| */ | | */ | |
| ~SlottedSpinLock(); | | ~SlottedSpinLock(); | |
| /** | | /** | |
| | | | |
| skipping to change at line 301 | | skipping to change at line 301 | |
| */ | | */ | |
| void unlock(size_t idx); | | void unlock(size_t idx); | |
| /** | | /** | |
| * Get the locks of all slots. | | * Get the locks of all slots. | |
| */ | | */ | |
| void lock_all(); | | void lock_all(); | |
| /** | | /** | |
| * Release the locks of all slots. | | * Release the locks of all slots. | |
| */ | | */ | |
| void unlock_all(); | | void unlock_all(); | |
|
| private: | | private: | |
| /** Opaque pointer. */ | | /** Opaque pointer. */ | |
| void* opq_; | | void* opq_; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Reader-writer locking device. | | * Reader-writer locking device. | |
| */ | | */ | |
| class RWLock { | | class RWLock { | |
|
| public: | | public: | |
| /** | | /** | |
| * Default constructor. | | * Default constructor. | |
| */ | | */ | |
| explicit RWLock(); | | explicit RWLock(); | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| */ | | */ | |
| ~RWLock(); | | ~RWLock(); | |
| /** | | /** | |
| * Get the writer lock. | | * Get the writer lock. | |
| | | | |
| skipping to change at line 341 | | skipping to change at line 341 | |
| void lock_reader(); | | void lock_reader(); | |
| /** | | /** | |
| * Try to get a reader lock. | | * Try to get a reader lock. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool lock_reader_try(); | | bool lock_reader_try(); | |
| /** | | /** | |
| * Release the lock. | | * Release the lock. | |
| */ | | */ | |
| void unlock(); | | void unlock(); | |
|
| private: | | private: | |
| /** Dummy constructor to forbid the use. */ | | /** Dummy constructor to forbid the use. */ | |
| RWLock(const RWLock&); | | RWLock(const RWLock&); | |
| /** Dummy Operator to forbid the use. */ | | /** Dummy Operator to forbid the use. */ | |
| RWLock& operator =(const RWLock&); | | RWLock& operator =(const RWLock&); | |
| /** Opaque pointer. */ | | /** Opaque pointer. */ | |
| void* opq_; | | void* opq_; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Scoped reader-writer locking device. | | * Scoped reader-writer locking device. | |
| */ | | */ | |
| class ScopedRWLock { | | class ScopedRWLock { | |
|
| public: | | public: | |
| /** | | /** | |
| * Constructor. | | * Constructor. | |
| * @param rwlock a rwlock to lock the block. | | * @param rwlock a rwlock to lock the block. | |
| * @param writer true for writer lock, or false for reader lock. | | * @param writer true for writer lock, or false for reader lock. | |
| */ | | */ | |
| explicit ScopedRWLock(RWLock* rwlock, bool writer) : rwlock_(rwlock) { | | explicit ScopedRWLock(RWLock* rwlock, bool writer) : rwlock_(rwlock) { | |
| _assert_(rwlock); | | _assert_(rwlock); | |
| if (writer) { | | if (writer) { | |
| rwlock_->lock_writer(); | | rwlock_->lock_writer(); | |
| } else { | | } else { | |
| rwlock_->lock_reader(); | | rwlock_->lock_reader(); | |
| } | | } | |
| } | | } | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| */ | | */ | |
| ~ScopedRWLock() { | | ~ScopedRWLock() { | |
| _assert_(true); | | _assert_(true); | |
| rwlock_->unlock(); | | rwlock_->unlock(); | |
| } | | } | |
|
| private: | | private: | |
| /** Dummy constructor to forbid the use. */ | | /** Dummy constructor to forbid the use. */ | |
| ScopedRWLock(const ScopedRWLock&); | | ScopedRWLock(const ScopedRWLock&); | |
| /** Dummy Operator to forbid the use. */ | | /** Dummy Operator to forbid the use. */ | |
| ScopedRWLock& operator =(const ScopedRWLock&); | | ScopedRWLock& operator =(const ScopedRWLock&); | |
| /** The inner device. */ | | /** The inner device. */ | |
| RWLock* rwlock_; | | RWLock* rwlock_; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Slotted reader-writer lock devices. | | * Slotted reader-writer lock devices. | |
| */ | | */ | |
| class SlottedRWLock { | | class SlottedRWLock { | |
|
| public: | | public: | |
| /** | | /** | |
| * Constructor. | | * Constructor. | |
| * @param slotnum the number of slots. | | * @param slotnum the number of slots. | |
| */ | | */ | |
| explicit SlottedRWLock(size_t slotnum); | | explicit SlottedRWLock(size_t slotnum); | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| */ | | */ | |
| ~SlottedRWLock(); | | ~SlottedRWLock(); | |
| /** | | /** | |
| | | | |
| skipping to change at line 425 | | skipping to change at line 425 | |
| */ | | */ | |
| void lock_writer_all(); | | void lock_writer_all(); | |
| /** | | /** | |
| * Get the reader locks of all slots. | | * Get the reader locks of all slots. | |
| */ | | */ | |
| void lock_reader_all(); | | void lock_reader_all(); | |
| /** | | /** | |
| * Release the locks of all slots. | | * Release the locks of all slots. | |
| */ | | */ | |
| void unlock_all(); | | void unlock_all(); | |
|
| private: | | private: | |
| /** Opaque pointer. */ | | /** Opaque pointer. */ | |
| void* opq_; | | void* opq_; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Lightweight reader-writer locking device. | | * Lightweight reader-writer locking device. | |
| */ | | */ | |
| class SpinRWLock { | | class SpinRWLock { | |
|
| public: | | public: | |
| /** | | /** | |
| * Default constructor. | | * Default constructor. | |
| */ | | */ | |
| explicit SpinRWLock(); | | explicit SpinRWLock(); | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| */ | | */ | |
| ~SpinRWLock(); | | ~SpinRWLock(); | |
| /** | | /** | |
| * Get the writer lock. | | * Get the writer lock. | |
| | | | |
| skipping to change at line 474 | | skipping to change at line 474 | |
| void unlock(); | | void unlock(); | |
| /** | | /** | |
| * Promote a reader lock to the writer lock. | | * Promote a reader lock to the writer lock. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool promote(); | | bool promote(); | |
| /** | | /** | |
| * Demote the writer lock to a reader lock. | | * Demote the writer lock to a reader lock. | |
| */ | | */ | |
| void demote(); | | void demote(); | |
|
| private: | | private: | |
| /** Dummy constructor to forbid the use. */ | | /** Dummy constructor to forbid the use. */ | |
| SpinRWLock(const SpinRWLock&); | | SpinRWLock(const SpinRWLock&); | |
| /** Dummy Operator to forbid the use. */ | | /** Dummy Operator to forbid the use. */ | |
| SpinRWLock& operator =(const SpinRWLock&); | | SpinRWLock& operator =(const SpinRWLock&); | |
| /** Opaque pointer. */ | | /** Opaque pointer. */ | |
| void* opq_; | | void* opq_; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Scoped reader-writer locking device. | | * Scoped reader-writer locking device. | |
| */ | | */ | |
| class ScopedSpinRWLock { | | class ScopedSpinRWLock { | |
|
| public: | | public: | |
| /** | | /** | |
| * Constructor. | | * Constructor. | |
| * @param srwlock a spin rwlock to lock the block. | | * @param srwlock a spin rwlock to lock the block. | |
| * @param writer true for writer lock, or false for reader lock. | | * @param writer true for writer lock, or false for reader lock. | |
| */ | | */ | |
| explicit ScopedSpinRWLock(SpinRWLock* srwlock, bool writer) : srwlock_(sr
wlock) { | | explicit ScopedSpinRWLock(SpinRWLock* srwlock, bool writer) : srwlock_(sr
wlock) { | |
| _assert_(srwlock); | | _assert_(srwlock); | |
| if (writer) { | | if (writer) { | |
| srwlock_->lock_writer(); | | srwlock_->lock_writer(); | |
| } else { | | } else { | |
| srwlock_->lock_reader(); | | srwlock_->lock_reader(); | |
| } | | } | |
| } | | } | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| */ | | */ | |
| ~ScopedSpinRWLock() { | | ~ScopedSpinRWLock() { | |
| _assert_(true); | | _assert_(true); | |
| srwlock_->unlock(); | | srwlock_->unlock(); | |
| } | | } | |
|
| private: | | private: | |
| /** Dummy constructor to forbid the use. */ | | /** Dummy constructor to forbid the use. */ | |
| ScopedSpinRWLock(const ScopedSpinRWLock&); | | ScopedSpinRWLock(const ScopedSpinRWLock&); | |
| /** Dummy Operator to forbid the use. */ | | /** Dummy Operator to forbid the use. */ | |
| ScopedSpinRWLock& operator =(const ScopedSpinRWLock&); | | ScopedSpinRWLock& operator =(const ScopedSpinRWLock&); | |
| /** The inner device. */ | | /** The inner device. */ | |
| SpinRWLock* srwlock_; | | SpinRWLock* srwlock_; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Slotted lightweight reader-writer lock devices. | | * Slotted lightweight reader-writer lock devices. | |
| */ | | */ | |
| class SlottedSpinRWLock { | | class SlottedSpinRWLock { | |
|
| public: | | public: | |
| /** | | /** | |
| * Constructor. | | * Constructor. | |
| * @param slotnum the number of slots. | | * @param slotnum the number of slots. | |
| */ | | */ | |
| explicit SlottedSpinRWLock(size_t slotnum); | | explicit SlottedSpinRWLock(size_t slotnum); | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| */ | | */ | |
| ~SlottedSpinRWLock(); | | ~SlottedSpinRWLock(); | |
| /** | | /** | |
| | | | |
| skipping to change at line 558 | | skipping to change at line 558 | |
| */ | | */ | |
| void lock_writer_all(); | | void lock_writer_all(); | |
| /** | | /** | |
| * Get the reader locks of all slots. | | * Get the reader locks of all slots. | |
| */ | | */ | |
| void lock_reader_all(); | | void lock_reader_all(); | |
| /** | | /** | |
| * Release the locks of all slots. | | * Release the locks of all slots. | |
| */ | | */ | |
| void unlock_all(); | | void unlock_all(); | |
|
| private: | | private: | |
| /** Opaque pointer. */ | | /** Opaque pointer. */ | |
| void* opq_; | | void* opq_; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Condition variable. | | * Condition variable. | |
| */ | | */ | |
| class CondVar { | | class CondVar { | |
|
| public: | | public: | |
| /** | | /** | |
| * Default constructor. | | * Default constructor. | |
| */ | | */ | |
| explicit CondVar(); | | explicit CondVar(); | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| */ | | */ | |
| ~CondVar(); | | ~CondVar(); | |
| /** | | /** | |
| * Wait for the signal. | | * Wait for the signal. | |
| | | | |
| skipping to change at line 598 | | skipping to change at line 598 | |
| /** | | /** | |
| * Send the wake-up signal to another waiting thread. | | * Send the wake-up signal to another waiting thread. | |
| * @note The mutex used for the wait method should be locked by the calle
r. | | * @note The mutex used for the wait method should be locked by the calle
r. | |
| */ | | */ | |
| void signal(); | | void signal(); | |
| /** | | /** | |
| * Send the wake-up signal to all waiting threads. | | * Send the wake-up signal to all waiting threads. | |
| * @note The mutex used for the wait method should be locked by the calle
r. | | * @note The mutex used for the wait method should be locked by the calle
r. | |
| */ | | */ | |
| void broadcast(); | | void broadcast(); | |
|
| private: | | private: | |
| /** Dummy constructor to forbid the use. */ | | /** Dummy constructor to forbid the use. */ | |
| CondVar(const CondVar&); | | CondVar(const CondVar&); | |
| /** Dummy Operator to forbid the use. */ | | /** Dummy Operator to forbid the use. */ | |
| CondVar& operator =(const CondVar&); | | CondVar& operator =(const CondVar&); | |
| /** Opaque pointer. */ | | /** Opaque pointer. */ | |
| void* opq_; | | void* opq_; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Key of thread specific data. | | * Key of thread specific data. | |
| */ | | */ | |
| class TSDKey { | | class TSDKey { | |
|
| public: | | public: | |
| /** | | /** | |
| * Default constructor. | | * Default constructor. | |
| */ | | */ | |
| explicit TSDKey(); | | explicit TSDKey(); | |
| /** | | /** | |
| * Constructor. | | * Constructor. | |
| * @param dstr the destructor for the value. | | * @param dstr the destructor for the value. | |
| */ | | */ | |
| explicit TSDKey(void (*dstr)(void*)); | | explicit TSDKey(void (*dstr)(void*)); | |
| /** | | /** | |
| | | | |
| skipping to change at line 635 | | skipping to change at line 635 | |
| /** | | /** | |
| * Set the value. | | * Set the value. | |
| * @param ptr an arbitrary pointer. | | * @param ptr an arbitrary pointer. | |
| */ | | */ | |
| void set(void* ptr); | | void set(void* ptr); | |
| /** | | /** | |
| * Get the value. | | * Get the value. | |
| * @return the value. | | * @return the value. | |
| */ | | */ | |
| void* get() const ; | | void* get() const ; | |
|
| private: | | private: | |
| /** Opaque pointer. */ | | /** Opaque pointer. */ | |
| void* opq_; | | void* opq_; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Smart pointer to thread specific data. | | * Smart pointer to thread specific data. | |
| */ | | */ | |
| template <class TYPE> | | template <class TYPE> | |
| class TSD { | | class TSD { | |
|
| public: | | public: | |
| /** | | /** | |
| * Default constructor. | | * Default constructor. | |
| */ | | */ | |
| explicit TSD() : key_(delete_value) { | | explicit TSD() : key_(delete_value) { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| */ | | */ | |
| ~TSD() { | | ~TSD() { | |
| | | | |
| skipping to change at line 699 | | skipping to change at line 699 | |
| /** | | /** | |
| * Cast operator to the original type. | | * Cast operator to the original type. | |
| * @return the copy of the inner object. | | * @return the copy of the inner object. | |
| */ | | */ | |
| operator TYPE() const { | | operator TYPE() const { | |
| _assert_(true); | | _assert_(true); | |
| TYPE* obj = (TYPE*)key_.get(); | | TYPE* obj = (TYPE*)key_.get(); | |
| if (!obj) return TYPE(); | | if (!obj) return TYPE(); | |
| return *obj; | | return *obj; | |
| } | | } | |
|
| private: | | private: | |
| /** | | /** | |
| * Delete the inner object. | | * Delete the inner object. | |
| * @param obj the inner object. | | * @param obj the inner object. | |
| */ | | */ | |
| static void delete_value(void* obj) { | | static void delete_value(void* obj) { | |
| _assert_(true); | | _assert_(true); | |
| delete (TYPE*)obj; | | delete (TYPE*)obj; | |
| } | | } | |
| /** Dummy constructor to forbid the use. */ | | /** Dummy constructor to forbid the use. */ | |
| TSD(const TSD&); | | TSD(const TSD&); | |
| /** Dummy Operator to forbid the use. */ | | /** Dummy Operator to forbid the use. */ | |
| TSD& operator =(const TSD&); | | TSD& operator =(const TSD&); | |
| /** Key of thread specific data. */ | | /** Key of thread specific data. */ | |
| TSDKey key_; | | TSDKey key_; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Integer with atomic operations. | | * Integer with atomic operations. | |
| */ | | */ | |
| class AtomicInt64 { | | class AtomicInt64 { | |
|
| public: | | public: | |
| /** | | /** | |
| * Default constructor. | | * Default constructor. | |
| */ | | */ | |
| explicit AtomicInt64() : value_(0), lock_() { | | explicit AtomicInt64() : value_(0), lock_() { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| /** | | /** | |
| * Copy constructor. | | * Copy constructor. | |
| * @param src the source object. | | * @param src the source object. | |
| */ | | */ | |
| | | | |
| skipping to change at line 834 | | skipping to change at line 834 | |
| */ | | */ | |
| int64_t secure_least(int64_t val) { | | int64_t secure_least(int64_t val) { | |
| _assert_(true); | | _assert_(true); | |
| while (true) { | | while (true) { | |
| int64_t cur = get(); | | int64_t cur = get(); | |
| if (cur >= val) return cur; | | if (cur >= val) return cur; | |
| if (cas(cur, val)) break; | | if (cas(cur, val)) break; | |
| } | | } | |
| return val; | | return val; | |
| } | | } | |
|
| private: | | private: | |
| /** The value. */ | | /** The value. */ | |
| volatile int64_t value_; | | volatile int64_t value_; | |
| /** The alternative lock. */ | | /** The alternative lock. */ | |
| mutable SpinLock lock_; | | mutable SpinLock lock_; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Task queue device. | | * Task queue device. | |
| */ | | */ | |
| class TaskQueue { | | class TaskQueue { | |
|
| public: | | public: | |
| class Task; | | class Task; | |
|
| private: | | private: | |
| class WorkerThread; | | class WorkerThread; | |
| /** An alias of list of tasks. */ | | /** An alias of list of tasks. */ | |
| typedef std::list<Task*> TaskList; | | typedef std::list<Task*> TaskList; | |
|
| public: | | public: | |
| /** | | /** | |
| * Interface of a task. | | * Interface of a task. | |
| */ | | */ | |
| class Task { | | class Task { | |
| friend class TaskQueue; | | friend class TaskQueue; | |
|
| public: | | public: | |
| /** | | /** | |
| * Default constructor. | | * Default constructor. | |
| */ | | */ | |
| explicit Task() : id_(0), thid_(0), aborted_(false) { | | explicit Task() : id_(0), thid_(0), aborted_(false) { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| */ | | */ | |
| virtual ~Task() { | | virtual ~Task() { | |
| | | | |
| skipping to change at line 895 | | skipping to change at line 895 | |
| return thid_; | | return thid_; | |
| } | | } | |
| /** | | /** | |
| * Check whether the thread is to be aborted. | | * Check whether the thread is to be aborted. | |
| * @return true if the thread is to be aborted, or false if not. | | * @return true if the thread is to be aborted, or false if not. | |
| */ | | */ | |
| bool aborted() { | | bool aborted() { | |
| _assert_(true); | | _assert_(true); | |
| return aborted_; | | return aborted_; | |
| } | | } | |
|
| private: | | private: | |
| /** The task ID number. */ | | /** The task ID number. */ | |
| uint64_t id_; | | uint64_t id_; | |
| /** The thread ID number. */ | | /** The thread ID number. */ | |
| uint64_t thid_; | | uint64_t thid_; | |
| /** The flag to be aborted. */ | | /** The flag to be aborted. */ | |
| bool aborted_; | | bool aborted_; | |
| }; | | }; | |
| /** | | /** | |
| * Default Constructor. | | * Default Constructor. | |
| */ | | */ | |
| | | | |
| skipping to change at line 998 | | skipping to change at line 998 | |
| * Get the number of tasks in the queue. | | * Get the number of tasks in the queue. | |
| * @return the number of tasks in the queue. | | * @return the number of tasks in the queue. | |
| */ | | */ | |
| int64_t count() { | | int64_t count() { | |
| _assert_(true); | | _assert_(true); | |
| mutex_.lock(); | | mutex_.lock(); | |
| int64_t count = count_; | | int64_t count = count_; | |
| mutex_.unlock(); | | mutex_.unlock(); | |
| return count; | | return count; | |
| } | | } | |
|
| private: | | private: | |
| /** | | /** | |
| * Implementation of the worker thread. | | * Implementation of the worker thread. | |
| */ | | */ | |
| class WorkerThread : public Thread { | | class WorkerThread : public Thread { | |
| friend class TaskQueue; | | friend class TaskQueue; | |
|
| public: | | public: | |
| explicit WorkerThread() : id_(0), queue_(NULL), aborted_(false) { | | explicit WorkerThread() : id_(0), queue_(NULL), aborted_(false) { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
|
| private: | | private: | |
| void run() { | | void run() { | |
| _assert_(true); | | _assert_(true); | |
| bool empty = false; | | bool empty = false; | |
| while (true) { | | while (true) { | |
| queue_->mutex_.lock(); | | queue_->mutex_.lock(); | |
| if (aborted_) { | | if (aborted_) { | |
| queue_->mutex_.unlock(); | | queue_->mutex_.unlock(); | |
| break; | | break; | |
| } | | } | |
| if (empty) queue_->cond_.wait(&queue_->mutex_, 1.0); | | if (empty) queue_->cond_.wait(&queue_->mutex_, 1.0); | |
| | | | |
End of changes. 42 change blocks. |
| 42 lines changed or deleted | | 42 lines changed or added | |
|