| kchashdb.h | | kchashdb.h | |
| | | | |
| skipping to change at line 69 | | skipping to change at line 69 | |
| const uint8_t HDBDEFFPOW = 10; ///< default free block pool power | | const uint8_t HDBDEFFPOW = 10; ///< default free block pool power | |
| const uint8_t HDBMAXFPOW = 20; ///< maximum free block pool power | | const uint8_t HDBMAXFPOW = 20; ///< maximum free block pool power | |
| const int64_t HDBDEFBNUM = 1048583LL; ///< default bucket number | | const int64_t HDBDEFBNUM = 1048583LL; ///< default bucket number | |
| const int64_t HDBDEFMSIZ = 64LL << 20; ///< default size of the memory-ma
pped region | | const int64_t HDBDEFMSIZ = 64LL << 20; ///< default size of the memory-ma
pped region | |
| const uint8_t HDBRECMAGIC = 0xcc; ///< magic data for record | | const uint8_t HDBRECMAGIC = 0xcc; ///< magic data for record | |
| const uint8_t HDBPADMAGIC = 0xee; ///< magic data for padding | | const uint8_t HDBPADMAGIC = 0xee; ///< magic data for padding | |
| const uint8_t HDBFBMAGIC = 0xdd; ///< magic data for free block | | const uint8_t HDBFBMAGIC = 0xdd; ///< magic data for free block | |
| const int32_t HDBDFRGMAX = 512; ///< maximum unit of auto defragme
ntation | | const int32_t HDBDFRGMAX = 512; ///< maximum unit of auto defragme
ntation | |
| const int32_t HDBDFRGCEF = 2; ///< coefficient of auto defragmen
tation | | const int32_t HDBDFRGCEF = 2; ///< coefficient of auto defragmen
tation | |
| const int64_t HDBSLVGWIDTH = 1LL << 20; ///< checking width for record sal
vage | | const int64_t HDBSLVGWIDTH = 1LL << 20; ///< checking width for record sal
vage | |
|
| | | const uint32_t HDBLOCKBUSYLOOP = 8192; ///< threshold of busy loop and sl
eep for locking | |
| const char* HDBTMPPATHEXT = "tmpkch"; ///< extension of the temporary fi
le | | const char* HDBTMPPATHEXT = "tmpkch"; ///< extension of the temporary fi
le | |
| } | | } | |
| | | | |
| /** | | /** | |
| * File hash database. | | * File hash database. | |
| * @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 | |
| | | | |
| skipping to change at line 289 | | skipping to change at line 290 | |
| uint64_t hash = db_->hash_record(kbuf, ksiz); | | uint64_t hash = db_->hash_record(kbuf, ksiz); | |
| uint32_t pivot = db_->fold_hash(hash); | | uint32_t pivot = db_->fold_hash(hash); | |
| int64_t bidx = hash % db_->bnum_; | | int64_t bidx = hash % db_->bnum_; | |
| int64_t off = db_->get_bucket(bidx); | | int64_t off = db_->get_bucket(bidx); | |
| if (off < 0) return false; | | if (off < 0) return false; | |
| Record rec; | | Record rec; | |
| char rbuf[HDBRECBUFSIZ]; | | char rbuf[HDBRECBUFSIZ]; | |
| 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 == UINT16_MAX) { | | 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; | |
| | | | |
| skipping to change at line 440 | | skipping to change at line 441 | |
| if (off_ >= end_) { | | if (off_ >= end_) { | |
| db_->set_error(_KCCODELINE_, Error::BROKEN, "cursor after the end")
; | | db_->set_error(_KCCODELINE_, Error::BROKEN, "cursor after the end")
; | |
| db_->report(_KCCODELINE_, Logger::WARN, "psiz=%lld off=%lld fsiz=%l
ld", | | db_->report(_KCCODELINE_, Logger::WARN, "psiz=%lld off=%lld fsiz=%l
ld", | |
| (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; | |
| } | | } | |
| while (off_ < end_) { | | while (off_ < end_) { | |
| rec->off = off_; | | rec->off = off_; | |
| if (!db_->read_record(rec, rbuf)) return false; | | if (!db_->read_record(rec, rbuf)) return false; | |
| skip--; | | skip--; | |
|
| if (rec->psiz == UINT16_MAX) { | | if (rec->psiz == UINT16MAX) { | |
| off_ += rec->rsiz; | | off_ += rec->rsiz; | |
| } else { | | } else { | |
| if (skip < 0) return true; | | if (skip < 0) return true; | |
| delete[] rec->bbuf; | | delete[] rec->bbuf; | |
| off_ += rec->rsiz; | | off_ += rec->rsiz; | |
| } | | } | |
| } | | } | |
| db_->set_error(_KCCODELINE_, Error::NOREC, "no record"); | | db_->set_error(_KCCODELINE_, Error::NOREC, "no record"); | |
| off_ = 0; | | off_ = 0; | |
| return false; | | return false; | |
| | | | |
| skipping to change at line 919 | | skipping to change at line 920 | |
| return !err; | | return !err; | |
| } | | } | |
| /** | | /** | |
| * Begin transaction. | | * Begin transaction. | |
| * @param hard true for physical synchronization with the device, or fals
e for logical | | * @param hard true for physical synchronization with the device, or fals
e for logical | |
| * synchronization with the file system. | | * synchronization with the file system. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool begin_transaction(bool hard = false) { | | bool begin_transaction(bool hard = false) { | |
| _assert_(true); | | _assert_(true); | |
|
| for (double wsec = 1.0 / CLOCKTICK; true; wsec *= 2) { | | uint32_t wcnt = 0; | |
| | | while (true) { | |
| mlock_.lock_writer(); | | mlock_.lock_writer(); | |
| 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 (!writer_) { | | if (!writer_) { | |
| set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | | set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | |
| mlock_.unlock(); | | mlock_.unlock(); | |
| return false; | | return false; | |
| } | | } | |
| if (!tran_) break; | | if (!tran_) break; | |
| mlock_.unlock(); | | mlock_.unlock(); | |
|
| if (wsec > 1.0) wsec = 1.0; | | if (wcnt >= HDBLOCKBUSYLOOP) { | |
| Thread::sleep(wsec); | | Thread::chill(); | |
| | | } else { | |
| | | Thread::yield(); | |
| | | wcnt++; | |
| | | } | |
| } | | } | |
| trhard_ = hard; | | trhard_ = hard; | |
| if (!begin_transaction_impl()) { | | if (!begin_transaction_impl()) { | |
| mlock_.unlock(); | | mlock_.unlock(); | |
| return false; | | return false; | |
| } | | } | |
| tran_ = true; | | tran_ = true; | |
| trigger_meta(MetaTrigger::BEGINTRAN, "begin_transaction"); | | trigger_meta(MetaTrigger::BEGINTRAN, "begin_transaction"); | |
| mlock_.unlock(); | | mlock_.unlock(); | |
| return true; | | return true; | |
| | | | |
| skipping to change at line 1243 | | skipping to change at line 1249 | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool tune_buckets(int64_t bnum) { | | bool tune_buckets(int64_t bnum) { | |
| _assert_(true); | | _assert_(true); | |
| ScopedSpinRWLock lock(&mlock_, true); | | ScopedSpinRWLock lock(&mlock_, true); | |
| if (omode_ != 0) { | | if (omode_ != 0) { | |
| set_error(_KCCODELINE_, Error::INVALID, "already opened"); | | set_error(_KCCODELINE_, Error::INVALID, "already opened"); | |
| return false; | | return false; | |
| } | | } | |
| bnum_ = bnum > 0 ? bnum : HDBDEFBNUM; | | bnum_ = bnum > 0 ? bnum : HDBDEFBNUM; | |
|
| if (bnum_ > INT16_MAX) bnum_ = nearbyprime(bnum_); | | if (bnum_ > INT16MAX) bnum_ = nearbyprime(bnum_); | |
| return true; | | return true; | |
| } | | } | |
| /** | | /** | |
| * Set the size of the internal memory-mapped region. | | * Set the size of the internal memory-mapped region. | |
| * @param msiz the size of the internal memory-mapped region. | | * @param msiz the size of the internal memory-mapped region. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool tune_map(int64_t msiz) { | | bool tune_map(int64_t msiz) { | |
| _assert_(true); | | _assert_(true); | |
| ScopedSpinRWLock lock(&mlock_, true); | | ScopedSpinRWLock lock(&mlock_, true); | |
| | | | |
| skipping to change at line 1344 | | skipping to change at line 1350 | |
| } | | } | |
| if (!writer_) { | | if (!writer_) { | |
| set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | | set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | |
| return false; | | return false; | |
| } | | } | |
| bool err = false; | | bool err = false; | |
| if (step > 0) { | | if (step > 0) { | |
| if (!defrag_impl(step)) err = true; | | if (!defrag_impl(step)) err = true; | |
| } else { | | } else { | |
| dfcur_ = roff_; | | dfcur_ = roff_; | |
|
| if (!defrag_impl(INT64_MAX)) err = true; | | if (!defrag_impl(INT64MAX)) err = true; | |
| } | | } | |
| frgcnt_ = 0; | | frgcnt_ = 0; | |
| return !err; | | return !err; | |
| } | | } | |
| /** | | /** | |
| * Get the status flags. | | * Get the status flags. | |
| * @return the status flags, or 0 on failure. | | * @return the status flags, or 0 on failure. | |
| */ | | */ | |
| uint8_t flags() { | | uint8_t flags() { | |
| _assert_(true); | | _assert_(true); | |
| | | | |
| skipping to change at line 1715 | | skipping to change at line 1721 | |
| int64_t top = get_bucket(bidx); | | int64_t top = get_bucket(bidx); | |
| int64_t off = top; | | int64_t off = top; | |
| if (off < 0) return false; | | if (off < 0) return false; | |
| enum { DIREMPTY, DIRLEFT, DIRRIGHT, DIRMIXED } entdir = DIREMPTY; | | enum { DIREMPTY, DIRLEFT, DIRRIGHT, DIRMIXED } entdir = DIREMPTY; | |
| int64_t entoff = 0; | | int64_t entoff = 0; | |
| Record rec; | | Record rec; | |
| char rbuf[HDBRECBUFSIZ]; | | char rbuf[HDBRECBUFSIZ]; | |
| while (off > 0) { | | while (off > 0) { | |
| rec.off = off; | | rec.off = off; | |
| if (!read_record(&rec, rbuf)) return false; | | if (!read_record(&rec, rbuf)) return false; | |
|
| if (rec.psiz == UINT16_MAX) { | | if (rec.psiz == UINT16MAX) { | |
| set_error(_KCCODELINE_, Error::BROKEN, "free block in the chain"); | | set_error(_KCCODELINE_, Error::BROKEN, "free block in the chain"); | |
| report(_KCCODELINE_, Logger::WARN, "psiz=%lld off=%lld fsiz=%lld", | | report(_KCCODELINE_, Logger::WARN, "psiz=%lld off=%lld fsiz=%lld", | |
| (long long)psiz_, (long long)rec.off, (long long)file_.size(
)); | | (long long)psiz_, (long long)rec.off, (long long)file_.size(
)); | |
| return false; | | return false; | |
| } | | } | |
| uint32_t tpivot = linear_ ? pivot : fold_hash(hash_record(rec.kbuf, r
ec.ksiz)); | | uint32_t tpivot = linear_ ? pivot : fold_hash(hash_record(rec.kbuf, r
ec.ksiz)); | |
| if (pivot > tpivot) { | | if (pivot > tpivot) { | |
| delete[] rec.bbuf; | | delete[] rec.bbuf; | |
| off = rec.left; | | off = rec.left; | |
| switch (entdir) { | | switch (entdir) { | |
| | | | |
| skipping to change at line 2022 | | skipping to change at line 2028 | |
| return false; | | return false; | |
| } | | } | |
| int64_t off = roff_; | | int64_t off = roff_; | |
| int64_t end = lsiz_; | | int64_t end = lsiz_; | |
| Record rec; | | Record rec; | |
| char rbuf[HDBRECBUFSIZ]; | | char rbuf[HDBRECBUFSIZ]; | |
| int64_t curcnt = 0; | | int64_t curcnt = 0; | |
| while (off > 0 && off < end) { | | while (off > 0 && off < end) { | |
| rec.off = off; | | rec.off = off; | |
| if (!read_record(&rec, rbuf)) return false; | | if (!read_record(&rec, rbuf)) return false; | |
|
| if (rec.psiz == UINT16_MAX) { | | if (rec.psiz == UINT16MAX) { | |
| off += rec.rsiz; | | off += rec.rsiz; | |
| } else { | | } else { | |
| if (!rec.vbuf && !read_record_body(&rec)) { | | if (!rec.vbuf && !read_record_body(&rec)) { | |
| delete[] rec.bbuf; | | delete[] rec.bbuf; | |
| return false; | | return false; | |
| } | | } | |
| const char* vbuf = rec.vbuf; | | const char* vbuf = rec.vbuf; | |
| size_t vsiz = rec.vsiz; | | size_t vsiz = rec.vsiz; | |
| char* zbuf = NULL; | | char* zbuf = NULL; | |
| size_t zsiz = 0; | | size_t zsiz = 0; | |
| | | | |
| skipping to change at line 2187 | | skipping to change at line 2193 | |
| Record rec; | | Record rec; | |
| char rbuf[HDBRECBUFSIZ]; | | char rbuf[HDBRECBUFSIZ]; | |
| while (true) { | | while (true) { | |
| if (dfcur_ >= end) { | | if (dfcur_ >= end) { | |
| dfcur_ = roff_; | | dfcur_ = roff_; | |
| return true; | | return true; | |
| } | | } | |
| if (step-- < 1) return true; | | if (step-- < 1) return true; | |
| rec.off = dfcur_; | | rec.off = dfcur_; | |
| if (!read_record(&rec, rbuf)) return false; | | if (!read_record(&rec, rbuf)) return false; | |
|
| if (rec.psiz == UINT16_MAX) break; | | if (rec.psiz == UINT16MAX) break; | |
| delete[] rec.bbuf; | | delete[] rec.bbuf; | |
| dfcur_ += rec.rsiz; | | dfcur_ += rec.rsiz; | |
| } | | } | |
| bool atran = false; | | bool atran = false; | |
| if (autotran_ && !tran_) { | | if (autotran_ && !tran_) { | |
| if (!begin_auto_transaction()) return false; | | if (!begin_auto_transaction()) return false; | |
| atran = true; | | atran = true; | |
| } | | } | |
| int64_t base = dfcur_; | | int64_t base = dfcur_; | |
| int64_t dest = base; | | int64_t dest = base; | |
| dfcur_ += rec.rsiz; | | dfcur_ += rec.rsiz; | |
| step++; | | step++; | |
| while (step-- > 0 && dfcur_ < end) { | | while (step-- > 0 && dfcur_ < end) { | |
| rec.off = dfcur_; | | rec.off = dfcur_; | |
| if (!read_record(&rec, rbuf)) { | | if (!read_record(&rec, rbuf)) { | |
| if (atran) abort_auto_transaction(); | | if (atran) abort_auto_transaction(); | |
| return false; | | return false; | |
| } | | } | |
| escape_cursors(rec.off, dest); | | escape_cursors(rec.off, dest); | |
| dfcur_ += rec.rsiz; | | dfcur_ += rec.rsiz; | |
|
| if (rec.psiz != UINT16_MAX) { | | if (rec.psiz != UINT16MAX) { | |
| if (!rec.vbuf && !read_record_body(&rec)) { | | if (!rec.vbuf && !read_record_body(&rec)) { | |
| if (atran) abort_auto_transaction(); | | if (atran) abort_auto_transaction(); | |
| delete[] rec.bbuf; | | delete[] rec.bbuf; | |
| return false; | | return false; | |
| } | | } | |
| if (rec.psiz >= align_) { | | if (rec.psiz >= align_) { | |
| size_t diff = rec.psiz - rec.psiz % align_; | | size_t diff = rec.psiz - rec.psiz % align_; | |
| rec.psiz -= diff; | | rec.psiz -= diff; | |
| rec.rsiz -= diff; | | rec.rsiz -= diff; | |
| } | | } | |
| | | | |
| skipping to change at line 2501 | | skipping to change at line 2507 | |
| int64_t checkend = off + HDBSLVGWIDTH; | | int64_t checkend = off + HDBSLVGWIDTH; | |
| if (checkend > end - (int64_t)rhsiz_) checkend = end - rhsiz_; | | if (checkend > end - (int64_t)rhsiz_) checkend = end - rhsiz_; | |
| bool hit = false; | | bool hit = false; | |
| for (off += rhsiz_; off < checkend; off++) { | | for (off += rhsiz_; off < checkend; off++) { | |
| rec.off = off; | | rec.off = off; | |
| if (!read_record(&rec, rbuf)) continue; | | if (!read_record(&rec, rbuf)) continue; | |
| if ((int64_t)rec.rsiz > HDBSLVGWIDTH || rec.off + (int64_t)rec.rs
iz >= checkend) { | | if ((int64_t)rec.rsiz > HDBSLVGWIDTH || rec.off + (int64_t)rec.rs
iz >= checkend) { | |
| delete[] rec.bbuf; | | delete[] rec.bbuf; | |
| continue; | | continue; | |
| } | | } | |
|
| if (rec.psiz != UINT16_MAX && !rec.vbuf && !read_record_body(&rec
)) { | | if (rec.psiz != UINT16MAX && !rec.vbuf && !read_record_body(&rec)
) { | |
| delete[] rec.bbuf; | | delete[] rec.bbuf; | |
| continue; | | continue; | |
| } | | } | |
| delete[] rec.bbuf; | | delete[] rec.bbuf; | |
| nrec.off = off + rec.rsiz; | | nrec.off = off + rec.rsiz; | |
| if (!read_record(&nrec, nbuf)) continue; | | if (!read_record(&nrec, nbuf)) continue; | |
| if ((int64_t)nrec.rsiz > HDBSLVGWIDTH || nrec.off + (int64_t)nrec
.rsiz >= checkend) { | | if ((int64_t)nrec.rsiz > HDBSLVGWIDTH || nrec.off + (int64_t)nrec
.rsiz >= checkend) { | |
| delete[] nrec.bbuf; | | delete[] nrec.bbuf; | |
| continue; | | continue; | |
| } | | } | |
|
| if (nrec.psiz != UINT16_MAX && !nrec.vbuf && !read_record_body(&n
rec)) { | | if (nrec.psiz != UINT16MAX && !nrec.vbuf && !read_record_body(&nr
ec)) { | |
| delete[] nrec.bbuf; | | delete[] nrec.bbuf; | |
| continue; | | continue; | |
| } | | } | |
| delete[] nrec.bbuf; | | delete[] nrec.bbuf; | |
| hit = true; | | hit = true; | |
| break; | | break; | |
| } | | } | |
| if (!hit || !read_record(&rec, rbuf)) break; | | if (!hit || !read_record(&rec, rbuf)) break; | |
| } | | } | |
|
| if (rec.psiz == UINT16_MAX) { | | if (rec.psiz == UINT16MAX) { | |
| off += rec.rsiz; | | off += rec.rsiz; | |
| continue; | | continue; | |
| } | | } | |
| if (!rec.vbuf && !read_record_body(&rec)) { | | if (!rec.vbuf && !read_record_body(&rec)) { | |
| delete[] rec.bbuf; | | delete[] rec.bbuf; | |
| bool hit = false; | | bool hit = false; | |
| if (rec.rsiz <= MEMMAXSIZ && off + (int64_t)rec.rsiz < end) { | | if (rec.rsiz <= MEMMAXSIZ && off + (int64_t)rec.rsiz < end) { | |
| nrec.off = off + rec.rsiz; | | nrec.off = off + rec.rsiz; | |
| if (read_record(&nrec, nbuf)) { | | if (read_record(&nrec, nbuf)) { | |
| if (nrec.rsiz > MEMMAXSIZ || nrec.off + (int64_t)nrec.rsiz >= e
nd) { | | if (nrec.rsiz > MEMMAXSIZ || nrec.off + (int64_t)nrec.rsiz >= e
nd) { | |
| delete[] nrec.bbuf; | | delete[] nrec.bbuf; | |
|
| } else if (nrec.psiz != UINT16_MAX && !nrec.vbuf && !read_recor
d_body(&nrec)) { | | } else if (nrec.psiz != UINT16MAX && !nrec.vbuf && !read_record
_body(&nrec)) { | |
| delete[] nrec.bbuf; | | delete[] nrec.bbuf; | |
| } else { | | } else { | |
| delete[] nrec.bbuf; | | delete[] nrec.bbuf; | |
| hit = true; | | hit = true; | |
| } | | } | |
| } | | } | |
| } | | } | |
| if (hit) { | | if (hit) { | |
| off += rec.rsiz; | | off += rec.rsiz; | |
| continue; | | continue; | |
| | | | |
| skipping to change at line 2751 | | skipping to change at line 2757 | |
| report_binary(_KCCODELINE_, Logger::WARN, "rbuf", rbuf, rsiz); | | report_binary(_KCCODELINE_, Logger::WARN, "rbuf", rbuf, rsiz); | |
| return false; | | return false; | |
| } | | } | |
| if (rec->rsiz < rhsiz_) { | | if (rec->rsiz < rhsiz_) { | |
| set_error(_KCCODELINE_, Error::BROKEN, "invalid size of a free bloc
k"); | | set_error(_KCCODELINE_, Error::BROKEN, "invalid size of a free bloc
k"); | |
| report(_KCCODELINE_, Logger::WARN, "psiz=%lld off=%lld rsiz=%lld fs
iz=%lld", | | report(_KCCODELINE_, Logger::WARN, "psiz=%lld off=%lld rsiz=%lld fs
iz=%lld", | |
| (long long)psiz_, (long long)rec->off, (long long)rsiz, (lon
g long)file_.size()); | | (long long)psiz_, (long long)rec->off, (long long)rsiz, (lon
g long)file_.size()); | |
| report_binary(_KCCODELINE_, Logger::WARN, "rbuf", rbuf, rsiz); | | report_binary(_KCCODELINE_, Logger::WARN, "rbuf", rbuf, rsiz); | |
| return false; | | return false; | |
| } | | } | |
|
| rec->psiz = UINT16_MAX; | | rec->psiz = UINT16MAX; | |
| rec->ksiz = 0; | | rec->ksiz = 0; | |
| rec->vsiz = 0; | | rec->vsiz = 0; | |
| rec->left = 0; | | rec->left = 0; | |
| rec->right = 0; | | rec->right = 0; | |
| rec->kbuf = NULL; | | rec->kbuf = NULL; | |
| rec->vbuf = NULL; | | rec->vbuf = NULL; | |
| rec->boff = 0; | | rec->boff = 0; | |
| rec->bbuf = NULL; | | rec->bbuf = NULL; | |
| return true; | | return true; | |
| } else if (*rp == 0) { | | } else if (*rp == 0) { | |
| | | | |
| skipping to change at line 2927 | | skipping to change at line 2933 | |
| if (rbuf != stack) delete[] rbuf; | | if (rbuf != stack) delete[] rbuf; | |
| return !err; | | return !err; | |
| } | | } | |
| /** | | /** | |
| * Adjust the padding of a record. | | * Adjust the padding of a record. | |
| * @param rec the record structure. | | * @param rec the record structure. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool adjust_record(Record* rec) { | | bool adjust_record(Record* rec) { | |
| _assert_(rec); | | _assert_(rec); | |
|
| if (rec->psiz > INT16_MAX || rec->psiz > rec->rsiz / 2) { | | if (rec->psiz > (size_t)INT16MAX || rec->psiz > rec->rsiz / 2) { | |
| size_t nsiz = (rec->psiz >> apow_) << apow_; | | size_t nsiz = (rec->psiz >> apow_) << apow_; | |
| if (nsiz < rhsiz_) return true; | | if (nsiz < rhsiz_) return true; | |
| rec->rsiz -= nsiz; | | rec->rsiz -= nsiz; | |
| rec->psiz -= nsiz; | | rec->psiz -= nsiz; | |
| int64_t noff = rec->off + rec->rsiz; | | int64_t noff = rec->off + rec->rsiz; | |
| char nbuf[HDBRECBUFSIZ]; | | char nbuf[HDBRECBUFSIZ]; | |
| if (!write_free_block(noff, nsiz, nbuf)) return false; | | if (!write_free_block(noff, nsiz, nbuf)) return false; | |
| insert_free_block(noff, nsiz); | | insert_free_block(noff, nsiz); | |
| } | | } | |
| return true; | | return true; | |
| | | | |
| skipping to change at line 3010 | | skipping to change at line 3016 | |
| if (!write_record(orec, true)) return false; | | if (!write_record(orec, true)) return false; | |
| if (!set_bucket(bidx, dest)) return false; | | if (!set_bucket(bidx, dest)) return false; | |
| return true; | | return true; | |
| } | | } | |
| int64_t entoff = 0; | | int64_t entoff = 0; | |
| Record rec; | | Record rec; | |
| char rbuf[HDBRECBUFSIZ]; | | char rbuf[HDBRECBUFSIZ]; | |
| while (off > 0) { | | while (off > 0) { | |
| rec.off = off; | | rec.off = off; | |
| if (!read_record(&rec, rbuf)) return false; | | if (!read_record(&rec, rbuf)) return false; | |
|
| if (rec.psiz == UINT16_MAX) { | | if (rec.psiz == UINT16MAX) { | |
| set_error(_KCCODELINE_, Error::BROKEN, "free block in the chain"); | | set_error(_KCCODELINE_, Error::BROKEN, "free block in the chain"); | |
| report(_KCCODELINE_, Logger::WARN, "psiz=%lld off=%lld fsiz=%lld", | | report(_KCCODELINE_, Logger::WARN, "psiz=%lld off=%lld fsiz=%lld", | |
| (long long)psiz_, (long long)rec.off, (long long)file_.size(
)); | | (long long)psiz_, (long long)rec.off, (long long)file_.size(
)); | |
| return false; | | return false; | |
| } | | } | |
| uint32_t tpivot = linear_ ? pivot : fold_hash(hash_record(rec.kbuf, r
ec.ksiz)); | | uint32_t tpivot = linear_ ? pivot : fold_hash(hash_record(rec.kbuf, r
ec.ksiz)); | |
| if (pivot > tpivot) { | | if (pivot > tpivot) { | |
| delete[] rec.bbuf; | | delete[] rec.bbuf; | |
| off = rec.left; | | off = rec.left; | |
| entoff = rec.off + sizeof(uint16_t); | | entoff = rec.off + sizeof(uint16_t); | |
| | | | |
| skipping to change at line 3104 | | skipping to change at line 3110 | |
| /** | | /** | |
| * Fetch the free block pool from a decent sized block. | | * Fetch the free block pool from a decent sized block. | |
| * @param rsiz the minimum size of the block. | | * @param rsiz the minimum size of the block. | |
| * @param res the structure for the result. | | * @param res the structure for the result. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool fetch_free_block(size_t rsiz, FreeBlock* res) { | | bool fetch_free_block(size_t rsiz, FreeBlock* res) { | |
| _assert_(res); | | _assert_(res); | |
| if (fbpnum_ < 1) return false; | | if (fbpnum_ < 1) return false; | |
| ScopedSpinLock lock(&flock_); | | ScopedSpinLock lock(&flock_); | |
|
| FreeBlock fb = { INT64_MAX, rsiz }; | | FreeBlock fb = { INT64MAX, rsiz }; | |
| FBP::const_iterator it = fbp_.upper_bound(fb); | | FBP::const_iterator it = fbp_.upper_bound(fb); | |
| if (it == fbp_.end()) return false; | | if (it == fbp_.end()) return false; | |
| res->off = it->off; | | res->off = it->off; | |
| res->rsiz = it->rsiz; | | res->rsiz = it->rsiz; | |
| fbp_.erase(it); | | fbp_.erase(it); | |
| escape_cursors(res->off, res->off + res->rsiz); | | escape_cursors(res->off, res->off + res->rsiz); | |
| return true; | | return true; | |
| } | | } | |
| /** | | /** | |
| * Trim invalid free blocks. | | * Trim invalid free blocks. | |
| | | | |
| skipping to change at line 3325 | | skipping to change at line 3331 | |
| if (rec->left > 0 && rec->right < 1) { | | if (rec->left > 0 && rec->right < 1) { | |
| child = rec->left; | | child = rec->left; | |
| } else if (rec->left < 1 && rec->right > 0) { | | } else if (rec->left < 1 && rec->right > 0) { | |
| child = rec->right; | | child = rec->right; | |
| } else if (rec->left < 1) { | | } else if (rec->left < 1) { | |
| child = 0; | | child = 0; | |
| } else { | | } else { | |
| Record prec; | | Record prec; | |
| prec.off = rec->left; | | prec.off = rec->left; | |
| if (!read_record(&prec, rbuf)) return false; | | if (!read_record(&prec, rbuf)) return false; | |
|
| if (prec.psiz == UINT16_MAX) { | | if (prec.psiz == UINT16MAX) { | |
| set_error(_KCCODELINE_, Error::BROKEN, "free block in the chain"); | | set_error(_KCCODELINE_, Error::BROKEN, "free block in the chain"); | |
| report(_KCCODELINE_, Logger::WARN, "psiz=%lld off=%lld fsiz=%lld", | | report(_KCCODELINE_, Logger::WARN, "psiz=%lld off=%lld fsiz=%lld", | |
| (long long)psiz_, (long long)prec.off, (long long)file_.size
()); | | (long long)psiz_, (long long)prec.off, (long long)file_.size
()); | |
| report_binary(_KCCODELINE_, Logger::WARN, "rbuf", rbuf, rhsiz_); | | report_binary(_KCCODELINE_, Logger::WARN, "rbuf", rbuf, rhsiz_); | |
| return false; | | return false; | |
| } | | } | |
| delete[] prec.bbuf; | | delete[] prec.bbuf; | |
| if (prec.right > 0) { | | if (prec.right > 0) { | |
| int64_t off = prec.right; | | int64_t off = prec.right; | |
| int64_t pentoff = prec.off + sizeof(uint16_t) + width_; | | int64_t pentoff = prec.off + sizeof(uint16_t) + width_; | |
| while (true) { | | while (true) { | |
| prec.off = off; | | prec.off = off; | |
| if (!read_record(&prec, rbuf)) return false; | | if (!read_record(&prec, rbuf)) return false; | |
|
| if (prec.psiz == UINT16_MAX) { | | if (prec.psiz == UINT16MAX) { | |
| set_error(_KCCODELINE_, Error::BROKEN, "free block in the chain
"); | | set_error(_KCCODELINE_, Error::BROKEN, "free block in the chain
"); | |
| report(_KCCODELINE_, Logger::WARN, "psiz=%lld off=%lld fsiz=%ll
d", | | report(_KCCODELINE_, Logger::WARN, "psiz=%lld off=%lld fsiz=%ll
d", | |
| (long long)psiz_, (long long)prec.off, (long long)file_.
size()); | | (long long)psiz_, (long long)prec.off, (long long)file_.
size()); | |
| report_binary(_KCCODELINE_, Logger::WARN, "rbuf", rbuf, rhsiz_)
; | | report_binary(_KCCODELINE_, Logger::WARN, "rbuf", rbuf, rhsiz_)
; | |
| return false; | | return false; | |
| } | | } | |
| delete[] prec.bbuf; | | delete[] prec.bbuf; | |
| if (prec.right < 1) break; | | if (prec.right < 1) break; | |
| off = prec.right; | | off = prec.right; | |
| pentoff = prec.off + sizeof(uint16_t) + width_; | | pentoff = prec.off + sizeof(uint16_t) + width_; | |
| | | | |
End of changes. 21 change blocks. |
| 21 lines changed or deleted | | 27 lines changed or added | |
|
| kcplantdb.h | | kcplantdb.h | |
| | | | |
| skipping to change at line 34 | | skipping to change at line 34 | |
| #include <kcmap.h> | | #include <kcmap.h> | |
| #include <kcregex.h> | | #include <kcregex.h> | |
| #include <kcdb.h> | | #include <kcdb.h> | |
| | | | |
| namespace kyotocabinet { // common namespace | | namespace kyotocabinet { // common namespace | |
| | | | |
| /** | | /** | |
| * Constants for implementation. | | * Constants for implementation. | |
| */ | | */ | |
| namespace { | | namespace { | |
|
| const int32_t PDBSLOTNUM = 16; ///< number of cache slots | | const int32_t PLDBSLOTNUM = 16; ///< number of cache slots | |
| const uint8_t PDBDEFAPOW = 8; ///< default alignment power | | const uint8_t PLDBDEFAPOW = 8; ///< default alignment power | |
| const uint8_t PDBDEFFPOW = 10; ///< default free block pool power | | const uint8_t PLDBDEFFPOW = 10; ///< default free block pool power | |
| const int64_t PDBDEFBNUM = 64LL << 10; ///< default bucket number | | const int64_t PLDBDEFBNUM = 64LL << 10; ///< default bucket number | |
| const int32_t PDBDEFPSIZ = 8192; ///< default page size | | const int32_t PLDBDEFPSIZ = 8192; ///< default page size | |
| const int64_t PDBDEFPCCAP = 64LL << 20; ///< default capacity size of the | | const int64_t PLDBDEFPCCAP = 64LL << 20; ///< default capacity size of the | |
| page cache | | page cache | |
| const char PDBMETAKEY[] = "@"; ///< key of the record for meta da | | const char PLDBMETAKEY[] = "@"; ///< key of the record for meta da | |
| ta | | ta | |
| const int64_t PDBHEADSIZ = 80; ///< size of the header | | const int64_t PLDBHEADSIZ = 80; ///< size of the header | |
| const int64_t PDBMOFFNUMS = 8; ///< offset of the numbers | | const int64_t PLDBMOFFNUMS = 8; ///< offset of the numbers | |
| const char PDBLNPREFIX = 'L'; ///< prefix of leaf nodes | | const char PLDBLNPREFIX = 'L'; ///< prefix of leaf nodes | |
| const char PDBINPREFIX = 'I'; ///< prefix of inner nodes | | const char PLDBINPREFIX = 'I'; ///< prefix of inner nodes | |
| const size_t PDBAVGWAY = 16; ///< average number of ways of eac | | const size_t PLDBAVGWAY = 16; ///< average number of ways of eac | |
| h node | | h node | |
| const size_t PDBWARMRATIO = 4; ///< ratio of the warm cache | | const size_t PLDBWARMRATIO = 4; ///< ratio of the warm cache | |
| const size_t PDBINFLRATIO = 32; ///< ratio of flushing inner nodes | | const size_t PLDBINFLRATIO = 32; ///< ratio of flushing inner nodes | |
| const size_t PDBDEFLINUM = 64; ///< default number of items in ea | | const size_t PLDBDEFLINUM = 64; ///< default number of items in ea | |
| ch leaf node | | ch leaf node | |
| const size_t PDBDEFIINUM = 128; ///< default number of items in ea | | const size_t PLDBDEFIINUM = 128; ///< default number of items in ea | |
| ch inner node | | ch inner node | |
| const size_t PDBRECBUFSIZ = 64; ///< size of the record buffer | | const size_t PLDBRECBUFSIZ = 64; ///< size of the record buffer | |
| const int64_t PDBINIDBASE = 1LL << 48; ///< base ID number for inner node | | const int64_t PLDBINIDBASE = 1LL << 48; ///< base ID number for inner node | |
| s | | s | |
| const size_t PDBINLINKMIN = 8; ///< minimum number of links in ea | | const size_t PLDBINLINKMIN = 8; ///< minimum number of links in ea | |
| ch inner node | | ch inner node | |
| const int32_t PDBLEVELMAX = 16; ///< maximum level of B+ tree | | const int32_t PLDBLEVELMAX = 16; ///< maximum level of B+ tree | |
| const int32_t PDBATRANCNUM = 256; ///< number of cached nodes for au | | const int32_t PLDBATRANCNUM = 256; ///< number of cached nodes for au | |
| to transaction | | to transaction | |
| const char* PDBTMPPATHEXT = "tmpkct"; ///< extension of the temporary fi | | const uint32_t PLDBLOCKBUSYLOOP = 8192; ///< threshold of busy loop and sl | |
| le | | eep for locking | |
| | | const char* PLDBTMPPATHEXT = "tmpkct"; ///< extension of the temporary fi | |
| | | le | |
| } | | } | |
| | | | |
| /** | | /** | |
| * 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 | |
| * 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 | |
| | | | |
| skipping to change at line 436 | | skipping to change at line 437 | |
| * @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[PDBRECBUFSIZ]; | | char rstack[PLDBRECBUFSIZ]; | |
| 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[PDBRECBUFSIZ]; | | char lstack[PLDBRECBUFSIZ]; | |
| char* lbuf = NULL; | | char* lbuf = NULL; | |
| size_t lsiz = 0; | | size_t lsiz = 0; | |
| Link* link = NULL; | | Link* link = NULL; | |
|
| int64_t hist[PDBLEVELMAX]; | | int64_t hist[PLDBLEVELMAX]; | |
| 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(); | |
| } | | } | |
| RecordArray& recs = node->recs; | | RecordArray& recs = node->recs; | |
| if (!recs.empty()) { | | if (!recs.empty()) { | |
| Record* frec = recs.front(); | | Record* frec = recs.front(); | |
| Record* lrec = recs.back(); | | Record* lrec = recs.back(); | |
| | | | |
| skipping to change at line 564 | | skipping to change at line 565 | |
| 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 { | |
| db_->set_error(_KCCODELINE_, Error::BROKEN, "search failed"
); | | db_->set_error(_KCCODELINE_, Error::BROKEN, "search failed"
); | |
| err = true; | | err = true; | |
| } | | } | |
| } else if (flush) { | | } else if (flush) { | |
|
| int32_t idx = id % PDBSLOTNUM; | | int32_t idx = id % PLDBSLOTNUM; | |
| 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; | |
| } | | } | |
| } | | } | |
| if (lbuf != lstack) delete[] lbuf; | | if (lbuf != lstack) delete[] lbuf; | |
| | | | |
| skipping to change at line 592 | | skipping to change at line 593 | |
| * @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[PDBRECBUFSIZ]; | | char lstack[PLDBRECBUFSIZ]; | |
| 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[PDBLEVELMAX]; | | int64_t hist[PLDBLEVELMAX]; | |
| 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; | |
| } | | } | |
| if (node->recs.empty()) { | | if (node->recs.empty()) { | |
| if (lbuf != lstack) delete[] lbuf; | | if (lbuf != lstack) delete[] lbuf; | |
| clear_position(); | | clear_position(); | |
| | | | |
| skipping to change at line 629 | | skipping to change at line 630 | |
| 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[PDBRECBUFSIZ]; | | char rstack[PLDBRECBUFSIZ]; | |
| 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 704 | | skipping to change at line 705 | |
| set_position(node->next); | | set_position(node->next); | |
| } | | } | |
| } | | } | |
| bool atran = db_->autotran_ && !db_->tran_ && node->dirty; | | bool atran = db_->autotran_ && !db_->tran_ && node->dirty; | |
| bool async = db_->autosync_ && !db_->autotran_ && !db_->tran_ && no
de->dirty; | | bool async = db_->autosync_ && !db_->autotran_ && !db_->tran_ && no
de->dirty; | |
| if (atran && !reorg && !db_->fix_auto_transaction_leaf(node)) err =
true; | | if (atran && !reorg && !db_->fix_auto_transaction_leaf(node)) err =
true; | |
| if (reorg) { | | if (reorg) { | |
| if (!db_->reorganize_tree(node, hist, hnum)) err = true; | | if (!db_->reorganize_tree(node, hist, hnum)) err = true; | |
| if (atran && !db_->fix_auto_transaction_tree()) err = true; | | if (atran && !db_->fix_auto_transaction_tree()) err = true; | |
| } else if (db_->cusage_ > db_->pccap_) { | | } else if (db_->cusage_ > db_->pccap_) { | |
|
| int32_t idx = node->id % PDBSLOTNUM; | | int32_t idx = node->id % PLDBSLOTNUM; | |
| 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->cou
nt() + 1 && | | if (islot->warm->count() > lslot->warm->count() + lslot->hot->cou
nt() + 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 { | | } else { | |
| int64_t lid = lid_; | | int64_t lid = lid_; | |
| clear_position(); | | clear_position(); | |
| | | | |
| skipping to change at line 737 | | skipping to change at line 738 | |
| 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[PDBRECBUFSIZ]; | | char lstack[PLDBRECBUFSIZ]; | |
| 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[PDBLEVELMAX]; | | int64_t hist[PLDBLEVELMAX]; | |
| 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[PDBRECBUFSIZ]; | | char rstack[PLDBRECBUFSIZ]; | |
| 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 786 | | skipping to change at line 787 | |
| } | | } | |
| /** | | /** | |
| * 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[PDBRECBUFSIZ]; | | char rstack[PLDBRECBUFSIZ]; | |
| 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 837 | | skipping to change at line 838 | |
| 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[PDBRECBUFSIZ]; | | char lstack[PLDBRECBUFSIZ]; | |
| 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[PDBLEVELMAX]; | | int64_t hist[PLDBLEVELMAX]; | |
| 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[PDBRECBUFSIZ]; | | char rstack[PLDBRECBUFSIZ]; | |
| 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 890 | | skipping to change at line 891 | |
| 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_[PDBRECBUFSIZ]; | | char stack_[PLDBRECBUFSIZ]; | |
| /** 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 918 | | skipping to change at line 919 | |
| */ | | */ | |
| 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),
autosync_(false), | | mlock_(), mtrigger_(NULL), omode_(0), writer_(false), autotran_(false),
autosync_(false), | |
|
| db_(), curs_(), apow_(PDBDEFAPOW), fpow_(PDBDEFFPOW), opts_(0), bnum_(P | | db_(), curs_(), apow_(PLDBDEFAPOW), fpow_(PLDBDEFFPOW), opts_(0), bnum_ | |
| DBDEFBNUM), | | (PLDBDEFBNUM), | |
| psiz_(PDBDEFPSIZ), pccap_(PDBDEFPCCAP), | | psiz_(PLDBDEFPSIZ), pccap_(PLDBDEFPCCAP), | |
| 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() { | |
| | | | |
| skipping to change at line 966 | | skipping to change at line 967 | |
| 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[PDBRECBUFSIZ]; | | char lstack[PLDBRECBUFSIZ]; | |
| 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[PDBLEVELMAX]; | | int64_t hist[PLDBLEVELMAX]; | |
| 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[PDBRECBUFSIZ]; | | char rstack[PLDBRECBUFSIZ]; | |
| 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 1007 | | skipping to change at line 1008 | |
| node->lock.unlock(); | | node->lock.unlock(); | |
| bool flush = false; | | bool flush = false; | |
| bool err = false; | | bool err = false; | |
| int64_t id = node->id; | | int64_t id = node->id; | |
| if (atran && !reorg && !fix_auto_transaction_leaf(node)) err = true; | | if (atran && !reorg && !fix_auto_transaction_leaf(node)) err = true; | |
| if (reorg && mlock_.promote()) { | | if (reorg && mlock_.promote()) { | |
| if (!reorganize_tree(node, hist, hnum)) err = true; | | if (!reorganize_tree(node, hist, hnum)) err = true; | |
| if (atran && !fix_auto_transaction_tree()) err = true; | | if (atran && !fix_auto_transaction_tree()) err = true; | |
| reorg = false; | | reorg = false; | |
| } else if (cusage_ > pccap_) { | | } else if (cusage_ > pccap_) { | |
|
| int32_t idx = id % PDBSLOTNUM; | | int32_t idx = id % PLDBSLOTNUM; | |
| LeafSlot* lslot = lslots_ + idx; | | LeafSlot* lslot = lslots_ + idx; | |
| if (!clean_leaf_cache_part(lslot)) err = true; | | if (!clean_leaf_cache_part(lslot)) err = true; | |
| if (mlock_.promote()) { | | if (mlock_.promote()) { | |
| if (!flush_leaf_cache_part(lslot)) err = true; | | if (!flush_leaf_cache_part(lslot)) err = true; | |
| InnerSlot* islot = islots_ + idx; | | InnerSlot* islot = islots_ + idx; | |
| if (islot->warm->count() > lslot->warm->count() + lslot->hot->count
() + 1 && | | if (islot->warm->count() > lslot->warm->count() + lslot->hot->count
() + 1 && | |
| !flush_inner_cache_part(islot)) err = true; | | !flush_inner_cache_part(islot)) err = true; | |
| } else { | | } else { | |
| flush = true; | | flush = true; | |
| } | | } | |
| | | | |
| skipping to change at line 1029 | | skipping to change at line 1030 | |
| mlock_.unlock(); | | mlock_.unlock(); | |
| if (reorg) { | | if (reorg) { | |
| mlock_.lock_writer(); | | mlock_.lock_writer(); | |
| node = search_tree(link, false, hist, &hnum); | | node = search_tree(link, false, hist, &hnum); | |
| if (node) { | | if (node) { | |
| if (!reorganize_tree(node, hist, hnum)) err = true; | | if (!reorganize_tree(node, hist, hnum)) err = true; | |
| if (atran && !tran_ && !fix_auto_transaction_tree()) err = true; | | if (atran && !tran_ && !fix_auto_transaction_tree()) err = true; | |
| } | | } | |
| mlock_.unlock(); | | mlock_.unlock(); | |
| } else if (flush) { | | } else if (flush) { | |
|
| int32_t idx = id % PDBSLOTNUM; | | int32_t idx = id % PLDBSLOTNUM; | |
| LeafSlot* lslot = lslots_ + idx; | | LeafSlot* lslot = lslots_ + idx; | |
| mlock_.lock_writer(); | | mlock_.lock_writer(); | |
| if (!flush_leaf_cache_part(lslot)) err = true; | | if (!flush_leaf_cache_part(lslot)) err = true; | |
| InnerSlot* islot = islots_ + idx; | | InnerSlot* islot = islots_ + idx; | |
| if (islot->warm->count() > lslot->warm->count() + lslot->hot->count()
+ 1 && | | if (islot->warm->count() > lslot->warm->count() + lslot->hot->count()
+ 1 && | |
| !flush_inner_cache_part(islot)) err = true; | | !flush_inner_cache_part(islot)) err = true; | |
| mlock_.unlock(); | | mlock_.unlock(); | |
| } | | } | |
| if (rbuf != rstack) delete[] rbuf; | | if (rbuf != rstack) delete[] rbuf; | |
| if (lbuf != lstack) delete[] lbuf; | | if (lbuf != lstack) delete[] lbuf; | |
| | | | |
| skipping to change at line 1075 | | skipping to change at line 1076 | |
| if (writable && !writer_) { | | if (writable && !writer_) { | |
| set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | | set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | |
| return false; | | return false; | |
| } | | } | |
| 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[PDBRECBUFSIZ]; | | char lstack[PLDBRECBUFSIZ]; | |
| 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[PDBLEVELMAX]; | | int64_t hist[PLDBLEVELMAX]; | |
| 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[PDBRECBUFSIZ]; | | char rstack[PLDBRECBUFSIZ]; | |
| 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; | |
| if (reorg) { | | if (reorg) { | |
| if (!reorganize_tree(node, hist, hnum)) err = true; | | if (!reorganize_tree(node, hist, hnum)) err = true; | |
| if (atran && !fix_auto_transaction_tree()) err = true; | | if (atran && !fix_auto_transaction_tree()) err = true; | |
| } else if (cusage_ > pccap_) { | | } else if (cusage_ > pccap_) { | |
|
| int32_t idx = node->id % PDBSLOTNUM; | | int32_t idx = node->id % PLDBSLOTNUM; | |
| LeafSlot* lslot = lslots_ + idx; | | LeafSlot* lslot = lslots_ + idx; | |
| if (!clean_leaf_cache_part(lslot)) err = true; | | if (!clean_leaf_cache_part(lslot)) err = true; | |
| if (!flush_leaf_cache_part(lslot)) err = true; | | if (!flush_leaf_cache_part(lslot)) err = true; | |
| InnerSlot* islot = islots_ + idx; | | InnerSlot* islot = islots_ + idx; | |
| if (islot->warm->count() > lslot->warm->count() + lslot->hot->count
() + 1 && | | if (islot->warm->count() > lslot->warm->count() + lslot->hot->count
() + 1 && | |
| !flush_inner_cache_part(islot)) err = true; | | !flush_inner_cache_part(islot)) err = true; | |
| } | | } | |
| if (rbuf != rstack) delete[] rbuf; | | if (rbuf != rstack) delete[] rbuf; | |
| if (lbuf != lstack) delete[] lbuf; | | if (lbuf != lstack) delete[] lbuf; | |
| if (async && !fix_auto_synchronization()) err = true; | | if (async && !fix_auto_synchronization()) err = true; | |
| | | | |
| skipping to change at line 1200 | | skipping to change at line 1201 | |
| 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[PDBRECBUFSIZ]; | | char lstack[PLDBRECBUFSIZ]; | |
| 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[PDBLEVELMAX]; | | int64_t hist[PLDBLEVELMAX]; | |
| 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) { | |
| if (!reorganize_tree(node, hist, hnum)) err = true; | | if (!reorganize_tree(node, hist, hnum)) err = true; | |
| } else { | | } else { | |
| set_error(_KCCODELINE_, Error::BROKEN, "search failed"); | | set_error(_KCCODELINE_, Error::BROKEN, "search failed"); | |
| err = true; | | err = true; | |
| } | | } | |
| if (lbuf != lstack) delete[] lbuf; | | if (lbuf != lstack) delete[] lbuf; | |
| } | | } | |
| if (cusage_ > pccap_) { | | if (cusage_ > pccap_) { | |
|
| for (int32_t i = 0; i < PDBSLOTNUM; i++) { | | for (int32_t i = 0; i < PLDBSLOTNUM; i++) { | |
| LeafSlot* lslot = lslots_ + i; | | LeafSlot* lslot = lslots_ + i; | |
| if (!flush_leaf_cache_part(lslot)) err = true; | | if (!flush_leaf_cache_part(lslot)) err = true; | |
| } | | } | |
|
| InnerSlot* islot = islots_ + (flcnt++) % PDBSLOTNUM; | | InnerSlot* islot = islots_ + (flcnt++) % PLDBSLOTNUM; | |
| if (islot->warm->count() > 2 && !flush_inner_cache_part(islot)) err
= true; | | if (islot->warm->count() > 2 && !flush_inner_cache_part(islot)) err
= true; | |
| } | | } | |
| kit = keys.begin(); | | kit = keys.begin(); | |
| while (kit != kitend) { | | while (kit != kitend) { | |
| xfree(*kit); | | xfree(*kit); | |
| kit++; | | kit++; | |
| } | | } | |
| } | | } | |
| if (checker && !checker->check("iterate", "ending", -1, allcnt)) { | | if (checker && !checker->check("iterate", "ending", -1, allcnt)) { | |
| set_error(_KCCODELINE_, Error::LOGIC, "checker failed"); | | set_error(_KCCODELINE_, Error::LOGIC, "checker failed"); | |
| | | | |
| skipping to change at line 1500 | | skipping to change at line 1501 | |
| return !err; | | return !err; | |
| } | | } | |
| /** | | /** | |
| * Begin transaction. | | * Begin transaction. | |
| * @param hard true for physical synchronization with the device, or fals
e for logical | | * @param hard true for physical synchronization with the device, or fals
e for logical | |
| * synchronization with the file system. | | * synchronization with the file system. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool begin_transaction(bool hard = false) { | | bool begin_transaction(bool hard = false) { | |
| _assert_(true); | | _assert_(true); | |
|
| for (double wsec = 1.0 / CLOCKTICK; true; wsec *= 2) { | | uint32_t wcnt = 0; | |
| | | while (true) { | |
| mlock_.lock_writer(); | | mlock_.lock_writer(); | |
| 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 (!writer_) { | | if (!writer_) { | |
| set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | | set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | |
| mlock_.unlock(); | | mlock_.unlock(); | |
| return false; | | return false; | |
| } | | } | |
| if (!tran_) break; | | if (!tran_) break; | |
| mlock_.unlock(); | | mlock_.unlock(); | |
|
| if (wsec > 1.0) wsec = 1.0; | | if (wcnt >= PLDBLOCKBUSYLOOP) { | |
| Thread::sleep(wsec); | | Thread::chill(); | |
| | | } else { | |
| | | Thread::yield(); | |
| | | wcnt++; | |
| | | } | |
| } | | } | |
| if (!begin_transaction_impl(hard)) { | | if (!begin_transaction_impl(hard)) { | |
| mlock_.unlock(); | | mlock_.unlock(); | |
| return false; | | return false; | |
| } | | } | |
| tran_ = true; | | tran_ = true; | |
| trigger_meta(MetaTrigger::BEGINTRAN, "begin_transaction"); | | trigger_meta(MetaTrigger::BEGINTRAN, "begin_transaction"); | |
| mlock_.unlock(); | | mlock_.unlock(); | |
| return true; | | return true; | |
| } | | } | |
| | | | |
| skipping to change at line 1705 | | skipping to change at line 1711 | |
| (*strmap)["cusage_lcnt"] = strprintf("%lld", (long long)calc_leaf_cac
he_count()); | | (*strmap)["cusage_lcnt"] = strprintf("%lld", (long long)calc_leaf_cac
he_count()); | |
| if (strmap->count("cusage_lsiz") > 0) | | if (strmap->count("cusage_lsiz") > 0) | |
| (*strmap)["cusage_lsiz"] = strprintf("%lld", (long long)calc_leaf_cac
he_size()); | | (*strmap)["cusage_lsiz"] = strprintf("%lld", (long long)calc_leaf_cac
he_size()); | |
| if (strmap->count("cusage_icnt") > 0) | | if (strmap->count("cusage_icnt") > 0) | |
| (*strmap)["cusage_icnt"] = strprintf("%lld", (long long)calc_inner_ca
che_count()); | | (*strmap)["cusage_icnt"] = strprintf("%lld", (long long)calc_inner_ca
che_count()); | |
| if (strmap->count("cusage_isiz") > 0) | | if (strmap->count("cusage_isiz") > 0) | |
| (*strmap)["cusage_isiz"] = strprintf("%lld", (long long)calc_inner_ca
che_size()); | | (*strmap)["cusage_isiz"] = strprintf("%lld", (long long)calc_inner_ca
che_size()); | |
| if (strmap->count("tree_level") > 0) { | | if (strmap->count("tree_level") > 0) { | |
| Link link; | | Link link; | |
| link.ksiz = 0; | | link.ksiz = 0; | |
|
| int64_t hist[PDBLEVELMAX]; | | int64_t hist[PLDBLEVELMAX]; | |
| int32_t hnum = 0; | | int32_t hnum = 0; | |
| search_tree(&link, false, hist, &hnum); | | search_tree(&link, false, hist, &hnum); | |
| (*strmap)["tree_level"] = strprintf("%d", hnum + 1); | | (*strmap)["tree_level"] = strprintf("%d", hnum + 1); | |
| } | | } | |
| return true; | | return true; | |
| } | | } | |
| /** | | /** | |
| * Create a cursor object. | | * Create a cursor object. | |
| * @return the return value is the created cursor object. | | * @return the return value is the created cursor object. | |
| * @note Because the object of the return value is allocated by the const
ructor, it should be | | * @note Because the object of the return value is allocated by the const
ructor, it should be | |
| | | | |
| skipping to change at line 1766 | | skipping to change at line 1772 | |
| * @param apow the power of the alignment of record size. | | * @param apow the power of the alignment of record size. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool tune_alignment(int8_t apow) { | | bool tune_alignment(int8_t apow) { | |
| _assert_(true); | | _assert_(true); | |
| ScopedSpinRWLock lock(&mlock_, true); | | ScopedSpinRWLock lock(&mlock_, true); | |
| if (omode_ != 0) { | | if (omode_ != 0) { | |
| set_error(_KCCODELINE_, Error::INVALID, "already opened"); | | set_error(_KCCODELINE_, Error::INVALID, "already opened"); | |
| return false; | | return false; | |
| } | | } | |
|
| apow_ = apow >= 0 ? apow : PDBDEFAPOW; | | apow_ = apow >= 0 ? apow : PLDBDEFAPOW; | |
| 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. | |
| * @param fpow the power of the capacity of the free block pool. | | * @param fpow the power of the capacity of the free block pool. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool tune_fbp(int8_t fpow) { | | bool tune_fbp(int8_t fpow) { | |
| _assert_(true); | | _assert_(true); | |
| ScopedSpinRWLock lock(&mlock_, true); | | ScopedSpinRWLock lock(&mlock_, true); | |
| if (omode_ != 0) { | | if (omode_ != 0) { | |
| set_error(_KCCODELINE_, Error::INVALID, "already opened"); | | set_error(_KCCODELINE_, Error::INVALID, "already opened"); | |
| return false; | | return false; | |
| } | | } | |
|
| fpow_ = fpow >= 0 ? fpow : PDBDEFFPOW; | | fpow_ = fpow >= 0 ? fpow : PLDBDEFFPOW; | |
| return true; | | return true; | |
| } | | } | |
| /** | | /** | |
| * Set the optional features. | | * Set the optional features. | |
| * @param opts the optional features by bitwise-or: BasicDB::TSMALL to us
e 32-bit addressing, | | * @param opts the optional features by bitwise-or: BasicDB::TSMALL to us
e 32-bit addressing, | |
| * BasicDB::TLINEAR to use linear collision chaining, BasicDB::TCOMPRESS
to compress each | | * BasicDB::TLINEAR to use linear collision chaining, BasicDB::TCOMPRESS
to compress each | |
| * record. | | * record. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool tune_options(int8_t opts) { | | bool tune_options(int8_t opts) { | |
| | | | |
| skipping to change at line 1813 | | skipping to change at line 1819 | |
| * @param bnum the number of buckets of the hash table. | | * @param bnum the number of buckets of the hash table. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool tune_buckets(int64_t bnum) { | | bool tune_buckets(int64_t bnum) { | |
| _assert_(true); | | _assert_(true); | |
| ScopedSpinRWLock lock(&mlock_, true); | | ScopedSpinRWLock lock(&mlock_, true); | |
| if (omode_ != 0) { | | if (omode_ != 0) { | |
| set_error(_KCCODELINE_, Error::INVALID, "already opened"); | | set_error(_KCCODELINE_, Error::INVALID, "already opened"); | |
| return false; | | return false; | |
| } | | } | |
|
| bnum_ = bnum > 0 ? bnum : PDBDEFBNUM; | | bnum_ = bnum > 0 ? bnum : PLDBDEFBNUM; | |
| return true; | | return true; | |
| } | | } | |
| /** | | /** | |
| * Set the size of each page. | | * Set the size of each page. | |
| * @param psiz the size of each page. | | * @param psiz the size of each page. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool tune_page(int32_t psiz) { | | bool tune_page(int32_t psiz) { | |
| _assert_(true); | | _assert_(true); | |
| ScopedSpinRWLock lock(&mlock_, true); | | ScopedSpinRWLock lock(&mlock_, true); | |
| if (omode_ != 0) { | | if (omode_ != 0) { | |
| set_error(_KCCODELINE_, Error::INVALID, "already opened"); | | set_error(_KCCODELINE_, Error::INVALID, "already opened"); | |
| return false; | | return false; | |
| } | | } | |
|
| psiz_ = psiz > 0 ? psiz : PDBDEFPSIZ; | | psiz_ = psiz > 0 ? psiz : PLDBDEFPSIZ; | |
| return true; | | return true; | |
| } | | } | |
| /** | | /** | |
| * Set the size of the internal memory-mapped region. | | * Set the size of the internal memory-mapped region. | |
| * @param msiz the size of the internal memory-mapped region. | | * @param msiz the size of the internal memory-mapped region. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool tune_map(int64_t msiz) { | | bool tune_map(int64_t msiz) { | |
| _assert_(true); | | _assert_(true); | |
| ScopedSpinRWLock lock(&mlock_, true); | | ScopedSpinRWLock lock(&mlock_, true); | |
| | | | |
| skipping to change at line 1871 | | skipping to change at line 1877 | |
| * @param pccap the capacity size of the page cache. | | * @param pccap the capacity size of the page cache. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool tune_page_cache(int64_t pccap) { | | bool tune_page_cache(int64_t pccap) { | |
| _assert_(true); | | _assert_(true); | |
| ScopedSpinRWLock lock(&mlock_, true); | | ScopedSpinRWLock lock(&mlock_, true); | |
| if (omode_ != 0) { | | if (omode_ != 0) { | |
| set_error(_KCCODELINE_, Error::INVALID, "already opened"); | | set_error(_KCCODELINE_, Error::INVALID, "already opened"); | |
| return false; | | return false; | |
| } | | } | |
|
| pccap_ = pccap > 0 ? pccap : PDBDEFPCCAP; | | pccap_ = pccap > 0 ? pccap : PLDBDEFPCCAP; | |
| return true; | | return true; | |
| } | | } | |
| /** | | /** | |
| * Set the data compressor. | | * Set the data compressor. | |
| * @param comp the data compressor object. | | * @param comp the data compressor object. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool tune_compressor(Compressor* comp) { | | bool tune_compressor(Compressor* comp) { | |
| _assert_(comp); | | _assert_(comp); | |
| ScopedSpinRWLock lock(&mlock_, true); | | ScopedSpinRWLock lock(&mlock_, true); | |
| | | | |
| skipping to change at line 2128 | | skipping to change at line 2134 | |
| */ | | */ | |
| struct InnerSlot { | | struct InnerSlot { | |
| SpinLock lock; ///< lock | | SpinLock lock; ///< lock | |
| InnerCache* warm; ///< warm cache | | InnerCache* warm; ///< warm cache | |
| }; | | }; | |
| /** | | /** | |
| * Open the leaf cache. | | * Open the leaf cache. | |
| */ | | */ | |
| void create_leaf_cache() { | | void create_leaf_cache() { | |
| _assert_(true); | | _assert_(true); | |
|
| int64_t bnum = bnum_ / PDBSLOTNUM + 1; | | int64_t bnum = bnum_ / PLDBSLOTNUM + 1; | |
| if (bnum < INT8_MAX) bnum = INT8_MAX; | | if (bnum < INT8MAX) bnum = INT8MAX; | |
| bnum = nearbyprime(bnum); | | bnum = nearbyprime(bnum); | |
|
| for (int32_t i = 0; i < PDBSLOTNUM; i++) { | | for (int32_t i = 0; i < PLDBSLOTNUM; i++) { | |
| lslots_[i].hot = new LeafCache(bnum); | | lslots_[i].hot = new LeafCache(bnum); | |
| lslots_[i].warm = new LeafCache(bnum); | | lslots_[i].warm = new LeafCache(bnum); | |
| } | | } | |
| } | | } | |
| /** | | /** | |
| * Close the leaf cache. | | * Close the leaf cache. | |
| */ | | */ | |
| void delete_leaf_cache() { | | void delete_leaf_cache() { | |
| _assert_(true); | | _assert_(true); | |
|
| for (int32_t i = PDBSLOTNUM - 1; i >= 0; i--) { | | for (int32_t i = PLDBSLOTNUM - 1; i >= 0; i--) { | |
| LeafSlot* slot = lslots_ + i; | | LeafSlot* slot = lslots_ + i; | |
| delete slot->warm; | | delete slot->warm; | |
| delete slot->hot; | | delete slot->hot; | |
| } | | } | |
| } | | } | |
| /** | | /** | |
| * Remove all leaf nodes from the leaf cache. | | * Remove all leaf nodes from the leaf cache. | |
| * @param save whether to save dirty nodes. | | * @param save whether to save dirty nodes. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool flush_leaf_cache(bool save) { | | bool flush_leaf_cache(bool save) { | |
| _assert_(true); | | _assert_(true); | |
| bool err = false; | | bool err = false; | |
|
| for (int32_t i = PDBSLOTNUM - 1; i >= 0; i--) { | | for (int32_t i = PLDBSLOTNUM - 1; i >= 0; i--) { | |
| LeafSlot* slot = lslots_ + i; | | LeafSlot* slot = lslots_ + i; | |
| typename LeafCache::Iterator it = slot->warm->begin(); | | typename LeafCache::Iterator it = slot->warm->begin(); | |
| typename LeafCache::Iterator itend = slot->warm->end(); | | typename LeafCache::Iterator itend = slot->warm->end(); | |
| while (it != itend) { | | while (it != itend) { | |
| LeafNode* node = it.value(); | | LeafNode* node = it.value(); | |
| it++; | | it++; | |
| if (!flush_leaf_node(node, save)) err = true; | | if (!flush_leaf_node(node, save)) err = true; | |
| } | | } | |
| it = slot->hot->begin(); | | it = slot->hot->begin(); | |
| itend = slot->hot->end(); | | itend = slot->hot->end(); | |
| | | | |
| skipping to change at line 2198 | | skipping to change at line 2204 | |
| } | | } | |
| return !err; | | return !err; | |
| } | | } | |
| /** | | /** | |
| * Clean all of the leaf cache. | | * Clean all of the leaf cache. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool clean_leaf_cache() { | | bool clean_leaf_cache() { | |
| _assert_(true); | | _assert_(true); | |
| bool err = false; | | bool err = false; | |
|
| for (int32_t i = 0; i < PDBSLOTNUM; i++) { | | for (int32_t i = 0; i < PLDBSLOTNUM; i++) { | |
| LeafSlot* slot = lslots_ + i; | | LeafSlot* slot = lslots_ + i; | |
| ScopedSpinLock lock(&slot->lock); | | ScopedSpinLock lock(&slot->lock); | |
| typename LeafCache::Iterator it = slot->warm->begin(); | | typename LeafCache::Iterator it = slot->warm->begin(); | |
| typename LeafCache::Iterator itend = slot->warm->end(); | | typename LeafCache::Iterator itend = slot->warm->end(); | |
| while (it != itend) { | | while (it != itend) { | |
| LeafNode* node = it.value(); | | LeafNode* node = it.value(); | |
| if (!save_leaf_node(node)) err = true; | | if (!save_leaf_node(node)) err = true; | |
| it++; | | it++; | |
| } | | } | |
| it = slot->hot->begin(); | | it = slot->hot->begin(); | |
| | | | |
| skipping to change at line 2247 | | skipping to change at line 2253 | |
| * Create a new leaf node. | | * Create a new leaf node. | |
| * @param prev the ID of the previous node. | | * @param prev the ID of the previous node. | |
| * @param next the ID of the next node. | | * @param next the ID of the next node. | |
| * @return the created leaf node. | | * @return the created leaf node. | |
| */ | | */ | |
| LeafNode* create_leaf_node(int64_t prev, int64_t next) { | | LeafNode* create_leaf_node(int64_t prev, int64_t next) { | |
| _assert_(true); | | _assert_(true); | |
| LeafNode* node = new LeafNode; | | LeafNode* node = new LeafNode; | |
| node->id = ++lcnt_; | | node->id = ++lcnt_; | |
| node->size = sizeof(int32_t) * 2; | | node->size = sizeof(int32_t) * 2; | |
|
| node->recs.reserve(PDBDEFLINUM); | | node->recs.reserve(PLDBDEFLINUM); | |
| node->prev = prev; | | node->prev = prev; | |
| node->next = next; | | node->next = next; | |
| node->hot = false; | | node->hot = false; | |
| node->dirty = true; | | node->dirty = true; | |
| node->dead = false; | | node->dead = false; | |
|
| int32_t sidx = node->id % PDBSLOTNUM; | | int32_t sidx = node->id % PLDBSLOTNUM; | |
| LeafSlot* slot = lslots_ + sidx; | | LeafSlot* slot = lslots_ + sidx; | |
| slot->warm->set(node->id, node, LeafCache::MLAST); | | slot->warm->set(node->id, node, LeafCache::MLAST); | |
| cusage_ += node->size; | | cusage_ += node->size; | |
| return node; | | return node; | |
| } | | } | |
| /** | | /** | |
| * Remove a leaf node from the cache. | | * Remove a leaf node from the cache. | |
| * @param node the leaf node. | | * @param node the leaf node. | |
| * @param save whether to save dirty node. | | * @param save whether to save dirty node. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| | | | |
| skipping to change at line 2276 | | skipping to change at line 2282 | |
| _assert_(node); | | _assert_(node); | |
| bool err = false; | | bool err = false; | |
| if (save && !save_leaf_node(node)) err = true; | | if (save && !save_leaf_node(node)) err = true; | |
| typename RecordArray::const_iterator rit = node->recs.begin(); | | typename RecordArray::const_iterator rit = node->recs.begin(); | |
| typename RecordArray::const_iterator ritend = node->recs.end(); | | typename RecordArray::const_iterator ritend = node->recs.end(); | |
| while (rit != ritend) { | | while (rit != ritend) { | |
| Record* rec = *rit; | | Record* rec = *rit; | |
| xfree(rec); | | xfree(rec); | |
| rit++; | | rit++; | |
| } | | } | |
|
| int32_t sidx = node->id % PDBSLOTNUM; | | int32_t sidx = node->id % PLDBSLOTNUM; | |
| LeafSlot* slot = lslots_ + sidx; | | LeafSlot* slot = lslots_ + sidx; | |
| if (node->hot) { | | if (node->hot) { | |
| slot->hot->remove(node->id); | | slot->hot->remove(node->id); | |
| } else { | | } else { | |
| slot->warm->remove(node->id); | | slot->warm->remove(node->id); | |
| } | | } | |
| cusage_ -= node->size; | | cusage_ -= node->size; | |
| delete node; | | delete node; | |
| return !err; | | return !err; | |
| } | | } | |
| | | | |
| skipping to change at line 2298 | | skipping to change at line 2304 | |
| * Save a leaf node. | | * Save a leaf node. | |
| * @param node the leaf node. | | * @param node the leaf node. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool save_leaf_node(LeafNode* node) { | | bool save_leaf_node(LeafNode* node) { | |
| _assert_(node); | | _assert_(node); | |
| ScopedSpinRWLock lock(&node->lock, false); | | ScopedSpinRWLock lock(&node->lock, false); | |
| if (!node->dirty) return true; | | if (!node->dirty) return true; | |
| bool err = false; | | bool err = false; | |
| char hbuf[NUMBUFSIZ]; | | char hbuf[NUMBUFSIZ]; | |
|
| size_t hsiz = std::sprintf(hbuf, "%c%llX", PDBLNPREFIX, (long long)node
->id); | | size_t hsiz = std::sprintf(hbuf, "%c%llX", PLDBLNPREFIX, (long long)nod
e->id); | |
| if (node->dead) { | | if (node->dead) { | |
| if (!db_.remove(hbuf, hsiz) && db_.error().code() != Error::NOREC) er
r = true; | | if (!db_.remove(hbuf, hsiz) && db_.error().code() != Error::NOREC) er
r = true; | |
| } else { | | } else { | |
| char* rbuf = new char[node->size]; | | char* rbuf = new char[node->size]; | |
| char* wp = rbuf; | | char* wp = rbuf; | |
| wp += writevarnum(wp, node->prev); | | wp += writevarnum(wp, node->prev); | |
| wp += writevarnum(wp, node->next); | | wp += writevarnum(wp, node->next); | |
| typename RecordArray::const_iterator rit = node->recs.begin(); | | typename RecordArray::const_iterator rit = node->recs.begin(); | |
| typename RecordArray::const_iterator ritend = node->recs.end(); | | typename RecordArray::const_iterator ritend = node->recs.end(); | |
| while (rit != ritend) { | | while (rit != ritend) { | |
| | | | |
| skipping to change at line 2333 | | skipping to change at line 2339 | |
| return !err; | | return !err; | |
| } | | } | |
| /** | | /** | |
| * Load a leaf node. | | * Load a leaf node. | |
| * @param id the ID number of the leaf node. | | * @param id the ID number of the leaf node. | |
| * @param prom whether to promote the warm cache. | | * @param prom whether to promote the warm cache. | |
| * @return the loaded leaf node. | | * @return the loaded leaf node. | |
| */ | | */ | |
| LeafNode* load_leaf_node(int64_t id, bool prom) { | | LeafNode* load_leaf_node(int64_t id, bool prom) { | |
| _assert_(id > 0); | | _assert_(id > 0); | |
|
| int32_t sidx = id % PDBSLOTNUM; | | int32_t sidx = id % PLDBSLOTNUM; | |
| LeafSlot* slot = lslots_ + sidx; | | LeafSlot* slot = lslots_ + sidx; | |
| ScopedSpinLock lock(&slot->lock); | | ScopedSpinLock lock(&slot->lock); | |
| LeafNode** np = slot->hot->get(id, LeafCache::MLAST); | | LeafNode** np = slot->hot->get(id, LeafCache::MLAST); | |
| if (np) return *np; | | if (np) return *np; | |
| if (prom) { | | if (prom) { | |
|
| if (slot->hot->count() * PDBWARMRATIO > slot->warm->count() + PDBWARM
RATIO) { | | if (slot->hot->count() * PLDBWARMRATIO > slot->warm->count() + PLDBWA
RMRATIO) { | |
| slot->hot->first_value()->hot = false; | | slot->hot->first_value()->hot = false; | |
| slot->hot->migrate(slot->hot->first_key(), slot->warm, LeafCache::M
LAST); | | slot->hot->migrate(slot->hot->first_key(), slot->warm, LeafCache::M
LAST); | |
| } | | } | |
| np = slot->warm->migrate(id, slot->hot, LeafCache::MLAST); | | np = slot->warm->migrate(id, slot->hot, LeafCache::MLAST); | |
| if (np) { | | if (np) { | |
| (*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", PDBLNPREFIX, (long long)id); | | size_t hsiz = std::sprintf(hbuf, "%c%llX", PLDBLNPREFIX, (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; | |
| | | | |
| skipping to change at line 2551 | | skipping to change at line 2557 | |
| } | | } | |
| escape_cursors(node->id, node->next, *mid); | | escape_cursors(node->id, node->next, *mid); | |
| recs.erase(mid, ritend); | | recs.erase(mid, ritend); | |
| return newnode; | | return newnode; | |
| } | | } | |
| /** | | /** | |
| * Open the inner cache. | | * Open the inner cache. | |
| */ | | */ | |
| void create_inner_cache() { | | void create_inner_cache() { | |
| _assert_(true); | | _assert_(true); | |
|
| int64_t bnum = (bnum_ / PDBAVGWAY) / PDBSLOTNUM + 1; | | int64_t bnum = (bnum_ / PLDBAVGWAY) / PLDBSLOTNUM + 1; | |
| if (bnum < INT8_MAX) bnum = INT8_MAX; | | if (bnum < INT8MAX) bnum = INT8MAX; | |
| bnum = nearbyprime(bnum); | | bnum = nearbyprime(bnum); | |
|
| for (int32_t i = 0; i < PDBSLOTNUM; i++) { | | for (int32_t i = 0; i < PLDBSLOTNUM; i++) { | |
| islots_[i].warm = new InnerCache(bnum); | | islots_[i].warm = new InnerCache(bnum); | |
| } | | } | |
| } | | } | |
| /** | | /** | |
| * Close the inner cache. | | * Close the inner cache. | |
| */ | | */ | |
| void delete_inner_cache() { | | void delete_inner_cache() { | |
| _assert_(true); | | _assert_(true); | |
|
| for (int32_t i = PDBSLOTNUM - 1; i >= 0; i--) { | | for (int32_t i = PLDBSLOTNUM - 1; i >= 0; i--) { | |
| InnerSlot* slot = islots_ + i; | | InnerSlot* slot = islots_ + i; | |
| delete slot->warm; | | delete slot->warm; | |
| } | | } | |
| } | | } | |
| /** | | /** | |
| * Remove all inner nodes from the inner cache. | | * Remove all inner nodes from the inner cache. | |
| * @param save whether to save dirty nodes. | | * @param save whether to save dirty nodes. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool flush_inner_cache(bool save) { | | bool flush_inner_cache(bool save) { | |
| _assert_(true); | | _assert_(true); | |
| bool err = false; | | bool err = false; | |
|
| for (int32_t i = PDBSLOTNUM - 1; i >= 0; i--) { | | for (int32_t i = PLDBSLOTNUM - 1; i >= 0; i--) { | |
| InnerSlot* slot = islots_ + i; | | InnerSlot* slot = islots_ + i; | |
| typename InnerCache::Iterator it = slot->warm->begin(); | | typename InnerCache::Iterator it = slot->warm->begin(); | |
| typename InnerCache::Iterator itend = slot->warm->end(); | | typename InnerCache::Iterator itend = slot->warm->end(); | |
| while (it != itend) { | | while (it != itend) { | |
| InnerNode* node = it.value(); | | InnerNode* node = it.value(); | |
| it++; | | it++; | |
| if (!flush_inner_node(node, save)) err = true; | | if (!flush_inner_node(node, save)) err = true; | |
| } | | } | |
| } | | } | |
| return !err; | | return !err; | |
| | | | |
| skipping to change at line 2609 | | skipping to change at line 2615 | |
| } | | } | |
| return !err; | | return !err; | |
| } | | } | |
| /** | | /** | |
| * Clean all of the inner cache. | | * Clean all of the inner cache. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool clean_inner_cache() { | | bool clean_inner_cache() { | |
| _assert_(true); | | _assert_(true); | |
| bool err = false; | | bool err = false; | |
|
| for (int32_t i = 0; i < PDBSLOTNUM; i++) { | | for (int32_t i = 0; i < PLDBSLOTNUM; i++) { | |
| InnerSlot* slot = islots_ + i; | | InnerSlot* slot = islots_ + i; | |
| ScopedSpinLock lock(&slot->lock); | | ScopedSpinLock lock(&slot->lock); | |
| typename InnerCache::Iterator it = slot->warm->begin(); | | typename InnerCache::Iterator it = slot->warm->begin(); | |
| typename InnerCache::Iterator itend = slot->warm->end(); | | typename InnerCache::Iterator itend = slot->warm->end(); | |
| while (it != itend) { | | while (it != itend) { | |
| InnerNode* node = it.value(); | | InnerNode* node = it.value(); | |
| if (!save_inner_node(node)) err = true; | | if (!save_inner_node(node)) err = true; | |
| it++; | | it++; | |
| } | | } | |
| } | | } | |
| return !err; | | return !err; | |
| } | | } | |
| /** | | /** | |
| * Create a new inner node. | | * Create a new inner node. | |
| * @param heir the ID of the child before the first link. | | * @param heir the ID of the child before the first link. | |
| * @return the created inner node. | | * @return the created inner node. | |
| */ | | */ | |
| InnerNode* create_inner_node(int64_t heir) { | | InnerNode* create_inner_node(int64_t heir) { | |
| _assert_(true); | | _assert_(true); | |
| InnerNode* node = new InnerNode; | | InnerNode* node = new InnerNode; | |
|
| node->id = ++icnt_ + PDBINIDBASE; | | node->id = ++icnt_ + PLDBINIDBASE; | |
| node->heir = heir; | | node->heir = heir; | |
|
| node->links.reserve(PDBDEFIINUM); | | node->links.reserve(PLDBDEFIINUM); | |
| node->size = sizeof(int64_t); | | node->size = sizeof(int64_t); | |
| node->dirty = true; | | node->dirty = true; | |
| node->dead = false; | | node->dead = false; | |
|
| int32_t sidx = node->id % PDBSLOTNUM; | | int32_t sidx = node->id % PLDBSLOTNUM; | |
| InnerSlot* slot = islots_ + sidx; | | InnerSlot* slot = islots_ + sidx; | |
| slot->warm->set(node->id, node, InnerCache::MLAST); | | slot->warm->set(node->id, node, InnerCache::MLAST); | |
| cusage_ += node->size; | | cusage_ += node->size; | |
| return node; | | return node; | |
| } | | } | |
| /** | | /** | |
| * Remove an inner node from the cache. | | * Remove an inner node from the cache. | |
| * @param node the inner node. | | * @param node the inner node. | |
| * @param save whether to save dirty node. | | * @param save whether to save dirty node. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| | | | |
| skipping to change at line 2659 | | skipping to change at line 2665 | |
| _assert_(node); | | _assert_(node); | |
| bool err = false; | | bool err = false; | |
| if (save && !save_inner_node(node)) err = true; | | if (save && !save_inner_node(node)) err = true; | |
| typename LinkArray::const_iterator lit = node->links.begin(); | | typename LinkArray::const_iterator lit = node->links.begin(); | |
| typename LinkArray::const_iterator litend = node->links.end(); | | typename LinkArray::const_iterator litend = node->links.end(); | |
| while (lit != litend) { | | while (lit != litend) { | |
| Link* link = *lit; | | Link* link = *lit; | |
| xfree(link); | | xfree(link); | |
| lit++; | | lit++; | |
| } | | } | |
|
| int32_t sidx = node->id % PDBSLOTNUM; | | int32_t sidx = node->id % PLDBSLOTNUM; | |
| InnerSlot* slot = islots_ + sidx; | | InnerSlot* slot = islots_ + sidx; | |
| slot->warm->remove(node->id); | | slot->warm->remove(node->id); | |
| cusage_ -= node->size; | | cusage_ -= node->size; | |
| delete node; | | delete node; | |
| return !err; | | return !err; | |
| } | | } | |
| /** | | /** | |
| * Save a inner node. | | * Save a inner node. | |
| * @param node the inner node. | | * @param node the inner node. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool save_inner_node(InnerNode* node) { | | bool save_inner_node(InnerNode* node) { | |
| _assert_(true); | | _assert_(true); | |
| if (!node->dirty) return true; | | if (!node->dirty) return true; | |
| bool err = false; | | bool err = false; | |
| char hbuf[NUMBUFSIZ]; | | char hbuf[NUMBUFSIZ]; | |
| size_t hsiz = std::sprintf(hbuf, "%c%llX", | | size_t hsiz = std::sprintf(hbuf, "%c%llX", | |
|
| PDBINPREFIX, (long long)(node->id - PDBINIDB
ASE)); | | PLDBINPREFIX, (long long)(node->id - PLDBINI
DBASE)); | |
| if (node->dead) { | | if (node->dead) { | |
| if (!db_.remove(hbuf, hsiz) && db_.error().code() != Error::NOREC) er
r = true; | | if (!db_.remove(hbuf, hsiz) && db_.error().code() != Error::NOREC) er
r = true; | |
| } else { | | } else { | |
| char* rbuf = new char[node->size]; | | char* rbuf = new char[node->size]; | |
| char* wp = rbuf; | | char* wp = rbuf; | |
| wp += writevarnum(wp, node->heir); | | wp += writevarnum(wp, node->heir); | |
| typename LinkArray::const_iterator lit = node->links.begin(); | | typename LinkArray::const_iterator lit = node->links.begin(); | |
| typename LinkArray::const_iterator litend = node->links.end(); | | typename LinkArray::const_iterator litend = node->links.end(); | |
| while (lit != litend) { | | while (lit != litend) { | |
| Link* link = *lit; | | Link* link = *lit; | |
| | | | |
| skipping to change at line 2708 | | skipping to change at line 2714 | |
| node->dirty = false; | | node->dirty = false; | |
| return !err; | | return !err; | |
| } | | } | |
| /** | | /** | |
| * Load an inner node. | | * Load an inner node. | |
| * @param id the ID number of the inner node. | | * @param id the ID number of the inner node. | |
| * @return the loaded inner node. | | * @return the loaded inner node. | |
| */ | | */ | |
| InnerNode* load_inner_node(int64_t id) { | | InnerNode* load_inner_node(int64_t id) { | |
| _assert_(id > 0); | | _assert_(id > 0); | |
|
| int32_t sidx = id % PDBSLOTNUM; | | int32_t sidx = id % PLDBSLOTNUM; | |
| 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", PDBINPREFIX, (long long)(id
- PDBINIDBASE)); | | size_t hsiz = std::sprintf(hbuf, "%c%llX", PLDBINPREFIX, (long long)(id
- PLDBINIDBASE)); | |
| 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; | |
| | | | |
| skipping to change at line 2792 | | skipping to change at line 2798 | |
| * @param link the link containing the key only. | | * @param link the link containing the key only. | |
| * @param prom whether to promote the warm cache. | | * @param prom whether to promote the warm cache. | |
| * @param hist the array of visiting history. | | * @param hist the array of visiting history. | |
| * @param hnp the pointer to the variable into which the number of the hi
story is assigned. | | * @param hnp the pointer to the variable into which the number of the hi
story is assigned. | |
| * @return the corresponding leaf node, or NULL on failure. | | * @return the corresponding leaf node, or NULL on failure. | |
| */ | | */ | |
| LeafNode* search_tree(Link* link, bool prom, int64_t* hist, int32_t* hnp)
{ | | LeafNode* search_tree(Link* link, bool prom, int64_t* hist, int32_t* hnp)
{ | |
| _assert_(link && hist && hnp); | | _assert_(link && hist && hnp); | |
| int64_t id = root_; | | int64_t id = root_; | |
| int32_t hnum = 0; | | int32_t hnum = 0; | |
|
| while (id > PDBINIDBASE) { | | while (id > PLDBINIDBASE) { | |
| InnerNode* node = load_inner_node(id); | | InnerNode* node = load_inner_node(id); | |
| if (!node) { | | if (!node) { | |
| set_error(_KCCODELINE_, Error::BROKEN, "missing inner node"); | | set_error(_KCCODELINE_, Error::BROKEN, "missing inner node"); | |
| db_.report(_KCCODELINE_, Logger::WARN, "id=%lld", (long long)id); | | db_.report(_KCCODELINE_, Logger::WARN, "id=%lld", (long long)id); | |
| return NULL; | | return NULL; | |
| } | | } | |
| hist[hnum++] = id; | | hist[hnum++] = id; | |
| const LinkArray& links = node->links; | | const LinkArray& links = node->links; | |
| typename LinkArray::const_iterator litbeg = links.begin(); | | typename LinkArray::const_iterator litbeg = links.begin(); | |
| typename LinkArray::const_iterator litend = links.end(); | | typename LinkArray::const_iterator litend = links.end(); | |
| | | | |
| skipping to change at line 2854 | | skipping to change at line 2860 | |
| InnerNode* inode = load_inner_node(parent); | | InnerNode* inode = load_inner_node(parent); | |
| if (!inode) { | | if (!inode) { | |
| set_error(_KCCODELINE_, Error::BROKEN, "missing inner node"); | | set_error(_KCCODELINE_, Error::BROKEN, "missing inner node"); | |
| db_.report(_KCCODELINE_, Logger::WARN, "id=%lld", (long long)pare
nt); | | db_.report(_KCCODELINE_, Logger::WARN, "id=%lld", (long long)pare
nt); | |
| delete[] kbuf; | | delete[] kbuf; | |
| return false; | | return false; | |
| } | | } | |
| add_link_inner_node(inode, child, kbuf, ksiz); | | add_link_inner_node(inode, child, kbuf, ksiz); | |
| delete[] kbuf; | | delete[] kbuf; | |
| LinkArray& links = inode->links; | | LinkArray& links = inode->links; | |
|
| if (inode->size <= psiz_ || links.size() <= PDBINLINKMIN) break; | | if (inode->size <= psiz_ || links.size() <= PLDBINLINKMIN) break; | |
| typename LinkArray::iterator litbeg = links.begin(); | | typename LinkArray::iterator litbeg = links.begin(); | |
| typename LinkArray::iterator mid = litbeg + links.size() / 2; | | typename LinkArray::iterator mid = litbeg + links.size() / 2; | |
| Link* link = *mid; | | Link* link = *mid; | |
| InnerNode* newinode = create_inner_node(link->child); | | InnerNode* newinode = create_inner_node(link->child); | |
| heir = inode->id; | | heir = inode->id; | |
| child = newinode->id; | | child = newinode->id; | |
| char* dbuf = (char*)link + sizeof(*link); | | char* dbuf = (char*)link + sizeof(*link); | |
| ksiz = link->ksiz; | | ksiz = link->ksiz; | |
| kbuf = new char[ksiz]; | | kbuf = new char[ksiz]; | |
| std::memcpy(kbuf, dbuf, ksiz); | | std::memcpy(kbuf, dbuf, ksiz); | |
| | | | |
| skipping to change at line 2976 | | skipping to change at line 2982 | |
| if (!pnode) { | | if (!pnode) { | |
| set_error(_KCCODELINE_, Error::BROKEN, "missing inner node"); | | set_error(_KCCODELINE_, Error::BROKEN, "missing inner node"); | |
| db_.report(_KCCODELINE_, Logger::WARN, "id=%lld", (long long)hist
[hnum]); | | db_.report(_KCCODELINE_, Logger::WARN, "id=%lld", (long long)hist
[hnum]); | |
| return false; | | return false; | |
| } | | } | |
| node->dead = true; | | node->dead = true; | |
| return sub_link_tree(pnode, node->id, hist, hnum); | | return sub_link_tree(pnode, node->id, hist, hnum); | |
| } | | } | |
| node->dead = true; | | node->dead = true; | |
| root_ = child; | | root_ = child; | |
|
| while (child > PDBINIDBASE) { | | while (child > PLDBINIDBASE) { | |
| node = load_inner_node(child); | | node = load_inner_node(child); | |
| if (!node) { | | if (!node) { | |
| set_error(_KCCODELINE_, Error::BROKEN, "missing inner node"); | | set_error(_KCCODELINE_, Error::BROKEN, "missing inner node"); | |
| db_.report(_KCCODELINE_, Logger::WARN, "id=%lld", (long long)chil
d); | | db_.report(_KCCODELINE_, Logger::WARN, "id=%lld", (long long)chil
d); | |
| return false; | | return false; | |
| } | | } | |
| if (node->dead) { | | if (node->dead) { | |
| child = node->heir; | | child = node->heir; | |
| root_ = child; | | root_ = child; | |
| } else { | | } else { | |
| | | | |
| skipping to change at line 3010 | | skipping to change at line 3016 | |
| } | | } | |
| set_error(_KCCODELINE_, Error::BROKEN, "invalid tree"); | | set_error(_KCCODELINE_, Error::BROKEN, "invalid tree"); | |
| return false; | | return false; | |
| } | | } | |
| /** | | /** | |
| * Dump the meta data into the file. | | * Dump the meta data into the file. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool dump_meta() { | | bool dump_meta() { | |
| _assert_(true); | | _assert_(true); | |
|
| char head[PDBHEADSIZ]; | | char head[PLDBHEADSIZ]; | |
| std::memset(head, 0, sizeof(head)); | | std::memset(head, 0, sizeof(head)); | |
| char* wp = head; | | char* wp = head; | |
| if (reccomp_.comp == LEXICALCOMP) { | | if (reccomp_.comp == LEXICALCOMP) { | |
| *(uint8_t*)(wp++) = 0x10; | | *(uint8_t*)(wp++) = 0x10; | |
| } else if (reccomp_.comp == DECIMALCOMP) { | | } else if (reccomp_.comp == DECIMALCOMP) { | |
| *(uint8_t*)(wp++) = 0x11; | | *(uint8_t*)(wp++) = 0x11; | |
| } else if (reccomp_.comp == LEXICALDESCCOMP) { | | } else if (reccomp_.comp == LEXICALDESCCOMP) { | |
| *(uint8_t*)(wp++) = 0x18; | | *(uint8_t*)(wp++) = 0x18; | |
| } else if (reccomp_.comp == DECIMALDESCCOMP) { | | } else if (reccomp_.comp == DECIMALDESCCOMP) { | |
| *(uint8_t*)(wp++) = 0x19; | | *(uint8_t*)(wp++) = 0x19; | |
| } else { | | } else { | |
| *(uint8_t*)(wp++) = 0xff; | | *(uint8_t*)(wp++) = 0xff; | |
| } | | } | |
|
| wp = head + PDBMOFFNUMS; | | wp = head + PLDBMOFFNUMS; | |
| uint64_t num = hton64(psiz_); | | uint64_t num = hton64(psiz_); | |
| std::memcpy(wp, &num, sizeof(num)); | | std::memcpy(wp, &num, sizeof(num)); | |
| wp += sizeof(num); | | wp += sizeof(num); | |
| num = hton64(root_); | | num = hton64(root_); | |
| std::memcpy(wp, &num, sizeof(num)); | | std::memcpy(wp, &num, sizeof(num)); | |
| wp += sizeof(num); | | wp += sizeof(num); | |
| num = hton64(first_); | | num = hton64(first_); | |
| std::memcpy(wp, &num, sizeof(num)); | | std::memcpy(wp, &num, sizeof(num)); | |
| wp += sizeof(num); | | wp += sizeof(num); | |
| num = hton64(last_); | | num = hton64(last_); | |
| | | | |
| skipping to change at line 3051 | | skipping to change at line 3057 | |
| std::memcpy(wp, &num, sizeof(num)); | | std::memcpy(wp, &num, sizeof(num)); | |
| wp += sizeof(num); | | wp += sizeof(num); | |
| num = hton64(count_); | | num = hton64(count_); | |
| std::memcpy(wp, &num, sizeof(num)); | | std::memcpy(wp, &num, sizeof(num)); | |
| wp += sizeof(num); | | wp += sizeof(num); | |
| num = hton64(bnum_); | | num = hton64(bnum_); | |
| std::memcpy(wp, &num, sizeof(num)); | | std::memcpy(wp, &num, sizeof(num)); | |
| wp += sizeof(num); | | wp += sizeof(num); | |
| std::memcpy(wp, "\x0a\x42\x6f\x6f\x66\x79\x21\x0a", sizeof(num)); | | std::memcpy(wp, "\x0a\x42\x6f\x6f\x66\x79\x21\x0a", sizeof(num)); | |
| wp += sizeof(num); | | wp += sizeof(num); | |
|
| if (!db_.set(PDBMETAKEY, sizeof(PDBMETAKEY) - 1, head, sizeof(head))) r
eturn false; | | if (!db_.set(PLDBMETAKEY, sizeof(PLDBMETAKEY) - 1, head, sizeof(head)))
return false; | |
| trlcnt_ = lcnt_; | | trlcnt_ = lcnt_; | |
| trcount_ = count_; | | trcount_ = count_; | |
| return true; | | return true; | |
| } | | } | |
| /** | | /** | |
| * Load the meta data from the file. | | * Load the meta data from the file. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool load_meta() { | | bool load_meta() { | |
| _assert_(true); | | _assert_(true); | |
|
| char head[PDBHEADSIZ]; | | char head[PLDBHEADSIZ]; | |
| int32_t hsiz = db_.get(PDBMETAKEY, sizeof(PDBMETAKEY) - 1, head, sizeof | | int32_t hsiz = db_.get(PLDBMETAKEY, sizeof(PLDBMETAKEY) - 1, head, size | |
| (head)); | | of(head)); | |
| if (hsiz < 0) return false; | | if (hsiz < 0) return false; | |
| if (hsiz != sizeof(head)) { | | if (hsiz != sizeof(head)) { | |
| set_error(_KCCODELINE_, Error::BROKEN, "invalid meta data record"); | | set_error(_KCCODELINE_, Error::BROKEN, "invalid meta data record"); | |
| db_.report(_KCCODELINE_, Logger::WARN, "hsiz=%d", hsiz); | | db_.report(_KCCODELINE_, Logger::WARN, "hsiz=%d", hsiz); | |
| return false; | | return false; | |
| } | | } | |
| const char* rp = head; | | const char* rp = head; | |
| if (*(uint8_t*)rp == 0x10) { | | if (*(uint8_t*)rp == 0x10) { | |
| reccomp_.comp = LEXICALCOMP; | | reccomp_.comp = LEXICALCOMP; | |
| linkcomp_.comp = LEXICALCOMP; | | linkcomp_.comp = LEXICALCOMP; | |
| | | | |
| skipping to change at line 3093 | | skipping to change at line 3099 | |
| } else if (*(uint8_t*)rp == 0xff) { | | } else if (*(uint8_t*)rp == 0xff) { | |
| if (!reccomp_.comp) { | | if (!reccomp_.comp) { | |
| set_error(_KCCODELINE_, Error::INVALID, "the custom comparator is n
ot given"); | | set_error(_KCCODELINE_, Error::INVALID, "the custom comparator is n
ot given"); | |
| return false; | | return false; | |
| } | | } | |
| linkcomp_.comp = reccomp_.comp; | | linkcomp_.comp = reccomp_.comp; | |
| } else { | | } else { | |
| set_error(_KCCODELINE_, Error::BROKEN, "comparator is invalid"); | | set_error(_KCCODELINE_, Error::BROKEN, "comparator is invalid"); | |
| return false; | | return false; | |
| } | | } | |
|
| rp = head + PDBMOFFNUMS; | | rp = head + PLDBMOFFNUMS; | |
| uint64_t num; | | uint64_t num; | |
| std::memcpy(&num, rp, sizeof(num)); | | std::memcpy(&num, rp, sizeof(num)); | |
| psiz_ = ntoh64(num); | | psiz_ = ntoh64(num); | |
| rp += sizeof(num); | | rp += sizeof(num); | |
| std::memcpy(&num, rp, sizeof(num)); | | std::memcpy(&num, rp, sizeof(num)); | |
| root_ = ntoh64(num); | | root_ = ntoh64(num); | |
| rp += sizeof(num); | | rp += sizeof(num); | |
| std::memcpy(&num, rp, sizeof(num)); | | std::memcpy(&num, rp, sizeof(num)); | |
| first_ = ntoh64(num); | | first_ = ntoh64(num); | |
| rp += sizeof(num); | | rp += sizeof(num); | |
| | | | |
| skipping to change at line 3130 | | skipping to change at line 3136 | |
| trcount_ = count_; | | trcount_ = count_; | |
| return true; | | return true; | |
| } | | } | |
| /** | | /** | |
| * Caluculate the total number of nodes in the leaf cache. | | * Caluculate the total number of nodes in the leaf cache. | |
| * @return the total number of nodes in the leaf cache. | | * @return the total number of nodes in the leaf cache. | |
| */ | | */ | |
| int64_t calc_leaf_cache_count() { | | int64_t calc_leaf_cache_count() { | |
| _assert_(true); | | _assert_(true); | |
| int64_t sum = 0; | | int64_t sum = 0; | |
|
| for (int32_t i = 0; i < PDBSLOTNUM; i++) { | | for (int32_t i = 0; i < PLDBSLOTNUM; i++) { | |
| LeafSlot* slot = lslots_ + i; | | LeafSlot* slot = lslots_ + i; | |
| sum += slot->warm->count(); | | sum += slot->warm->count(); | |
| sum += slot->hot->count(); | | sum += slot->hot->count(); | |
| } | | } | |
| return sum; | | return sum; | |
| } | | } | |
| /** | | /** | |
| * Caluculate the amount of memory usage of the leaf cache. | | * Caluculate the amount of memory usage of the leaf cache. | |
| * @return the amount of memory usage of the leaf cache. | | * @return the amount of memory usage of the leaf cache. | |
| */ | | */ | |
| int64_t calc_leaf_cache_size() { | | int64_t calc_leaf_cache_size() { | |
| _assert_(true); | | _assert_(true); | |
| int64_t sum = 0; | | int64_t sum = 0; | |
|
| for (int32_t i = 0; i < PDBSLOTNUM; i++) { | | for (int32_t i = 0; i < PLDBSLOTNUM; i++) { | |
| LeafSlot* slot = lslots_ + i; | | LeafSlot* slot = lslots_ + i; | |
| typename LeafCache::Iterator it = slot->warm->begin(); | | typename LeafCache::Iterator it = slot->warm->begin(); | |
| typename LeafCache::Iterator itend = slot->warm->end(); | | typename LeafCache::Iterator itend = slot->warm->end(); | |
| while (it != itend) { | | while (it != itend) { | |
| LeafNode* node = it.value(); | | LeafNode* node = it.value(); | |
| sum += node->size; | | sum += node->size; | |
| it++; | | it++; | |
| } | | } | |
| it = slot->hot->begin(); | | it = slot->hot->begin(); | |
| itend = slot->hot->end(); | | itend = slot->hot->end(); | |
| | | | |
| skipping to change at line 3170 | | skipping to change at line 3176 | |
| } | | } | |
| return sum; | | return sum; | |
| } | | } | |
| /** | | /** | |
| * Caluculate the total number of nodes in the inner cache. | | * Caluculate the total number of nodes in the inner cache. | |
| * @return the total number of nodes in the inner cache. | | * @return the total number of nodes in the inner cache. | |
| */ | | */ | |
| int64_t calc_inner_cache_count() { | | int64_t calc_inner_cache_count() { | |
| _assert_(true); | | _assert_(true); | |
| int64_t sum = 0; | | int64_t sum = 0; | |
|
| for (int32_t i = 0; i < PDBSLOTNUM; i++) { | | for (int32_t i = 0; i < PLDBSLOTNUM; i++) { | |
| InnerSlot* slot = islots_ + i; | | InnerSlot* slot = islots_ + i; | |
| sum += slot->warm->count(); | | sum += slot->warm->count(); | |
| } | | } | |
| return sum; | | return sum; | |
| } | | } | |
| /** | | /** | |
| * Caluculate the amount of memory usage of the inner cache. | | * Caluculate the amount of memory usage of the inner cache. | |
| * @return the amount of memory usage of the inner cache. | | * @return the amount of memory usage of the inner cache. | |
| */ | | */ | |
| int64_t calc_inner_cache_size() { | | int64_t calc_inner_cache_size() { | |
| _assert_(true); | | _assert_(true); | |
| int64_t sum = 0; | | int64_t sum = 0; | |
|
| for (int32_t i = 0; i < PDBSLOTNUM; i++) { | | for (int32_t i = 0; i < PLDBSLOTNUM; i++) { | |
| InnerSlot* slot = islots_ + i; | | InnerSlot* slot = islots_ + i; | |
| typename InnerCache::Iterator it = slot->warm->begin(); | | typename InnerCache::Iterator it = slot->warm->begin(); | |
| typename InnerCache::Iterator itend = slot->warm->end(); | | typename InnerCache::Iterator itend = slot->warm->end(); | |
| while (it != itend) { | | while (it != itend) { | |
| InnerNode* node = it.value(); | | InnerNode* node = it.value(); | |
| sum += node->size; | | sum += node->size; | |
| it++; | | it++; | |
| } | | } | |
| } | | } | |
| return sum; | | return sum; | |
| | | | |
| skipping to change at line 3270 | | skipping to change at line 3276 | |
| 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] != PDBLNPREFIX) return NOP; | | if (ksiz < 2 || kbuf[0] != PLDBLNPREFIX) 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); | |
| if (step < 1) return NOP; | | if (step < 1) return NOP; | |
| vbuf += step; | | vbuf += step; | |
| vsiz -= step; | | vsiz -= step; | |
| | | | |
| skipping to change at line 3327 | | skipping to change at line 3333 | |
| _assert_(true); | | _assert_(true); | |
| if (!load_meta()) { | | if (!load_meta()) { | |
| if (reccomp_.comp) { | | if (reccomp_.comp) { | |
| linkcomp_.comp = reccomp_.comp; | | linkcomp_.comp = reccomp_.comp; | |
| } else { | | } else { | |
| reccomp_.comp = LEXICALCOMP; | | reccomp_.comp = LEXICALCOMP; | |
| linkcomp_.comp = LEXICALCOMP; | | linkcomp_.comp = LEXICALCOMP; | |
| } | | } | |
| } | | } | |
| const std::string& path = db_.path(); | | const std::string& path = db_.path(); | |
|
| const std::string& npath = path + File::EXTCHR + PDBTMPPATHEXT; | | const std::string& npath = path + File::EXTCHR + PLDBTMPPATHEXT; | |
| PlantDB tdb; | | PlantDB tdb; | |
| tdb.tune_comparator(reccomp_.comp); | | tdb.tune_comparator(reccomp_.comp); | |
| if (!tdb.open(npath, OWRITER | OCREATE | OTRUNCATE)) { | | if (!tdb.open(npath, OWRITER | OCREATE | OTRUNCATE)) { | |
| set_error(_KCCODELINE_, tdb.error().code(), "opening the destination
failed"); | | set_error(_KCCODELINE_, tdb.error().code(), "opening the destination
failed"); | |
| return false; | | return false; | |
| } | | } | |
| db_.report(_KCCODELINE_, Logger::WARN, "reorganizing the database"); | | db_.report(_KCCODELINE_, Logger::WARN, "reorganizing the database"); | |
| bool err = false; | | bool err = false; | |
| create_leaf_cache(); | | create_leaf_cache(); | |
| create_inner_cache(); | | create_inner_cache(); | |
| DB::Cursor* cur = db_.cursor(); | | DB::Cursor* cur = db_.cursor(); | |
| cur->jump(); | | cur->jump(); | |
| char* kbuf; | | char* kbuf; | |
| size_t ksiz; | | size_t ksiz; | |
| while (!err && (kbuf = cur->get_key(&ksiz)) != NULL) { | | while (!err && (kbuf = cur->get_key(&ksiz)) != NULL) { | |
|
| if (*kbuf == PDBLNPREFIX) { | | if (*kbuf == PLDBLNPREFIX) { | |
| int64_t id = std::strtol(kbuf + 1, NULL, 16); | | int64_t id = std::strtol(kbuf + 1, NULL, 16); | |
|
| if (id > 0 && id < PDBINIDBASE) { | | if (id > 0 && id < PLDBINIDBASE) { | |
| LeafNode* node = load_leaf_node(id, false); | | LeafNode* node = load_leaf_node(id, false); | |
| if (node) { | | if (node) { | |
| const RecordArray& recs = node->recs; | | const RecordArray& recs = node->recs; | |
| typename RecordArray::const_iterator rit = recs.begin(); | | typename RecordArray::const_iterator rit = recs.begin(); | |
| typename RecordArray::const_iterator ritend = recs.end(); | | typename RecordArray::const_iterator ritend = recs.end(); | |
| while (rit != ritend) { | | while (rit != ritend) { | |
| Record* rec = *rit; | | Record* rec = *rit; | |
| char* dbuf = (char*)rec + sizeof(*rec); | | char* dbuf = (char*)rec + sizeof(*rec); | |
| if (!tdb.set(dbuf, rec->ksiz, dbuf + rec->ksiz, rec->vsiz)) { | | if (!tdb.set(dbuf, rec->ksiz, dbuf + rec->ksiz, rec->vsiz)) { | |
| set_error(_KCCODELINE_, tdb.error().code(), | | set_error(_KCCODELINE_, tdb.error().code(), | |
| | | | |
| skipping to change at line 3385 | | skipping to change at line 3391 | |
| if (DBTYPE == TYPETREE) { | | if (DBTYPE == TYPETREE) { | |
| if (File::rename(npath, path)) { | | if (File::rename(npath, path)) { | |
| if (!db_.close()) err = true; | | if (!db_.close()) err = true; | |
| if (!db_.open(path, mode)) err = true; | | if (!db_.open(path, mode)) err = true; | |
| } else { | | } else { | |
| set_error(_KCCODELINE_, Error::SYSTEM, "renaming the destination fa
iled"); | | set_error(_KCCODELINE_, Error::SYSTEM, "renaming the destination fa
iled"); | |
| err = true; | | err = true; | |
| } | | } | |
| File::remove(npath); | | File::remove(npath); | |
| } else if (DBTYPE == TYPEFOREST) { | | } else if (DBTYPE == TYPEFOREST) { | |
|
| const std::string& tpath = npath + File::EXTCHR + PDBTMPPATHEXT; | | const std::string& tpath = npath + File::EXTCHR + PLDBTMPPATHEXT; | |
| File::remove_recursively(tpath); | | File::remove_recursively(tpath); | |
| if (File::rename(path, tpath)) { | | if (File::rename(path, tpath)) { | |
| if (File::rename(npath, path)) { | | if (File::rename(npath, path)) { | |
| if (!db_.close()) err = true; | | if (!db_.close()) err = true; | |
| if (!db_.open(path, mode)) err = true; | | if (!db_.open(path, mode)) err = true; | |
| } else { | | } else { | |
| set_error(_KCCODELINE_, Error::SYSTEM, "renaming the destination
failed"); | | set_error(_KCCODELINE_, Error::SYSTEM, "renaming the destination
failed"); | |
| File::rename(tpath, path); | | File::rename(tpath, path); | |
| err = true; | | err = true; | |
| } | | } | |
| | | | |
| skipping to change at line 3439 | | skipping to change at line 3445 | |
| /** | | /** | |
| * Begin transaction. | | * Begin transaction. | |
| * @param hard true for physical synchronization with the device, or fals
e for logical | | * @param hard true for physical synchronization with the device, or fals
e for logical | |
| * synchronization with the file system. | | * synchronization with the file system. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool begin_transaction_impl(bool hard) { | | bool begin_transaction_impl(bool hard) { | |
| _assert_(true); | | _assert_(true); | |
| if (!clean_leaf_cache()) return false; | | if (!clean_leaf_cache()) return false; | |
| if (!clean_inner_cache()) return false; | | if (!clean_inner_cache()) return false; | |
|
| int32_t idx = trclock_++ % PDBSLOTNUM; | | int32_t idx = trclock_++ % PLDBSLOTNUM; | |
| LeafSlot* lslot = lslots_ + idx; | | LeafSlot* lslot = lslots_ + idx; | |
| if (lslot->warm->count() + lslot->hot->count() > 1) flush_leaf_cache_pa
rt(lslot); | | if (lslot->warm->count() + lslot->hot->count() > 1) flush_leaf_cache_pa
rt(lslot); | |
| InnerSlot* islot = islots_ + idx; | | InnerSlot* islot = islots_ + idx; | |
| if (islot->warm->count() > 1) flush_inner_cache_part(islot); | | if (islot->warm->count() > 1) flush_inner_cache_part(islot); | |
| if ((trlcnt_ != lcnt_ || count_ != trcount_) && !dump_meta()) return fa
lse; | | if ((trlcnt_ != lcnt_ || count_ != trcount_) && !dump_meta()) return fa
lse; | |
| if (!db_.begin_transaction(hard)) return false; | | if (!db_.begin_transaction(hard)) return false; | |
| return true; | | return true; | |
| } | | } | |
| /** | | /** | |
| * Commit transaction. | | * Commit transaction. | |
| | | | |
| skipping to change at line 3485 | | skipping to change at line 3491 | |
| /** | | /** | |
| * Fix auto transaction for the B+ tree. | | * Fix auto transaction for the B+ tree. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool fix_auto_transaction_tree() { | | bool fix_auto_transaction_tree() { | |
| _assert_(true); | | _assert_(true); | |
| if (!db_.begin_transaction(autosync_)) return false; | | if (!db_.begin_transaction(autosync_)) return false; | |
| bool err = false; | | bool err = false; | |
| if (!clean_leaf_cache()) err = true; | | if (!clean_leaf_cache()) err = true; | |
| if (!clean_inner_cache()) err = true; | | if (!clean_inner_cache()) err = true; | |
|
| size_t cnum = PDBATRANCNUM / PDBSLOTNUM; | | size_t cnum = PLDBATRANCNUM / PLDBSLOTNUM; | |
| int32_t idx = trclock_++ % PDBSLOTNUM; | | int32_t idx = trclock_++ % PLDBSLOTNUM; | |
| LeafSlot* lslot = lslots_ + idx; | | LeafSlot* lslot = lslots_ + idx; | |
| if (lslot->warm->count() + lslot->hot->count() > cnum) flush_leaf_cache
_part(lslot); | | if (lslot->warm->count() + lslot->hot->count() > cnum) flush_leaf_cache
_part(lslot); | |
| InnerSlot* islot = islots_ + idx; | | InnerSlot* islot = islots_ + idx; | |
| if (islot->warm->count() > cnum) flush_inner_cache_part(islot); | | if (islot->warm->count() > cnum) flush_inner_cache_part(islot); | |
| if (!dump_meta()) err = true; | | if (!dump_meta()) err = true; | |
| if (!db_.end_transaction(true)) err = true; | | if (!db_.end_transaction(true)) err = true; | |
| return !err; | | return !err; | |
| } | | } | |
| /** | | /** | |
| * Fix auto transaction for a leaf. | | * Fix auto transaction for a leaf. | |
| | | | |
| skipping to change at line 3565 | | skipping to change at line 3571 | |
| int64_t last_; | | int64_t last_; | |
| /** The count of leaf nodes. */ | | /** The count of leaf nodes. */ | |
| int64_t lcnt_; | | int64_t lcnt_; | |
| /** The count of inner nodes. */ | | /** The count of inner nodes. */ | |
| int64_t icnt_; | | int64_t icnt_; | |
| /** The record number. */ | | /** The record number. */ | |
| AtomicInt64 count_; | | AtomicInt64 count_; | |
| /** The cache memory usage. */ | | /** The cache memory usage. */ | |
| AtomicInt64 cusage_; | | AtomicInt64 cusage_; | |
| /** The Slots of leaf nodes. */ | | /** The Slots of leaf nodes. */ | |
|
| LeafSlot lslots_[PDBSLOTNUM]; | | LeafSlot lslots_[PLDBSLOTNUM]; | |
| /** The Slots of inner nodes. */ | | /** The Slots of inner nodes. */ | |
|
| InnerSlot islots_[PDBSLOTNUM]; | | InnerSlot islots_[PLDBSLOTNUM]; | |
| /** The record comparator. */ | | /** The record comparator. */ | |
| RecordComparator reccomp_; | | RecordComparator reccomp_; | |
| /** The link comparator. */ | | /** The link comparator. */ | |
| LinkComparator linkcomp_; | | LinkComparator linkcomp_; | |
| /** The flag whether in transaction. */ | | /** The flag whether in transaction. */ | |
| bool tran_; | | bool tran_; | |
| /** The logical clock for transaction. */ | | /** The logical clock for transaction. */ | |
| int64_t trclock_; | | int64_t trclock_; | |
| /** The leaf count history for transaction. */ | | /** The leaf count history for transaction. */ | |
| int64_t trlcnt_; | | int64_t trlcnt_; | |
| | | | |
End of changes. 84 change blocks. |
| 122 lines changed or deleted | | 129 lines changed or added | |
|