| kchashdb.h | | kchashdb.h | |
| | | | |
| skipping to change at line 59 | | skipping to change at line 59 | |
| 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. */ | |
| | | static const int64_t MOFFLIBVER = 4; | |
| | | /** The offset of the library revision. */ | |
| | | static const int64_t MOFFLIBREV = 5; | |
| | | /** The offset of the format revision. */ | |
| | | static const int64_t MOFFFMTVER = 6; | |
| | | /** The offset of the module checksum. */ | |
| | | static const int64_t MOFFCHKSUM = 7; | |
| | | /** The offset of the database type. */ | |
| | | static const int64_t MOFFTYPE = 8; | |
| | | /** The offset of the alignment power. */ | |
| | | static const int64_t MOFFAPOW = 9; | |
| | | /** The offset of the free block pool power. */ | |
| | | static const int64_t MOFFFPOW = 10; | |
| | | /** The offset of the options. */ | |
| | | static const int64_t MOFFOPTS = 11; | |
| | | /** The offset of the bucket number. */ | |
| | | static const int64_t MOFFBNUM = 16; | |
| | | /** The offset of the status flags. */ | |
| | | static const int64_t MOFFFLAGS = 24; | |
| | | /** The offset of the record number. */ | |
| | | static const int64_t MOFFCOUNT = 32; | |
| | | /** The offset of the file size. */ | |
| | | static const int64_t MOFFSIZE = 40; | |
| | | /** The offset of the opaque data. */ | |
| | | static const int64_t MOFFOPAQUE = 48; | |
| | | /** The size of the header. */ | |
| | | static const int64_t HEADSIZ = 64; | |
| | | /** The width of the free block. */ | |
| | | static const int32_t FBPWIDTH = 6; | |
| | | /** The large width of the record address. */ | |
| | | static const int32_t WIDTHLARGE = 6; | |
| | | /** The small width of the record address. */ | |
| | | static const int32_t WIDTHSMALL = 4; | |
| | | /** The size of the record buffer. */ | |
| | | static const size_t RECBUFSIZ = 48; | |
| | | /** The size of the IO buffer. */ | |
| | | static const size_t IOBUFSIZ = 1024; | |
| | | /** The number of slots of the record lock. */ | |
| | | static const int32_t RLOCKSLOT = 1024; | |
| | | /** The default alignment power. */ | |
| | | static const uint8_t DEFAPOW = 3; | |
| | | /** The maximum alignment power. */ | |
| | | static const uint8_t MAXAPOW = 15; | |
| | | /** The default free block pool power. */ | |
| | | static const uint8_t DEFFPOW = 10; | |
| | | /** The maximum free block pool power. */ | |
| | | static const uint8_t MAXFPOW = 20; | |
| | | /** The default bucket number. */ | |
| | | static const int64_t DEFBNUM = 1048583LL; | |
| | | /** The default size of the memory-mapped region. */ | |
| | | static const int64_t DEFMSIZ = 64LL << 20; | |
| | | /** The magic data for record. */ | |
| | | static const uint8_t RECMAGIC = 0xcc; | |
| | | /** The magic data for padding. */ | |
| | | static const uint8_t PADMAGIC = 0xee; | |
| | | /** The magic data for free block. */ | |
| | | static const uint8_t FBMAGIC = 0xdd; | |
| | | /** The maximum unit of auto defragmentation. */ | |
| | | static const int32_t DFRGMAX = 512; | |
| | | /** The coefficient of auto defragmentation. */ | |
| | | static const int32_t DFRGCEF = 2; | |
| | | /** The checking width for record salvage. */ | |
| | | static const int64_t SLVGWIDTH = 1LL << 20; | |
| | | /** The threshold of busy loop and sleep for locking. */ | |
| | | 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. | |
| | | | |
| skipping to change at line 1610 | | skipping to change at line 1676 | |
| 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: | |
|
| /** The offset of the library version. */ | | | |
| static const int64_t MOFFLIBVER = 4; | | | |
| /** The offset of the library revision. */ | | | |
| static const int64_t MOFFLIBREV = 5; | | | |
| /** The offset of the format revision. */ | | | |
| static const int64_t MOFFFMTVER = 6; | | | |
| /** The offset of the module checksum. */ | | | |
| static const int64_t MOFFCHKSUM = 7; | | | |
| /** The offset of the database type. */ | | | |
| static const int64_t MOFFTYPE = 8; | | | |
| /** The offset of the alignment power. */ | | | |
| static const int64_t MOFFAPOW = 9; | | | |
| /** The offset of the free block pool power. */ | | | |
| static const int64_t MOFFFPOW = 10; | | | |
| /** The offset of the options. */ | | | |
| static const int64_t MOFFOPTS = 11; | | | |
| /** The offset of the bucket number. */ | | | |
| static const int64_t MOFFBNUM = 16; | | | |
| /** The offset of the status flags. */ | | | |
| static const int64_t MOFFFLAGS = 24; | | | |
| /** The offset of the record number. */ | | | |
| static const int64_t MOFFCOUNT = 32; | | | |
| /** The offset of the file size. */ | | | |
| static const int64_t MOFFSIZE = 40; | | | |
| /** The offset of the opaque data. */ | | | |
| static const int64_t MOFFOPAQUE = 48; | | | |
| /** The size of the header. */ | | | |
| static const int64_t HEADSIZ = 64; | | | |
| /** The width of the free block. */ | | | |
| static const int32_t FBPWIDTH = 6; | | | |
| /** The large width of the record address. */ | | | |
| static const int32_t WIDTHLARGE = 6; | | | |
| /** The small width of the record address. */ | | | |
| static const int32_t WIDTHSMALL = 4; | | | |
| /** The size of the record buffer. */ | | | |
| static const size_t RECBUFSIZ = 48; | | | |
| /** The size of the IO buffer. */ | | | |
| static const size_t IOBUFSIZ = 1024; | | | |
| /** The number of slots of the record lock. */ | | | |
| static const int32_t RLOCKSLOT = 1024; | | | |
| /** The default alignment power. */ | | | |
| static const uint8_t DEFAPOW = 3; | | | |
| /** The maximum alignment power. */ | | | |
| static const uint8_t MAXAPOW = 15; | | | |
| /** The default free block pool power. */ | | | |
| static const uint8_t DEFFPOW = 10; | | | |
| /** The maximum free block pool power. */ | | | |
| static const uint8_t MAXFPOW = 20; | | | |
| /** The default bucket number. */ | | | |
| static const int64_t DEFBNUM = 1048583LL; | | | |
| /** The default size of the memory-mapped region. */ | | | |
| static const int64_t DEFMSIZ = 64LL << 20; | | | |
| /** The magic data for record. */ | | | |
| static const uint8_t RECMAGIC = 0xcc; | | | |
| /** The magic data for padding. */ | | | |
| static const uint8_t PADMAGIC = 0xee; | | | |
| /** The magic data for free block. */ | | | |
| static const uint8_t FBMAGIC = 0xdd; | | | |
| /** The maximum unit of auto defragmentation. */ | | | |
| static const int32_t DFRGMAX = 512; | | | |
| /** The coefficient of auto defragmentation. */ | | | |
| static const int32_t DFRGCEF = 2; | | | |
| /** The checking width for record salvage. */ | | | |
| static const int64_t SLVGWIDTH = 1LL << 20; | | | |
| /** The threshold of busy loop and sleep for locking. */ | | | |
| static const uint32_t LOCKBUSYLOOP = 8192; | | | |
| /** | | /** | |
| * 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 | |
| | | | |
End of changes. 2 change blocks. |
| 66 lines changed or deleted | | 66 lines changed or added | |
|
| kcplantdb.h | | kcplantdb.h | |
| | | | |
| skipping to change at line 30 | | skipping to change at line 30 | |
| #include <kcthread.h> | | #include <kcthread.h> | |
| #include <kcfile.h> | | #include <kcfile.h> | |
| #include <kccompress.h> | | #include <kccompress.h> | |
| #include <kccompare.h> | | #include <kccompare.h> | |
| #include <kcmap.h> | | #include <kcmap.h> | |
| #include <kcregex.h> | | #include <kcregex.h> | |
| #include <kcdb.h> | | #include <kcdb.h> | |
| | | | |
| #define KCPDBMETAKEY "@" ///< key of the record for meta da
ta | | #define KCPDBMETAKEY "@" ///< key of the record for meta da
ta | |
| #define KCPDBTMPPATHEXT "tmpkct" ///< extension of the temporary fi
le | | #define KCPDBTMPPATHEXT "tmpkct" ///< extension of the temporary fi
le | |
|
| | | #define KCPDRECBUFSIZ 128 ///< size of the record buffer | |
| | | | |
| namespace kyotocabinet { // common namespace | | namespace kyotocabinet { // common namespace | |
| | | | |
| /** | | /** | |
| * Plant database. | | * Plant database. | |
| * @param BASEDB a class compatible with the file hash database class. | | * @param BASEDB a class compatible with the file hash database class. | |
| * @param DBTYPE the database type number of the class. | | * @param DBTYPE the database type number of the class. | |
| * @note This class template is a template for concrete classes to operate
tree databases. | | * @note This class template is a template for concrete classes to operate
tree databases. | |
| * Template instance classes can be inherited but overwriting methods is fo
rbidden. The class | | * Template instance classes can be inherited but overwriting methods is fo
rbidden. The class | |
| * 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 | |
| | | | |
| skipping to change at line 71 | | skipping to change at line 72 | |
| /** An alias of array of records. */ | | /** An alias of array of records. */ | |
| typedef std::vector<Record*> RecordArray; | | typedef std::vector<Record*> RecordArray; | |
| /** An alias of array of records. */ | | /** An alias of array of records. */ | |
| typedef std::vector<Link*> LinkArray; | | typedef std::vector<Link*> LinkArray; | |
| /** An alias of leaf node cache. */ | | /** An alias of leaf node cache. */ | |
| typedef LinkedHashMap<int64_t, LeafNode*> LeafCache; | | typedef LinkedHashMap<int64_t, LeafNode*> LeafCache; | |
| /** An alias of inner node cache. */ | | /** An alias of inner node cache. */ | |
| typedef LinkedHashMap<int64_t, InnerNode*> InnerCache; | | typedef LinkedHashMap<int64_t, InnerNode*> InnerCache; | |
| /** An alias of list of cursors. */ | | /** An alias of list of cursors. */ | |
| typedef std::list<Cursor*> CursorList; | | typedef std::list<Cursor*> CursorList; | |
|
| | | /** The number of cache slots. */ | |
| | | static const int32_t SLOTNUM = 16; | |
| | | /** The default alignment power. */ | |
| | | static const uint8_t DEFAPOW = 8; | |
| | | /** The default free block pool power. */ | |
| | | static const uint8_t DEFFPOW = 10; | |
| | | /** The default bucket number. */ | |
| | | static const int64_t DEFBNUM = 64LL << 10; | |
| | | /** The default page size. */ | |
| | | static const int32_t DEFPSIZ = 8192; | |
| | | /** The default capacity size of the page cache. */ | |
| | | static const int64_t DEFPCCAP = 64LL << 20; | |
| | | /** The size of the header. */ | |
| | | static const int64_t HEADSIZ = 80; | |
| | | /** The offset of the numbers. */ | |
| | | static const int64_t MOFFNUMS = 8; | |
| | | /** The prefix of leaf nodes. */ | |
| | | static const char LNPREFIX = 'L'; | |
| | | /** The prefix of inner nodes. */ | |
| | | static const char INPREFIX = 'I'; | |
| | | /** The average number of ways of each node. */ | |
| | | static const size_t AVGWAY = 16; | |
| | | /** The ratio of the warm cache. */ | |
| | | static const size_t WARMRATIO = 4; | |
| | | /** The ratio of flushing inner nodes. */ | |
| | | static const size_t INFLRATIO = 32; | |
| | | /** The default number of items in each leaf node. */ | |
| | | static const size_t DEFLINUM = 64; | |
| | | /** The default number of items in each inner node. */ | |
| | | static const size_t DEFIINUM = 128; | |
| | | /** The base ID number for inner nodes. */ | |
| | | static const int64_t INIDBASE = 1LL << 48; | |
| | | /** The minimum number of links in each inner node. */ | |
| | | static const size_t INLINKMIN = 8; | |
| | | /** The maximum level of B+ tree. */ | |
| | | static const int32_t LEVELMAX = 16; | |
| | | /** The number of cached nodes for auto transaction. */ | |
| | | static const int32_t ATRANCNUM = 256; | |
| | | /** The threshold of busy loop and sleep for locking. */ | |
| | | 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. | |
| | | | |
| skipping to change at line 412 | | skipping to change at line 453 | |
| * @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. | |
| * @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. | |
| * @param hitp the pointer to the variable for the hit flag. | | * @param hitp the pointer to the variable for the hit flag. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool accept_spec(Visitor* visitor, bool writable, bool step, bool* hitp
) { | | bool accept_spec(Visitor* visitor, bool writable, bool step, bool* hitp
) { | |
| _assert_(visitor && hitp); | | _assert_(visitor && hitp); | |
| bool err = false; | | bool err = false; | |
| bool hit = false; | | bool hit = false; | |
|
| char rstack[PlantDB::RECBUFSIZ]; | | char rstack[KCPDRECBUFSIZ]; | |
| size_t rsiz = sizeof(Record) + ksiz_; | | size_t rsiz = sizeof(Record) + ksiz_; | |
| char* rbuf = rsiz > sizeof(rstack) ? new char[rsiz] : rstack; | | char* rbuf = rsiz > sizeof(rstack) ? new char[rsiz] : rstack; | |
| Record* rec = (Record*)rbuf; | | Record* rec = (Record*)rbuf; | |
| rec->ksiz = ksiz_; | | rec->ksiz = ksiz_; | |
| rec->vsiz = 0; | | rec->vsiz = 0; | |
| std::memcpy(rbuf + sizeof(*rec), kbuf_, ksiz_); | | std::memcpy(rbuf + sizeof(*rec), kbuf_, ksiz_); | |
| LeafNode* node = db_->load_leaf_node(lid_, false); | | LeafNode* node = db_->load_leaf_node(lid_, false); | |
| if (node) { | | if (node) { | |
|
| char lstack[PlantDB::RECBUFSIZ]; | | char lstack[KCPDRECBUFSIZ]; | |
| char* lbuf = NULL; | | char* lbuf = NULL; | |
| size_t lsiz = 0; | | size_t lsiz = 0; | |
| Link* link = NULL; | | Link* link = NULL; | |
| int64_t hist[LEVELMAX]; | | int64_t hist[LEVELMAX]; | |
| int32_t hnum = 0; | | int32_t hnum = 0; | |
| if (writable) { | | if (writable) { | |
| node->lock.lock_writer(); | | node->lock.lock_writer(); | |
| } else { | | } else { | |
| node->lock.lock_reader(); | | node->lock.lock_reader(); | |
| } | | } | |
| | | | |
| skipping to change at line 524 | | skipping to change at line 565 | |
| bool async = db_->autosync_ && !db_->autotran_ && !db_->tran_ && no
de->dirty; | | bool async = db_->autosync_ && !db_->autotran_ && !db_->tran_ && no
de->dirty; | |
| node->lock.unlock(); | | node->lock.unlock(); | |
| if (hit && step) { | | if (hit && step) { | |
| clear_position(); | | clear_position(); | |
| set_position(node->next); | | set_position(node->next); | |
| } | | } | |
| if (hit) { | | if (hit) { | |
| bool flush = db_->cusage_ > db_->pccap_; | | bool flush = db_->cusage_ > db_->pccap_; | |
| if (link || flush || async) { | | if (link || flush || async) { | |
| int64_t id = node->id; | | int64_t id = node->id; | |
|
| if (atran && !link && !db_->fix_auto_transaction_leaf(node)) | | if (atran && !link && !db_->fix_auto_transaction_leaf(node)) er | |
| err = true; | | r = true; | |
| if (!db_->mlock_.promote()) { | | if (!db_->mlock_.promote()) { | |
| db_->mlock_.unlock(); | | db_->mlock_.unlock(); | |
| db_->mlock_.lock_writer(); | | db_->mlock_.lock_writer(); | |
| } | | } | |
| if (link) { | | if (link) { | |
| node = db_->search_tree(link, true, hist, &hnum); | | node = db_->search_tree(link, true, hist, &hnum); | |
| if (node) { | | if (node) { | |
| if (!db_->reorganize_tree(node, hist, hnum)) err = true; | | if (!db_->reorganize_tree(node, hist, hnum)) err = true; | |
| if (atran && !db_->tran_ && !db_->fix_auto_transaction_tree
()) err = true; | | if (atran && !db_->tran_ && !db_->fix_auto_transaction_tree
()) err = true; | |
| } else { | | } else { | |
| | | | |
| skipping to change at line 548 | | skipping to change at line 588 | |
| } | | } | |
| } else if (flush) { | | } else if (flush) { | |
| int32_t idx = id % SLOTNUM; | | int32_t idx = id % SLOTNUM; | |
| LeafSlot* lslot = db_->lslots_ + idx; | | LeafSlot* lslot = db_->lslots_ + idx; | |
| if (!db_->flush_leaf_cache_part(lslot)) err = true; | | if (!db_->flush_leaf_cache_part(lslot)) err = true; | |
| InnerSlot* islot = db_->islots_ + idx; | | InnerSlot* islot = db_->islots_ + idx; | |
| if (islot->warm->count() > lslot->warm->count() + lslot->hot-
>count() + 1 && | | if (islot->warm->count() > lslot->warm->count() + lslot->hot-
>count() + 1 && | |
| !db_->flush_inner_cache_part(islot)) err = true; | | !db_->flush_inner_cache_part(islot)) err = true; | |
| } | | } | |
| if (async && !db_->fix_auto_synchronization()) err = true; | | if (async && !db_->fix_auto_synchronization()) err = true; | |
|
| | | } else { | |
| | | if (!db_->fix_auto_transaction_leaf(node)) err = true; | |
| } | | } | |
| } | | } | |
| if (lbuf != lstack) delete[] lbuf; | | if (lbuf != lstack) delete[] lbuf; | |
| } | | } | |
| if (rbuf != rstack) delete[] rbuf; | | if (rbuf != rstack) delete[] rbuf; | |
| *hitp = hit; | | *hitp = hit; | |
| return !err; | | return !err; | |
| } | | } | |
| /** | | /** | |
| * Accept a visitor to the current record atomically. | | * Accept a visitor to the current record atomically. | |
| * @param visitor a visitor object. | | * @param visitor a visitor object. | |
| * @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. | |
| * @param retryp the pointer to the variable for the retry flag. | | * @param retryp the pointer to the variable for the retry flag. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool accept_atom(Visitor* visitor, bool step, bool *retryp) { | | bool accept_atom(Visitor* visitor, bool step, bool *retryp) { | |
| _assert_(visitor && retryp); | | _assert_(visitor && retryp); | |
| bool err = false; | | bool err = false; | |
| bool reorg = false; | | bool reorg = false; | |
| *retryp = false; | | *retryp = false; | |
|
| char lstack[PlantDB::RECBUFSIZ]; | | char lstack[KCPDRECBUFSIZ]; | |
| size_t lsiz = sizeof(Link) + ksiz_; | | size_t lsiz = sizeof(Link) + ksiz_; | |
| char* lbuf = lsiz > sizeof(lstack) ? new char[lsiz] : lstack; | | char* lbuf = lsiz > sizeof(lstack) ? new char[lsiz] : lstack; | |
| Link* link = (Link*)lbuf; | | Link* link = (Link*)lbuf; | |
| link->child = 0; | | link->child = 0; | |
| link->ksiz = ksiz_; | | link->ksiz = ksiz_; | |
| std::memcpy(lbuf + sizeof(*link), kbuf_, ksiz_); | | std::memcpy(lbuf + sizeof(*link), kbuf_, ksiz_); | |
| int64_t hist[LEVELMAX]; | | int64_t hist[LEVELMAX]; | |
| int32_t hnum = 0; | | int32_t hnum = 0; | |
| LeafNode* node = db_->search_tree(link, true, hist, &hnum); | | LeafNode* node = db_->search_tree(link, true, hist, &hnum); | |
| if (!node) { | | if (!node) { | |
| | | | |
| skipping to change at line 605 | | skipping to change at line 647 | |
| link->child = 0; | | link->child = 0; | |
| link->ksiz = ksiz_; | | link->ksiz = ksiz_; | |
| std::memcpy(lbuf + sizeof(*link), kbuf_, ksiz_); | | std::memcpy(lbuf + sizeof(*link), kbuf_, ksiz_); | |
| node = db_->search_tree(link, true, hist, &hnum); | | node = db_->search_tree(link, true, hist, &hnum); | |
| if (node->id != lid_) { | | if (node->id != lid_) { | |
| db_->set_error(_KCCODELINE_, Error::BROKEN, "invalid tree"); | | db_->set_error(_KCCODELINE_, Error::BROKEN, "invalid tree"); | |
| if (lbuf != lstack) delete[] lbuf; | | if (lbuf != lstack) delete[] lbuf; | |
| return false; | | return false; | |
| } | | } | |
| } | | } | |
|
| char rstack[PlantDB::RECBUFSIZ]; | | char rstack[KCPDRECBUFSIZ]; | |
| size_t rsiz = sizeof(Record) + ksiz_; | | size_t rsiz = sizeof(Record) + ksiz_; | |
| char* rbuf = rsiz > sizeof(rstack) ? new char[rsiz] : rstack; | | char* rbuf = rsiz > sizeof(rstack) ? new char[rsiz] : rstack; | |
| Record* rec = (Record*)rbuf; | | Record* rec = (Record*)rbuf; | |
| rec->ksiz = ksiz_; | | rec->ksiz = ksiz_; | |
| rec->vsiz = 0; | | rec->vsiz = 0; | |
| std::memcpy(rbuf + sizeof(*rec), kbuf_, ksiz_); | | std::memcpy(rbuf + sizeof(*rec), kbuf_, ksiz_); | |
| RecordArray& recs = node->recs; | | RecordArray& recs = node->recs; | |
| typename RecordArray::iterator ritend = recs.end(); | | typename RecordArray::iterator ritend = recs.end(); | |
| typename RecordArray::iterator rit = std::lower_bound(recs.begin(), r
itend, | | typename RecordArray::iterator rit = std::lower_bound(recs.begin(), r
itend, | |
| rec, db_->recco
mp_); | | rec, db_->recco
mp_); | |
| | | | |
| skipping to change at line 713 | | skipping to change at line 755 | |
| if (rbuf != rstack) delete[] rbuf; | | if (rbuf != rstack) delete[] rbuf; | |
| if (lbuf != lstack) delete[] lbuf; | | if (lbuf != lstack) delete[] lbuf; | |
| return !err; | | return !err; | |
| } | | } | |
| /** | | /** | |
| * Adjust the position to an existing record. | | * Adjust the position to an existing record. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool adjust_position() { | | bool adjust_position() { | |
| _assert_(true); | | _assert_(true); | |
|
| char lstack[PlantDB::RECBUFSIZ]; | | char lstack[KCPDRECBUFSIZ]; | |
| size_t lsiz = sizeof(Link) + ksiz_; | | size_t lsiz = sizeof(Link) + ksiz_; | |
| char* lbuf = lsiz > sizeof(lstack) ? new char[lsiz] : lstack; | | char* lbuf = lsiz > sizeof(lstack) ? new char[lsiz] : lstack; | |
| Link* link = (Link*)lbuf; | | Link* link = (Link*)lbuf; | |
| link->child = 0; | | link->child = 0; | |
| link->ksiz = ksiz_; | | link->ksiz = ksiz_; | |
| std::memcpy(lbuf + sizeof(*link), kbuf_, ksiz_); | | std::memcpy(lbuf + sizeof(*link), kbuf_, ksiz_); | |
| int64_t hist[LEVELMAX]; | | int64_t hist[LEVELMAX]; | |
| int32_t hnum = 0; | | int32_t hnum = 0; | |
| LeafNode* node = db_->search_tree(link, true, hist, &hnum); | | LeafNode* node = db_->search_tree(link, true, hist, &hnum); | |
| if (!node) { | | if (!node) { | |
| db_->set_error(_KCCODELINE_, Error::BROKEN, "search failed"); | | db_->set_error(_KCCODELINE_, Error::BROKEN, "search failed"); | |
| if (lbuf != lstack) delete[] lbuf; | | if (lbuf != lstack) delete[] lbuf; | |
| return false; | | return false; | |
| } | | } | |
|
| char rstack[PlantDB::RECBUFSIZ]; | | char rstack[KCPDRECBUFSIZ]; | |
| size_t rsiz = sizeof(Record) + ksiz_; | | size_t rsiz = sizeof(Record) + ksiz_; | |
| char* rbuf = rsiz > sizeof(rstack) ? new char[rsiz] : rstack; | | char* rbuf = rsiz > sizeof(rstack) ? new char[rsiz] : rstack; | |
| Record* rec = (Record*)rbuf; | | Record* rec = (Record*)rbuf; | |
| rec->ksiz = ksiz_; | | rec->ksiz = ksiz_; | |
| rec->vsiz = 0; | | rec->vsiz = 0; | |
| std::memcpy(rbuf + sizeof(*rec), kbuf_, ksiz_); | | std::memcpy(rbuf + sizeof(*rec), kbuf_, ksiz_); | |
| bool err = false; | | bool err = false; | |
| node->lock.lock_reader(); | | node->lock.lock_reader(); | |
| const RecordArray& recs = node->recs; | | const RecordArray& recs = node->recs; | |
| typename RecordArray::const_iterator ritend = node->recs.end(); | | typename RecordArray::const_iterator ritend = node->recs.end(); | |
| | | | |
| skipping to change at line 762 | | skipping to change at line 804 | |
| } | | } | |
| /** | | /** | |
| * Back the position to the previous record speculatively. | | * Back the position to the previous record speculatively. | |
| * @param hitp the pointer to the variable for the hit flag. | | * @param hitp the pointer to the variable for the hit flag. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool back_position_spec(bool* hitp) { | | bool back_position_spec(bool* hitp) { | |
| _assert_(hitp); | | _assert_(hitp); | |
| bool err = false; | | bool err = false; | |
| bool hit = false; | | bool hit = false; | |
|
| char rstack[PlantDB::RECBUFSIZ]; | | char rstack[KCPDRECBUFSIZ]; | |
| size_t rsiz = sizeof(Record) + ksiz_; | | size_t rsiz = sizeof(Record) + ksiz_; | |
| char* rbuf = rsiz > sizeof(rstack) ? new char[rsiz] : rstack; | | char* rbuf = rsiz > sizeof(rstack) ? new char[rsiz] : rstack; | |
| Record* rec = (Record*)rbuf; | | Record* rec = (Record*)rbuf; | |
| rec->ksiz = ksiz_; | | rec->ksiz = ksiz_; | |
| rec->vsiz = 0; | | rec->vsiz = 0; | |
| std::memcpy(rbuf + sizeof(*rec), kbuf_, ksiz_); | | std::memcpy(rbuf + sizeof(*rec), kbuf_, ksiz_); | |
| LeafNode* node = db_->load_leaf_node(lid_, false); | | LeafNode* node = db_->load_leaf_node(lid_, false); | |
| if (node) { | | if (node) { | |
| node->lock.lock_reader(); | | node->lock.lock_reader(); | |
| RecordArray& recs = node->recs; | | RecordArray& recs = node->recs; | |
| | | | |
| skipping to change at line 813 | | skipping to change at line 855 | |
| if (rbuf != rstack) delete[] rbuf; | | if (rbuf != rstack) delete[] rbuf; | |
| *hitp = hit; | | *hitp = hit; | |
| return !err; | | return !err; | |
| } | | } | |
| /** | | /** | |
| * Back the position to the previous record atomically. | | * Back the position to the previous record atomically. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool back_position_atom() { | | bool back_position_atom() { | |
| _assert_(true); | | _assert_(true); | |
|
| char lstack[PlantDB::RECBUFSIZ]; | | char lstack[KCPDRECBUFSIZ]; | |
| size_t lsiz = sizeof(Link) + ksiz_; | | size_t lsiz = sizeof(Link) + ksiz_; | |
| char* lbuf = lsiz > sizeof(lstack) ? new char[lsiz] : lstack; | | char* lbuf = lsiz > sizeof(lstack) ? new char[lsiz] : lstack; | |
| Link* link = (Link*)lbuf; | | Link* link = (Link*)lbuf; | |
| link->child = 0; | | link->child = 0; | |
| link->ksiz = ksiz_; | | link->ksiz = ksiz_; | |
| std::memcpy(lbuf + sizeof(*link), kbuf_, ksiz_); | | std::memcpy(lbuf + sizeof(*link), kbuf_, ksiz_); | |
| int64_t hist[LEVELMAX]; | | int64_t hist[LEVELMAX]; | |
| int32_t hnum = 0; | | int32_t hnum = 0; | |
| LeafNode* node = db_->search_tree(link, true, hist, &hnum); | | LeafNode* node = db_->search_tree(link, true, hist, &hnum); | |
| if (!node) { | | if (!node) { | |
| db_->set_error(_KCCODELINE_, Error::BROKEN, "search failed"); | | db_->set_error(_KCCODELINE_, Error::BROKEN, "search failed"); | |
| if (lbuf != lstack) delete[] lbuf; | | if (lbuf != lstack) delete[] lbuf; | |
| return false; | | return false; | |
| } | | } | |
|
| char rstack[PlantDB::RECBUFSIZ]; | | char rstack[KCPDRECBUFSIZ]; | |
| size_t rsiz = sizeof(Record) + ksiz_; | | size_t rsiz = sizeof(Record) + ksiz_; | |
| char* rbuf = rsiz > sizeof(rstack) ? new char[rsiz] : rstack; | | char* rbuf = rsiz > sizeof(rstack) ? new char[rsiz] : rstack; | |
| Record* rec = (Record*)rbuf; | | Record* rec = (Record*)rbuf; | |
| rec->ksiz = ksiz_; | | rec->ksiz = ksiz_; | |
| rec->vsiz = 0; | | rec->vsiz = 0; | |
| std::memcpy(rbuf + sizeof(*rec), kbuf_, ksiz_); | | std::memcpy(rbuf + sizeof(*rec), kbuf_, ksiz_); | |
| bool err = false; | | bool err = false; | |
| node->lock.lock_reader(); | | node->lock.lock_reader(); | |
| const RecordArray& recs = node->recs; | | const RecordArray& recs = node->recs; | |
| typename RecordArray::const_iterator ritbeg = node->recs.begin(); | | typename RecordArray::const_iterator ritbeg = node->recs.begin(); | |
| | | | |
| skipping to change at line 866 | | skipping to change at line 908 | |
| if (lbuf != lstack) delete[] lbuf; | | if (lbuf != lstack) delete[] lbuf; | |
| return !err; | | return !err; | |
| } | | } | |
| /** Dummy constructor to forbid the use. */ | | /** Dummy constructor to forbid the use. */ | |
| Cursor(const Cursor&); | | Cursor(const Cursor&); | |
| /** Dummy Operator to forbid the use. */ | | /** Dummy Operator to forbid the use. */ | |
| Cursor& operator =(const Cursor&); | | Cursor& operator =(const Cursor&); | |
| /** The inner database. */ | | /** The inner database. */ | |
| PlantDB* db_; | | PlantDB* db_; | |
| /** The stack buffer for the key. */ | | /** The stack buffer for the key. */ | |
|
| char stack_[PlantDB::RECBUFSIZ]; | | char stack_[KCPDRECBUFSIZ]; | |
| /** The pointer to the key region. */ | | /** The pointer to the key region. */ | |
| char* kbuf_; | | char* kbuf_; | |
| /** The size of the key region. */ | | /** The size of the key region. */ | |
| size_t ksiz_; | | size_t ksiz_; | |
| /** The last visited leaf. */ | | /** The last visited leaf. */ | |
| int64_t lid_; | | int64_t lid_; | |
| }; | | }; | |
| /** | | /** | |
| * Tuning options. | | * Tuning options. | |
| */ | | */ | |
| | | | |
| skipping to change at line 942 | | skipping to change at line 984 | |
| if (omode_ == 0) { | | if (omode_ == 0) { | |
| set_error(_KCCODELINE_, Error::INVALID, "not opened"); | | set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |
| mlock_.unlock(); | | mlock_.unlock(); | |
| return false; | | return false; | |
| } | | } | |
| if (writable && !writer_) { | | if (writable && !writer_) { | |
| set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | | set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | |
| mlock_.unlock(); | | mlock_.unlock(); | |
| return false; | | return false; | |
| } | | } | |
|
| char lstack[RECBUFSIZ]; | | char lstack[KCPDRECBUFSIZ]; | |
| size_t lsiz = sizeof(Link) + ksiz; | | size_t lsiz = sizeof(Link) + ksiz; | |
| char* lbuf = lsiz > sizeof(lstack) ? new char[lsiz] : lstack; | | char* lbuf = lsiz > sizeof(lstack) ? new char[lsiz] : lstack; | |
| Link* link = (Link*)lbuf; | | Link* link = (Link*)lbuf; | |
| link->child = 0; | | link->child = 0; | |
| link->ksiz = ksiz; | | link->ksiz = ksiz; | |
| std::memcpy(lbuf + sizeof(*link), kbuf, ksiz); | | std::memcpy(lbuf + sizeof(*link), kbuf, ksiz); | |
| int64_t hist[LEVELMAX]; | | int64_t hist[LEVELMAX]; | |
| int32_t hnum = 0; | | int32_t hnum = 0; | |
| LeafNode* node = search_tree(link, true, hist, &hnum); | | LeafNode* node = search_tree(link, true, hist, &hnum); | |
| if (!node) { | | if (!node) { | |
| set_error(_KCCODELINE_, Error::BROKEN, "search failed"); | | set_error(_KCCODELINE_, Error::BROKEN, "search failed"); | |
| if (lbuf != lstack) delete[] lbuf; | | if (lbuf != lstack) delete[] lbuf; | |
| mlock_.unlock(); | | mlock_.unlock(); | |
| return false; | | return false; | |
| } | | } | |
|
| char rstack[RECBUFSIZ]; | | char rstack[KCPDRECBUFSIZ]; | |
| size_t rsiz = sizeof(Record) + ksiz; | | size_t rsiz = sizeof(Record) + ksiz; | |
| char* rbuf = rsiz > sizeof(rstack) ? new char[rsiz] : rstack; | | char* rbuf = rsiz > sizeof(rstack) ? new char[rsiz] : rstack; | |
| Record* rec = (Record*)rbuf; | | Record* rec = (Record*)rbuf; | |
| rec->ksiz = ksiz; | | rec->ksiz = ksiz; | |
| rec->vsiz = 0; | | rec->vsiz = 0; | |
| std::memcpy(rbuf + sizeof(*rec), kbuf, ksiz); | | std::memcpy(rbuf + sizeof(*rec), kbuf, ksiz); | |
| if (writable) { | | if (writable) { | |
| node->lock.lock_writer(); | | node->lock.lock_writer(); | |
| } else { | | } else { | |
| node->lock.lock_reader(); | | node->lock.lock_reader(); | |
| | | | |
| skipping to change at line 1053 | | skipping to change at line 1095 | |
| return false; | | return false; | |
| } | | } | |
| ScopedVisitor svis(visitor); | | ScopedVisitor svis(visitor); | |
| if (keys.empty()) return true; | | if (keys.empty()) return true; | |
| bool err = false; | | bool err = false; | |
| std::vector<std::string>::const_iterator kit = keys.begin(); | | std::vector<std::string>::const_iterator kit = keys.begin(); | |
| std::vector<std::string>::const_iterator kitend = keys.end(); | | std::vector<std::string>::const_iterator kitend = keys.end(); | |
| while (!err && kit != kitend) { | | while (!err && kit != kitend) { | |
| const char* kbuf = kit->data(); | | const char* kbuf = kit->data(); | |
| size_t ksiz = kit->size(); | | size_t ksiz = kit->size(); | |
|
| char lstack[RECBUFSIZ]; | | char lstack[KCPDRECBUFSIZ]; | |
| size_t lsiz = sizeof(Link) + ksiz; | | size_t lsiz = sizeof(Link) + ksiz; | |
| char* lbuf = lsiz > sizeof(lstack) ? new char[lsiz] : lstack; | | char* lbuf = lsiz > sizeof(lstack) ? new char[lsiz] : lstack; | |
| Link* link = (Link*)lbuf; | | Link* link = (Link*)lbuf; | |
| link->child = 0; | | link->child = 0; | |
| link->ksiz = ksiz; | | link->ksiz = ksiz; | |
| std::memcpy(lbuf + sizeof(*link), kbuf, ksiz); | | std::memcpy(lbuf + sizeof(*link), kbuf, ksiz); | |
| int64_t hist[LEVELMAX]; | | int64_t hist[LEVELMAX]; | |
| int32_t hnum = 0; | | int32_t hnum = 0; | |
| LeafNode* node = search_tree(link, true, hist, &hnum); | | LeafNode* node = search_tree(link, true, hist, &hnum); | |
| if (!node) { | | if (!node) { | |
| set_error(_KCCODELINE_, Error::BROKEN, "search failed"); | | set_error(_KCCODELINE_, Error::BROKEN, "search failed"); | |
| if (lbuf != lstack) delete[] lbuf; | | if (lbuf != lstack) delete[] lbuf; | |
| err = true; | | err = true; | |
| break; | | break; | |
| } | | } | |
|
| char rstack[RECBUFSIZ]; | | char rstack[KCPDRECBUFSIZ]; | |
| size_t rsiz = sizeof(Record) + ksiz; | | size_t rsiz = sizeof(Record) + ksiz; | |
| char* rbuf = rsiz > sizeof(rstack) ? new char[rsiz] : rstack; | | char* rbuf = rsiz > sizeof(rstack) ? new char[rsiz] : rstack; | |
| Record* rec = (Record*)rbuf; | | Record* rec = (Record*)rbuf; | |
| rec->ksiz = ksiz; | | rec->ksiz = ksiz; | |
| rec->vsiz = 0; | | rec->vsiz = 0; | |
| std::memcpy(rbuf + sizeof(*rec), kbuf, ksiz); | | std::memcpy(rbuf + sizeof(*rec), kbuf, ksiz); | |
| bool reorg = accept_impl(node, rec, visitor); | | bool reorg = accept_impl(node, rec, visitor); | |
| bool atran = autotran_ && !tran_ && node->dirty; | | bool atran = autotran_ && !tran_ && node->dirty; | |
| bool async = autosync_ && !autotran_ && !tran_ && node->dirty; | | bool async = autosync_ && !autotran_ && !tran_ && node->dirty; | |
| if (atran && !reorg && !fix_auto_transaction_leaf(node)) err = true; | | if (atran && !reorg && !fix_auto_transaction_leaf(node)) err = true; | |
| | | | |
| skipping to change at line 1179 | | skipping to change at line 1221 | |
| if (checker && !checker->check("iterate", "processing", curcnt, all
cnt)) { | | if (checker && !checker->check("iterate", "processing", curcnt, all
cnt)) { | |
| set_error(_KCCODELINE_, Error::LOGIC, "checker failed"); | | set_error(_KCCODELINE_, Error::LOGIC, "checker failed"); | |
| err = true; | | err = true; | |
| break; | | break; | |
| } | | } | |
| ++kit; | | ++kit; | |
| } | | } | |
| if (reorg) { | | if (reorg) { | |
| Record* rec = keys.front(); | | Record* rec = keys.front(); | |
| char* dbuf = (char*)rec + sizeof(*rec); | | char* dbuf = (char*)rec + sizeof(*rec); | |
|
| char lstack[RECBUFSIZ]; | | char lstack[KCPDRECBUFSIZ]; | |
| size_t lsiz = sizeof(Link) + rec->ksiz; | | size_t lsiz = sizeof(Link) + rec->ksiz; | |
| char* lbuf = lsiz > sizeof(lstack) ? new char[lsiz] : lstack; | | char* lbuf = lsiz > sizeof(lstack) ? new char[lsiz] : lstack; | |
| Link* link = (Link*)lbuf; | | Link* link = (Link*)lbuf; | |
| link->child = 0; | | link->child = 0; | |
| link->ksiz = rec->ksiz; | | link->ksiz = rec->ksiz; | |
| std::memcpy(lbuf + sizeof(*link), dbuf, rec->ksiz); | | std::memcpy(lbuf + sizeof(*link), dbuf, rec->ksiz); | |
| int64_t hist[LEVELMAX]; | | int64_t hist[LEVELMAX]; | |
| int32_t hnum = 0; | | int32_t hnum = 0; | |
| node = search_tree(link, false, hist, &hnum); | | node = search_tree(link, false, hist, &hnum); | |
| if (node) { | | if (node) { | |
| | | | |
| skipping to change at line 1292 | | skipping to change at line 1334 | |
| if (!db_.tune_fbp(fpow_)) return false; | | if (!db_.tune_fbp(fpow_)) return false; | |
| if (!db_.tune_options(opts_)) return false; | | if (!db_.tune_options(opts_)) return false; | |
| if (!db_.tune_buckets(bnum_)) return false; | | if (!db_.tune_buckets(bnum_)) return false; | |
| if (!db_.open(path, mode)) return false; | | if (!db_.open(path, mode)) return false; | |
| if (db_.type() != DBTYPE) { | | if (db_.type() != DBTYPE) { | |
| set_error(_KCCODELINE_, Error::INVALID, "invalid database type"); | | set_error(_KCCODELINE_, Error::INVALID, "invalid database type"); | |
| db_.close(); | | db_.close(); | |
| return false; | | return false; | |
| } | | } | |
| if (db_.reorganized()) { | | if (db_.reorganized()) { | |
|
| | | if (!reorganize_file(mode)) return false; | |
| | | } else if (db_.recovered()) { | |
| if (!writer_) { | | if (!writer_) { | |
| if (!db_.close()) return false; | | if (!db_.close()) return false; | |
|
| mode &= ~OREADER; | | uint32_t tmode = (mode & ~OREADER) | OWRITER; | |
| mode |= OWRITER; | | if (!db_.open(path, tmode)) return false; | |
| if (!db_.open(path, mode)) return false; | | | |
| } | | } | |
|
| if (!reorganize_file(mode)) return false; | | if (!recalc_count()) return false; | |
| } else if (db_.recovered()) { | | | |
| if (!writer_) { | | if (!writer_) { | |
| if (!db_.close()) return false; | | if (!db_.close()) return false; | |
|
| mode &= ~OREADER; | | | |
| mode |= OWRITER; | | | |
| if (!db_.open(path, mode)) return false; | | if (!db_.open(path, mode)) return false; | |
| } | | } | |
|
| if (!recalc_count()) return false; | | | |
| } | | } | |
| if (writer_ && db_.count() < 1) { | | if (writer_ && db_.count() < 1) { | |
| root_ = 0; | | root_ = 0; | |
| first_ = 0; | | first_ = 0; | |
| last_ = 0; | | last_ = 0; | |
| count_ = 0; | | count_ = 0; | |
| create_leaf_cache(); | | create_leaf_cache(); | |
| create_inner_cache(); | | create_inner_cache(); | |
| lcnt_ = 0; | | lcnt_ = 0; | |
| create_leaf_node(0, 0); | | create_leaf_node(0, 0); | |
| | | | |
| skipping to change at line 2020 | | skipping to change at line 2059 | |
| * 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: | |
|
| /** The number of cache slots. */ | | | |
| static const int32_t SLOTNUM = 16; | | | |
| /** The default alignment power. */ | | | |
| static const uint8_t DEFAPOW = 8; | | | |
| /** The default free block pool power. */ | | | |
| static const uint8_t DEFFPOW = 10; | | | |
| /** The default bucket number. */ | | | |
| static const int64_t DEFBNUM = 64LL << 10; | | | |
| /** The default page size. */ | | | |
| static const int32_t DEFPSIZ = 8192; | | | |
| /** The default capacity size of the page cache. */ | | | |
| static const int64_t DEFPCCAP = 64LL << 20; | | | |
| /** The size of the header. */ | | | |
| static const int64_t HEADSIZ = 80; | | | |
| /** The offset of the numbers. */ | | | |
| static const int64_t MOFFNUMS = 8; | | | |
| /** The prefix of leaf nodes. */ | | | |
| static const char LNPREFIX = 'L'; | | | |
| /** The prefix of inner nodes. */ | | | |
| static const char INPREFIX = 'I'; | | | |
| /** The average number of ways of each node. */ | | | |
| static const size_t AVGWAY = 16; | | | |
| /** The ratio of the warm cache. */ | | | |
| static const size_t WARMRATIO = 4; | | | |
| /** The ratio of flushing inner nodes. */ | | | |
| static const size_t INFLRATIO = 32; | | | |
| /** The default number of items in each leaf node. */ | | | |
| static const size_t DEFLINUM = 64; | | | |
| /** The default number of items in each inner node. */ | | | |
| static const size_t DEFIINUM = 128; | | | |
| /** The size of the record buffer. */ | | | |
| static const size_t RECBUFSIZ = 64; | | | |
| /** The base ID number for inner nodes. */ | | | |
| static const int64_t INIDBASE = 1LL << 48; | | | |
| /** The minimum number of links in each inner node. */ | | | |
| static const size_t INLINKMIN = 8; | | | |
| /** The maximum level of B+ tree. */ | | | |
| static const int32_t LEVELMAX = 16; | | | |
| /** The number of cached nodes for auto transaction. */ | | | |
| static const int32_t ATRANCNUM = 256; | | | |
| /** The threshold of busy loop and sleep for locking. */ | | | |
| static const uint32_t LOCKBUSYLOOP = 8192; | | | |
| /** | | /** | |
| * 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 3449 | | skipping to change at line 3446 | |
| } | | } | |
| } else { | | } else { | |
| set_error(_KCCODELINE_, Error::SYSTEM, "renaming the source failed"
); | | set_error(_KCCODELINE_, Error::SYSTEM, "renaming the source failed"
); | |
| err = true; | | err = true; | |
| } | | } | |
| File::remove_recursively(tpath); | | File::remove_recursively(tpath); | |
| File::remove_recursively(npath); | | File::remove_recursively(npath); | |
| } else { | | } else { | |
| BASEDB udb; | | BASEDB udb; | |
| if (!err && udb.open(npath, OREADER)) { | | if (!err && udb.open(npath, OREADER)) { | |
|
| if (!db_.clear()) err = true; | | if (writer_) { | |
| | | if (!db_.clear()) err = true; | |
| | | } else { | |
| | | if (!db_.close()) err = true; | |
| | | uint32_t tmode = (mode & ~OREADER) | OWRITER | OCREATE | OTRUNCAT | |
| | | E; | |
| | | if (!db_.open(path, tmode)) err = true; | |
| | | } | |
| cur = udb.cursor(); | | cur = udb.cursor(); | |
| cur->jump(); | | cur->jump(); | |
| const char* vbuf; | | const char* vbuf; | |
| size_t vsiz; | | size_t vsiz; | |
| while (!err && (kbuf = cur->get(&ksiz, &vbuf, &vsiz)) != NULL) { | | while (!err && (kbuf = cur->get(&ksiz, &vbuf, &vsiz)) != NULL) { | |
| if (!db_.set(kbuf, ksiz, vbuf, vsiz)) err = true; | | if (!db_.set(kbuf, ksiz, vbuf, vsiz)) err = true; | |
| delete[] kbuf; | | delete[] kbuf; | |
| cur->step(); | | cur->step(); | |
| } | | } | |
| delete cur; | | delete cur; | |
|
| if (!db_.synchronize(false, NULL)) err = true; | | if (writer_) { | |
| | | if (!db_.synchronize(false, NULL)) err = true; | |
| | | } else { | |
| | | if (!db_.close()) err = true; | |
| | | if (!db_.open(path, mode)) err = true; | |
| | | } | |
| if (!udb.close()) { | | if (!udb.close()) { | |
| set_error(_KCCODELINE_, udb.error().code(), "closing the destinat
ion failed"); | | set_error(_KCCODELINE_, udb.error().code(), "closing the destinat
ion failed"); | |
| err = true; | | err = true; | |
| } | | } | |
| } else { | | } else { | |
| set_error(_KCCODELINE_, udb.error().code(), "opening the destinatio
n failed"); | | set_error(_KCCODELINE_, udb.error().code(), "opening the destinatio
n failed"); | |
| err = true; | | err = true; | |
| } | | } | |
| File::remove_recursively(npath); | | File::remove_recursively(npath); | |
| } | | } | |
| | | | |
End of changes. 27 change blocks. |
| 69 lines changed or deleted | | 79 lines changed or added | |
|