| kccachedb.h | | kccachedb.h | |
| /**************************************************************************
*********************** | | /**************************************************************************
*********************** | |
| * Cache database | | * Cache database | |
|
| * Copyright (C) 2009-
2010 Mikio Hirabayashi | | * Copyright
(C) 2009-2010 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 293 | | skipping to change at line 293 | |
| bnum_(CDBDEFBNUM), capcnt_(-1), capsiz_(-1), slots_(), tran_(false) { | | bnum_(CDBDEFBNUM), capcnt_(-1), capsiz_(-1), slots_(), tran_(false) { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| * @note If the database is not closed, it is closed implicitly. | | * @note If the database is not closed, it is closed implicitly. | |
| */ | | */ | |
| virtual ~CacheDB() { | | virtual ~CacheDB() { | |
| _assert_(true); | | _assert_(true); | |
| if (omode_ != 0) close(); | | if (omode_ != 0) close(); | |
|
| if (curs_.size() > 0) { | | if (!curs_.empty()) { | |
| CursorList::const_iterator cit = curs_.begin(); | | CursorList::const_iterator cit = curs_.begin(); | |
| CursorList::const_iterator citend = curs_.end(); | | CursorList::const_iterator citend = curs_.end(); | |
| while (cit != citend) { | | while (cit != citend) { | |
| Cursor* cur = *cit; | | Cursor* cur = *cit; | |
| cur->db_ = NULL; | | cur->db_ = NULL; | |
| cit++; | | cit++; | |
| } | | } | |
| } | | } | |
| } | | } | |
| /** | | /** | |
| | | | |
| skipping to change at line 813 | | skipping to change at line 813 | |
| entp = &rec->right; | | entp = &rec->right; | |
| rec = rec->right; | | rec = rec->right; | |
| } else { | | } else { | |
| size_t vsiz; | | size_t vsiz; | |
| const char* vbuf = visitor->visit_full(dbuf, rksiz, dbuf + rksiz,
rec->vsiz, &vsiz); | | const char* vbuf = visitor->visit_full(dbuf, rksiz, dbuf + rksiz,
rec->vsiz, &vsiz); | |
| if (vbuf == Visitor::REMOVE) { | | if (vbuf == Visitor::REMOVE) { | |
| if (tran_) { | | if (tran_) { | |
| TranLog log(kbuf, ksiz, dbuf + rksiz, rec->vsiz); | | TranLog log(kbuf, ksiz, dbuf + rksiz, rec->vsiz); | |
| slot->trlogs.push_back(log); | | slot->trlogs.push_back(log); | |
| } | | } | |
|
| if (curs_.size() > 0) escape_cursors(rec); | | if (!curs_.empty()) escape_cursors(rec); | |
| if (rec == slot->first) slot->first = rec->next; | | if (rec == slot->first) slot->first = rec->next; | |
| if (rec == slot->last) slot->last = rec->prev; | | if (rec == slot->last) slot->last = rec->prev; | |
| if (rec->prev) rec->prev->next = rec->next; | | if (rec->prev) rec->prev->next = rec->next; | |
| if (rec->next) rec->next->prev = rec->prev; | | if (rec->next) rec->next->prev = rec->prev; | |
| if (rec->left && !rec->right) { | | if (rec->left && !rec->right) { | |
| *entp = rec->left; | | *entp = rec->left; | |
| } else if (!rec->left && rec->right) { | | } else if (!rec->left && rec->right) { | |
| *entp = rec->right; | | *entp = rec->right; | |
| } else if (!rec->left) { | | } else if (!rec->left) { | |
| *entp = NULL; | | *entp = NULL; | |
| | | | |
| skipping to change at line 860 | | skipping to change at line 860 | |
| slot->trlogs.push_back(log); | | slot->trlogs.push_back(log); | |
| } else { | | } else { | |
| adj = vsiz > rec->vsiz; | | adj = vsiz > rec->vsiz; | |
| } | | } | |
| slot->size -= rec->vsiz; | | slot->size -= rec->vsiz; | |
| slot->size += vsiz; | | slot->size += vsiz; | |
| if (vsiz > rec->vsiz) { | | if (vsiz > rec->vsiz) { | |
| Record* old = rec; | | Record* old = rec; | |
| rec = (Record*)xrealloc(rec, sizeof(*rec) + ksiz + vsiz); | | rec = (Record*)xrealloc(rec, sizeof(*rec) + ksiz + vsiz); | |
| if (rec != old) { | | if (rec != old) { | |
|
| if (curs_.size() > 0) adjust_cursors(old, rec); | | if (!curs_.empty()) adjust_cursors(old, rec); | |
| if (slot->first == old) slot->first = rec; | | if (slot->first == old) slot->first = rec; | |
| if (slot->last == old) slot->last = rec; | | if (slot->last == old) slot->last = rec; | |
| *entp = rec; | | *entp = rec; | |
| if (rec->prev) rec->prev->next = rec; | | if (rec->prev) rec->prev->next = rec; | |
| if (rec->next) rec->next->prev = rec; | | if (rec->next) rec->next->prev = rec; | |
| dbuf = (char*)rec + sizeof(*rec); | | dbuf = (char*)rec + sizeof(*rec); | |
| } | | } | |
| } | | } | |
| std::memcpy(dbuf + ksiz, vbuf, vsiz); | | std::memcpy(dbuf + ksiz, vbuf, vsiz); | |
| rec->vsiz = vsiz; | | rec->vsiz = vsiz; | |
| } | | } | |
| if (!isiter && slot->last != rec) { | | if (!isiter && slot->last != rec) { | |
|
| if (curs_.size() > 0) escape_cursors(rec); | | if (!curs_.empty()) escape_cursors(rec); | |
| if (slot->first == rec) slot->first = rec->next; | | if (slot->first == rec) slot->first = rec->next; | |
| if (rec->prev) rec->prev->next = rec->next; | | if (rec->prev) rec->prev->next = rec->next; | |
| if (rec->next) rec->next->prev = rec->prev; | | if (rec->next) rec->next->prev = rec->prev; | |
| rec->prev = slot->last; | | rec->prev = slot->last; | |
| rec->next = NULL; | | rec->next = NULL; | |
| slot->last->next = rec; | | slot->last->next = rec; | |
| slot->last = rec; | | slot->last = rec; | |
| } | | } | |
| if (adj) adjust_slot_capacity(slot); | | if (adj) adjust_slot_capacity(slot); | |
| } | | } | |
| | | | |
| skipping to change at line 1085 | | skipping to change at line 1085 | |
| int32_t compare_keys(const char* abuf, size_t asiz, const char* bbuf, siz
e_t bsiz) { | | int32_t compare_keys(const char* abuf, size_t asiz, const char* bbuf, siz
e_t bsiz) { | |
| if (asiz != bsiz) return (int32_t)asiz - (int32_t)bsiz; | | if (asiz != bsiz) return (int32_t)asiz - (int32_t)bsiz; | |
| return std::memcmp(abuf, bbuf, asiz); | | return std::memcmp(abuf, bbuf, asiz); | |
| } | | } | |
| /** | | /** | |
| * Escape cursors on a shifted or removed records. | | * Escape cursors on a shifted or removed records. | |
| * @param rec the record. | | * @param rec the record. | |
| */ | | */ | |
| void escape_cursors(Record* rec) { | | void escape_cursors(Record* rec) { | |
| ScopedSpinLock lock(&flock_); | | ScopedSpinLock lock(&flock_); | |
|
| if (curs_.size() < 1) return; | | if (curs_.empty()) return; | |
| CursorList::const_iterator cit = curs_.begin(); | | CursorList::const_iterator cit = curs_.begin(); | |
| CursorList::const_iterator citend = curs_.end(); | | CursorList::const_iterator citend = curs_.end(); | |
| while (cit != citend) { | | while (cit != citend) { | |
| Cursor* cur = *cit; | | Cursor* cur = *cit; | |
| if (cur->rec_ == rec) cur->step_impl(); | | if (cur->rec_ == rec) cur->step_impl(); | |
| cit++; | | cit++; | |
| } | | } | |
| } | | } | |
| /** | | /** | |
| * Adjust cursors on re-allocated records. | | * Adjust cursors on re-allocated records. | |
| * @param orec the old address. | | * @param orec the old address. | |
| * @param nrec the new address. | | * @param nrec the new address. | |
| */ | | */ | |
| void adjust_cursors(Record* orec, Record* nrec) { | | void adjust_cursors(Record* orec, Record* nrec) { | |
| ScopedSpinLock lock(&flock_); | | ScopedSpinLock lock(&flock_); | |
|
| if (curs_.size() < 1) return; | | if (curs_.empty()) return; | |
| CursorList::const_iterator cit = curs_.begin(); | | CursorList::const_iterator cit = curs_.begin(); | |
| CursorList::const_iterator citend = curs_.end(); | | CursorList::const_iterator citend = curs_.end(); | |
| while (cit != citend) { | | while (cit != citend) { | |
| Cursor* cur = *cit; | | Cursor* cur = *cit; | |
| if (cur->rec_ == orec) cur->rec_ = nrec; | | if (cur->rec_ == orec) cur->rec_ = nrec; | |
| cit++; | | cit++; | |
| } | | } | |
| } | | } | |
| /** | | /** | |
| * Disable all cursors. | | * Disable all cursors. | |
| | | | |
End of changes. 7 change blocks. |
| 7 lines changed or deleted | | 7 lines changed or added | |
|
| kccompress.h | | kccompress.h | |
| /**************************************************************************
*********************** | | /**************************************************************************
*********************** | |
| * Data compressor and decompressor | | * Data compressor and decompressor | |
|
| * Copyright (C) 2009-
2010 Mikio Hirabayashi | | * Copyright
(C) 2009-2010 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 74 | | skipping to change at line 74 | |
| /** | | /** | |
| * Compression modes. | | * Compression modes. | |
| */ | | */ | |
| enum Mode { | | enum Mode { | |
| RAW, ///< without any checksum | | RAW, ///< without any checksum | |
| DEFLATE, ///< with Adler32 checksum | | DEFLATE, ///< with Adler32 checksum | |
| GZIP ///< with CRC32 checksum and vario
us meta data | | GZIP ///< with CRC32 checksum and vario
us meta data | |
| }; | | }; | |
| /** | | /** | |
| * Compress a serial data. | | * Compress a serial data. | |
|
| * @param mode the compression mode. | | | |
| * @param buf the input buffer. | | * @param buf the input buffer. | |
| * @param size the size of the input buffer. | | * @param size the size of the input buffer. | |
| * @param sp the pointer to the variable into which the size of the regio
n of the return | | * @param sp the pointer to the variable into which the size of the regio
n of the return | |
| * value is assigned. | | * value is assigned. | |
|
| | | * @param mode the compression mode. | |
| * @return the pointer to the result data, or NULL on failure. | | * @return the pointer to the result data, or NULL on failure. | |
| * @note Because the region of the return value is allocated with the the
new[] operator, it | | * @note Because the region of the return value is allocated with the the
new[] operator, it | |
| * should be released with the delete[] operator when it is no longer in
use. | | * should be released with the delete[] operator when it is no longer in
use. | |
| */ | | */ | |
|
| static char* compress(Mode mode, const void* buf, size_t size, size_t* sp
); | | static char* compress(const void* buf, size_t size, size_t* sp, Mode mode
= RAW); | |
| /** | | /** | |
| * Decompress a serial data. | | * Decompress a serial data. | |
|
| * @param mode the compression mode. | | | |
| * @param buf the input buffer. | | * @param buf the input buffer. | |
| * @param size the size of the input buffer. | | * @param size the size of the input buffer. | |
| * @param sp the pointer to the variable into which the size of the regio
n of the return | | * @param sp the pointer to the variable into which the size of the regio
n of the return | |
| * value is assigned. | | * value is assigned. | |
|
| | | * @param mode the compression mode. | |
| * @return the pointer to the result data, or NULL on failure. | | * @return the pointer to the result data, or NULL on failure. | |
| * @note Because an additional zero code is appended at the end of the re
gion of the return | | * @note Because an additional zero code is appended at the end of the re
gion of the return | |
| * value, the return value can be treated as a C-style string. Because t
he region of the | | * value, the return value can be treated as a C-style string. Because t
he region of the | |
| * return value is allocated with the the new[] operator, it should be re
leased with the | | * return value is allocated with the the new[] operator, it should be re
leased with the | |
| * delete[] operator when it is no longer in use. | | * delete[] operator when it is no longer in use. | |
| */ | | */ | |
|
| static char* decompress(Mode mode, const void* buf, size_t size, size_t* | | static char* decompress(const void* buf, size_t size, size_t* sp, Mode mo | |
| sp); | | de = RAW); | |
| | | /** | |
| | | * Calculate the CRC32 checksum of a serial data. | |
| | | * @param buf the input buffer. | |
| | | * @param size the size of the input buffer. | |
| | | * @param seed the cyclic seed value. | |
| | | * @return the CRC32 checksum. | |
| | | */ | |
| | | static uint32_t calculate_crc(const void* buf, size_t size, uint32_t seed | |
| | | = 0); | |
| }; | | }; | |
| | | | |
| /** | | /** | |
|
| * Compressor with the Zlib raw mode. | | * Compressor with the Zlib. | |
| */ | | */ | |
|
| class ZlibRawCompressor : public Compressor { | | template <Zlib::Mode MODE> | |
| | | class ZlibCompressor : public Compressor { | |
| | | private: | |
| | | /** | |
| | | * Compress a serial data. | |
| | | */ | |
| char* compress(const void* buf, size_t size, size_t* sp) { | | char* compress(const void* buf, size_t size, size_t* sp) { | |
|
| _assert_(buf && sp); | | _assert_(buf && size <= MEMMAXSIZ && sp); | |
| return Zlib::compress(Zlib::RAW, buf, size, sp); | | return Zlib::compress(buf, size, sp, MODE); | |
| } | | } | |
|
| | | /** | |
| | | * Decompress a serial data. | |
| | | */ | |
| char* decompress(const void* buf, size_t size, size_t* sp) { | | char* decompress(const void* buf, size_t size, size_t* sp) { | |
|
| _assert_(buf && sp); | | _assert_(buf && size <= MEMMAXSIZ && sp); | |
| return Zlib::decompress(Zlib::RAW, buf, size, sp); | | return Zlib::decompress(buf, size, sp, MODE); | |
| } | | } | |
| }; | | }; | |
| | | | |
| /** | | /** | |
|
| * Compressor with the Zlib deflate mode. | | * Compressor with the Arcfour cipher. | |
| */ | | */ | |
|
| class ZlibDeflateCompressor : public Compressor { | | class ArcfourCompressor : public Compressor { | |
| char* compress(const void* buf, size_t size, size_t* sp) { | | public: | |
| _assert_(buf && sp); | | /** | |
| return Zlib::compress(Zlib::DEFLATE, buf, size, sp); | | * Constructor. | |
| | | */ | |
| | | ArcfourCompressor() : kbuf_(NULL), ksiz_(0), salt_(0), cycle_(false) { | |
| | | _assert_(true); | |
| | | kbuf_ = new char[0]; | |
| | | ksiz_ = 0; | |
| } | | } | |
|
| char* decompress(const void* buf, size_t size, size_t* sp) { | | /** | |
| _assert_(buf && sp); | | * Destructor. | |
| return Zlib::decompress(Zlib::DEFLATE, buf, size, sp); | | */ | |
| | | ~ArcfourCompressor() { | |
| | | _assert_(true); | |
| | | delete[] kbuf_; | |
| } | | } | |
|
| }; | | /** | |
| | | * Set the cipher key. | |
| /** | | * @param kbuf the pointer to the region of the cipher key. | |
| * Compressor with the Zlib gzip mode. | | * @param ksiz the size of the region of the cipher key. | |
| */ | | */ | |
| class ZlibGzipCompressor : public Compressor { | | void set_key(const void* kbuf, size_t ksiz) { | |
| | | _assert_(kbuf && ksiz <= MEMMAXSIZ); | |
| | | delete[] kbuf_; | |
| | | if (ksiz > NUMBUFSIZ) ksiz = NUMBUFSIZ; | |
| | | kbuf_ = new char[ksiz]; | |
| | | std::memcpy(kbuf_, kbuf, ksiz); | |
| | | ksiz_ = ksiz; | |
| | | } | |
| | | /** | |
| | | * Begin the cycle of ciper salt. | |
| | | * @param salt the additional cipher salt. | |
| | | */ | |
| | | void begin_cycle(uint64_t salt = 0) { | |
| | | salt_ = salt; | |
| | | cycle_ = true; | |
| | | } | |
| | | private: | |
| | | /** | |
| | | * Compress a serial data. | |
| | | */ | |
| char* compress(const void* buf, size_t size, size_t* sp) { | | char* compress(const void* buf, size_t size, size_t* sp) { | |
|
| _assert_(buf && sp); | | _assert_(buf && size <= MEMMAXSIZ && sp); | |
| return Zlib::compress(Zlib::GZIP, buf, size, sp); | | uint64_t salt = cycle_ ? salt_.add(1) : 0; | |
| | | char kbuf[NUMBUFSIZ*2]; | |
| | | writefixnum(kbuf, salt, sizeof(salt)); | |
| | | std::memcpy(kbuf + sizeof(salt), kbuf_, ksiz_); | |
| | | char* zbuf = new char[NUMBUFSIZ+size]; | |
| | | char* wp = zbuf; | |
| | | writefixnum(wp, salt, sizeof(salt)); | |
| | | wp += sizeof(salt); | |
| | | arccipher(buf, size, kbuf, sizeof(salt) + ksiz_, wp); | |
| | | if (cycle_) { | |
| | | size_t range = size < sizeof(uint64_t) ? size : sizeof(uint64_t); | |
| | | salt_.add(hashmurmur(wp, range) << 32); | |
| | | } | |
| | | *sp = sizeof(salt) + size; | |
| | | return zbuf; | |
| } | | } | |
|
| | | /** | |
| | | * Decompress a serial data. | |
| | | */ | |
| char* decompress(const void* buf, size_t size, size_t* sp) { | | char* decompress(const void* buf, size_t size, size_t* sp) { | |
|
| _assert_(buf && sp); | | _assert_(buf && size <= MEMMAXSIZ && sp); | |
| return Zlib::decompress(Zlib::GZIP, buf, size, sp); | | if (size < sizeof(uint64_t)) return NULL; | |
| | | char kbuf[NUMBUFSIZ*2]; | |
| | | std::memcpy(kbuf, buf, sizeof(uint64_t)); | |
| | | std::memcpy(kbuf + sizeof(uint64_t), kbuf_, ksiz_); | |
| | | buf = (char*)buf + sizeof(uint64_t); | |
| | | size -= sizeof(uint64_t); | |
| | | char* zbuf = new char[size]; | |
| | | arccipher(buf, size, kbuf, sizeof(uint64_t) + ksiz_, zbuf); | |
| | | *sp = size; | |
| | | return zbuf; | |
| } | | } | |
|
| | | /** The pointer to the key. */ | |
| | | char* kbuf_; | |
| | | /** The size of the key. */ | |
| | | size_t ksiz_; | |
| | | /** The cipher salt. */ | |
| | | AtomicInt64 salt_; | |
| | | /** The flag of the salt cycle */ | |
| | | bool cycle_; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Prepared variable of the compressor with the Zlib raw mode. | | * Prepared variable of the compressor with the Zlib raw mode. | |
| */ | | */ | |
|
| extern ZlibRawCompressor ZLIBRAWCOMP; | | extern ZlibCompressor<Zlib::RAW> ZLIBRAWCOMP; | |
| | | | |
| /** | | | |
| * Prepared variable of the compressor with the Zlib deflate mode. | | | |
| */ | | | |
| extern ZlibDeflateCompressor ZLIBDEFLCOMP; | | | |
| | | | |
| /** | | | |
| * Prepared variable of the compressor with the Zlib gzip mode. | | | |
| */ | | | |
| extern ZlibGzipCompressor ZLIBGZIPCOMP; | | | |
| | | | |
| } // common namespace | | } // common namespace | |
| | | | |
| #endif // duplication check | | #endif // duplication check | |
| | | | |
| // END OF FILE | | // END OF FILE | |
| | | | |
End of changes. 21 change blocks. |
| 41 lines changed or deleted | | 109 lines changed or added | |
|
| kcfile.h | | kcfile.h | |
| /**************************************************************************
*********************** | | /**************************************************************************
*********************** | |
| * Filesystem abstraction | | * Filesystem abstraction | |
|
| * Copyright (C) 2009-
2010 Mikio Hirabayashi | | * Copyright
(C) 2009-2010 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 240 | | skipping to change at line 240 | |
| * Get the path of the file. | | * Get the path of the file. | |
| * @return the path of the file in bytes, or an empty string on failure. | | * @return the path of the file in bytes, or an empty string on failure. | |
| */ | | */ | |
| std::string path() const; | | std::string path() const; | |
| /** | | /** | |
| * Check whether the file was recovered or not. | | * Check whether the file was recovered or not. | |
| * @return true if recovered, or false if not. | | * @return true if recovered, or false if not. | |
| */ | | */ | |
| bool recovered() const; | | bool recovered() const; | |
| /** | | /** | |
|
| | | * Read the whole data from a file. | |
| | | * @param path the path of a file. | |
| | | * @param sp the pointer to the variable into which the size of the regio | |
| | | n of the return value | |
| | | * is assigned. | |
| | | * @param limit the limit length to read. If it is nagative, no limit is | |
| | | specified. | |
| | | * @return the pointer to the region of the read data, or NULL on failure | |
| | | . | |
| | | * @note Because an additional zero code is appended at the end of the re | |
| | | gion of the return | |
| | | * value, the return value can be treated as a C-style string. Because t | |
| | | he region of the | |
| | | * return value is allocated with the the new[] operator, it should be re | |
| | | leased with the | |
| | | * delete[] operator when it is no longer in use. | |
| | | */ | |
| | | static char* read_file(const std::string& path, int64_t* sp, int64_t limi | |
| | | t = -1); | |
| | | /** | |
| | | * Write the whole data into a file. | |
| | | * @param path the path of a file. | |
| | | * @param buf the data buffer to write. | |
| | | * @param size the size of the data buffer. | |
| | | * @return true on success, or false on failure. | |
| | | * @note The existing file corresponding to the path is overwritten. If | |
| | | no file corresponds | |
| | | * to the path, a new file is created. | |
| | | */ | |
| | | static bool write_file(const std::string& path, const char* buf, int64_t | |
| | | size); | |
| | | /** | |
| * Get the status information of a file. | | * Get the status information of a file. | |
| * @param path the path of a file. | | * @param path the path of a file. | |
|
| * @param buf a structure of status information. | | * @param buf a structure of status information. If it is NULL, it is om
itted. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
|
| static bool status(const std::string& path, Status* buf); | | static bool status(const std::string& path, Status* buf = NULL); | |
| /** | | /** | |
| * Get the absolute path of a file. | | * Get the absolute path of a file. | |
| * @param path the path of a file. | | * @param path the path of a file. | |
| * @return the absolute path of the file, or an empty string on failure. | | * @return the absolute path of the file, or an empty string on failure. | |
| */ | | */ | |
| static std::string absolute_path(const std::string& path); | | static std::string absolute_path(const std::string& path); | |
| /** | | /** | |
| * Remove a file. | | * Remove a file. | |
| * @param path the path of a file. | | * @param path the path of a file. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| | | | |
| skipping to change at line 295 | | skipping to change at line 318 | |
| * Get the path of the current working directory. | | * Get the path of the current working directory. | |
| * @return the path of the current working directory, or an empty string
on failure. | | * @return the path of the current working directory, or an empty string
on failure. | |
| */ | | */ | |
| static std::string get_current_directory(); | | static std::string get_current_directory(); | |
| /** | | /** | |
| * Set the current working directory. | | * Set the current working directory. | |
| * @param path the path of a directory. | | * @param path the path of a directory. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| static bool set_current_directory(const std::string& path); | | static bool set_current_directory(const std::string& path); | |
|
| | | /** | |
| | | * Synchronize the whole of the file system with the device. | |
| | | * @return true on success, or false on failure. | |
| | | */ | |
| | | static bool synchronize_whole(); | |
| private: | | private: | |
| /** Dummy constructor to forbid the use. */ | | /** Dummy constructor to forbid the use. */ | |
| File(const File&); | | File(const File&); | |
| /** Dummy Operator to forbid the use. */ | | /** Dummy Operator to forbid the use. */ | |
| File& operator =(const File&); | | File& operator =(const File&); | |
| /** Opaque pointer. */ | | /** Opaque pointer. */ | |
| void* opq_; | | void* opq_; | |
| }; | | }; | |
| | | | |
|
| | | /** | |
| | | * Directory stream abstraction. | |
| | | */ | |
| | | class DirStream { | |
| | | public: | |
| | | /** | |
| | | * Default constructor. | |
| | | */ | |
| | | explicit DirStream(); | |
| | | /** | |
| | | * Destructor. | |
| | | * @note If the file is not closed, it is closed implicitly. | |
| | | */ | |
| | | ~DirStream(); | |
| | | /** | |
| | | * Open a directory. | |
| | | * @param path the path of a directory. | |
| | | * @return true on success, or false on failure. | |
| | | */ | |
| | | bool open(const std::string& path); | |
| | | /** | |
| | | * Close the file. | |
| | | * @return true on success, or false on failure. | |
| | | */ | |
| | | bool close(); | |
| | | /** | |
| | | * Read the next file in the directory. | |
| | | * @param path a string to store the file path. | |
| | | * @return true on success, or false on failure. | |
| | | */ | |
| | | bool read(std::string* path); | |
| | | private: | |
| | | /** Dummy constructor to forbid the use. */ | |
| | | DirStream(const DirStream&); | |
| | | /** Dummy Operator to forbid the use. */ | |
| | | DirStream& operator =(const DirStream&); | |
| | | /** Opaque pointer. */ | |
| | | void* opq_; | |
| | | }; | |
| | | | |
| } // common namespace | | } // common namespace | |
| | | | |
| #endif // duplication check | | #endif // duplication check | |
| | | | |
| // END OF FILE | | // END OF FILE | |
| | | | |
End of changes. 6 change blocks. |
| 3 lines changed or deleted | | 80 lines changed or added | |
|
| kchashdb.h | | kchashdb.h | |
| /**************************************************************************
*********************** | | /**************************************************************************
*********************** | |
| * File hash database | | * File hash database | |
|
| * Copyright (C) 2009-
2010 Mikio Hirabayashi | | * Copyright
(C) 2009-2010 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 436 | | skipping to change at line 436 | |
| tran_(false), trhard_(false), trfbp_() { | | tran_(false), trhard_(false), trfbp_() { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| /** | | /** | |
| * Destructor. | | * Destructor. | |
| * @note If the database is not closed, it is closed implicitly. | | * @note If the database is not closed, it is closed implicitly. | |
| */ | | */ | |
| virtual ~HashDB() { | | virtual ~HashDB() { | |
| _assert_(true); | | _assert_(true); | |
| if (omode_ != 0) close(); | | if (omode_ != 0) close(); | |
|
| if (curs_.size() > 0) { | | if (!curs_.empty()) { | |
| CursorList::const_iterator cit = curs_.begin(); | | CursorList::const_iterator cit = curs_.begin(); | |
| CursorList::const_iterator citend = curs_.end(); | | CursorList::const_iterator citend = curs_.end(); | |
| while (cit != citend) { | | while (cit != citend) { | |
| Cursor* cur = *cit; | | Cursor* cur = *cit; | |
| cur->db_ = NULL; | | cur->db_ = NULL; | |
| cit++; | | cit++; | |
| } | | } | |
| } | | } | |
| } | | } | |
| /** | | /** | |
| | | | |
| skipping to change at line 599 | | skipping to change at line 599 | |
| lsiz_ = roff_; | | lsiz_ = roff_; | |
| if (!file_.truncate(lsiz_)) { | | if (!file_.truncate(lsiz_)) { | |
| set_error(__FILE__, __LINE__, Error::SYSTEM, file_.error()); | | set_error(__FILE__, __LINE__, Error::SYSTEM, file_.error()); | |
| file_.close(); | | file_.close(); | |
| return false; | | return false; | |
| } | | } | |
| if (!dump_meta()) { | | if (!dump_meta()) { | |
| file_.close(); | | file_.close(); | |
| return false; | | return false; | |
| } | | } | |
|
| | | if (autosync_ && !File::synchronize_whole()) { | |
| | | set_error(__FILE__, __LINE__, Error::SYSTEM, "synchronizing the fil | |
| | | e system failed"); | |
| | | file_.close(); | |
| | | return false; | |
| | | } | |
| } | | } | |
| if (!load_meta()) { | | if (!load_meta()) { | |
| file_.close(); | | file_.close(); | |
| return false; | | return false; | |
| } | | } | |
| calc_meta(); | | calc_meta(); | |
| uint8_t chksum = calc_checksum(); | | uint8_t chksum = calc_checksum(); | |
| if (chksum != chksum_) { | | if (chksum != chksum_) { | |
| set_error(__FILE__, __LINE__, Error::INVALID, "invalid module checksu
m"); | | set_error(__FILE__, __LINE__, Error::INVALID, "invalid module checksu
m"); | |
| report(__FILE__, __LINE__, "info", "saved=%02X calculated=%02X", | | report(__FILE__, __LINE__, "info", "saved=%02X calculated=%02X", | |
|
| (unsigned)chksum, (unsigned)chksum_); | | (unsigned)chksum_, (unsigned)chksum); | |
| file_.close(); | | file_.close(); | |
| return false; | | return false; | |
| } | | } | |
| if (((flags_ & FOPEN) || (flags_ & FFATAL)) && !(mode & ONOREPAIR) && !
(mode & ONOLOCK) && | | if (((flags_ & FOPEN) || (flags_ & FFATAL)) && !(mode & ONOREPAIR) && !
(mode & ONOLOCK) && | |
| !reorganize_file(path)) { | | !reorganize_file(path)) { | |
| file_.close(); | | file_.close(); | |
| return false; | | return false; | |
| } | | } | |
| if (type_ == 0 || apow_ > HDBMAXAPOW || fpow_ > HDBMAXFPOW || | | if (type_ == 0 || apow_ > HDBMAXAPOW || fpow_ > HDBMAXFPOW || | |
| bnum_ < 1 || count_ < 0 || lsiz_ < roff_) { | | bnum_ < 1 || count_ < 0 || lsiz_ < roff_) { | |
| | | | |
| skipping to change at line 1156 | | skipping to change at line 1161 | |
| * @param file the file name of the epicenter. | | * @param file the file name of the epicenter. | |
| * @param line the line number of the epicenter. | | * @param line the line number of the epicenter. | |
| * @param type the type string. | | * @param type the type string. | |
| * @param format the printf-like format string. | | * @param format the printf-like format string. | |
| * @param ... used according to the format string. | | * @param ... used according to the format string. | |
| */ | | */ | |
| void report(const char* file, int32_t line, const char* type, | | void report(const char* file, int32_t line, const char* type, | |
| const char* format, ...) { | | const char* format, ...) { | |
| _assert_(file && line > 0 && type && format); | | _assert_(file && line > 0 && type && format); | |
| if (!erstrm_) return; | | if (!erstrm_) return; | |
|
| const std::string& path = path_.size() > 0 ? path_ : "-"; | | const std::string& path = path_.empty() ? "-" : path_; | |
| std::string message; | | std::string message; | |
| va_list ap; | | va_list ap; | |
| va_start(ap, format); | | va_start(ap, format); | |
| strprintf(&message, format, ap); | | strprintf(&message, format, ap); | |
| va_end(ap); | | va_end(ap); | |
| *erstrm_ << "[" << type << "]: " << path << ": " << file << ": " << lin
e; | | *erstrm_ << "[" << type << "]: " << path << ": " << file << ": " << lin
e; | |
| *erstrm_ << ": " << message << std::endl; | | *erstrm_ << ": " << message << std::endl; | |
| } | | } | |
| /** | | /** | |
| * Report the content of a binary buffer for debugging. | | * Report the content of a binary buffer for debugging. | |
| | | | |
| skipping to change at line 1926 | | skipping to change at line 1931 | |
| if (fbpnum_ > 0) boff_ += width_ * 2 + sizeof(uint8_t) * 2; | | if (fbpnum_ > 0) boff_ += width_ * 2 + sizeof(uint8_t) * 2; | |
| roff_ = boff_ + width_ * bnum_; | | roff_ = boff_ + width_ * bnum_; | |
| int64_t rem = roff_ % align_; | | int64_t rem = roff_ % align_; | |
| if (rem > 0) roff_ += align_ - rem; | | if (rem > 0) roff_ += align_ - rem; | |
| dfcur_ = roff_; | | dfcur_ = roff_; | |
| frgcnt_ = 0; | | frgcnt_ = 0; | |
| tran_ = false; | | tran_ = false; | |
| } | | } | |
| /** | | /** | |
| * Calculate the module checksum. | | * Calculate the module checksum. | |
|
| | | * @return the module checksum. | |
| */ | | */ | |
| uint8_t calc_checksum() { | | uint8_t calc_checksum() { | |
| _assert_(true); | | _assert_(true); | |
| const char* kbuf = HDBCHKSUMSEED; | | const char* kbuf = HDBCHKSUMSEED; | |
| size_t ksiz = sizeof(HDBCHKSUMSEED) - 1; | | size_t ksiz = sizeof(HDBCHKSUMSEED) - 1; | |
| char* zbuf = NULL; | | char* zbuf = NULL; | |
| size_t zsiz = 0; | | size_t zsiz = 0; | |
| if (comp_) { | | if (comp_) { | |
| zbuf = comp_->compress(kbuf, ksiz, &zsiz); | | zbuf = comp_->compress(kbuf, ksiz, &zsiz); | |
| if (!zbuf) return 0; | | if (!zbuf) return 0; | |
| | | | |
| skipping to change at line 2874 | | skipping to change at line 2880 | |
| } | | } | |
| delete[] blocks; | | delete[] blocks; | |
| delete[] rbuf; | | delete[] rbuf; | |
| return true; | | return true; | |
| } | | } | |
| /** | | /** | |
| * Disable all cursors. | | * Disable all cursors. | |
| */ | | */ | |
| void disable_cursors() { | | void disable_cursors() { | |
| _assert_(true); | | _assert_(true); | |
|
| if (curs_.size() < 1) return; | | if (curs_.empty()) return; | |
| CursorList::const_iterator cit = curs_.begin(); | | CursorList::const_iterator cit = curs_.begin(); | |
| CursorList::const_iterator citend = curs_.end(); | | CursorList::const_iterator citend = curs_.end(); | |
| while (cit != citend) { | | while (cit != citend) { | |
| Cursor* cur = *cit; | | Cursor* cur = *cit; | |
| cur->off_ = 0; | | cur->off_ = 0; | |
| cit++; | | cit++; | |
| } | | } | |
| } | | } | |
| /** | | /** | |
| * Escape cursors on a free block. | | * Escape cursors on a free block. | |
| * @param off the offset of the free block. | | * @param off the offset of the free block. | |
| * @param dest the destination offset. | | * @param dest the destination offset. | |
| */ | | */ | |
| void escape_cursors(int64_t off, int64_t dest) { | | void escape_cursors(int64_t off, int64_t dest) { | |
| _assert_(off >= 0 && dest >= 0); | | _assert_(off >= 0 && dest >= 0); | |
|
| if (curs_.size() < 1) return; | | if (curs_.empty()) return; | |
| CursorList::const_iterator cit = curs_.begin(); | | CursorList::const_iterator cit = curs_.begin(); | |
| CursorList::const_iterator citend = curs_.end(); | | CursorList::const_iterator citend = curs_.end(); | |
| while (cit != citend) { | | while (cit != citend) { | |
| Cursor* cur = *cit; | | Cursor* cur = *cit; | |
| if (cur->end_ == off) { | | if (cur->end_ == off) { | |
| cur->end_ = dest; | | cur->end_ = dest; | |
| if (cur->off_ >= cur->end_) cur->off_ = 0; | | if (cur->off_ >= cur->end_) cur->off_ = 0; | |
| } | | } | |
| if (cur->off_ == off) { | | if (cur->off_ == off) { | |
| cur->off_ = dest; | | cur->off_ = dest; | |
| if (cur->off_ >= cur->end_) cur->off_ = 0; | | if (cur->off_ >= cur->end_) cur->off_ = 0; | |
| } | | } | |
| cit++; | | cit++; | |
| } | | } | |
| } | | } | |
| /** | | /** | |
| * Trim invalid cursors. | | * Trim invalid cursors. | |
| */ | | */ | |
| void trim_cursors() { | | void trim_cursors() { | |
| _assert_(true); | | _assert_(true); | |
|
| if (curs_.size() < 1) return; | | if (curs_.empty()) return; | |
| int64_t end = lsiz_; | | int64_t end = lsiz_; | |
| CursorList::const_iterator cit = curs_.begin(); | | CursorList::const_iterator cit = curs_.begin(); | |
| CursorList::const_iterator citend = curs_.end(); | | CursorList::const_iterator citend = curs_.end(); | |
| while (cit != citend) { | | while (cit != citend) { | |
| Cursor* cur = *cit; | | Cursor* cur = *cit; | |
| if (cur->off_ >= end) { | | if (cur->off_ >= end) { | |
| cur->off_ = 0; | | cur->off_ = 0; | |
| } else if (cur->end_ > end) { | | } else if (cur->end_ > end) { | |
| cur->end_ = end; | | cur->end_ = end; | |
| } | | } | |
| | | | |
End of changes. 9 change blocks. |
| 7 lines changed or deleted | | 14 lines changed or added | |
|
| kclangc.h | | kclangc.h | |
| /**************************************************************************
*********************** | | /**************************************************************************
*********************** | |
| * C language binding | | * C language binding | |
|
| * Copyright (C) 2009-
2010 Mikio Hirabayashi | | * Copyright
(C) 2009-2010 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 244 | | skipping to change at line 244 | |
| */ | | */ | |
| void kcdbdel(KCDB* db); | | void kcdbdel(KCDB* db); | |
| | | | |
| /** | | /** | |
| * Open a database file. | | * Open a database file. | |
| * @param db a database object. | | * @param db a database object. | |
| * @param path the path of a database file. If it is "-", the database wil
l be a prototype | | * @param path the path of a database file. If it is "-", the database wil
l be a prototype | |
| * hash database. If it is "+", the database will be a prototype tree data
base. If it is | | * hash database. If it is "+", the database will be a prototype tree data
base. If it is | |
| * "*", the database will be a cache database. If its suffix is ".kch", th
e database will be | | * "*", the database will be a cache database. If its suffix is ".kch", th
e database will be | |
| * a file hash database. If its suffix is ".kct", the database will be a f
ile tree database. | | * a file hash database. If its suffix is ".kct", the database will be a f
ile tree database. | |
|
| * Otherwise, this function fails. Tuning parameters can trail the name, s | | * If its suffix is ".kcd", the database will be a directory database. Oth | |
| eparated by "#". | | erwise, this | |
| * Each parameter is composed of the name and the value, separated by "=". | | * function fails. Tuning parameters can trail the name, separated by "#". | |
| If the "type" | | Each parameter is | |
| * parameter is specified, the database type is determined by the value in | | * composed of the name and the value, separated by "=". If the "type" par | |
| "-", "+", "*", | | ameter is specified, | |
| * "kch", and "kct". The prototype hash hash database and the prototype tr | | * the database type is determined by the value in "-", "+", "*", "kch", "k | |
| ee database do not | | ct", and "kcd". The | |
| * support any other tuning parameter. The cache database supports "bnum", | | * prototype hash database and the prototype tree database do not support a | |
| "capcount", and | | ny other tuning | |
| * "capsize". The file hash database supports "apow", "fpow", "opts", "bnu | | * parameter. The cache database supports "bnum", "capcount", and "capsize | |
| m", "msiz", | | ". The file hash | |
| * "dfunit", "erstrm", and "ervbs". The file tree database supports all pa | | * database supports "apow", "fpow", "opts", "bnum", "msiz", "dfunit", "zco | |
| rameters of the | | mp", "erstrm", | |
| * file hash database and "psiz", "rcomp", "pccap" in addition. | | * "ervbs", and "zkey". The file tree database supports all parameters of | |
| | | the file hash | |
| | | * database and "psiz", "rcomp", "pccap" in addition. The directory databa | |
| | | se supports "opts", | |
| | | * "zcomp", and "zkey". | |
| * @param mode the connection mode. KCOWRITER as a writer, KCOREADER as a
reader. | | * @param mode the connection mode. KCOWRITER as a writer, KCOREADER as a
reader. | |
| * The following may be added to the writer mode by bitwise-or: KCOCREATE,
which means | | * The following may be added to the writer mode by bitwise-or: KCOCREATE,
which means | |
| * it creates a new database if the file does not exist, KCOTRUNCATE, which
means it | | * it creates a new database if the file does not exist, KCOTRUNCATE, which
means it | |
| * creates a new database regardless if the file exists, KCOAUTOTRAN, which
means each | | * creates a new database regardless if the file exists, KCOAUTOTRAN, which
means each | |
| * updating operation is performed in implicit transaction, KCOAUTOSYNC, wh
ich means | | * updating operation is performed in implicit transaction, KCOAUTOSYNC, wh
ich means | |
| * each updating operation is followed by implicit synchronization with the
file system. The | | * each updating operation is followed by implicit synchronization with the
file system. The | |
| * following may be added to both of the reader mode and the writer mode by
bitwise-or: | | * following may be added to both of the reader mode and the writer mode by
bitwise-or: | |
| * KCONOLOCK, which means it opens the database file without file locking, | | * KCONOLOCK, which means it opens the database file without file locking, | |
| * KCOTRYLOCK, which means locking is performed without blocking, KCONOREPA
IR, which | | * KCOTRYLOCK, which means locking is performed without blocking, KCONOREPA
IR, which | |
| * means the database file is not repaired implicitly even if file destruct
ion is detected. | | * means the database file is not repaired implicitly even if file destruct
ion is detected. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| * @note The tuning parameter "bnum" corresponds to the original "tune_buck
et" method. | | * @note The tuning parameter "bnum" corresponds to the original "tune_buck
et" method. | |
|
| * "capcount" is for "cap_count". "capsize" is for "cap_size". "apow" is | | * "capcount" is for "cap_count". "capsize" is for "cap_size". "apow" is | |
| for "tune_alignment". | | for | |
| * "fpow" is for "tune_fbp". "opts" is for "tune_options" and the value ca | | * "tune_alignment". "fpow" is for "tune_fbp". "opts" is for "tune_option | |
| n contain "s" for | | s" and the value | |
| * the small option, "l" for the linear option, and "c" for the copmress op | | * can contain "s" for the small option, "l" for the linear option, and "c" | |
| tion. "msiz" is for | | for the compress | |
| * "tune_map". "dfunit" is for "tune_defrag". "erstrm" and "ervbs" are fo | | * option. "msiz" is for "tune_map". "dfunit" is for "tune_defrag". "zco | |
| r | | mp" is for | |
| * "tune_error_reporter" and the formar value can be "stdout" or "stderr" a | | * "tune_compressor" and the value can be "zlib" for the Zlib raw compresso | |
| nd the latter value | | r, "def" for the | |
| * can be "true" or "false". "psiz" is for "tune_page". "rcomp" is for "t | | * Zlib deflate compressor, "gz" for the Zlib gzip compressor, or "arc" for | |
| une_comparator" and | | the Arcfour cipher. | |
| * the value can be "lex" for the lexical comparator or "dec" for the decim | | * "erstrm" and "ervbs" are for "tune_error_reporter" and the formar value | |
| al comparator. | | can be "stdout" or | |
| * "pccap" is for "tune_page_cache". Every opened database must be closed | | * "stderr" and the latter value can be "true" or "false". "zkey" specifie | |
| by the kcdbclose | | s the cipher key of | |
| * function when it is no longer in use. It is not allowed for two or more | | * the compressor. "psiz" is for "tune_page". "rcomp" is for "tune_compar | |
| database objects in | | ator" and the value | |
| * the same process to keep their connections to the same database file at | | * can be "lex" for the lexical comparator or "dec" for the decimal compara | |
| the same time. | | tor. "pccap" is for | |
| | | * "tune_page_cache". Every opened database must be closed by the PolyDB:: | |
| | | close method when it | |
| | | * is no longer in use. It is not allowed for two or more database objects | |
| | | in the same process | |
| | | * to keep their connections to the same database file at the same time. | |
| */ | | */ | |
| int32_t kcdbopen(KCDB* db, const char* path, uint32_t mode); | | int32_t kcdbopen(KCDB* db, const char* path, uint32_t mode); | |
| | | | |
| /** | | /** | |
| * Close the database file. | | * Close the database file. | |
| * @param db a database object. | | * @param db a database object. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| int32_t kcdbclose(KCDB* db); | | int32_t kcdbclose(KCDB* db); | |
| | | | |
| | | | |
End of changes. 3 change blocks. |
| 36 lines changed or deleted | | 45 lines changed or added | |
|
| kcpolydb.h | | kcpolydb.h | |
| /**************************************************************************
*********************** | | /**************************************************************************
*********************** | |
| * Polymorphic database | | * Polymorphic database | |
|
| * Copyright (C) 2009-
2010 Mikio Hirabayashi | | * Copyright
(C) 2009-2010 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 30 | | skipping to change at line 30 | |
| #include <kcdb.h> | | #include <kcdb.h> | |
| #include <kcthread.h> | | #include <kcthread.h> | |
| #include <kcfile.h> | | #include <kcfile.h> | |
| #include <kccompress.h> | | #include <kccompress.h> | |
| #include <kccompare.h> | | #include <kccompare.h> | |
| #include <kcmap.h> | | #include <kcmap.h> | |
| #include <kcprotodb.h> | | #include <kcprotodb.h> | |
| #include <kccachedb.h> | | #include <kccachedb.h> | |
| #include <kchashdb.h> | | #include <kchashdb.h> | |
| #include <kctreedb.h> | | #include <kctreedb.h> | |
|
| | | #include <kcdirdb.h> | |
| | | | |
| namespace kyotocabinet { // common namespace | | namespace kyotocabinet { // common namespace | |
| | | | |
| /** | | /** | |
| * Polymorphic database. | | * Polymorphic database. | |
| */ | | */ | |
| class PolyDB : public FileDB { | | class PolyDB : public FileDB { | |
| public: | | public: | |
| class Cursor; | | class Cursor; | |
| public: | | public: | |
| | | | |
| skipping to change at line 154 | | skipping to change at line 155 | |
| /** 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. */ | |
| PolyDB* db_; | | PolyDB* db_; | |
| /** The inner cursor. */ | | /** The inner cursor. */ | |
| FileDB::Cursor* cur_; | | FileDB::Cursor* cur_; | |
| }; | | }; | |
| /** | | /** | |
| * Default constructor. | | * Default constructor. | |
| */ | | */ | |
|
| explicit PolyDB() : type_(TYPEVOID), db_(NULL), error_() { | | explicit PolyDB() : type_(TYPEVOID), db_(NULL), error_(), zcomp_(NULL) { | |
| _assert_(true); | | _assert_(true); | |
| } | | } | |
| /** | | /** | |
| * Constructor. | | * Constructor. | |
| * @param db the internal database object. Its possession is transferred
inside and the | | * @param db the internal database object. Its possession is transferred
inside and the | |
| * object is deleted automatically. | | * object is deleted automatically. | |
| */ | | */ | |
|
| explicit PolyDB(FileDB* db) : type_(TYPEMISC), db_(db), error_() { | | explicit PolyDB(FileDB* db) : type_(TYPEMISC), db_(db), error_(), zcomp_(
NULL) { | |
| _assert_(db); | | _assert_(db); | |
| } | | } | |
| /** | | /** | |
| * 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 ~PolyDB() { | | virtual ~PolyDB() { | |
| _assert_(true); | | _assert_(true); | |
| if (type_ != TYPEVOID) close(); | | if (type_ != TYPEVOID) close(); | |
|
| | | delete zcomp_; | |
| } | | } | |
| /** | | /** | |
| * Accept a visitor to a record. | | * Accept a visitor to a record. | |
| * @param kbuf the pointer to the key region. | | * @param kbuf the pointer to the key region. | |
| * @param ksiz the size of the key region. | | * @param ksiz the size of the key region. | |
| * @param visitor a visitor object. | | * @param visitor a visitor object. | |
| * @param 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. | |
| * @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. | | * same record are blocked. | |
| | | | |
| skipping to change at line 234 | | skipping to change at line 236 | |
| return; | | return; | |
| } | | } | |
| db_->set_error(code, message); | | db_->set_error(code, message); | |
| } | | } | |
| /** | | /** | |
| * Open a database file. | | * Open a database file. | |
| * @param path the path of a database file. If it is "-", the database w
ill be a prototype | | * @param path the path of a database file. If it is "-", the database w
ill be a prototype | |
| * hash database. If it is "+", the database will be a prototype tree da
tabase. If it is | | * hash database. If it is "+", the database will be a prototype tree da
tabase. If it is | |
| * "*", the database will be a cache database. If its suffix is ".kch",
the database will be | | * "*", the database will be a cache database. If its suffix is ".kch",
the database will be | |
| * a file hash database. If its suffix is ".kct", the database will be a
file tree database. | | * a file hash database. If its suffix is ".kct", the database will be a
file tree database. | |
|
| * Otherwise, this function fails. Tuning parameters can trail the name, | | * If its suffix is ".kcd", the database will be a directory database. O | |
| separated by "#". | | therwise, this | |
| * Each parameter is composed of the name and the value, separated by "=" | | * function fails. Tuning parameters can trail the name, separated by "# | |
| . If the "type" | | ". Each parameter is | |
| * parameter is specified, the database type is determined by the value i | | * composed of the name and the value, separated by "=". If the "type" p | |
| n "-", "+", "*", | | arameter is specified, | |
| * "kch", and "kct". The prototype hash hash database and the prototype | | * the database type is determined by the value in "-", "+", "*", "kch", | |
| tree database do not | | "kct", and "kcd". The | |
| * support any other tuning parameter. The cache database supports "bnum | | * prototype hash database and the prototype tree database do not support | |
| ", "capcount", and | | any other tuning | |
| * "capsize". The file hash database supports "apow", "fpow", "opts", "b | | * parameter. The cache database supports "bnum", "capcount", and "capsi | |
| num", "msiz", | | ze". The file hash | |
| * "dfunit", "erstrm", and "ervbs". The file tree database supports all | | * database supports "apow", "fpow", "opts", "bnum", "msiz", "dfunit", "z | |
| parameters of the | | comp", "erstrm", | |
| * file hash database and "psiz", "rcomp", "pccap" in addition. | | * "ervbs", and "zkey". The file tree database supports all parameters o | |
| | | f the file hash | |
| | | * database and "psiz", "rcomp", "pccap" in addition. The directory data | |
| | | base supports "opts", | |
| | | * "zcomp", and "zkey". | |
| * @param mode the connection mode. PolyDB::OWRITER as a writer, PolyDB:
:OREADER as a | | * @param mode the connection mode. PolyDB::OWRITER as a writer, PolyDB:
:OREADER as a | |
| * reader. The following may be added to the writer mode by bitwise-or:
PolyDB::OCREATE, | | * reader. The following may be added to the writer mode by bitwise-or:
PolyDB::OCREATE, | |
| * which means it creates a new database if the file does not exist, Poly
DB::OTRUNCATE, which | | * which means it creates a new database if the file does not exist, Poly
DB::OTRUNCATE, which | |
| * means it creates a new database regardless if the file exists, PolyDB:
:OAUTOTRAN, which | | * means it creates a new database regardless if the file exists, PolyDB:
:OAUTOTRAN, which | |
| * means each updating operation is performed in implicit transaction, Po
lyDB::OAUTOSYNC, | | * means each updating operation is performed in implicit transaction, Po
lyDB::OAUTOSYNC, | |
| * which means each updating operation is followed by implicit synchroniz
ation with the file | | * which means each updating operation is followed by implicit synchroniz
ation with the file | |
| * system. The following may be added to both of the reader mode and the
writer mode by | | * system. The following may be added to both of the reader mode and the
writer mode by | |
| * bitwise-or: PolyDB::ONOLOCK, which means it opens the database file wi
thout file locking, | | * bitwise-or: PolyDB::ONOLOCK, which means it opens the database file wi
thout file locking, | |
| * PolyDB::OTRYLOCK, which means locking is performed without blocking, P
olyDB::ONOREPAIR, | | * PolyDB::OTRYLOCK, which means locking is performed without blocking, P
olyDB::ONOREPAIR, | |
| * which means the database file is not repaired implicitly even if file
destruction is | | * which means the database file is not repaired implicitly even if file
destruction is | |
| * detected. | | * detected. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| * @note The tuning parameter "bnum" corresponds to the original "tune_bu
cket" method. | | * @note The tuning parameter "bnum" corresponds to the original "tune_bu
cket" method. | |
| * "capcount" is for "cap_count". "capsize" is for "cap_size". "apow" i
s for | | * "capcount" is for "cap_count". "capsize" is for "cap_size". "apow" i
s for | |
| * "tune_alignment". "fpow" is for "tune_fbp". "opts" is for "tune_opti
ons" and the value | | * "tune_alignment". "fpow" is for "tune_fbp". "opts" is for "tune_opti
ons" and the value | |
|
| * can contain "s" for the small option, "l" for the linear option, and " | | * can contain "s" for the small option, "l" for the linear option, and " | |
| c" for the copmress | | c" for the compress | |
| * option. "msiz" is for "tune_map". "dfunit" is for "tune_defrag". "e | | * option. "msiz" is for "tune_map". "dfunit" is for "tune_defrag". "z | |
| rstrm" and "ervbs" | | comp" is for | |
| * are for "tune_error_reporter" and the formar value can be "stdout" or | | * "tune_compressor" and the value can be "zlib" for the Zlib raw compres | |
| "stderr" and the | | sor, "def" for the | |
| * latter value can be "true" or "false". "psiz" is for "tune_page". "r | | * Zlib deflate compressor, "gz" for the Zlib gzip compressor, or "arc" f | |
| comp" is for | | or the Arcfour cipher. | |
| * "tune_comparator" and the value can be "lex" for the lexical comparato | | * "erstrm" and "ervbs" are for "tune_error_reporter" and the formar valu | |
| r or "dec" for the | | e can be "stdout" or | |
| * decimal comparator. "pccap" is for "tune_page_cache". Every opened d | | * "stderr" and the latter value can be "true" or "false". "zkey" specif | |
| atabase must be | | ies the cipher key of | |
| * closed by the PolyDB::close method when it is no longer in use. It is | | * the compressor. "psiz" is for "tune_page". "rcomp" is for "tune_comp | |
| not allowed for two | | arator" and the value | |
| * or more database objects in the same process to keep their connections | | * can be "lex" for the lexical comparator or "dec" for the decimal compa | |
| to the same | | rator. "pccap" is for | |
| * database file at the same time. | | * "tune_page_cache". Every opened database must be closed by the PolyDB | |
| | | ::close method when it | |
| | | * is no longer in use. It is not allowed for two or more database objec | |
| | | ts in the same process | |
| | | * to keep their connections to the same database file at the same time. | |
| */ | | */ | |
| bool open(const std::string& path, uint32_t mode = OWRITER | OCREATE) { | | bool open(const std::string& path, uint32_t mode = OWRITER | OCREATE) { | |
| _assert_(true); | | _assert_(true); | |
| if (type_ == TYPEMISC) return db_->open(path, mode); | | if (type_ == TYPEMISC) return db_->open(path, mode); | |
| if (type_ != TYPEVOID) { | | if (type_ != TYPEVOID) { | |
| set_error(Error::INVALID, "already opened"); | | set_error(Error::INVALID, "already opened"); | |
| return false; | | return false; | |
| } | | } | |
| std::vector<std::string> elems; | | std::vector<std::string> elems; | |
| strsplit(path, '#', &elems); | | strsplit(path, '#', &elems); | |
| | | | |
| skipping to change at line 288 | | skipping to change at line 294 | |
| int64_t bnum = -1; | | int64_t bnum = -1; | |
| int64_t capcount = -1; | | int64_t capcount = -1; | |
| int64_t capsize = -1; | | int64_t capsize = -1; | |
| int32_t apow = -1; | | int32_t apow = -1; | |
| int32_t fpow = -1; | | int32_t fpow = -1; | |
| bool tsmall = false; | | bool tsmall = false; | |
| bool tlinear = false; | | bool tlinear = false; | |
| bool tcompress = false; | | bool tcompress = false; | |
| int64_t msiz = -1; | | int64_t msiz = -1; | |
| int64_t dfunit = -1; | | int64_t dfunit = -1; | |
|
| | | Compressor *zcomp = NULL; | |
| int64_t psiz = -1; | | int64_t psiz = -1; | |
| Comparator *rcomp = NULL; | | Comparator *rcomp = NULL; | |
| int64_t pccap = 0; | | int64_t pccap = 0; | |
| std::ostream* erstrm = NULL; | | std::ostream* erstrm = NULL; | |
| bool ervbs = false; | | bool ervbs = false; | |
|
| | | std::string zkey = ""; | |
| | | ArcfourCompressor *arccomp = NULL; | |
| std::vector<std::string>::iterator it = elems.begin(); | | std::vector<std::string>::iterator it = elems.begin(); | |
| std::vector<std::string>::iterator itend = elems.end(); | | std::vector<std::string>::iterator itend = elems.end(); | |
| if (it != itend) { | | if (it != itend) { | |
| fpath = *it; | | fpath = *it; | |
| it++; | | it++; | |
| } | | } | |
| const char* fstr = fpath.c_str(); | | const char* fstr = fpath.c_str(); | |
| const char* pv = std::strrchr(fstr, File::PATHCHR); | | const char* pv = std::strrchr(fstr, File::PATHCHR); | |
| if (pv) fstr = pv + 1; | | if (pv) fstr = pv + 1; | |
| if (!std::strcmp(fstr, "-")) { | | if (!std::strcmp(fstr, "-")) { | |
| | | | |
| skipping to change at line 316 | | skipping to change at line 325 | |
| } else if (!std::strcmp(fstr, "*")) { | | } else if (!std::strcmp(fstr, "*")) { | |
| type = TYPECACHE; | | type = TYPECACHE; | |
| } else { | | } else { | |
| pv = std::strrchr(fstr, File::EXTCHR); | | pv = std::strrchr(fstr, File::EXTCHR); | |
| if (pv) { | | if (pv) { | |
| pv++; | | pv++; | |
| if (!std::strcmp(pv, "kch") || !std::strcmp(pv, "hdb")) { | | if (!std::strcmp(pv, "kch") || !std::strcmp(pv, "hdb")) { | |
| type = TYPEHASH; | | type = TYPEHASH; | |
| } else if (!std::strcmp(pv, "kct") || !std::strcmp(pv, "tdb")) { | | } else if (!std::strcmp(pv, "kct") || !std::strcmp(pv, "tdb")) { | |
| type = TYPETREE; | | type = TYPETREE; | |
|
| | | } else if (!std::strcmp(pv, "kcd") || !std::strcmp(pv, "ddb")) { | |
| | | type = TYPEDIR; | |
| } | | } | |
| } | | } | |
| } | | } | |
| while (it != itend) { | | while (it != itend) { | |
| std::vector<std::string> fields; | | std::vector<std::string> fields; | |
| if (strsplit(*it, '=', &fields) > 1) { | | if (strsplit(*it, '=', &fields) > 1) { | |
| const char* key = fields[0].c_str(); | | const char* key = fields[0].c_str(); | |
| const char* value = fields[1].c_str(); | | const char* value = fields[1].c_str(); | |
| if (!std::strcmp(key, "type")) { | | if (!std::strcmp(key, "type")) { | |
| if (!std::strcmp(value, "-") || !std::strcmp(value, "phash")) { | | if (!std::strcmp(value, "-") || !std::strcmp(value, "phash")) { | |
| | | | |
| skipping to change at line 337 | | skipping to change at line 348 | |
| } else if (!std::strcmp(value, "+") || !std::strcmp(value, "ptree
")) { | | } else if (!std::strcmp(value, "+") || !std::strcmp(value, "ptree
")) { | |
| type = TYPEPTREE; | | type = TYPEPTREE; | |
| } else if (!std::strcmp(value, "*") || !std::strcmp(value, "cache
")) { | | } else if (!std::strcmp(value, "*") || !std::strcmp(value, "cache
")) { | |
| type = TYPECACHE; | | type = TYPECACHE; | |
| } else if (!std::strcmp(value, "kch") || !std::strcmp(value, "hdb
") || | | } else if (!std::strcmp(value, "kch") || !std::strcmp(value, "hdb
") || | |
| !std::strcmp(value, "hash")) { | | !std::strcmp(value, "hash")) { | |
| type = TYPEHASH; | | type = TYPEHASH; | |
| } else if (!std::strcmp(value, "kct") || !std::strcmp(value, "tdb
") || | | } else if (!std::strcmp(value, "kct") || !std::strcmp(value, "tdb
") || | |
| !std::strcmp(value, "tree")) { | | !std::strcmp(value, "tree")) { | |
| type = TYPETREE; | | type = TYPETREE; | |
|
| | | } else if (!std::strcmp(value, "kcd") || !std::strcmp(value, "ddb | |
| | | ") || | |
| | | !std::strcmp(value, "dir")) { | |
| | | type = TYPEDIR; | |
| } | | } | |
| } else if (!std::strcmp(key, "bnum") || !std::strcmp(key, "buckets"
)) { | | } else if (!std::strcmp(key, "bnum") || !std::strcmp(key, "buckets"
)) { | |
| bnum = atoix(value); | | bnum = atoix(value); | |
| } else if (!std::strcmp(key, "capcount") || !std::strcmp(key, "cap_
count")) { | | } else if (!std::strcmp(key, "capcount") || !std::strcmp(key, "cap_
count")) { | |
| capcount = atoix(value); | | capcount = atoix(value); | |
| } else if (!std::strcmp(key, "capsize") || !std::strcmp(key, "cap_s
ize")) { | | } else if (!std::strcmp(key, "capsize") || !std::strcmp(key, "cap_s
ize")) { | |
| capsize = atoix(value); | | capsize = atoix(value); | |
| } else if (!std::strcmp(key, "apow") || !std::strcmp(key, "alignmen
t")) { | | } else if (!std::strcmp(key, "apow") || !std::strcmp(key, "alignmen
t")) { | |
| apow = atoix(value); | | apow = atoix(value); | |
| } else if (!std::strcmp(key, "fpow") || !std::strcmp(key, "fbp")) { | | } else if (!std::strcmp(key, "fpow") || !std::strcmp(key, "fbp")) { | |
| fpow = atoix(value); | | fpow = atoix(value); | |
| } else if (!std::strcmp(key, "opts") || !std::strcmp(key, "options"
)) { | | } else if (!std::strcmp(key, "opts") || !std::strcmp(key, "options"
)) { | |
| if (std::strchr(value, 's')) tsmall = true; | | if (std::strchr(value, 's')) tsmall = true; | |
| if (std::strchr(value, 'l')) tlinear = true; | | if (std::strchr(value, 'l')) tlinear = true; | |
| if (std::strchr(value, 'c')) tcompress = true; | | if (std::strchr(value, 'c')) tcompress = true; | |
| } else if (!std::strcmp(key, "msiz") || !std::strcmp(key, "map")) { | | } else if (!std::strcmp(key, "msiz") || !std::strcmp(key, "map")) { | |
| msiz = atoix(value); | | msiz = atoix(value); | |
| } else if (!std::strcmp(key, "dfunit") || !std::strcmp(key, "defrag
")) { | | } else if (!std::strcmp(key, "dfunit") || !std::strcmp(key, "defrag
")) { | |
| dfunit = atoix(value); | | dfunit = atoix(value); | |
|
| | | } else if (!std::strcmp(key, "zcomp") || !std::strcmp(key, "compres | |
| | | sor")) { | |
| | | delete zcomp; | |
| | | zcomp = NULL; | |
| | | arccomp = NULL; | |
| | | if (!std::strcmp(value, "zlib") || !std::strcmp(value, "raw")) { | |
| | | zcomp = new ZlibCompressor<Zlib::RAW>; | |
| | | } else if (!std::strcmp(value, "def") || !std::strcmp(value, "def | |
| | | late")) { | |
| | | zcomp = new ZlibCompressor<Zlib::DEFLATE>; | |
| | | } else if (!std::strcmp(value, "gz") || !std::strcmp(value, "gzip | |
| | | ")) { | |
| | | zcomp = new ZlibCompressor<Zlib::GZIP>; | |
| | | } else if (!std::strcmp(value, "arc") || !std::strcmp(value, "rc4 | |
| | | ")) { | |
| | | arccomp = new ArcfourCompressor(); | |
| | | zcomp = arccomp; | |
| | | } | |
| } else if (!std::strcmp(key, "psiz") || !std::strcmp(key, "page"))
{ | | } else if (!std::strcmp(key, "psiz") || !std::strcmp(key, "page"))
{ | |
| psiz = atoix(value); | | psiz = atoix(value); | |
| } else if (!std::strcmp(key, "pccap") || !std::strcmp(key, "cache")
) { | | } else if (!std::strcmp(key, "pccap") || !std::strcmp(key, "cache")
) { | |
| pccap = atoix(value); | | pccap = atoix(value); | |
| } else if (!std::strcmp(key, "rcomp") || !std::strcmp(key, "compara
tor")) { | | } else if (!std::strcmp(key, "rcomp") || !std::strcmp(key, "compara
tor")) { | |
| if (!std::strcmp(value, "lex") || !std::strcmp(value, "lexical"))
{ | | if (!std::strcmp(value, "lex") || !std::strcmp(value, "lexical"))
{ | |
| rcomp = &LEXICALCOMP; | | rcomp = &LEXICALCOMP; | |
| } else if (!std::strcmp(value, "dec") || !std::strcmp(value, "dec
imal")) { | | } else if (!std::strcmp(value, "dec") || !std::strcmp(value, "dec
imal")) { | |
| rcomp = &DECIMALCOMP; | | rcomp = &DECIMALCOMP; | |
| } | | } | |
| } else if (!std::strcmp(key, "erstrm") || !std::strcmp(key, "report
er")) { | | } else if (!std::strcmp(key, "erstrm") || !std::strcmp(key, "report
er")) { | |
| if (!std::strcmp(value, "stdout") || !std::strcmp(value, "cout")
|| | | if (!std::strcmp(value, "stdout") || !std::strcmp(value, "cout")
|| | |
| atoix(value) == 1) { | | atoix(value) == 1) { | |
| erstrm = &std::cout; | | erstrm = &std::cout; | |
| } else if (!std::strcmp(value, "stderr") || !std::strcmp(value, "
cerr") || | | } else if (!std::strcmp(value, "stderr") || !std::strcmp(value, "
cerr") || | |
| atoix(value) == 2) { | | atoix(value) == 2) { | |
| erstrm = &std::cerr; | | erstrm = &std::cerr; | |
| } | | } | |
| } else if (!std::strcmp(key, "ervbs") || !std::strcmp(key, "erv"))
{ | | } else if (!std::strcmp(key, "ervbs") || !std::strcmp(key, "erv"))
{ | |
| ervbs = !std::strcmp(value, "true") || atoix(value) > 0; | | ervbs = !std::strcmp(value, "true") || atoix(value) > 0; | |
|
| | | } else if (!std::strcmp(key, "zkey") || !std::strcmp(key, "pass") | | |
| | | | | |
| | | !std::strcmp(key, "password")) { | |
| | | zkey = value; | |
| } | | } | |
| } | | } | |
| it++; | | it++; | |
| } | | } | |
|
| | | if (zcomp) { | |
| | | delete zcomp_; | |
| | | zcomp_ = zcomp; | |
| | | tcompress = true; | |
| | | } | |
| FileDB *db; | | FileDB *db; | |
| switch (type) { | | switch (type) { | |
| default: { | | default: { | |
| set_error(Error::INVALID, "unknown database type"); | | set_error(Error::INVALID, "unknown database type"); | |
| return false; | | return false; | |
| } | | } | |
| case TYPEPHASH: { | | case TYPEPHASH: { | |
| ProtoHashDB* phdb = new ProtoHashDB(); | | ProtoHashDB* phdb = new ProtoHashDB(); | |
| db = phdb; | | db = phdb; | |
| break; | | break; | |
| | | | |
| skipping to change at line 416 | | skipping to change at line 452 | |
| if (tsmall) opts |= HashDB::TSMALL; | | if (tsmall) opts |= HashDB::TSMALL; | |
| if (tlinear) opts |= HashDB::TLINEAR; | | if (tlinear) opts |= HashDB::TLINEAR; | |
| if (tcompress) opts |= HashDB::TCOMPRESS; | | if (tcompress) opts |= HashDB::TCOMPRESS; | |
| HashDB* hdb = new HashDB(); | | HashDB* hdb = new HashDB(); | |
| if (apow >= 0) hdb->tune_alignment(apow); | | if (apow >= 0) hdb->tune_alignment(apow); | |
| if (fpow >= 0) hdb->tune_fbp(fpow); | | if (fpow >= 0) hdb->tune_fbp(fpow); | |
| if (opts > 0) hdb->tune_options(opts); | | if (opts > 0) hdb->tune_options(opts); | |
| if (bnum > 0) hdb->tune_buckets(bnum); | | if (bnum > 0) hdb->tune_buckets(bnum); | |
| if (msiz >= 0) hdb->tune_map(msiz); | | if (msiz >= 0) hdb->tune_map(msiz); | |
| if (dfunit > 0) hdb->tune_defrag(dfunit); | | if (dfunit > 0) hdb->tune_defrag(dfunit); | |
|
| | | if (zcomp) hdb->tune_compressor(zcomp); | |
| if (erstrm) hdb->tune_error_reporter(erstrm, ervbs); | | if (erstrm) hdb->tune_error_reporter(erstrm, ervbs); | |
| db = hdb; | | db = hdb; | |
| break; | | break; | |
| } | | } | |
| case TYPETREE: { | | case TYPETREE: { | |
| int8_t opts = 0; | | int8_t opts = 0; | |
| if (tsmall) opts |= TreeDB::TSMALL; | | if (tsmall) opts |= TreeDB::TSMALL; | |
| if (tlinear) opts |= TreeDB::TLINEAR; | | if (tlinear) opts |= TreeDB::TLINEAR; | |
| if (tcompress) opts |= TreeDB::TCOMPRESS; | | if (tcompress) opts |= TreeDB::TCOMPRESS; | |
| TreeDB* tdb = new TreeDB(); | | TreeDB* tdb = new TreeDB(); | |
| if (apow >= 0) tdb->tune_alignment(apow); | | if (apow >= 0) tdb->tune_alignment(apow); | |
| if (fpow >= 0) tdb->tune_fbp(fpow); | | if (fpow >= 0) tdb->tune_fbp(fpow); | |
| if (opts > 0) tdb->tune_options(opts); | | if (opts > 0) tdb->tune_options(opts); | |
| if (bnum > 0) tdb->tune_buckets(bnum); | | if (bnum > 0) tdb->tune_buckets(bnum); | |
| if (psiz > 0) tdb->tune_page(psiz); | | if (psiz > 0) tdb->tune_page(psiz); | |
| if (msiz >= 0) tdb->tune_map(msiz); | | if (msiz >= 0) tdb->tune_map(msiz); | |
| if (dfunit > 0) tdb->tune_defrag(dfunit); | | if (dfunit > 0) tdb->tune_defrag(dfunit); | |
|
| | | if (zcomp) tdb->tune_compressor(zcomp); | |
| if (pccap > 0) tdb->tune_page_cache(pccap); | | if (pccap > 0) tdb->tune_page_cache(pccap); | |
| if (rcomp) tdb->tune_comparator(rcomp); | | if (rcomp) tdb->tune_comparator(rcomp); | |
| if (erstrm) tdb->tune_error_reporter(erstrm, ervbs); | | if (erstrm) tdb->tune_error_reporter(erstrm, ervbs); | |
| db = tdb; | | db = tdb; | |
| break; | | break; | |
| } | | } | |
|
| | | case TYPEDIR: { | |
| | | int8_t opts = 0; | |
| | | if (tcompress) opts |= DirDB::TCOMPRESS; | |
| | | DirDB* ddb = new DirDB(); | |
| | | if (opts > 0) ddb->tune_options(opts); | |
| | | if (zcomp) ddb->tune_compressor(zcomp); | |
| | | db = ddb; | |
| | | break; | |
| | | } | |
| } | | } | |
|
| | | if (arccomp) arccomp->set_key(zkey.c_str(), zkey.size()); | |
| if (!db->open(fpath, mode)) { | | if (!db->open(fpath, mode)) { | |
| const Error& error = db->error(); | | const Error& error = db->error(); | |
| set_error(error.code(), error.message()); | | set_error(error.code(), error.message()); | |
| delete db; | | delete db; | |
| return false; | | return false; | |
| } | | } | |
|
| | | if (arccomp) { | |
| | | const std::string& apath = File::absolute_path(fpath); | |
| | | uint64_t hash = (hashmurmur(apath.c_str(), apath.size()) >> 16) << 40 | |
| | | ; | |
| | | hash += (uint64_t)(time() * 256); | |
| | | arccomp->begin_cycle(hash); | |
| | | } | |
| type_ = type; | | type_ = type; | |
| db_ = db; | | db_ = db; | |
| return true; | | return true; | |
| } | | } | |
| /** | | /** | |
| * Close the database file. | | * Close the database file. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool close() { | | bool close() { | |
| _assert_(true); | | _assert_(true); | |
| if (type_ == TYPEVOID) { | | if (type_ == TYPEVOID) { | |
| set_error(Error::INVALID, "not opened"); | | set_error(Error::INVALID, "not opened"); | |
| return false; | | return false; | |
| } | | } | |
| bool err = false; | | bool err = false; | |
| if (!db_->close()) { | | if (!db_->close()) { | |
| const Error& error = db_->error(); | | const Error& error = db_->error(); | |
| set_error(error.code(), error.message()); | | set_error(error.code(), error.message()); | |
| err = true; | | err = true; | |
| } | | } | |
|
| | | delete zcomp_; | |
| delete db_; | | delete db_; | |
| type_ = TYPEVOID; | | type_ = TYPEVOID; | |
| db_ = NULL; | | db_ = NULL; | |
|
| | | zcomp_ = NULL; | |
| return !err; | | return !err; | |
| } | | } | |
| /** | | /** | |
| * Synchronize updated contents with the file and the device. | | * Synchronize updated contents with the file and the device. | |
| * @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. | |
| * @param proc a postprocessor object. If it is NULL, no postprocessing
is performed. | | * @param proc a postprocessor object. If it is NULL, no postprocessing
is performed. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool synchronize(bool hard = false, FileProcessor* proc = NULL) { | | bool synchronize(bool hard = false, FileProcessor* proc = NULL) { | |
| | | | |
| skipping to change at line 621 | | skipping to change at line 677 | |
| /** Dummy constructor to forbid the use. */ | | /** Dummy constructor to forbid the use. */ | |
| PolyDB(const PolyDB&); | | PolyDB(const PolyDB&); | |
| /** Dummy Operator to forbid the use. */ | | /** Dummy Operator to forbid the use. */ | |
| PolyDB& operator =(const PolyDB&); | | PolyDB& operator =(const PolyDB&); | |
| /** The database type. */ | | /** The database type. */ | |
| Type type_; | | Type type_; | |
| /** The internal database. */ | | /** The internal database. */ | |
| FileDB* db_; | | FileDB* db_; | |
| /** The last happened error. */ | | /** The last happened error. */ | |
| TSD<Error> error_; | | TSD<Error> error_; | |
|
| | | /** The custom compressor. */ | |
| | | Compressor* zcomp_; | |
| }; | | }; | |
| | | | |
| } // common namespace | | } // common namespace | |
| | | | |
| #endif // duplication check | | #endif // duplication check | |
| | | | |
| // END OF FILE | | // END OF FILE | |
| | | | |
End of changes. 22 change blocks. |
| 35 lines changed or deleted | | 104 lines changed or added | |
|
| kctreedb.h | | kctreedb.h | |
| /**************************************************************************
*********************** | | /**************************************************************************
*********************** | |
| * File tree database | | * File tree database | |
|
| * Copyright (C) 2009-
2010 Mikio Hirabayashi | | * Copyright
(C) 2009-2010 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 275 | | skipping to change at line 275 | |
| _assert_(true); | | _assert_(true); | |
| while (id > 0) { | | while (id > 0) { | |
| LeafNode* node = db_->load_leaf_node(id, false); | | LeafNode* node = db_->load_leaf_node(id, false); | |
| if (!node) { | | if (!node) { | |
| db_->set_error(__FILE__, __LINE__, Error::BROKEN, "missing leaf n
ode"); | | db_->set_error(__FILE__, __LINE__, Error::BROKEN, "missing leaf n
ode"); | |
| db_->hdb_.report(__FILE__, __LINE__, "info", "id=%ld", (long)id); | | db_->hdb_.report(__FILE__, __LINE__, "info", "id=%ld", (long)id); | |
| return false; | | return false; | |
| } | | } | |
| ScopedSpinRWLock lock(&node->lock, false); | | ScopedSpinRWLock lock(&node->lock, false); | |
| RecordArray& recs = node->recs; | | RecordArray& recs = node->recs; | |
|
| if (recs.size() > 0) { | | if (!recs.empty()) { | |
| set_position(recs.front(), id); | | set_position(recs.front(), id); | |
| return true; | | return true; | |
| } else { | | } else { | |
| id = node->next; | | id = node->next; | |
| } | | } | |
| } | | } | |
| db_->set_error(__FILE__, __LINE__, Error::NOREC, "no record"); | | db_->set_error(__FILE__, __LINE__, Error::NOREC, "no record"); | |
| return false; | | return false; | |
| } | | } | |
| /** | | /** | |
| | | | |
| skipping to change at line 318 | | skipping to change at line 318 | |
| size_t lsiz = 0; | | size_t lsiz = 0; | |
| Link* link = NULL; | | Link* link = NULL; | |
| int64_t hist[TDBLEVELMAX]; | | int64_t hist[TDBLEVELMAX]; | |
| 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.size() > 0) { | | if (!recs.empty()) { | |
| Record* frec = recs.front(); | | Record* frec = recs.front(); | |
| Record* lrec = recs.back(); | | Record* lrec = recs.back(); | |
| if (!db_->reccomp_(rec, frec) && !db_->reccomp_(lrec, rec)) { | | if (!db_->reccomp_(rec, frec) && !db_->reccomp_(lrec, rec)) { | |
| RecordArray::iterator ritend = recs.end(); | | RecordArray::iterator ritend = recs.end(); | |
| RecordArray::iterator rit = std::lower_bound(recs.begin(), rite
nd, | | RecordArray::iterator rit = std::lower_bound(recs.begin(), rite
nd, | |
| rec, db_->reccomp_
); | | rec, db_->reccomp_
); | |
| if (rit != ritend) { | | if (rit != ritend) { | |
| hit = true; | | hit = true; | |
| if (db_->reccomp_(rec, *rit)) { | | if (db_->reccomp_(rec, *rit)) { | |
| clear_position(); | | clear_position(); | |
| | | | |
| skipping to change at line 468 | | skipping to change at line 468 | |
| link->ksiz = ksiz_; | | link->ksiz = ksiz_; | |
| std::memcpy(lbuf + sizeof(*link), kbuf_, ksiz_); | | std::memcpy(lbuf + sizeof(*link), kbuf_, ksiz_); | |
| int64_t hist[TDBLEVELMAX]; | | int64_t hist[TDBLEVELMAX]; | |
| 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(__FILE__, __LINE__, Error::BROKEN, "search failed"); | | db_->set_error(__FILE__, __LINE__, Error::BROKEN, "search failed"); | |
| if (lbuf != lstack) delete[] lbuf; | | if (lbuf != lstack) delete[] lbuf; | |
| return false; | | return false; | |
| } | | } | |
|
| if (node->recs.size() < 1) { | | if (node->recs.empty()) { | |
| if (lbuf != lstack) delete[] lbuf; | | if (lbuf != lstack) delete[] lbuf; | |
| clear_position(); | | clear_position(); | |
| if (!set_position(node->next)) return false; | | if (!set_position(node->next)) return false; | |
| node = db_->load_leaf_node(lid_, false); | | node = db_->load_leaf_node(lid_, false); | |
| if (!node) { | | if (!node) { | |
| db_->set_error(__FILE__, __LINE__, Error::BROKEN, "search failed"
); | | db_->set_error(__FILE__, __LINE__, Error::BROKEN, "search failed"
); | |
| return false; | | return false; | |
| } | | } | |
| lsiz = sizeof(Link) + ksiz_; | | lsiz = sizeof(Link) + ksiz_; | |
| char* lbuf = lsiz > sizeof(lstack) ? new char[lsiz] : lstack; | | char* lbuf = lsiz > sizeof(lstack) ? new char[lsiz] : lstack; | |
| | | | |
| skipping to change at line 533 | | skipping to change at line 533 | |
| node->size -= rsiz; | | node->size -= rsiz; | |
| node->dirty = true; | | node->dirty = true; | |
| xfree(rec); | | xfree(rec); | |
| RecordArray::iterator ritnext = rit + 1; | | RecordArray::iterator ritnext = rit + 1; | |
| if (ritnext != ritend) { | | if (ritnext != ritend) { | |
| clear_position(); | | clear_position(); | |
| set_position(*ritnext, node->id); | | set_position(*ritnext, node->id); | |
| step = false; | | step = false; | |
| } | | } | |
| recs.erase(rit); | | recs.erase(rit); | |
|
| if (recs.size() < 1) reorg = true; | | if (recs.empty()) reorg = true; | |
| } else if (vbuf != Visitor::NOP) { | | } else if (vbuf != Visitor::NOP) { | |
| int64_t diff = (int64_t)vsiz - (int64_t)rec->vsiz; | | int64_t diff = (int64_t)vsiz - (int64_t)rec->vsiz; | |
| db_->cusage_ += diff; | | db_->cusage_ += diff; | |
| node->size += diff; | | node->size += diff; | |
| node->dirty = true; | | node->dirty = true; | |
| if (vsiz > rec->vsiz) { | | if (vsiz > rec->vsiz) { | |
| *rit = (Record*)xrealloc(rec, sizeof(*rec) + rec->ksiz + vsiz); | | *rit = (Record*)xrealloc(rec, sizeof(*rec) + rec->ksiz + vsiz); | |
| rec = *rit; | | rec = *rit; | |
| kbuf = (char*)rec + sizeof(*rec); | | kbuf = (char*)rec + sizeof(*rec); | |
| } | | } | |
| | | | |
| skipping to change at line 685 | | skipping to change at line 685 | |
| lslots_(), islots_(), reccomp_(), linkcomp_(), tran_(false), trcnt_(0)
{ | | lslots_(), islots_(), reccomp_(), linkcomp_(), tran_(false), trcnt_(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 ~TreeDB() { | | virtual ~TreeDB() { | |
| _assert_(true); | | _assert_(true); | |
| if (omode_ != 0) close(); | | if (omode_ != 0) close(); | |
|
| if (curs_.size() > 0) { | | if (!curs_.empty()) { | |
| CursorList::const_iterator cit = curs_.begin(); | | CursorList::const_iterator cit = curs_.begin(); | |
| CursorList::const_iterator citend = curs_.end(); | | CursorList::const_iterator citend = curs_.end(); | |
| while (cit != citend) { | | while (cit != citend) { | |
| Cursor* cur = *cit; | | Cursor* cur = *cit; | |
| cur->db_ = NULL; | | cur->db_ = NULL; | |
| cit++; | | cit++; | |
| } | | } | |
| } | | } | |
| } | | } | |
| /** | | /** | |
| | | | |
| skipping to change at line 1972 | | skipping to change at line 1972 | |
| } | | } | |
| /** | | /** | |
| * Check whether a record is in the range of a leaf node. | | * Check whether a record is in the range of a leaf node. | |
| * @param node the leaf node. | | * @param node the leaf node. | |
| * @param rec the record containing the key only. | | * @param rec the record containing the key only. | |
| * @return true for in range, or false for out of range. | | * @return true for in range, or false for out of range. | |
| */ | | */ | |
| bool check_leaf_node_range(LeafNode* node, Record* rec) { | | bool check_leaf_node_range(LeafNode* node, Record* rec) { | |
| _assert_(node && rec); | | _assert_(node && rec); | |
| RecordArray& recs = node->recs; | | RecordArray& recs = node->recs; | |
|
| if (recs.size() < 1) return false; | | if (recs.empty()) return false; | |
| Record* frec = recs.front(); | | Record* frec = recs.front(); | |
| Record* lrec = recs.back(); | | Record* lrec = recs.back(); | |
| return !reccomp_(rec, frec) && !reccomp_(lrec, rec); | | return !reccomp_(rec, frec) && !reccomp_(lrec, rec); | |
| } | | } | |
| /** | | /** | |
| * Accept a visitor at a leaf node. | | * Accept a visitor at a leaf node. | |
| * @param node the leaf node. | | * @param node the leaf node. | |
| * @param rec the record containing the key only. | | * @param rec the record containing the key only. | |
| * @param visitor a visitor object. | | * @param visitor a visitor object. | |
| * @return true to reorganize the tree, or false if not. | | * @return true to reorganize the tree, or false if not. | |
| | | | |
| skipping to change at line 2004 | | skipping to change at line 2004 | |
| size_t vsiz; | | size_t vsiz; | |
| const char* vbuf = visitor->visit_full(kbuf, ksiz, kbuf + ksiz, rec->
vsiz, &vsiz); | | const char* vbuf = visitor->visit_full(kbuf, ksiz, kbuf + ksiz, rec->
vsiz, &vsiz); | |
| if (vbuf == Visitor::REMOVE) { | | if (vbuf == Visitor::REMOVE) { | |
| size_t rsiz = sizeof(*rec) + rec->ksiz + rec->vsiz; | | size_t rsiz = sizeof(*rec) + rec->ksiz + rec->vsiz; | |
| count_ -= 1; | | count_ -= 1; | |
| cusage_ -= rsiz; | | cusage_ -= rsiz; | |
| node->size -= rsiz; | | node->size -= rsiz; | |
| node->dirty = true; | | node->dirty = true; | |
| xfree(rec); | | xfree(rec); | |
| recs.erase(rit); | | recs.erase(rit); | |
|
| if (recs.size() < 1) reorg = true; | | if (recs.empty()) reorg = true; | |
| } else if (vbuf != Visitor::NOP) { | | } else if (vbuf != Visitor::NOP) { | |
| int64_t diff = (int64_t)vsiz - (int64_t)rec->vsiz; | | int64_t diff = (int64_t)vsiz - (int64_t)rec->vsiz; | |
| cusage_ += diff; | | cusage_ += diff; | |
| node->size += diff; | | node->size += diff; | |
| node->dirty = true; | | node->dirty = true; | |
| if (vsiz > rec->vsiz) { | | if (vsiz > rec->vsiz) { | |
| *rit = (Record*)xrealloc(rec, sizeof(*rec) + rec->ksiz + vsiz); | | *rit = (Record*)xrealloc(rec, sizeof(*rec) + rec->ksiz + vsiz); | |
| rec = *rit; | | rec = *rit; | |
| kbuf = (char*)rec + sizeof(*rec); | | kbuf = (char*)rec + sizeof(*rec); | |
| } | | } | |
| | | | |
| skipping to change at line 2417 | | skipping to change at line 2417 | |
| for (int32_t i = 0; i <= num; i++) { | | for (int32_t i = 0; i <= num; i++) { | |
| Link* link = links.back(); | | Link* link = links.back(); | |
| size_t rsiz = sizeof(*link) + link->ksiz; | | size_t rsiz = sizeof(*link) + link->ksiz; | |
| cusage_ -= rsiz; | | cusage_ -= rsiz; | |
| inode->size -= rsiz; | | inode->size -= rsiz; | |
| xfree(link); | | xfree(link); | |
| links.pop_back(); | | links.pop_back(); | |
| } | | } | |
| inode->dirty = true; | | inode->dirty = true; | |
| } | | } | |
|
| } else if (node->recs.size() < 1 && hnum > 0) { | | } else if (node->recs.empty() && hnum > 0) { | |
| if (!escape_cursors(node->id, node->next)) return false; | | if (!escape_cursors(node->id, node->next)) return false; | |
| InnerNode* inode = load_inner_node(hist[--hnum]); | | InnerNode* inode = load_inner_node(hist[--hnum]); | |
| if (!inode) { | | if (!inode) { | |
| set_error(__FILE__, __LINE__, Error::BROKEN, "missing inner node"); | | set_error(__FILE__, __LINE__, Error::BROKEN, "missing inner node"); | |
| hdb_.report(__FILE__, __LINE__, "info", "id=%ld", (long)hist[hnum])
; | | hdb_.report(__FILE__, __LINE__, "info", "id=%ld", (long)hist[hnum])
; | |
| return false; | | return false; | |
| } | | } | |
| if (sub_link_tree(inode, node->id, hist, hnum)) { | | if (sub_link_tree(inode, node->id, hist, hnum)) { | |
| if (node->prev > 0) { | | if (node->prev > 0) { | |
| LeafNode* tnode = load_leaf_node(node->prev, false); | | LeafNode* tnode = load_leaf_node(node->prev, false); | |
| | | | |
| skipping to change at line 2491 | | skipping to change at line 2491 | |
| * @param hnum the number of the history. | | * @param hnum the number of the history. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool sub_link_tree(InnerNode* node, int64_t child, int64_t* hist, int32_t
hnum) { | | bool sub_link_tree(InnerNode* node, int64_t child, int64_t* hist, int32_t
hnum) { | |
| _assert_(node && hist && hnum >= 0); | | _assert_(node && hist && hnum >= 0); | |
| node->dirty = true; | | node->dirty = true; | |
| LinkArray& links = node->links; | | LinkArray& links = node->links; | |
| LinkArray::iterator lit = links.begin(); | | LinkArray::iterator lit = links.begin(); | |
| LinkArray::iterator litend = links.end(); | | LinkArray::iterator litend = links.end(); | |
| if (node->heir == child) { | | if (node->heir == child) { | |
|
| if (links.size() > 0) { | | if (!links.empty()) { | |
| Link* link = *lit; | | Link* link = *lit; | |
| node->heir = link->child; | | node->heir = link->child; | |
| xfree(link); | | xfree(link); | |
| links.erase(lit); | | links.erase(lit); | |
| return true; | | return true; | |
| } else if (hnum > 0) { | | } else if (hnum > 0) { | |
| InnerNode* pnode = load_inner_node(hist[--hnum]); | | InnerNode* pnode = load_inner_node(hist[--hnum]); | |
| if (!pnode) { | | if (!pnode) { | |
| set_error(__FILE__, __LINE__, Error::BROKEN, "missing inner node"
); | | set_error(__FILE__, __LINE__, Error::BROKEN, "missing inner node"
); | |
| hdb_.report(__FILE__, __LINE__, "info", "id=%ld", (long)hist[hnum
]); | | hdb_.report(__FILE__, __LINE__, "info", "id=%ld", (long)hist[hnum
]); | |
| | | | |
| skipping to change at line 2705 | | skipping to change at line 2705 | |
| it++; | | it++; | |
| } | | } | |
| } | | } | |
| return sum; | | return sum; | |
| } | | } | |
| /** | | /** | |
| * Disable all cursors. | | * Disable all cursors. | |
| */ | | */ | |
| void disable_cursors() { | | void disable_cursors() { | |
| _assert_(true); | | _assert_(true); | |
|
| if (curs_.size() < 1) return; | | if (curs_.empty()) return; | |
| CursorList::const_iterator cit = curs_.begin(); | | CursorList::const_iterator cit = curs_.begin(); | |
| CursorList::const_iterator citend = curs_.end(); | | CursorList::const_iterator citend = curs_.end(); | |
| while (cit != citend) { | | while (cit != citend) { | |
| Cursor* cur = *cit; | | Cursor* cur = *cit; | |
| if (cur->kbuf_) cur->clear_position(); | | if (cur->kbuf_) cur->clear_position(); | |
| cit++; | | cit++; | |
| } | | } | |
| } | | } | |
| /** | | /** | |
| * Escape cursors on a divided leaf node. | | * Escape cursors on a divided leaf node. | |
| * @param src the ID of the source node. | | * @param src the ID of the source node. | |
| * @param dest the ID of the destination node. | | * @param dest the ID of the destination node. | |
| * @param rec the pivot record. | | * @param rec the pivot record. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| void escape_cursors(int64_t src, int64_t dest, Record* rec) { | | void escape_cursors(int64_t src, int64_t dest, Record* rec) { | |
| _assert_(src > 0 && dest >= 0 && rec); | | _assert_(src > 0 && dest >= 0 && rec); | |
|
| if (curs_.size() < 1) return; | | if (curs_.empty()) return; | |
| CursorList::const_iterator cit = curs_.begin(); | | CursorList::const_iterator cit = curs_.begin(); | |
| CursorList::const_iterator citend = curs_.end(); | | CursorList::const_iterator citend = curs_.end(); | |
| while (cit != citend) { | | while (cit != citend) { | |
| Cursor* cur = *cit; | | Cursor* cur = *cit; | |
| if (cur->lid_ == src) { | | if (cur->lid_ == src) { | |
| char* dbuf = (char*)rec + sizeof(*rec); | | char* dbuf = (char*)rec + sizeof(*rec); | |
| if (reccomp_.comp->compare(cur->kbuf_, cur->ksiz_, dbuf, rec->ksiz)
>= 0) | | if (reccomp_.comp->compare(cur->kbuf_, cur->ksiz_, dbuf, rec->ksiz)
>= 0) | |
| cur->lid_ = dest; | | cur->lid_ = dest; | |
| } | | } | |
| cit++; | | cit++; | |
| } | | } | |
| } | | } | |
| /** | | /** | |
| * Escape cursors on a removed leaf node. | | * Escape cursors on a removed leaf node. | |
| * @param src the ID of the source node. | | * @param src the ID of the source node. | |
| * @param dest the ID of the destination node. | | * @param dest the ID of the destination node. | |
| * @return true on success, or false on failure. | | * @return true on success, or false on failure. | |
| */ | | */ | |
| bool escape_cursors(int64_t src, int64_t dest) { | | bool escape_cursors(int64_t src, int64_t dest) { | |
| _assert_(src > 0 && dest >= 0); | | _assert_(src > 0 && dest >= 0); | |
|
| if (curs_.size() < 1) return true; | | if (curs_.empty()) return true; | |
| bool err = false; | | bool err = false; | |
| CursorList::const_iterator cit = curs_.begin(); | | CursorList::const_iterator cit = curs_.begin(); | |
| CursorList::const_iterator citend = curs_.end(); | | CursorList::const_iterator citend = curs_.end(); | |
| while (cit != citend) { | | while (cit != citend) { | |
| Cursor* cur = *cit; | | Cursor* cur = *cit; | |
| if (cur->lid_ == src) { | | if (cur->lid_ == src) { | |
| cur->clear_position(); | | cur->clear_position(); | |
| if (!cur->set_position(dest) && hdb_.error().code() != Error::NOREC
) err = true; | | if (!cur->set_position(dest) && hdb_.error().code() != Error::NOREC
) err = true; | |
| } | | } | |
| cit++; | | cit++; | |
| | | | |
End of changes. 13 change blocks. |
| 13 lines changed or deleted | | 13 lines changed or added | |
|
| kcutil.h | | kcutil.h | |
| /**************************************************************************
*********************** | | /**************************************************************************
*********************** | |
| * Utility functions | | * Utility functions | |
|
| * Copyright (C) 2009-
2010 Mikio Hirabayashi | | * Copyright
(C) 2009-2010 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 175 | | skipping to change at line 175 | |
| | | | |
| /** | | /** | |
| * Get the hash value by FNV hashing. | | * Get the hash value by FNV hashing. | |
| * @param buf the source buffer. | | * @param buf the source buffer. | |
| * @param size the size of the source buffer. | | * @param size the size of the source buffer. | |
| * @return the hash value. | | * @return the hash value. | |
| */ | | */ | |
| uint64_t hashfnv(const void* buf, size_t size); | | uint64_t hashfnv(const void* buf, size_t size); | |
| | | | |
| /** | | /** | |
|
| | | * Get the hash value suitable for a file name. | |
| | | * @param buf the source buffer. | |
| | | * @param size the size of the source buffer. | |
| | | * @param obuf the buffer into which the result hash string is written. It | |
| | | must be more than | |
| | | * NUMBUFSIZ. | |
| | | * @return the auxiliary hash value. | |
| | | */ | |
| | | uint32_t hashpath(const void* buf, size_t size, char* obuf); | |
| | | | |
| | | /** | |
| * Get a prime number nearby a number. | | * Get a prime number nearby a number. | |
| * @param num a natural number. | | * @param num a natural number. | |
| * @return the result number. | | * @return the result number. | |
| */ | | */ | |
| uint64_t nearbyprime(uint64_t num); | | uint64_t nearbyprime(uint64_t num); | |
| | | | |
| /** | | /** | |
| * Get the quiet Not-a-Number value. | | * Get the quiet Not-a-Number value. | |
| * @return the quiet Not-a-Number value. | | * @return the quiet Not-a-Number value. | |
| */ | | */ | |
| | | | |
| skipping to change at line 252 | | skipping to change at line 262 | |
| size_t strsplit(const std::string& str, char delim, std::vector<std::string
>* elems); | | size_t strsplit(const std::string& str, char delim, std::vector<std::string
>* elems); | |
| | | | |
| /** | | /** | |
| * Encode a serial object with hexadecimal encoding. | | * Encode a serial object with hexadecimal encoding. | |
| * @param buf the pointer to the region. | | * @param buf the pointer to the region. | |
| * @param size the size of the region. | | * @param size the size of the region. | |
| * @return the result string. | | * @return the result string. | |
| * @note Because the region of the return value is allocated with the the n
ew[] operator, it | | * @note Because the region of the return value is allocated with the the n
ew[] operator, it | |
| * should be released with the delete[] operator when it is no longer in us
e. | | * should be released with the delete[] operator when it is no longer in us
e. | |
| */ | | */ | |
|
| char* hexencode(const char* buf, size_t size); | | char* hexencode(const void* buf, size_t size); | |
| | | | |
| /** | | /** | |
| * Decode a string encoded with hexadecimal encoding. | | * Decode a string encoded with hexadecimal encoding. | |
| * @param str specifies the encoded string. | | * @param str specifies the encoded string. | |
| * @param sp the pointer to the variable into which the size of the region
of the return value | | * @param sp the pointer to the variable into which the size of the region
of the return value | |
| * is assigned. | | * is assigned. | |
| * @return the pointer to the region of the result. | | * @return the pointer to the region of the result. | |
| * @note Because an additional zero code is appended at the end of the regi
on of the return | | * @note Because an additional zero code is appended at the end of the regi
on of the return | |
| * value, the return value can be treated as a character string. Because t
he region of the | | * value, the return value can be treated as a character string. Because t
he region of the | |
| * return value is allocated with the the new[] operator, it should be rele
ased with the delete[] | | * return value is allocated with the the new[] operator, it should be rele
ased with the delete[] | |
| * operator when it is no longer in use. | | * operator when it is no longer in use. | |
| */ | | */ | |
| char* hexdecode(const char* str, size_t* sp); | | char* hexdecode(const char* str, size_t* sp); | |
| | | | |
| /** | | /** | |
|
| | | * Cipher or decipher a serial object with the Arcfour stream cipher. | |
| | | * @param ptr the pointer to the region. | |
| | | * @param size the size of the region. | |
| | | * @param kbuf the pointer to the region of the cipher key. | |
| | | * @param ksiz the size of the region of the cipher key. | |
| | | * @param obuf the pointer to the region into which the result data is writ | |
| | | ten. The size of the | |
| | | * buffer should be equal to or more than the input region. The region can | |
| | | be the same as the | |
| | | * source region. | |
| | | */ | |
| | | void arccipher(const void* ptr, size_t size, const void* kbuf, size_t ksiz, | |
| | | void* obuf); | |
| | | | |
| | | /** | |
| * Allocate a region on memory. | | * Allocate a region on memory. | |
| * @param size the size of the region. | | * @param size the size of the region. | |
| * @return the pointer to the allocated region. | | * @return the pointer to the allocated region. | |
| */ | | */ | |
| void* xmalloc(size_t size); | | void* xmalloc(size_t size); | |
| | | | |
| /** | | /** | |
| * Allocate a nullified region on memory. | | * Allocate a nullified region on memory. | |
| * @param nmemb the number of elements. | | * @param nmemb the number of elements. | |
| * @param size the size of each element. | | * @param size the size of each element. | |
| | | | |
| skipping to change at line 675 | | skipping to change at line 697 | |
| uint64_t hash = 14695981039346656037ULL; | | uint64_t hash = 14695981039346656037ULL; | |
| const unsigned char* rp = (unsigned char*)buf; | | const unsigned char* rp = (unsigned char*)buf; | |
| const unsigned char* ep = rp + size; | | const unsigned char* ep = rp + size; | |
| while (rp < ep) { | | while (rp < ep) { | |
| hash = (hash ^ *(rp++)) * 109951162811ULL; | | hash = (hash ^ *(rp++)) * 109951162811ULL; | |
| } | | } | |
| return hash; | | return hash; | |
| } | | } | |
| | | | |
| /** | | /** | |
|
| | | * Get the hash value suitable for a file name. | |
| | | */ | |
| | | inline uint32_t hashpath(const void* buf, size_t size, char* obuf) { | |
| | | _assert_(buf && size <= MEMMAXSIZ && obuf); | |
| | | const unsigned char* rp = (const unsigned char*)buf; | |
| | | uint32_t rv; | |
| | | char* wp = obuf; | |
| | | if (size <= 10) { | |
| | | if (size > 0) { | |
| | | const unsigned char* ep = rp + size; | |
| | | while (rp < ep) { | |
| | | int32_t num = *rp >> 4; | |
| | | if (num < 10) { | |
| | | *(wp++) = '0' + num; | |
| | | } else { | |
| | | *(wp++) = 'a' + num - 10; | |
| | | } | |
| | | num = *rp & 0x0f; | |
| | | if (num < 10) { | |
| | | *(wp++) = '0' + num; | |
| | | } else { | |
| | | *(wp++) = 'a' + num - 10; | |
| | | } | |
| | | rp++; | |
| | | } | |
| | | } else { | |
| | | *(wp++) = '0'; | |
| | | } | |
| | | uint64_t hash = hashmurmur(buf, size); | |
| | | rv = (((hash & 0xffff000000000000ULL) >> 48) | ((hash & 0x0000ffff00000 | |
| | | 000ULL) >> 16)) ^ | |
| | | (((hash & 0x000000000000ffffULL) << 16) | ((hash & 0x00000000ffff0000 | |
| | | ULL) >> 16)); | |
| | | } else { | |
| | | *(wp++) = 'f' + 1 + (size & 0x0f); | |
| | | int32_t num = (rp[0] >> 4) + (rp[1] & 0x01 ? 0x10 : 0); | |
| | | if (num < 10) { | |
| | | *(wp++) = '0' + num; | |
| | | } else { | |
| | | *(wp++) = 'a' + num - 10; | |
| | | } | |
| | | num = (rp[0] & 0x0f) + (rp[1] & 0x02 ? 0x10 : 0); | |
| | | if (num < 10) { | |
| | | *(wp++) = '0' + num; | |
| | | } else { | |
| | | *(wp++) = 'a' + num - 10; | |
| | | } | |
| | | num = (rp[1] >> 2) & 0x1f; | |
| | | if (num < 10) { | |
| | | *(wp++) = '0' + num; | |
| | | } else { | |
| | | *(wp++) = 'a' + num - 10; | |
| | | } | |
| | | uint64_t hash = hashmurmur(buf, size); | |
| | | rv = (((hash & 0xffff000000000000ULL) >> 48) | ((hash & 0x0000ffff00000 | |
| | | 000ULL) >> 16)) ^ | |
| | | (((hash & 0x000000000000ffffULL) << 16) | ((hash & 0x00000000ffff0000 | |
| | | ULL) >> 16)); | |
| | | uint64_t inc = hashfnv(buf, size); | |
| | | inc = (((inc & 0xffff000000000000ULL) >> 48) | ((inc & 0x0000ffff000000 | |
| | | 00ULL) >> 16)) ^ | |
| | | (((inc & 0x000000000000ffffULL) << 16) | ((inc & 0x00000000ffff0000UL | |
| | | L) >> 16)); | |
| | | for (size_t i = 0; i < sizeof(hash); i++) { | |
| | | uint32_t least = hash >> ((sizeof(hash) - 1) * 8); | |
| | | num = least >> 4; | |
| | | if (inc & 0x01) num += 0x10; | |
| | | inc = inc >> 1; | |
| | | if (num < 10) { | |
| | | *(wp++) = '0' + num; | |
| | | } else { | |
| | | *(wp++) = 'a' + num - 10; | |
| | | } | |
| | | num = least & 0x0f; | |
| | | if (inc & 0x01) num += 0x10; | |
| | | inc = inc >> 1; | |
| | | if (num < 10) { | |
| | | *(wp++) = '0' + num; | |
| | | } else { | |
| | | *(wp++) = 'a' + num - 10; | |
| | | } | |
| | | hash = hash << 8; | |
| | | } | |
| | | } | |
| | | *wp = '\0'; | |
| | | return rv; | |
| | | } | |
| | | | |
| | | /** | |
| * Get a prime number nearby a number. | | * Get a prime number nearby a number. | |
| */ | | */ | |
| inline uint64_t nearbyprime(uint64_t num) { | | inline uint64_t nearbyprime(uint64_t num) { | |
| _assert_(true); | | _assert_(true); | |
| static uint64_t table[] = { | | static uint64_t table[] = { | |
| 2ULL, 3ULL, 5ULL, 7ULL, 11ULL, 13ULL, 17ULL, 19ULL, 23ULL, 29ULL, 31ULL
, 37ULL, 41ULL, | | 2ULL, 3ULL, 5ULL, 7ULL, 11ULL, 13ULL, 17ULL, 19ULL, 23ULL, 29ULL, 31ULL
, 37ULL, 41ULL, | |
| 43ULL, 47ULL, 53ULL, 59ULL, 61ULL, 67ULL, 71ULL, 79ULL, 97ULL, 107ULL,
131ULL, 157ULL, | | 43ULL, 47ULL, 53ULL, 59ULL, 61ULL, 67ULL, 71ULL, 79ULL, 97ULL, 107ULL,
131ULL, 157ULL, | |
| 181ULL, 223ULL, 257ULL, 307ULL, 367ULL, 431ULL, 521ULL, 613ULL, 727ULL,
863ULL, 1031ULL, | | 181ULL, 223ULL, 257ULL, 307ULL, 367ULL, 431ULL, 521ULL, 613ULL, 727ULL,
863ULL, 1031ULL, | |
| 1217ULL, 1451ULL, 1723ULL, 2053ULL, 2437ULL, 2897ULL, 3449ULL, 4099ULL,
4871ULL, 5801ULL, | | 1217ULL, 1451ULL, 1723ULL, 2053ULL, 2437ULL, 2897ULL, 3449ULL, 4099ULL,
4871ULL, 5801ULL, | |
| 6899ULL, 8209ULL, 9743ULL, 11587ULL, 13781ULL, 16411ULL, 19483ULL, 2317
3ULL, 27581ULL, | | 6899ULL, 8209ULL, 9743ULL, 11587ULL, 13781ULL, 16411ULL, 19483ULL, 2317
3ULL, 27581ULL, | |
| | | | |
| skipping to change at line 897 | | skipping to change at line 1002 | |
| } | | } | |
| it++; | | it++; | |
| } | | } | |
| elems->push_back(field); | | elems->push_back(field); | |
| return elems->size(); | | return elems->size(); | |
| } | | } | |
| | | | |
| /** | | /** | |
| * Encode a serial object with hexadecimal encoding. | | * Encode a serial object with hexadecimal encoding. | |
| */ | | */ | |
|
| inline char* hexencode(const char* buf, size_t size) { | | inline char* hexencode(const void* buf, size_t size) { | |
| _assert_(buf && size <= MEMMAXSIZ); | | _assert_(buf && size <= MEMMAXSIZ); | |
|
| const unsigned char* rp = (const unsigned char* )buf; | | const unsigned char* rp = (const unsigned char*)buf; | |
| char* zbuf = new char[size*2+1]; | | char* zbuf = new char[size*2+1]; | |
| char* wp = zbuf; | | char* wp = zbuf; | |
|
| for (size_t i = 0; i < size; i++) { | | for (const unsigned char* ep = rp + size; rp < ep; rp++) { | |
| wp += std::sprintf(wp, "%02x", rp[i]); | | int32_t num = (*rp >> 4); | |
| | | if (num < 10) { | |
| | | *(wp++) = '0' + num; | |
| | | } else { | |
| | | *(wp++) = 'a' + num - 10; | |
| | | } | |
| | | num = (*rp & 0x0f); | |
| | | if (num < 10) { | |
| | | *(wp++) = '0' + num; | |
| | | } else { | |
| | | *(wp++) = 'a' + num - 10; | |
| | | } | |
| } | | } | |
| *wp = '\0'; | | *wp = '\0'; | |
| return zbuf; | | return zbuf; | |
| } | | } | |
| | | | |
| /** | | /** | |
| * Decode a string encoded with hexadecimal encoding. | | * Decode a string encoded with hexadecimal encoding. | |
| */ | | */ | |
| inline char* hexdecode(const char* str, size_t* sp) { | | inline char* hexdecode(const char* str, size_t* sp) { | |
| _assert_(str && sp); | | _assert_(str && sp); | |
| | | | |
| skipping to change at line 951 | | skipping to change at line 1067 | |
| break; | | break; | |
| } | | } | |
| *(wp++) = num; | | *(wp++) = num; | |
| } | | } | |
| *wp = '\0'; | | *wp = '\0'; | |
| *sp = wp - zbuf; | | *sp = wp - zbuf; | |
| return zbuf; | | return zbuf; | |
| } | | } | |
| | | | |
| /** | | /** | |
|
| | | * Cipher or decipher a serial object with the Arcfour stream cipher. | |
| | | */ | |
| | | inline void arccipher(const void* ptr, size_t size, const void* kbuf, size_ | |
| | | t ksiz, void* obuf) { | |
| | | _assert_(ptr && size <= MEMMAXSIZ && kbuf && ksiz <= MEMMAXSIZ && obuf); | |
| | | if (ksiz < 1) { | |
| | | kbuf = ""; | |
| | | ksiz = 1; | |
| | | } | |
| | | uint32_t sbox[0x100], kbox[0x100]; | |
| | | for(int32_t i = 0; i < 0x100; i++){ | |
| | | sbox[i] = i; | |
| | | kbox[i] = ((uint8_t*)kbuf)[i%ksiz]; | |
| | | } | |
| | | uint32_t sidx = 0; | |
| | | for(int i = 0; i < 0x100; i++){ | |
| | | sidx = (sidx + sbox[i] + kbox[i]) & 0xff; | |
| | | uint32_t swap = sbox[i]; | |
| | | sbox[i] = sbox[sidx]; | |
| | | sbox[sidx] = swap; | |
| | | } | |
| | | uint32_t x = 0; | |
| | | uint32_t y = 0; | |
| | | for(size_t i = 0; i < size; i++){ | |
| | | x = (x + 1) & 0xff; | |
| | | y = (y + sbox[x]) & 0xff; | |
| | | uint32_t swap = sbox[x]; | |
| | | sbox[x] = sbox[y]; | |
| | | sbox[y] = swap; | |
| | | ((uint8_t*)obuf)[i] = ((uint8_t*)ptr)[i] ^ sbox[(sbox[x]+sbox[y])&0xff] | |
| | | ; | |
| | | } | |
| | | } | |
| | | | |
| | | /** | |
| * Allocate a region on memory. | | * Allocate a region on memory. | |
| */ | | */ | |
| inline void* xmalloc(size_t size) { | | inline void* xmalloc(size_t size) { | |
| _assert_(size <= MEMMAXSIZ); | | _assert_(size <= MEMMAXSIZ); | |
| void* ptr = std::malloc(size); | | void* ptr = std::malloc(size); | |
| if (!ptr) throw std::bad_alloc(); | | if (!ptr) throw std::bad_alloc(); | |
| return ptr; | | return ptr; | |
| } | | } | |
| | | | |
| /** | | /** | |
| | | | |
End of changes. 9 change blocks. |
| 6 lines changed or deleted | | 167 lines changed or added | |
|