| kccachedb.h | | kccachedb.h | |
| /**************************************************************************
*********************** | | /**************************************************************************
*********************** | |
| * Cache hash database | | * Cache hash database | |
|
| * Copyright
(C) 2009-2010 FAL Labs | | * Copyright
(C) 2009-2011 FAL Labs | |
| * This file is part of Kyoto Cabinet. | | * This file is part of Kyoto Cabinet. | |
| * This program is free software: you can redistribute it and/or modify it
under the terms of | | * This program is free software: you can redistribute it and/or modify it
under the terms of | |
| * the GNU General Public License as published by the Free Software Foundat
ion, either version | | * the GNU General Public License as published by the Free Software Foundat
ion, either version | |
| * 3 of the License, or any later version. | | * 3 of the License, or any later version. | |
| * This program is distributed in the hope that it will be useful, but WITH
OUT ANY WARRANTY; | | * This program is distributed in the hope that it will be useful, but WITH
OUT ANY WARRANTY; | |
| * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PA
RTICULAR PURPOSE. | | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PA
RTICULAR PURPOSE. | |
| * See the GNU General Public License for more details. | | * See the GNU General Public License for more details. | |
| * You should have received a copy of the GNU General Public License along
with this program. | | * You should have received a copy of the GNU General Public License along
with this program. | |
| * If not, see <http://www.gnu.org/licenses/>. | | * If not, see <http://www.gnu.org/licenses/>. | |
| **************************************************************************
***********************/ | | **************************************************************************
***********************/ | |
| | | | |
| skipping to change at line 427 | | skipping to change at line 427 | |
| uint64_t hash = hash_record(kbuf, ksiz); | | uint64_t hash = hash_record(kbuf, ksiz); | |
| int32_t sidx = hash % CDBSLOTNUM; | | int32_t sidx = hash % CDBSLOTNUM; | |
| hash /= CDBSLOTNUM; | | hash /= CDBSLOTNUM; | |
| Slot* slot = slots_ + sidx; | | Slot* slot = slots_ + sidx; | |
| slot->lock.lock(); | | slot->lock.lock(); | |
| accept_impl(slot, hash, kbuf, ksiz, visitor, comp_, false); | | accept_impl(slot, hash, kbuf, ksiz, visitor, comp_, false); | |
| slot->lock.unlock(); | | slot->lock.unlock(); | |
| return true; | | return true; | |
| } | | } | |
| /** | | /** | |
|
| | | * Accept a visitor to multiple records at once. | |
| | | * @param keys specifies a string vector of the keys. | |
| | | * @param visitor a visitor object. | |
| | | * @param writable true for writable operation, or false for read-only op | |
| | | eration. | |
| | | * @return true on success, or false on failure. | |
| | | * @note The operations for specified records are performed atomically an | |
| | | d other threads | |
| | | * accessing the same records are blocked. To avoid deadlock, any databa | |
| | | se operation must not | |
| | | * be performed in this function. | |
| | | */ | |
| | | bool accept_bulk(const std::vector<std::string>& keys, Visitor* visitor, | |
| | | bool writable = true) { | |
| | | _assert_(visitor); | |
| | | size_t knum = keys.size(); | |
| | | if (knum < 1) return true; | |
| | | ScopedSpinRWLock lock(&mlock_, false); | |
| | | if (omode_ == 0) { | |
| | | set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |
| | | return false; | |
| | | } | |
| | | if (writable && !(omode_ & OWRITER)) { | |
| | | set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | |
| | | return false; | |
| | | } | |
| | | struct RecordKey { | |
| | | const char* kbuf; | |
| | | size_t ksiz; | |
| | | uint64_t hash; | |
| | | int32_t sidx; | |
| | | }; | |
| | | RecordKey* rkeys = new RecordKey[knum]; | |
| | | std::set<int32_t> sidxs; | |
| | | for (size_t i = 0; i < knum; i++) { | |
| | | const std::string& key = keys[i]; | |
| | | RecordKey* rkey = rkeys + i; | |
| | | rkey->kbuf = key.data(); | |
| | | rkey->ksiz = key.size(); | |
| | | if (rkey->ksiz > CDBKSIZMAX) rkey->ksiz = CDBKSIZMAX; | |
| | | rkey->hash = hash_record(rkey->kbuf, rkey->ksiz); | |
| | | rkey->sidx = rkey->hash % CDBSLOTNUM; | |
| | | sidxs.insert(rkey->sidx); | |
| | | rkey->hash /= CDBSLOTNUM; | |
| | | } | |
| | | std::set<int32_t>::iterator sit = sidxs.begin(); | |
| | | std::set<int32_t>::iterator sitend = sidxs.end(); | |
| | | while (sit != sitend) { | |
| | | Slot* slot = slots_ + *sit; | |
| | | slot->lock.lock(); | |
| | | sit++; | |
| | | } | |
| | | for (size_t i = 0; i < knum; i++) { | |
| | | RecordKey* rkey = rkeys + i; | |
| | | Slot* slot = slots_ + rkey->sidx; | |
| | | accept_impl(slot, rkey->hash, rkey->kbuf, rkey->ksiz, visitor, comp_, | |
| | | false); | |
| | | } | |
| | | sit = sidxs.begin(); | |
| | | sitend = sidxs.end(); | |
| | | while (sit != sitend) { | |
| | | Slot* slot = slots_ + *sit; | |
| | | slot->lock.unlock(); | |
| | | sit++; | |
| | | } | |
| | | delete[] rkeys; | |
| | | return true; | |
| | | } | |
| | | /** | |
| * Iterate to accept a visitor for each record. | | * Iterate to accept a visitor for each record. | |
| * @param visitor a visitor object. | | * @param visitor a visitor object. | |
| * @param writable true for writable operation, or false for read-only op
eration. | | * @param writable true for writable operation, or false for read-only op
eration. | |
| * @param checker a progress checker object. If it is NULL, no checking
is performed. | | * @param checker a progress checker object. If it is NULL, no checking
is performed. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| * @note The whole iteration is performed atomically and other threads ar
e blocked. To avoid | | * @note The whole iteration is performed atomically and other threads ar
e blocked. To avoid | |
| * deadlock, any database operation must not be performed in this functio
n. | | * deadlock, any database operation must not be performed in this functio
n. | |
| */ | | */ | |
| bool iterate(Visitor *visitor, bool writable = true, ProgressChecker* che
cker = NULL) { | | bool iterate(Visitor *visitor, bool writable = true, ProgressChecker* che
cker = NULL) { | |
| _assert_(visitor); | | _assert_(visitor); | |
| | | | |
End of changes. 2 change blocks. |
| 1 lines changed or deleted | | 70 lines changed or added | |
|
| kcdb.h | | kcdb.h | |
| /**************************************************************************
*********************** | | /**************************************************************************
*********************** | |
| * Database interface | | * Database interface | |
|
| * Copyright
(C) 2009-2010 FAL Labs | | * Copyright
(C) 2009-2011 FAL Labs | |
| * This file is part of Kyoto Cabinet. | | * This file is part of Kyoto Cabinet. | |
| * This program is free software: you can redistribute it and/or modify it
under the terms of | | * This program is free software: you can redistribute it and/or modify it
under the terms of | |
| * the GNU General Public License as published by the Free Software Foundat
ion, either version | | * the GNU General Public License as published by the Free Software Foundat
ion, either version | |
| * 3 of the License, or any later version. | | * 3 of the License, or any later version. | |
| * This program is distributed in the hope that it will be useful, but WITH
OUT ANY WARRANTY; | | * This program is distributed in the hope that it will be useful, but WITH
OUT ANY WARRANTY; | |
| * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PA
RTICULAR PURPOSE. | | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PA
RTICULAR PURPOSE. | |
| * See the GNU General Public License for more details. | | * See the GNU General Public License for more details. | |
| * You should have received a copy of the GNU General Public License along
with this program. | | * You should have received a copy of the GNU General Public License along
with this program. | |
| * If not, see <http://www.gnu.org/licenses/>. | | * If not, see <http://www.gnu.org/licenses/>. | |
| **************************************************************************
***********************/ | | **************************************************************************
***********************/ | |
| | | | |
| skipping to change at line 104 | | skipping to change at line 104 | |
| */ | | */ | |
| virtual ~Cursor() { | | virtual ~Cursor() { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| /** | | /** | |
| * Accept a visitor to the current record. | | * Accept a visitor to the current record. | |
| * @param visitor a visitor object. | | * @param visitor a visitor object. | |
| * @param writable true for writable operation, or false for read-only
operation. | | * @param writable true for writable operation, or false for read-only
operation. | |
| * @param step true to move the cursor to the next record, or false for
no move. | | * @param step true to move the cursor to the next record, or false for
no move. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
|
| * @note the operation for each record is performed atomically and othe
r threads accessing | | * @note The operation for each record is performed atomically and othe
r threads accessing | |
| * the same record are blocked. To avoid deadlock, any database operat
ion must not be | | * the same record are blocked. To avoid deadlock, any database operat
ion must not be | |
| * performed in this function. | | * performed in this function. | |
| */ | | */ | |
| virtual bool accept(Visitor* visitor, bool writable = true, bool step =
false) = 0; | | virtual bool accept(Visitor* visitor, bool writable = true, bool step =
false) = 0; | |
| /** | | /** | |
| * Set the value of the current record. | | * Set the value of the current record. | |
| * @param vbuf the pointer to the value region. | | * @param vbuf the pointer to the value region. | |
| * @param vsiz the size of the value region. | | * @param vsiz the size of the value region. | |
| * @param step true to move the cursor to the next record, or false for
no move. | | * @param step true to move the cursor to the next record, or false for
no move. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| | | | |
| skipping to change at line 1086 | | skipping to change at line 1086 | |
| * in use. It is not allowed for two or more database objects in the sam
e process to keep | | * in use. It is not allowed for two or more database objects in the sam
e process to keep | |
| * their connections to the same database file at the same time. | | * their connections to the same database file at the same time. | |
| */ | | */ | |
| virtual bool open(const std::string& path, uint32_t mode = OWRITER | OCRE
ATE) = 0; | | virtual bool open(const std::string& path, uint32_t mode = OWRITER | OCRE
ATE) = 0; | |
| /** | | /** | |
| * Close the database file. | | * Close the database file. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| virtual bool close() = 0; | | virtual bool close() = 0; | |
| /** | | /** | |
|
| | | * Accept a visitor to multiple records at once. | |
| | | * @param keys specifies a string vector of the keys. | |
| | | * @param visitor a visitor object. | |
| | | * @param writable true for writable operation, or false for read-only op | |
| | | eration. | |
| | | * @return true on success, or false on failure. | |
| | | * @note The operations for specified records are performed atomically an | |
| | | d other threads | |
| | | * accessing the same records are blocked. To avoid deadlock, any databa | |
| | | se operation must not | |
| | | * be performed in this function. | |
| | | */ | |
| | | virtual bool accept_bulk(const std::vector<std::string>& keys, Visitor* v | |
| | | isitor, | |
| | | bool writable = true) = 0; | |
| | | /** | |
| * Iterate to accept a visitor for each record. | | * Iterate to accept a visitor for each record. | |
| * @param visitor a visitor object. | | * @param visitor a visitor object. | |
| * @param writable true for writable operation, or false for read-only op
eration. | | * @param writable true for writable operation, or false for read-only op
eration. | |
| * @param checker a progress checker object. If it is NULL, no checking
is performed. | | * @param checker a progress checker object. If it is NULL, no checking
is performed. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| * @note The whole iteration is performed atomically and other threads ar
e blocked. To avoid | | * @note The whole iteration is performed atomically and other threads ar
e blocked. To avoid | |
| * deadlock, any database operation must not be performed in this functio
n. | | * deadlock, any database operation must not be performed in this functio
n. | |
| */ | | */ | |
| virtual bool iterate(Visitor *visitor, bool writable = true, | | virtual bool iterate(Visitor *visitor, bool writable = true, | |
| ProgressChecker* checker = NULL) = 0; | | ProgressChecker* checker = NULL) = 0; | |
| | | | |
| skipping to change at line 1798 | | skipping to change at line 1810 | |
| VisitorImpl visitor(vbuf, max); | | VisitorImpl visitor(vbuf, max); | |
| if (!accept(kbuf, ksiz, &visitor, false)) return -1; | | if (!accept(kbuf, ksiz, &visitor, false)) return -1; | |
| int32_t vsiz = visitor.vsiz(); | | int32_t vsiz = visitor.vsiz(); | |
| if (vsiz < 0) { | | if (vsiz < 0) { | |
| set_error(_KCCODELINE_, Error::NOREC, "no record"); | | set_error(_KCCODELINE_, Error::NOREC, "no record"); | |
| return -1; | | return -1; | |
| } | | } | |
| return vsiz; | | return vsiz; | |
| } | | } | |
| /** | | /** | |
|
| | | * Store records at once. | |
| | | * @param recs the records to store. | |
| | | * @param atomic true to perform all operations atomically, or false for | |
| | | non-atomic operations. | |
| | | * @return the number of stored records, or -1 on failure. | |
| | | */ | |
| | | int64_t set_bulk(const std::map<std::string, std::string>& recs, bool ato | |
| | | mic = true) { | |
| | | _assert_(true); | |
| | | if (atomic) { | |
| | | std::vector<std::string> keys; | |
| | | keys.reserve(recs.size()); | |
| | | std::map<std::string, std::string>::const_iterator rit = recs.begin() | |
| | | ; | |
| | | std::map<std::string, std::string>::const_iterator ritend = recs.end( | |
| | | ); | |
| | | while (rit != ritend) { | |
| | | keys.push_back(rit->first); | |
| | | rit++; | |
| | | } | |
| | | class VisitorImpl : public Visitor { | |
| | | public: | |
| | | explicit VisitorImpl(const std::map<std::string, std::string>& recs | |
| | | ) : recs_(recs) {} | |
| | | private: | |
| | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| | | std::map<std::string, std::string>::const_iterator rit = | |
| | | recs_.find(std::string(kbuf, ksiz)); | |
| | | if (rit == recs_.end()) return NOP; | |
| | | *sp = rit->second.size(); | |
| | | return rit->second.data(); | |
| | | } | |
| | | const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) | |
| | | { | |
| | | std::map<std::string, std::string>::const_iterator rit = | |
| | | recs_.find(std::string(kbuf, ksiz)); | |
| | | if (rit == recs_.end()) return NOP; | |
| | | *sp = rit->second.size(); | |
| | | return rit->second.data(); | |
| | | } | |
| | | const std::map<std::string, std::string>& recs_; | |
| | | }; | |
| | | VisitorImpl visitor(recs); | |
| | | if (!accept_bulk(keys, &visitor, true)) return -1; | |
| | | return keys.size(); | |
| | | } | |
| | | std::map<std::string, std::string>::const_iterator rit = recs.begin(); | |
| | | std::map<std::string, std::string>::const_iterator ritend = recs.end(); | |
| | | while (rit != ritend) { | |
| | | if (!set(rit->first.data(), rit->first.size(), rit->second.data(), ri | |
| | | t->second.size())) | |
| | | return -1; | |
| | | rit++; | |
| | | } | |
| | | return recs.size(); | |
| | | } | |
| | | /** | |
| | | * Remove records at once. | |
| | | * @param keys the keys of the records to remove. | |
| | | * @param atomic true to perform all operations atomically, or false for | |
| | | non-atomic operations. | |
| | | * @return the number of removed records, or -1 on failure. | |
| | | */ | |
| | | int64_t remove_bulk(const std::vector<std::string>& keys, bool atomic = t | |
| | | rue) { | |
| | | _assert_(true); | |
| | | if (atomic) { | |
| | | class VisitorImpl : public Visitor { | |
| | | public: | |
| | | explicit VisitorImpl() : cnt_(0) {} | |
| | | int64_t cnt() const { | |
| | | return cnt_; | |
| | | } | |
| | | private: | |
| | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| | | cnt_++; | |
| | | return REMOVE; | |
| | | } | |
| | | int64_t cnt_; | |
| | | }; | |
| | | VisitorImpl visitor; | |
| | | if (!accept_bulk(keys, &visitor, true)) return -1; | |
| | | return visitor.cnt(); | |
| | | } | |
| | | int64_t cnt = 0; | |
| | | std::vector<std::string>::const_iterator kit = keys.begin(); | |
| | | std::vector<std::string>::const_iterator kitend = keys.end(); | |
| | | while (kit != kitend) { | |
| | | if (remove(kit->data(), kit->size())) { | |
| | | cnt++; | |
| | | } else if (error() != Error::NOREC) { | |
| | | return -1; | |
| | | } | |
| | | kit++; | |
| | | } | |
| | | return cnt; | |
| | | } | |
| | | /** | |
| | | * Retrieve records at once. | |
| | | * @param keys the keys of the records to retrieve. | |
| | | * @param recs a string map to contain the retrieved records. | |
| | | * @param atomic true to perform all operations atomically, or false for | |
| | | non-atomic operations. | |
| | | * @return the number of retrieved records, or -1 on failure. | |
| | | */ | |
| | | int64_t get_bulk(const std::vector<std::string>& keys, | |
| | | std::map<std::string, std::string>* recs, bool atomic = | |
| | | true) { | |
| | | _assert_(recs); | |
| | | if (atomic) { | |
| | | class VisitorImpl : public Visitor { | |
| | | public: | |
| | | explicit VisitorImpl(std::map<std::string, std::string>* recs) : re | |
| | | cs_(recs) {} | |
| | | private: | |
| | | const char* visit_full(const char* kbuf, size_t ksiz, | |
| | | const char* vbuf, size_t vsiz, size_t* sp) { | |
| | | (*recs_)[std::string(kbuf, ksiz)] = std::string(vbuf, vsiz); | |
| | | return NOP; | |
| | | } | |
| | | std::map<std::string, std::string>* recs_; | |
| | | }; | |
| | | VisitorImpl visitor(recs); | |
| | | if (!accept_bulk(keys, &visitor, false)) return -1; | |
| | | return recs->size(); | |
| | | } | |
| | | std::vector<std::string>::const_iterator kit = keys.begin(); | |
| | | std::vector<std::string>::const_iterator kitend = keys.end(); | |
| | | while (kit != kitend) { | |
| | | size_t vsiz; | |
| | | const char* vbuf = get(kit->data(), kit->size(), &vsiz); | |
| | | if (vbuf) { | |
| | | (*recs)[*kit] = std::string(vbuf, vsiz); | |
| | | delete[] vbuf; | |
| | | } else if (error() != Error::NOREC) { | |
| | | return -1; | |
| | | } | |
| | | kit++; | |
| | | } | |
| | | return recs->size(); | |
| | | } | |
| | | /** | |
| * Dump records into a data stream. | | * Dump records into a data stream. | |
| * @param dest the destination stream. | | * @param dest the destination stream. | |
| * @param checker a progress checker object. If it is NULL, no checking
is performed. | | * @param checker a progress checker object. If it is NULL, no checking
is performed. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool dump_snapshot(std::ostream* dest, ProgressChecker* checker = NULL) { | | bool dump_snapshot(std::ostream* dest, ProgressChecker* checker = NULL) { | |
| _assert_(dest); | | _assert_(dest); | |
| if (dest->fail()) { | | if (dest->fail()) { | |
| set_error(_KCCODELINE_, Error::INVALID, "invalid stream"); | | set_error(_KCCODELINE_, Error::INVALID, "invalid stream"); | |
| return false; | | return false; | |
| | | | |
End of changes. 4 change blocks. |
| 2 lines changed or deleted | | 162 lines changed or added | |
|
| kcdirdb.h | | kcdirdb.h | |
| /**************************************************************************
*********************** | | /**************************************************************************
*********************** | |
| * Directory hash database | | * Directory hash database | |
|
| * Copyright
(C) 2009-2010 FAL Labs | | * Copyright
(C) 2009-2011 FAL Labs | |
| * This file is part of Kyoto Cabinet. | | * This file is part of Kyoto Cabinet. | |
| * This program is free software: you can redistribute it and/or modify it
under the terms of | | * This program is free software: you can redistribute it and/or modify it
under the terms of | |
| * the GNU General Public License as published by the Free Software Foundat
ion, either version | | * the GNU General Public License as published by the Free Software Foundat
ion, either version | |
| * 3 of the License, or any later version. | | * 3 of the License, or any later version. | |
| * This program is distributed in the hope that it will be useful, but WITH
OUT ANY WARRANTY; | | * This program is distributed in the hope that it will be useful, but WITH
OUT ANY WARRANTY; | |
| * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PA
RTICULAR PURPOSE. | | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PA
RTICULAR PURPOSE. | |
| * See the GNU General Public License for more details. | | * See the GNU General Public License for more details. | |
| * You should have received a copy of the GNU General Public License along
with this program. | | * You should have received a copy of the GNU General Public License along
with this program. | |
| * If not, see <http://www.gnu.org/licenses/>. | | * If not, see <http://www.gnu.org/licenses/>. | |
| **************************************************************************
***********************/ | | **************************************************************************
***********************/ | |
| | | | |
| skipping to change at line 43 | | skipping to change at line 43 | |
| */ | | */ | |
| namespace { | | namespace { | |
| const char* DDBMAGICFILE = "__KCDIR__"; ///< magic file of the directory | | const char* DDBMAGICFILE = "__KCDIR__"; ///< magic file of the directory | |
| const char* DDBMETAFILE = "__meta__"; ///< meta data file of the directo
ry | | const char* DDBMETAFILE = "__meta__"; ///< meta data file of the directo
ry | |
| const char* DDBOPAQUEFILE = "__opq__"; ///< opaque file of the directory | | const char* DDBOPAQUEFILE = "__opq__"; ///< opaque file of the directory | |
| const char* DDBATRANPREFIX = "_x"; ///< prefix of files for auto tran
saction | | const char* DDBATRANPREFIX = "_x"; ///< prefix of files for auto tran
saction | |
| const char DDBCHKSUMSEED[] = "__kyotocabinet__"; ///< seed of the module c
hecksum | | const char DDBCHKSUMSEED[] = "__kyotocabinet__"; ///< seed of the module c
hecksum | |
| const char DDBMAGICEOF[] = "_EOF_"; ///< magic data for the end of fil
e | | const char DDBMAGICEOF[] = "_EOF_"; ///< magic data for the end of fil
e | |
| const int64_t DDBMETABUFSIZ = 128; ///< size of the meta data buffer | | const int64_t DDBMETABUFSIZ = 128; ///< size of the meta data buffer | |
| const uint8_t DDBRECMAGIC = 0xcc; ///< magic data for record | | const uint8_t DDBRECMAGIC = 0xcc; ///< magic data for record | |
|
| const int32_t DDBRLOCKSLOT = 64; ///< number of slots of the record
lock | | const int32_t DDBRLOCKSLOT = 256; ///< number of slots of the record
lock | |
| const int32_t DDBRECUNITSIZ = 32; ///< unit size of a record | | const int32_t DDBRECUNITSIZ = 32; ///< unit size of a record | |
| const size_t DDBOPAQUESIZ = 16; ///< size of the opaque buffer | | const size_t DDBOPAQUESIZ = 16; ///< size of the opaque buffer | |
| const char* DDBWALPATHEXT = "wal"; ///< extension of the WAL director
y | | const char* DDBWALPATHEXT = "wal"; ///< extension of the WAL director
y | |
| const char* DDBTMPPATHEXT = "tmp"; ///< extension of the temporary di
rectory | | const char* DDBTMPPATHEXT = "tmp"; ///< extension of the temporary di
rectory | |
| } | | } | |
| | | | |
| /** | | /** | |
| * Directory hash database. | | * Directory hash database. | |
| * @note This class is a concrete class to operate a hash database in a dir
ectory. This class | | * @note This class is a concrete class to operate a hash database in a dir
ectory. This class | |
| * can be inherited but overwriting methods is forbidden. Before every dat
abase operation, it is | | * can be inherited but overwriting methods is forbidden. Before every dat
abase operation, it is | |
| | | | |
| skipping to change at line 414 | | skipping to change at line 414 | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| * @note The operation for each record is performed atomically and other
threads accessing the | | * @note The operation for each record is performed atomically and other
threads accessing the | |
| * same record are blocked. To avoid deadlock, any database operation mu
st not be performed in | | * same record are blocked. To avoid deadlock, any database operation mu
st not be performed in | |
| * this function. | | * this function. | |
| */ | | */ | |
| bool accept(const char* kbuf, size_t ksiz, Visitor* visitor, bool writabl
e = true) { | | bool accept(const char* kbuf, size_t ksiz, Visitor* visitor, bool writabl
e = true) { | |
| _assert_(kbuf && ksiz <= MEMMAXSIZ && visitor); | | _assert_(kbuf && ksiz <= MEMMAXSIZ && visitor); | |
| ScopedSpinRWLock lock(&mlock_, false); | | ScopedSpinRWLock lock(&mlock_, false); | |
| if (omode_ == 0) { | | if (omode_ == 0) { | |
| set_error(_KCCODELINE_, Error::INVALID, "not opened"); | | set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |
|
| 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(); | | | |
| return false; | | return false; | |
| } | | } | |
|
| | | bool err = false; | |
| char name[NUMBUFSIZ]; | | char name[NUMBUFSIZ]; | |
| size_t lidx = hashpath(kbuf, ksiz, name) % DDBRLOCKSLOT; | | size_t lidx = hashpath(kbuf, ksiz, name) % DDBRLOCKSLOT; | |
| if (writable) { | | if (writable) { | |
| rlock_.lock_writer(lidx); | | rlock_.lock_writer(lidx); | |
| } else { | | } else { | |
| rlock_.lock_reader(lidx); | | rlock_.lock_reader(lidx); | |
| } | | } | |
|
| bool err = false; | | | |
| if (!accept_impl(kbuf, ksiz, visitor, name)) err = true; | | if (!accept_impl(kbuf, ksiz, visitor, name)) err = true; | |
| rlock_.unlock(lidx); | | rlock_.unlock(lidx); | |
| return !err; | | return !err; | |
| } | | } | |
| /** | | /** | |
|
| | | * Accept a visitor to multiple records at once. | |
| | | * @param keys specifies a string vector of the keys. | |
| | | * @param visitor a visitor object. | |
| | | * @param writable true for writable operation, or false for read-only op | |
| | | eration. | |
| | | * @return true on success, or false on failure. | |
| | | * @note The operations for specified records are performed atomically an | |
| | | d other threads | |
| | | * accessing the same records are blocked. To avoid deadlock, any databa | |
| | | se operation must not | |
| | | * be performed in this function. | |
| | | */ | |
| | | bool accept_bulk(const std::vector<std::string>& keys, Visitor* visitor, | |
| | | bool writable = true) { | |
| | | _assert_(visitor); | |
| | | size_t knum = keys.size(); | |
| | | if (knum < 1) return true; | |
| | | ScopedSpinRWLock lock(&mlock_, false); | |
| | | if (omode_ == 0) { | |
| | | set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |
| | | return false; | |
| | | } | |
| | | if (writable && !writer_) { | |
| | | set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | |
| | | return false; | |
| | | } | |
| | | bool err = false; | |
| | | struct RecordKey { | |
| | | const char* kbuf; | |
| | | size_t ksiz; | |
| | | char name[NUMBUFSIZ]; | |
| | | }; | |
| | | RecordKey* rkeys = new RecordKey[knum]; | |
| | | std::set<size_t> lidxs; | |
| | | for (size_t i = 0; i < knum; i++) { | |
| | | const std::string& key = keys[i]; | |
| | | RecordKey* rkey = rkeys + i; | |
| | | rkey->kbuf = key.data(); | |
| | | rkey->ksiz = key.size(); | |
| | | lidxs.insert(hashpath(rkey->kbuf, rkey->ksiz, rkey->name) % DDBRLOCKS | |
| | | LOT); | |
| | | } | |
| | | std::set<size_t>::iterator lit = lidxs.begin(); | |
| | | std::set<size_t>::iterator litend = lidxs.end(); | |
| | | while (lit != litend) { | |
| | | if (writable) { | |
| | | rlock_.lock_writer(*lit); | |
| | | } else { | |
| | | rlock_.lock_reader(*lit); | |
| | | } | |
| | | lit++; | |
| | | } | |
| | | for (size_t i = 0; i < knum; i++) { | |
| | | RecordKey* rkey = rkeys + i; | |
| | | if (!accept_impl(rkey->kbuf, rkey->ksiz, visitor, rkey->name)) { | |
| | | err = true; | |
| | | break; | |
| | | } | |
| | | } | |
| | | lit = lidxs.begin(); | |
| | | litend = lidxs.end(); | |
| | | while (lit != litend) { | |
| | | rlock_.unlock(*lit); | |
| | | lit++; | |
| | | } | |
| | | delete[] rkeys; | |
| | | return !err; | |
| | | } | |
| | | /** | |
| * Iterate to accept a visitor for each record. | | * Iterate to accept a visitor for each record. | |
| * @param visitor a visitor object. | | * @param visitor a visitor object. | |
| * @param writable true for writable operation, or false for read-only op
eration. | | * @param writable true for writable operation, or false for read-only op
eration. | |
| * @param checker a progress checker object. If it is NULL, no checking
is performed. | | * @param checker a progress checker object. If it is NULL, no checking
is performed. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| * @note The whole iteration is performed atomically and other threads ar
e blocked. To avoid | | * @note The whole iteration is performed atomically and other threads ar
e blocked. To avoid | |
| * deadlock, any database operation must not be performed in this functio
n. | | * deadlock, any database operation must not be performed in this functio
n. | |
| */ | | */ | |
| bool iterate(Visitor *visitor, bool writable = true, ProgressChecker* che
cker = NULL) { | | bool iterate(Visitor *visitor, bool writable = true, ProgressChecker* che
cker = NULL) { | |
| _assert_(visitor); | | _assert_(visitor); | |
| | | | |
End of changes. 7 change blocks. |
| 5 lines changed or deleted | | 72 lines changed or added | |
|
| kchashdb.h | | kchashdb.h | |
| /**************************************************************************
*********************** | | /**************************************************************************
*********************** | |
| * File hash database | | * File hash database | |
|
| * Copyright
(C) 2009-2010 FAL Labs | | * Copyright
(C) 2009-2011 FAL Labs | |
| * This file is part of Kyoto Cabinet. | | * This file is part of Kyoto Cabinet. | |
| * This program is free software: you can redistribute it and/or modify it
under the terms of | | * This program is free software: you can redistribute it and/or modify it
under the terms of | |
| * the GNU General Public License as published by the Free Software Foundat
ion, either version | | * the GNU General Public License as published by the Free Software Foundat
ion, either version | |
| * 3 of the License, or any later version. | | * 3 of the License, or any later version. | |
| * This program is distributed in the hope that it will be useful, but WITH
OUT ANY WARRANTY; | | * This program is distributed in the hope that it will be useful, but WITH
OUT ANY WARRANTY; | |
| * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PA
RTICULAR PURPOSE. | | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PA
RTICULAR PURPOSE. | |
| * See the GNU General Public License for more details. | | * See the GNU General Public License for more details. | |
| * You should have received a copy of the GNU General Public License along
with this program. | | * You should have received a copy of the GNU General Public License along
with this program. | |
| * If not, see <http://www.gnu.org/licenses/>. | | * If not, see <http://www.gnu.org/licenses/>. | |
| **************************************************************************
***********************/ | | **************************************************************************
***********************/ | |
| | | | |
| skipping to change at line 56 | | skipping to change at line 56 | |
| const int64_t HDBMOFFFLAGS = 24; ///< offset of the status flags | | const int64_t HDBMOFFFLAGS = 24; ///< offset of the status flags | |
| const int64_t HDBMOFFCOUNT = 32; ///< offset of the record number | | const int64_t HDBMOFFCOUNT = 32; ///< offset of the record number | |
| const int64_t HDBMOFFSIZE = 40; ///< offset of the file size | | const int64_t HDBMOFFSIZE = 40; ///< offset of the file size | |
| const int64_t HDBMOFFOPAQUE = 48; ///< offset of the opaque data | | const int64_t HDBMOFFOPAQUE = 48; ///< offset of the opaque data | |
| const int64_t HDBHEADSIZ = 64; ///< size of the header | | const int64_t HDBHEADSIZ = 64; ///< size of the header | |
| const int32_t HDBFBPWIDTH = 6; ///< width of the free block | | const int32_t HDBFBPWIDTH = 6; ///< width of the free block | |
| const int32_t HDBWIDTHLARGE = 6; ///< large width of the record add
ress | | const int32_t HDBWIDTHLARGE = 6; ///< large width of the record add
ress | |
| const int32_t HDBWIDTHSMALL = 4; ///< small width of the record add
ress | | const int32_t HDBWIDTHSMALL = 4; ///< small width of the record add
ress | |
| const size_t HDBRECBUFSIZ = 48; ///< size of the record buffer | | const size_t HDBRECBUFSIZ = 48; ///< size of the record buffer | |
| const size_t HDBIOBUFSIZ = 1024; ///< size of the IO buffer | | const size_t HDBIOBUFSIZ = 1024; ///< size of the IO buffer | |
|
| const int32_t HDBRLOCKSLOT = 64; ///< number of slots of the record
lock | | const int32_t HDBRLOCKSLOT = 256; ///< number of slots of the record
lock | |
| const uint8_t HDBDEFAPOW = 3; ///< default alignment power | | const uint8_t HDBDEFAPOW = 3; ///< default alignment power | |
| const uint8_t HDBMAXAPOW = 15; ///< maximum alignment power | | const uint8_t HDBMAXAPOW = 15; ///< maximum alignment power | |
| 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 | |
| | | | |
| skipping to change at line 530 | | skipping to change at line 530 | |
| 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; | |
| } | | } | |
|
| | | bool err = false; | |
| uint64_t hash = hash_record(kbuf, ksiz); | | uint64_t hash = hash_record(kbuf, ksiz); | |
| uint32_t pivot = fold_hash(hash); | | uint32_t pivot = fold_hash(hash); | |
| int64_t bidx = hash % bnum_; | | int64_t bidx = hash % bnum_; | |
| size_t lidx = bidx % HDBRLOCKSLOT; | | size_t lidx = bidx % HDBRLOCKSLOT; | |
| if (writable) { | | if (writable) { | |
| rlock_.lock_writer(lidx); | | rlock_.lock_writer(lidx); | |
| } else { | | } else { | |
| rlock_.lock_reader(lidx); | | rlock_.lock_reader(lidx); | |
| } | | } | |
|
| bool err = false; | | | |
| if (!accept_impl(kbuf, ksiz, visitor, bidx, pivot, false)) err = true; | | if (!accept_impl(kbuf, ksiz, visitor, bidx, pivot, false)) err = true; | |
| rlock_.unlock(lidx); | | rlock_.unlock(lidx); | |
| if (!err && dfunit_ > 0 && frgcnt_ >= dfunit_ && mlock_.promote()) { | | if (!err && dfunit_ > 0 && frgcnt_ >= dfunit_ && mlock_.promote()) { | |
| int64_t unit = frgcnt_; | | int64_t unit = frgcnt_; | |
| if (unit >= dfunit_) { | | if (unit >= dfunit_) { | |
| if (unit > HDBDFRGMAX) unit = HDBDFRGMAX; | | if (unit > HDBDFRGMAX) unit = HDBDFRGMAX; | |
| if (!defrag_impl(unit * HDBDFRGCEF)) err = true; | | if (!defrag_impl(unit * HDBDFRGCEF)) err = true; | |
| frgcnt_ -= unit; | | frgcnt_ -= unit; | |
| } | | } | |
| } | | } | |
| mlock_.unlock(); | | mlock_.unlock(); | |
| return !err; | | return !err; | |
|
| | | } | |
| | | /** | |
| | | * Accept a visitor to multiple records at once. | |
| | | * @param keys specifies a string vector of the keys. | |
| | | * @param visitor a visitor object. | |
| | | * @param writable true for writable operation, or false for read-only op | |
| | | eration. | |
| | | * @return true on success, or false on failure. | |
| | | * @note The operations for specified records are performed atomically an | |
| | | d other threads | |
| | | * accessing the same records are blocked. To avoid deadlock, any databa | |
| | | se operation must not | |
| | | * be performed in this function. | |
| | | */ | |
| | | bool accept_bulk(const std::vector<std::string>& keys, Visitor* visitor, | |
| | | bool writable = true) { | |
| | | _assert_(visitor); | |
| | | size_t knum = keys.size(); | |
| | | if (knum < 1) return true; | |
| | | mlock_.lock_reader(); | |
| | | if (omode_ == 0) { | |
| | | set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |
| | | mlock_.unlock(); | |
| | | return false; | |
| | | } | |
| | | if (writable && !writer_) { | |
| | | set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | |
| | | mlock_.unlock(); | |
| | | return false; | |
| | | } | |
| | | bool err = false; | |
| | | struct RecordKey { | |
| | | const char* kbuf; | |
| | | size_t ksiz; | |
| | | uint32_t pivot; | |
| | | uint64_t bidx; | |
| | | }; | |
| | | RecordKey* rkeys = new RecordKey[knum]; | |
| | | std::set<size_t> lidxs; | |
| | | for (size_t i = 0; i < knum; i++) { | |
| | | const std::string& key = keys[i]; | |
| | | RecordKey* rkey = rkeys + i; | |
| | | rkey->kbuf = key.data(); | |
| | | rkey->ksiz = key.size(); | |
| | | uint64_t hash = hash_record(rkey->kbuf, rkey->ksiz); | |
| | | rkey->pivot = fold_hash(hash); | |
| | | rkey->bidx = hash % bnum_; | |
| | | lidxs.insert(rkey->bidx % HDBRLOCKSLOT); | |
| | | } | |
| | | std::set<size_t>::iterator lit = lidxs.begin(); | |
| | | std::set<size_t>::iterator litend = lidxs.end(); | |
| | | while (lit != litend) { | |
| | | if (writable) { | |
| | | rlock_.lock_writer(*lit); | |
| | | } else { | |
| | | rlock_.lock_reader(*lit); | |
| | | } | |
| | | lit++; | |
| | | } | |
| | | for (size_t i = 0; i < knum; i++) { | |
| | | RecordKey* rkey = rkeys + i; | |
| | | if (!accept_impl(rkey->kbuf, rkey->ksiz, visitor, rkey->bidx, rkey->p | |
| | | ivot, false)) { | |
| | | err = true; | |
| | | break; | |
| | | } | |
| | | } | |
| | | lit = lidxs.begin(); | |
| | | litend = lidxs.end(); | |
| | | while (lit != litend) { | |
| | | rlock_.unlock(*lit); | |
| | | lit++; | |
| | | } | |
| | | delete[] rkeys; | |
| | | if (!err && dfunit_ > 0 && frgcnt_ >= dfunit_ && mlock_.promote()) { | |
| | | int64_t unit = frgcnt_; | |
| | | if (unit >= dfunit_) { | |
| | | if (unit > HDBDFRGMAX) unit = HDBDFRGMAX; | |
| | | if (!defrag_impl(unit * HDBDFRGCEF)) err = true; | |
| | | frgcnt_ -= unit; | |
| | | } | |
| | | } | |
| | | mlock_.unlock(); | |
| | | return !err; | |
| } | | } | |
| /** | | /** | |
| * Iterate to accept a visitor for each record. | | * Iterate to accept a visitor for each record. | |
| * @param visitor a visitor object. | | * @param visitor a visitor object. | |
| * @param writable true for writable operation, or false for read-only op
eration. | | * @param writable true for writable operation, or false for read-only op
eration. | |
| * @param checker a progress checker object. If it is NULL, no checking
is performed. | | * @param checker a progress checker object. If it is NULL, no checking
is performed. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| * @note The whole iteration is performed atomically and other threads ar
e blocked. To avoid | | * @note The whole iteration is performed atomically and other threads ar
e blocked. To avoid | |
| * deadlock, any database operation must not be performed in this functio
n. | | * deadlock, any database operation must not be performed in this functio
n. | |
| */ | | */ | |
| | | | |
End of changes. 5 change blocks. |
| 3 lines changed or deleted | | 87 lines changed or added | |
|
| kcplantdb.h | | kcplantdb.h | |
| /**************************************************************************
*********************** | | /**************************************************************************
*********************** | |
| * Plant database | | * Plant database | |
|
| * Copyright
(C) 2009-2010 FAL Labs | | * Copyright
(C) 2009-2011 FAL Labs | |
| * This file is part of Kyoto Cabinet. | | * This file is part of Kyoto Cabinet. | |
| * This program is free software: you can redistribute it and/or modify it
under the terms of | | * This program is free software: you can redistribute it and/or modify it
under the terms of | |
| * the GNU General Public License as published by the Free Software Foundat
ion, either version | | * the GNU General Public License as published by the Free Software Foundat
ion, either version | |
| * 3 of the License, or any later version. | | * 3 of the License, or any later version. | |
| * This program is distributed in the hope that it will be useful, but WITH
OUT ANY WARRANTY; | | * This program is distributed in the hope that it will be useful, but WITH
OUT ANY WARRANTY; | |
| * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PA
RTICULAR PURPOSE. | | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PA
RTICULAR PURPOSE. | |
| * See the GNU General Public License for more details. | | * See the GNU General Public License for more details. | |
| * You should have received a copy of the GNU General Public License along
with this program. | | * You should have received a copy of the GNU General Public License along
with this program. | |
| * If not, see <http://www.gnu.org/licenses/>. | | * If not, see <http://www.gnu.org/licenses/>. | |
| **************************************************************************
***********************/ | | **************************************************************************
***********************/ | |
| | | | |
| skipping to change at line 1050 | | skipping to change at line 1050 | |
| if (rbuf != rstack) delete[] rbuf; | | if (rbuf != rstack) delete[] rbuf; | |
| if (lbuf != lstack) delete[] lbuf; | | if (lbuf != lstack) delete[] lbuf; | |
| if (async) { | | if (async) { | |
| mlock_.lock_writer(); | | mlock_.lock_writer(); | |
| if (!fix_auto_synchronization()) err = true; | | if (!fix_auto_synchronization()) err = true; | |
| mlock_.unlock(); | | mlock_.unlock(); | |
| } | | } | |
| return !err; | | return !err; | |
| } | | } | |
| /** | | /** | |
|
| | | * Accept a visitor to multiple records at once. | |
| | | * @param keys specifies a string vector of the keys. | |
| | | * @param visitor a visitor object. | |
| | | * @param writable true for writable operation, or false for read-only op | |
| | | eration. | |
| | | * @return true on success, or false on failure. | |
| | | * @note The operations for specified records are performed atomically an | |
| | | d other threads | |
| | | * accessing the same records are blocked. To avoid deadlock, any databa | |
| | | se operation must not | |
| | | * be performed in this function. | |
| | | */ | |
| | | bool accept_bulk(const std::vector<std::string>& keys, Visitor* visitor, | |
| | | bool writable = true) { | |
| | | _assert_(visitor); | |
| | | ScopedSpinRWLock lock(&mlock_, true); | |
| | | if (omode_ == 0) { | |
| | | set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |
| | | return false; | |
| | | } | |
| | | if (writable && !writer_) { | |
| | | set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | |
| | | return false; | |
| | | } | |
| | | bool err = false; | |
| | | std::vector<std::string>::const_iterator kit = keys.begin(); | |
| | | std::vector<std::string>::const_iterator kitend = keys.end(); | |
| | | while (!err && kit != kitend) { | |
| | | const char* kbuf = kit->data(); | |
| | | size_t ksiz = kit->size(); | |
| | | char lstack[PDBRECBUFSIZ]; | |
| | | size_t lsiz = sizeof(Link) + ksiz; | |
| | | char* lbuf = lsiz > sizeof(lstack) ? new char[lsiz] : lstack; | |
| | | Link* link = (Link*)lbuf; | |
| | | link->child = 0; | |
| | | link->ksiz = ksiz; | |
| | | std::memcpy(lbuf + sizeof(*link), kbuf, ksiz); | |
| | | int64_t hist[PDBLEVELMAX]; | |
| | | int32_t hnum = 0; | |
| | | LeafNode* node = search_tree(link, true, hist, &hnum); | |
| | | if (!node) { | |
| | | set_error(_KCCODELINE_, Error::BROKEN, "search failed"); | |
| | | if (lbuf != lstack) delete[] lbuf; | |
| | | err = true; | |
| | | break; | |
| | | } | |
| | | char rstack[PDBRECBUFSIZ]; | |
| | | size_t rsiz = sizeof(Record) + ksiz; | |
| | | char* rbuf = rsiz > sizeof(rstack) ? new char[rsiz] : rstack; | |
| | | Record* rec = (Record*)rbuf; | |
| | | rec->ksiz = ksiz; | |
| | | rec->vsiz = 0; | |
| | | std::memcpy(rbuf + sizeof(*rec), kbuf, ksiz); | |
| | | bool reorg = accept_impl(node, rec, visitor); | |
| | | bool atran = autotran_ && node->dirty; | |
| | | bool async = autosync_ && !autotran_ && node->dirty; | |
| | | if (atran && !reorg && !tran_ && !fix_auto_transaction_leaf(node)) er | |
| | | r = true; | |
| | | if (reorg) { | |
| | | if (!reorganize_tree(node, hist, hnum)) err = true; | |
| | | if (atran && !tran_ && !fix_auto_transaction_tree()) err = true; | |
| | | } else if (cusage_ > pccap_) { | |
| | | int32_t idx = node->id % PDBSLOTNUM; | |
| | | LeafSlot* lslot = lslots_ + idx; | |
| | | if (!clean_leaf_cache_part(lslot)) err = true; | |
| | | if (!flush_leaf_cache_part(lslot)) err = true; | |
| | | InnerSlot* islot = islots_ + idx; | |
| | | if (islot->warm->count() > lslot->warm->count() + lslot->hot->count | |
| | | () + 1 && | |
| | | !flush_inner_cache_part(islot)) err = true; | |
| | | } | |
| | | if (rbuf != rstack) delete[] rbuf; | |
| | | if (lbuf != lstack) delete[] lbuf; | |
| | | if (async && !fix_auto_synchronization()) err = true; | |
| | | kit++; | |
| | | } | |
| | | return !err; | |
| | | } | |
| | | /** | |
| * Iterate to accept a visitor for each record. | | * Iterate to accept a visitor for each record. | |
| * @param visitor a visitor object. | | * @param visitor a visitor object. | |
| * @param writable true for writable operation, or false for read-only op
eration. | | * @param writable true for writable operation, or false for read-only op
eration. | |
| * @param checker a progress checker object. If it is NULL, no checking
is performed. | | * @param checker a progress checker object. If it is NULL, no checking
is performed. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| * @note The whole iteration is performed atomically and other threads ar
e blocked. To avoid | | * @note The whole iteration is performed atomically and other threads ar
e blocked. To avoid | |
| * deadlock, any database operation must not be performed in this functio
n. | | * deadlock, any database operation must not be performed in this functio
n. | |
| */ | | */ | |
| bool iterate(Visitor *visitor, bool writable = true, ProgressChecker* che
cker = NULL) { | | bool iterate(Visitor *visitor, bool writable = true, ProgressChecker* che
cker = NULL) { | |
| _assert_(visitor); | | _assert_(visitor); | |
| | | | |
End of changes. 2 change blocks. |
| 1 lines changed or deleted | | 80 lines changed or added | |
|
| kcpolydb.h | | kcpolydb.h | |
| /**************************************************************************
*********************** | | /**************************************************************************
*********************** | |
| * Polymorphic database | | * Polymorphic database | |
|
| * Copyright
(C) 2009-2010 FAL Labs | | * Copyright
(C) 2009-2011 FAL Labs | |
| * This file is part of Kyoto Cabinet. | | * This file is part of Kyoto Cabinet. | |
| * This program is free software: you can redistribute it and/or modify it
under the terms of | | * This program is free software: you can redistribute it and/or modify it
under the terms of | |
| * the GNU General Public License as published by the Free Software Foundat
ion, either version | | * the GNU General Public License as published by the Free Software Foundat
ion, either version | |
| * 3 of the License, or any later version. | | * 3 of the License, or any later version. | |
| * This program is distributed in the hope that it will be useful, but WITH
OUT ANY WARRANTY; | | * This program is distributed in the hope that it will be useful, but WITH
OUT ANY WARRANTY; | |
| * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PA
RTICULAR PURPOSE. | | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PA
RTICULAR PURPOSE. | |
| * See the GNU General Public License for more details. | | * See the GNU General Public License for more details. | |
| * You should have received a copy of the GNU General Public License along
with this program. | | * You should have received a copy of the GNU General Public License along
with this program. | |
| * If not, see <http://www.gnu.org/licenses/>. | | * If not, see <http://www.gnu.org/licenses/>. | |
| **************************************************************************
***********************/ | | **************************************************************************
***********************/ | |
| | | | |
| skipping to change at line 286 | | skipping to change at line 286 | |
| */ | | */ | |
| bool accept(const char* kbuf, size_t ksiz, Visitor* visitor, bool writabl
e = true) { | | bool accept(const char* kbuf, size_t ksiz, Visitor* visitor, bool writabl
e = true) { | |
| _assert_(kbuf && ksiz <= MEMMAXSIZ && visitor); | | _assert_(kbuf && ksiz <= MEMMAXSIZ && visitor); | |
| if (type_ == TYPEVOID) { | | if (type_ == TYPEVOID) { | |
| set_error(_KCCODELINE_, Error::INVALID, "not opened"); | | set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |
| return false; | | return false; | |
| } | | } | |
| return db_->accept(kbuf, ksiz, visitor, writable); | | return db_->accept(kbuf, ksiz, visitor, writable); | |
| } | | } | |
| /** | | /** | |
|
| | | * Accept a visitor to multiple records at once. | |
| | | * @param keys specifies a string vector of the keys. | |
| | | * @param visitor a visitor object. | |
| | | * @param writable true for writable operation, or false for read-only op | |
| | | eration. | |
| | | * @return true on success, or false on failure. | |
| | | * @note The operations for specified records are performed atomically an | |
| | | d other threads | |
| | | * accessing the same records are blocked. To avoid deadlock, any databa | |
| | | se operation must not | |
| | | * be performed in this function. | |
| | | */ | |
| | | bool accept_bulk(const std::vector<std::string>& keys, Visitor* visitor, | |
| | | bool writable = true) { | |
| | | _assert_(visitor); | |
| | | if (type_ == TYPEVOID) { | |
| | | set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |
| | | return false; | |
| | | } | |
| | | return db_->accept_bulk(keys, visitor, writable); | |
| | | } | |
| | | /** | |
| * Iterate to accept a visitor for each record. | | * Iterate to accept a visitor for each record. | |
| * @param visitor a visitor object. | | * @param visitor a visitor object. | |
| * @param writable true for writable operation, or false for read-only op
eration. | | * @param writable true for writable operation, or false for read-only op
eration. | |
| * @param checker a progress checker object. If it is NULL, no checking
is performed. | | * @param checker a progress checker object. If it is NULL, no checking
is performed. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| * @note The whole iteration is performed atomically and other threads ar
e blocked. To avoid | | * @note The whole iteration is performed atomically and other threads ar
e blocked. To avoid | |
| * deadlock, any database operation must not be performed in this functio
n. | | * deadlock, any database operation must not be performed in this functio
n. | |
| */ | | */ | |
| bool iterate(Visitor *visitor, bool writable = true, ProgressChecker* che
cker = NULL) { | | bool iterate(Visitor *visitor, bool writable = true, ProgressChecker* che
cker = NULL) { | |
| _assert_(visitor); | | _assert_(visitor); | |
| | | | |
End of changes. 2 change blocks. |
| 1 lines changed or deleted | | 23 lines changed or added | |
|
| kcprotodb.h | | kcprotodb.h | |
| /**************************************************************************
*********************** | | /**************************************************************************
*********************** | |
| * Prototype database | | * Prototype database | |
|
| * Copyright
(C) 2009-2010 FAL Labs | | * Copyright
(C) 2009-2011 FAL Labs | |
| * This file is part of Kyoto Cabinet. | | * This file is part of Kyoto Cabinet. | |
| * This program is free software: you can redistribute it and/or modify it
under the terms of | | * This program is free software: you can redistribute it and/or modify it
under the terms of | |
| * the GNU General Public License as published by the Free Software Foundat
ion, either version | | * the GNU General Public License as published by the Free Software Foundat
ion, either version | |
| * 3 of the License, or any later version. | | * 3 of the License, or any later version. | |
| * This program is distributed in the hope that it will be useful, but WITH
OUT ANY WARRANTY; | | * This program is distributed in the hope that it will be useful, but WITH
OUT ANY WARRANTY; | |
| * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PA
RTICULAR PURPOSE. | | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PA
RTICULAR PURPOSE. | |
| * See the GNU General Public License for more details. | | * See the GNU General Public License for more details. | |
| * You should have received a copy of the GNU General Public License along
with this program. | | * You should have received a copy of the GNU General Public License along
with this program. | |
| * If not, see <http://www.gnu.org/licenses/>. | | * If not, see <http://www.gnu.org/licenses/>. | |
| **************************************************************************
***********************/ | | **************************************************************************
***********************/ | |
| | | | |
| skipping to change at line 148 | | skipping to change at line 148 | |
| db_->set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | | db_->set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | |
| return false; | | return false; | |
| } | | } | |
| if (it_ == db_->recs_.end()) { | | if (it_ == db_->recs_.end()) { | |
| db_->set_error(_KCCODELINE_, Error::NOREC, "no record"); | | db_->set_error(_KCCODELINE_, Error::NOREC, "no record"); | |
| return false; | | return false; | |
| } | | } | |
| const std::string& key = it_->first; | | const std::string& key = it_->first; | |
| const std::string& value = it_->second; | | const std::string& value = it_->second; | |
| size_t vsiz; | | size_t vsiz; | |
|
| const char* vbuf = visitor->visit_full(key.c_str(), key.size(), | | const char* vbuf = visitor->visit_full(key.data(), key.size(), | |
| value.c_str(), value.size(), & | | value.data(), value.size(), &v | |
| vsiz); | | siz); | |
| if (vbuf == Visitor::REMOVE) { | | if (vbuf == Visitor::REMOVE) { | |
| if (db_->tran_) { | | if (db_->tran_) { | |
| TranLog log(key, value); | | TranLog log(key, value); | |
| db_->trlogs_.push_back(log); | | db_->trlogs_.push_back(log); | |
| } | | } | |
| db_->size_ -= key.size() + value.size(); | | db_->size_ -= key.size() + value.size(); | |
| if (db_->curs_.size() > 1) { | | if (db_->curs_.size() > 1) { | |
| typename CursorList::const_iterator cit = db_->curs_.begin(); | | typename CursorList::const_iterator cit = db_->curs_.begin(); | |
| typename CursorList::const_iterator citend = db_->curs_.end(); | | typename CursorList::const_iterator citend = db_->curs_.end(); | |
| while (cit != citend) { | | while (cit != citend) { | |
| | | | |
| skipping to change at line 225 | | skipping to change at line 225 | |
| return false; | | return false; | |
| } | | } | |
| return true; | | return true; | |
| } | | } | |
| /** | | /** | |
| * Jump the cursor to a record for forward scan. | | * Jump the cursor to a record for forward scan. | |
| * @note Equal to the original Cursor::jump method except that the para
meter is std::string. | | * @note Equal to the original Cursor::jump method except that the para
meter is std::string. | |
| */ | | */ | |
| bool jump(const std::string& key) { | | bool jump(const std::string& key) { | |
| _assert_(true); | | _assert_(true); | |
|
| return jump(key.c_str(), key.size()); | | return jump(key.data(), key.size()); | |
| } | | } | |
| /** | | /** | |
| * Jump the cursor to the last record for backward scan. | | * Jump the cursor to the last record for backward scan. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool jump_back() { | | bool jump_back() { | |
| _assert_(true); | | _assert_(true); | |
| ScopedSpinRWLock lock(&db_->mlock_, true); | | ScopedSpinRWLock lock(&db_->mlock_, true); | |
| if (db_->omode_ == 0) { | | if (db_->omode_ == 0) { | |
| db_->set_error(_KCCODELINE_, Error::INVALID, "not opened"); | | db_->set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |
| | | | |
| skipping to change at line 297 | | skipping to change at line 297 | |
| } | | } | |
| return true; | | return true; | |
| } | | } | |
| /** | | /** | |
| * Jump the cursor to a record for backward scan. | | * Jump the cursor to a record for backward scan. | |
| * @note Equal to the original Cursor::jump_back method except that the
parameter is | | * @note Equal to the original Cursor::jump_back method except that the
parameter is | |
| * std::string. | | * std::string. | |
| */ | | */ | |
| bool jump_back(const std::string& key) { | | bool jump_back(const std::string& key) { | |
| _assert_(true); | | _assert_(true); | |
|
| return jump_back(key.c_str(), key.size()); | | return jump_back(key.data(), key.size()); | |
| } | | } | |
| /** | | /** | |
| * Step the cursor to the next record. | | * Step the cursor to the next record. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool step() { | | bool step() { | |
| _assert_(true); | | _assert_(true); | |
| ScopedSpinRWLock lock(&db_->mlock_, true); | | ScopedSpinRWLock lock(&db_->mlock_, true); | |
| if (db_->omode_ == 0) { | | if (db_->omode_ == 0) { | |
| db_->set_error(_KCCODELINE_, Error::INVALID, "not opened"); | | db_->set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |
| | | | |
| skipping to change at line 427 | | skipping to change at line 427 | |
| if (tran_) { | | if (tran_) { | |
| TranLog log(key); | | TranLog log(key); | |
| trlogs_.push_back(log); | | trlogs_.push_back(log); | |
| } | | } | |
| size_ += ksiz + vsiz; | | size_ += ksiz + vsiz; | |
| recs_[key] = std::string(vbuf, vsiz); | | recs_[key] = std::string(vbuf, vsiz); | |
| } | | } | |
| } else { | | } else { | |
| const std::string& value = it->second; | | const std::string& value = it->second; | |
| size_t vsiz; | | size_t vsiz; | |
|
| const char* vbuf = visitor->visit_full(kbuf, ksiz, value.c_str(), v
alue.size(), &vsiz); | | const char* vbuf = visitor->visit_full(kbuf, ksiz, value.data(), va
lue.size(), &vsiz); | |
| if (vbuf == Visitor::REMOVE) { | | if (vbuf == Visitor::REMOVE) { | |
| if (tran_) { | | if (tran_) { | |
| TranLog log(key, value); | | TranLog log(key, value); | |
| trlogs_.push_back(log); | | trlogs_.push_back(log); | |
| } | | } | |
| size_ -= ksiz + value.size(); | | size_ -= ksiz + value.size(); | |
| if (!curs_.empty()) { | | if (!curs_.empty()) { | |
| typename CursorList::const_iterator cit = curs_.begin(); | | typename CursorList::const_iterator cit = curs_.begin(); | |
| typename CursorList::const_iterator citend = curs_.end(); | | typename CursorList::const_iterator citend = curs_.end(); | |
| while (cit != citend) { | | while (cit != citend) { | |
| | | | |
| skipping to change at line 473 | | skipping to change at line 473 | |
| if (it == rrecs.end()) { | | if (it == rrecs.end()) { | |
| size_t vsiz; | | size_t vsiz; | |
| const char* vbuf = visitor->visit_empty(kbuf, ksiz, &vsiz); | | const char* vbuf = visitor->visit_empty(kbuf, ksiz, &vsiz); | |
| if (vbuf != Visitor::NOP && vbuf != Visitor::REMOVE) { | | if (vbuf != Visitor::NOP && vbuf != Visitor::REMOVE) { | |
| set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | | set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | |
| return false; | | return false; | |
| } | | } | |
| } else { | | } else { | |
| const std::string& value = it->second; | | const std::string& value = it->second; | |
| size_t vsiz; | | size_t vsiz; | |
|
| const char* vbuf = visitor->visit_full(kbuf, ksiz, value.c_str(), v
alue.size(), &vsiz); | | const char* vbuf = visitor->visit_full(kbuf, ksiz, value.data(), va
lue.size(), &vsiz); | |
| if (vbuf != Visitor::NOP && vbuf != Visitor::REMOVE) { | | if (vbuf != Visitor::NOP && vbuf != Visitor::REMOVE) { | |
| set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | | set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | |
| return false; | | return false; | |
| } | | } | |
| } | | } | |
| } | | } | |
| return true; | | return true; | |
| } | | } | |
| /** | | /** | |
|
| | | * Accept a visitor to multiple records at once. | |
| | | * @param keys specifies a string vector of the keys. | |
| | | * @param visitor a visitor object. | |
| | | * @param writable true for writable operation, or false for read-only op | |
| | | eration. | |
| | | * @return true on success, or false on failure. | |
| | | * @note The operations for specified records are performed atomically an | |
| | | d other threads | |
| | | * accessing the same records are blocked. To avoid deadlock, any databa | |
| | | se operation must not | |
| | | * be performed in this function. | |
| | | */ | |
| | | bool accept_bulk(const std::vector<std::string>& keys, Visitor* visitor, | |
| | | bool writable = true) { | |
| | | _assert_(visitor); | |
| | | ScopedSpinRWLock lock(&mlock_, true); | |
| | | if (omode_ == 0) { | |
| | | set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |
| | | return false; | |
| | | } | |
| | | if (!(omode_ & OWRITER)) { | |
| | | set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | |
| | | return false; | |
| | | } | |
| | | std::vector<std::string>::const_iterator kit = keys.begin(); | |
| | | std::vector<std::string>::const_iterator kitend = keys.end(); | |
| | | while (kit != kitend) { | |
| | | const std::string& key = *kit; | |
| | | typename STRMAP::iterator it = recs_.find(key); | |
| | | if (it == recs_.end()) { | |
| | | size_t vsiz; | |
| | | const char* vbuf = visitor->visit_empty(key.data(), key.size(), &vs | |
| | | iz); | |
| | | if (vbuf != Visitor::NOP && vbuf != Visitor::REMOVE) { | |
| | | if (tran_) { | |
| | | TranLog log(key); | |
| | | trlogs_.push_back(log); | |
| | | } | |
| | | size_ += key.size() + vsiz; | |
| | | recs_[key] = std::string(vbuf, vsiz); | |
| | | } | |
| | | } else { | |
| | | const std::string& value = it->second; | |
| | | size_t vsiz; | |
| | | const char* vbuf = visitor->visit_full(key.data(), key.size(), | |
| | | value.data(), value.size(), | |
| | | &vsiz); | |
| | | if (vbuf == Visitor::REMOVE) { | |
| | | if (tran_) { | |
| | | TranLog log(key, value); | |
| | | trlogs_.push_back(log); | |
| | | } | |
| | | size_ -= key.size() + value.size(); | |
| | | if (!curs_.empty()) { | |
| | | typename CursorList::const_iterator cit = curs_.begin(); | |
| | | typename CursorList::const_iterator citend = curs_.end(); | |
| | | while (cit != citend) { | |
| | | Cursor* cur = *cit; | |
| | | if (cur->it_ == it) cur->it_++; | |
| | | cit++; | |
| | | } | |
| | | } | |
| | | recs_.erase(it); | |
| | | } else if (vbuf != Visitor::NOP) { | |
| | | if (tran_) { | |
| | | TranLog log(key, value); | |
| | | trlogs_.push_back(log); | |
| | | } | |
| | | size_ -= value.size(); | |
| | | size_ += vsiz; | |
| | | it->second = std::string(vbuf, vsiz); | |
| | | } | |
| | | } | |
| | | kit++; | |
| | | } | |
| | | return true; | |
| | | } | |
| | | /** | |
| * Iterate to accept a visitor for each record. | | * Iterate to accept a visitor for each record. | |
| * @param visitor a visitor object. | | * @param visitor a visitor object. | |
| * @param writable true for writable operation, or false for read-only op
eration. | | * @param writable true for writable operation, or false for read-only op
eration. | |
| * @param checker a progress checker object. If it is NULL, no checking
is performed. | | * @param checker a progress checker object. If it is NULL, no checking
is performed. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| * @note The whole iteration is performed atomically and other threads ar
e blocked. To avoid | | * @note The whole iteration is performed atomically and other threads ar
e blocked. To avoid | |
| * deadlock, any database operation must not be performed in this functio
n. | | * deadlock, any database operation must not be performed in this functio
n. | |
| */ | | */ | |
| bool iterate(Visitor *visitor, bool writable = true, ProgressChecker* che
cker = NULL) { | | bool iterate(Visitor *visitor, bool writable = true, ProgressChecker* che
cker = NULL) { | |
| _assert_(visitor); | | _assert_(visitor); | |
| | | | |
| skipping to change at line 514 | | skipping to change at line 587 | |
| set_error(_KCCODELINE_, Error::LOGIC, "checker failed"); | | set_error(_KCCODELINE_, Error::LOGIC, "checker failed"); | |
| return false; | | return false; | |
| } | | } | |
| typename STRMAP::iterator it = recs_.begin(); | | typename STRMAP::iterator it = recs_.begin(); | |
| typename STRMAP::iterator itend = recs_.end(); | | typename STRMAP::iterator itend = recs_.end(); | |
| int64_t curcnt = 0; | | int64_t curcnt = 0; | |
| while (it != itend) { | | while (it != itend) { | |
| const std::string& key = it->first; | | const std::string& key = it->first; | |
| const std::string& value = it->second; | | const std::string& value = it->second; | |
| size_t vsiz; | | size_t vsiz; | |
|
| const char* vbuf = visitor->visit_full(key.c_str(), key.size(), | | const char* vbuf = visitor->visit_full(key.data(), key.size(), | |
| value.c_str(), value.size(), & | | value.data(), value.size(), &v | |
| vsiz); | | siz); | |
| if (vbuf == Visitor::REMOVE) { | | if (vbuf == Visitor::REMOVE) { | |
| size_ -= key.size() + value.size(); | | size_ -= key.size() + value.size(); | |
| recs_.erase(it++); | | recs_.erase(it++); | |
| } else if (vbuf == Visitor::NOP) { | | } else if (vbuf == Visitor::NOP) { | |
| it++; | | it++; | |
| } else { | | } else { | |
| size_ -= value.size(); | | size_ -= value.size(); | |
| size_ += vsiz; | | size_ += vsiz; | |
| it->second = std::string(vbuf, vsiz); | | it->second = std::string(vbuf, vsiz); | |
| it++; | | it++; | |
| | | | |
End of changes. 8 change blocks. |
| 11 lines changed or deleted | | 89 lines changed or added | |
|
| kcstashdb.h | | kcstashdb.h | |
| /**************************************************************************
*********************** | | /**************************************************************************
*********************** | |
| * Stash database | | * Stash database | |
|
| * Copyright
(C) 2009-2010 FAL Labs | | * Copyright
(C) 2009-2011 FAL Labs | |
| * This file is part of Kyoto Cabinet. | | * This file is part of Kyoto Cabinet. | |
| * This program is free software: you can redistribute it and/or modify it
under the terms of | | * This program is free software: you can redistribute it and/or modify it
under the terms of | |
| * the GNU General Public License as published by the Free Software Foundat
ion, either version | | * the GNU General Public License as published by the Free Software Foundat
ion, either version | |
| * 3 of the License, or any later version. | | * 3 of the License, or any later version. | |
| * This program is distributed in the hope that it will be useful, but WITH
OUT ANY WARRANTY; | | * This program is distributed in the hope that it will be useful, but WITH
OUT ANY WARRANTY; | |
| * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PA
RTICULAR PURPOSE. | | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PA
RTICULAR PURPOSE. | |
| * See the GNU General Public License for more details. | | * See the GNU General Public License for more details. | |
| * You should have received a copy of the GNU General Public License along
with this program. | | * You should have received a copy of the GNU General Public License along
with this program. | |
| * If not, see <http://www.gnu.org/licenses/>. | | * If not, see <http://www.gnu.org/licenses/>. | |
| **************************************************************************
***********************/ | | **************************************************************************
***********************/ | |
| | | | |
| skipping to change at line 35 | | skipping to change at line 35 | |
| #include <kcregex.h> | | #include <kcregex.h> | |
| #include <kcdb.h> | | #include <kcdb.h> | |
| #include <kcplantdb.h> | | #include <kcplantdb.h> | |
| | | | |
| namespace kyotocabinet { // common namespace | | namespace kyotocabinet { // common namespace | |
| | | | |
| /** | | /** | |
| * Constants for implementation. | | * Constants for implementation. | |
| */ | | */ | |
| namespace { | | namespace { | |
|
| const int32_t SDBRLOCKSLOT = 64; ///< number of slots of the record
lock | | const int32_t SDBRLOCKSLOT = 256; ///< number of slots of the record
lock | |
| const size_t SDBDEFBNUM = 1048583LL; ///< default bucket number | | const size_t SDBDEFBNUM = 1048583LL; ///< default bucket number | |
| const size_t SDBOPAQUESIZ = 16; ///< size of the opaque buffer | | const size_t SDBOPAQUESIZ = 16; ///< size of the opaque buffer | |
| } | | } | |
| | | | |
| /** | | /** | |
| * Economical on-memory hash database. | | * Economical on-memory hash database. | |
| * @note This class is a concrete class to operate a hash database on memor
y. This class can be | | * @note This class is a concrete class to operate a hash database on memor
y. This class can be | |
| * inherited but overwriting methods is forbidden. Before every database o
peration, it is | | * inherited but overwriting methods is forbidden. Before every database o
peration, it is | |
| * necessary to call the StashDB::open method in order to open a database f
ile and connect the | | * necessary to call the StashDB::open method in order to open a database f
ile and connect the | |
| * database object to it. To avoid data missing or corruption, it is impor
tant to close every | | * database object to it. To avoid data missing or corruption, it is impor
tant to close every | |
| | | | |
| skipping to change at line 365 | | skipping to change at line 365 | |
| if (writable) { | | if (writable) { | |
| rlock_.lock_writer(lidx); | | rlock_.lock_writer(lidx); | |
| } else { | | } else { | |
| rlock_.lock_reader(lidx); | | rlock_.lock_reader(lidx); | |
| } | | } | |
| accept_impl(kbuf, ksiz, visitor, bidx); | | accept_impl(kbuf, ksiz, visitor, bidx); | |
| rlock_.unlock(lidx); | | rlock_.unlock(lidx); | |
| return true; | | return true; | |
| } | | } | |
| /** | | /** | |
|
| | | * Accept a visitor to multiple records at once. | |
| | | * @param keys specifies a string vector of the keys. | |
| | | * @param visitor a visitor object. | |
| | | * @param writable true for writable operation, or false for read-only op | |
| | | eration. | |
| | | * @return true on success, or false on failure. | |
| | | * @note The operations for specified records are performed atomically an | |
| | | d other threads | |
| | | * accessing the same records are blocked. To avoid deadlock, any databa | |
| | | se operation must not | |
| | | * be performed in this function. | |
| | | */ | |
| | | bool accept_bulk(const std::vector<std::string>& keys, Visitor* visitor, | |
| | | bool writable = true) { | |
| | | _assert_(visitor); | |
| | | size_t knum = keys.size(); | |
| | | if (knum < 1) return true; | |
| | | ScopedSpinRWLock lock(&mlock_, false); | |
| | | if (omode_ == 0) { | |
| | | set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |
| | | return false; | |
| | | } | |
| | | if (writable && !(omode_ & OWRITER)) { | |
| | | set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); | |
| | | return false; | |
| | | } | |
| | | struct RecordKey { | |
| | | const char* kbuf; | |
| | | size_t ksiz; | |
| | | size_t bidx; | |
| | | }; | |
| | | RecordKey* rkeys = new RecordKey[knum]; | |
| | | std::set<size_t> lidxs; | |
| | | for (size_t i = 0; i < knum; i++) { | |
| | | const std::string& key = keys[i]; | |
| | | RecordKey* rkey = rkeys + i; | |
| | | rkey->kbuf = key.data(); | |
| | | rkey->ksiz = key.size(); | |
| | | rkey->bidx = hash_record(rkey->kbuf, rkey->ksiz) % bnum_; | |
| | | lidxs.insert(rkey->bidx % SDBRLOCKSLOT); | |
| | | } | |
| | | std::set<size_t>::iterator lit = lidxs.begin(); | |
| | | std::set<size_t>::iterator litend = lidxs.end(); | |
| | | while (lit != litend) { | |
| | | if (writable) { | |
| | | rlock_.lock_writer(*lit); | |
| | | } else { | |
| | | rlock_.lock_reader(*lit); | |
| | | } | |
| | | lit++; | |
| | | } | |
| | | for (size_t i = 0; i < knum; i++) { | |
| | | RecordKey* rkey = rkeys + i; | |
| | | accept_impl(rkey->kbuf, rkey->ksiz, visitor, rkey->bidx); | |
| | | } | |
| | | lit = lidxs.begin(); | |
| | | litend = lidxs.end(); | |
| | | while (lit != litend) { | |
| | | rlock_.unlock(*lit); | |
| | | lit++; | |
| | | } | |
| | | delete[] rkeys; | |
| | | return true; | |
| | | } | |
| | | /** | |
| * Iterate to accept a visitor for each record. | | * Iterate to accept a visitor for each record. | |
| * @param visitor a visitor object. | | * @param visitor a visitor object. | |
| * @param writable true for writable operation, or false for read-only op
eration. | | * @param writable true for writable operation, or false for read-only op
eration. | |
| * @param checker a progress checker object. If it is NULL, no checking
is performed. | | * @param checker a progress checker object. If it is NULL, no checking
is performed. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| * @note The whole iteration is performed atomically and other threads ar
e blocked. To avoid | | * @note The whole iteration is performed atomically and other threads ar
e blocked. To avoid | |
| * deadlock, any database operation must not be performed in this functio
n. | | * deadlock, any database operation must not be performed in this functio
n. | |
| */ | | */ | |
| bool iterate(Visitor *visitor, bool writable = true, ProgressChecker* che
cker = NULL) { | | bool iterate(Visitor *visitor, bool writable = true, ProgressChecker* che
cker = NULL) { | |
| _assert_(visitor); | | _assert_(visitor); | |
| | | | |
End of changes. 3 change blocks. |
| 2 lines changed or deleted | | 67 lines changed or added | |
|
| kcthread.h | | kcthread.h | |
| /**************************************************************************
*********************** | | /**************************************************************************
*********************** | |
| * Threading devices | | * Threading devices | |
|
| * Copyright
(C) 2009-2010 FAL Labs | | * Copyright
(C) 2009-2011 FAL Labs | |
| * This file is part of Kyoto Cabinet. | | * This file is part of Kyoto Cabinet. | |
| * This program is free software: you can redistribute it and/or modify it
under the terms of | | * This program is free software: you can redistribute it and/or modify it
under the terms of | |
| * the GNU General Public License as published by the Free Software Foundat
ion, either version | | * the GNU General Public License as published by the Free Software Foundat
ion, either version | |
| * 3 of the License, or any later version. | | * 3 of the License, or any later version. | |
| * This program is distributed in the hope that it will be useful, but WITH
OUT ANY WARRANTY; | | * This program is distributed in the hope that it will be useful, but WITH
OUT ANY WARRANTY; | |
| * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PA
RTICULAR PURPOSE. | | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PA
RTICULAR PURPOSE. | |
| * See the GNU General Public License for more details. | | * See the GNU General Public License for more details. | |
| * You should have received a copy of the GNU General Public License along
with this program. | | * You should have received a copy of the GNU General Public License along
with this program. | |
| * If not, see <http://www.gnu.org/licenses/>. | | * If not, see <http://www.gnu.org/licenses/>. | |
| **************************************************************************
***********************/ | | **************************************************************************
***********************/ | |
| | | | |
| skipping to change at line 213 | | skipping to change at line 213 | |
| _assert_(true); | | _assert_(true); | |
| for (int32_t i = 0; i < SLOTNUM; i++) { | | for (int32_t i = 0; i < SLOTNUM; i++) { | |
| locks_[i].lock(); | | locks_[i].lock(); | |
| } | | } | |
| } | | } | |
| /** | | /** | |
| * Release the locks of all slots. | | * Release the locks of all slots. | |
| */ | | */ | |
| void unlock_all() { | | void unlock_all() { | |
| _assert_(true); | | _assert_(true); | |
|
| for (int32_t i = SLOTNUM - 1; i >= 0; i--) { | | for (int32_t i = 0; i < SLOTNUM; i++) { | |
| locks_[i].unlock(); | | locks_[i].unlock(); | |
| } | | } | |
| } | | } | |
| private: | | private: | |
| /** The inner devices. */ | | /** The inner devices. */ | |
| Mutex locks_[SLOTNUM]; | | Mutex locks_[SLOTNUM]; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Lightweight mutual exclusion device. | | * Lightweight mutual exclusion device. | |
| | | | |
| skipping to change at line 335 | | skipping to change at line 335 | |
| _assert_(true); | | _assert_(true); | |
| for (int32_t i = 0; i < SLOTNUM; i++) { | | for (int32_t i = 0; i < SLOTNUM; i++) { | |
| locks_[i].lock(); | | locks_[i].lock(); | |
| } | | } | |
| } | | } | |
| /** | | /** | |
| * Release the locks of all slots. | | * Release the locks of all slots. | |
| */ | | */ | |
| void unlock_all() { | | void unlock_all() { | |
| _assert_(true); | | _assert_(true); | |
|
| for (int32_t i = SLOTNUM - 1; i >= 0; i--) { | | for (int32_t i = 0; i < SLOTNUM; i++) { | |
| locks_[i].unlock(); | | locks_[i].unlock(); | |
| } | | } | |
| } | | } | |
| private: | | private: | |
| /** The inner devices. */ | | /** The inner devices. */ | |
| SpinLock locks_[SLOTNUM]; | | SpinLock locks_[SLOTNUM]; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Reader-writer locking device. | | * Reader-writer locking device. | |
| | | | |
| skipping to change at line 488 | | skipping to change at line 488 | |
| _assert_(true); | | _assert_(true); | |
| for (int32_t i = 0; i < SLOTNUM; i++) { | | for (int32_t i = 0; i < SLOTNUM; i++) { | |
| locks_[i].lock_reader(); | | locks_[i].lock_reader(); | |
| } | | } | |
| } | | } | |
| /** | | /** | |
| * Release the locks of all slots. | | * Release the locks of all slots. | |
| */ | | */ | |
| void unlock_all() { | | void unlock_all() { | |
| _assert_(true); | | _assert_(true); | |
|
| for (int32_t i = SLOTNUM - 1; i >= 0; i--) { | | for (int32_t i = 0; i < SLOTNUM; i++) { | |
| locks_[i].unlock(); | | locks_[i].unlock(); | |
| } | | } | |
| } | | } | |
| private: | | private: | |
| /** The inner devices. */ | | /** The inner devices. */ | |
| RWLock locks_[SLOTNUM]; | | RWLock locks_[SLOTNUM]; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Lightweight reader-writer locking device. | | * Lightweight reader-writer locking device. | |
| | | | |
| skipping to change at line 650 | | skipping to change at line 650 | |
| _assert_(true); | | _assert_(true); | |
| for (int32_t i = 0; i < SLOTNUM; i++) { | | for (int32_t i = 0; i < SLOTNUM; i++) { | |
| locks_[i].lock_reader(); | | locks_[i].lock_reader(); | |
| } | | } | |
| } | | } | |
| /** | | /** | |
| * Release the locks of all slots. | | * Release the locks of all slots. | |
| */ | | */ | |
| void unlock_all() { | | void unlock_all() { | |
| _assert_(true); | | _assert_(true); | |
|
| for (int32_t i = SLOTNUM - 1; i >= 0; i--) { | | for (int32_t i = 0; i < SLOTNUM; i++) { | |
| locks_[i].unlock(); | | locks_[i].unlock(); | |
| } | | } | |
| } | | } | |
| private: | | private: | |
| /** The inner devices. */ | | /** The inner devices. */ | |
| SpinRWLock locks_[SLOTNUM]; | | SpinRWLock locks_[SLOTNUM]; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Condition variable. | | * Condition variable. | |
| | | | |
End of changes. 5 change blocks. |
| 5 lines changed or deleted | | 5 lines changed or added | |
|