kccachedb.h   kccachedb.h 
skipping to change at line 43 skipping to change at line 43
* @note This class is a concrete class to operate a hash database on memor y. This class can be * @note This class is a concrete class to operate a hash database on memor y. This class can be
* inherited but overwriting methods is forbidden. Before every database o peration, it is * inherited but overwriting methods is forbidden. Before every database o peration, it is
* necessary to call the CacheDB::open method in order to open a database f ile and connect the * necessary to call the CacheDB::open method in order to open a database f ile and connect the
* database object to it. To avoid data missing or corruption, it is impor tant to close every * database object to it. To avoid data missing or corruption, it is impor tant to close every
* database file by the CacheDB::close method when the database is no longe r in use. It is * database file by the CacheDB::close method when the database is no longe r in use. It is
* forbidden for multible database objects in a process to open the same da tabase at the same * forbidden for multible database objects in a process to open the same da tabase at the same
* time. It is forbidden to share a database object with child processes. * time. It is forbidden to share a database object with child processes.
*/ */
class CacheDB : public BasicDB { class CacheDB : public BasicDB {
friend class PlantDB<CacheDB, BasicDB::TYPEGRASS>; friend class PlantDB<CacheDB, BasicDB::TYPEGRASS>;
public: public:
class Cursor; class Cursor;
private: private:
struct Record; struct Record;
struct TranLog; struct TranLog;
struct Slot; struct Slot;
class Repeater; class Repeater;
class Setter; class Setter;
class Remover; class Remover;
class ScopedVisitor; class ScopedVisitor;
/** An alias of list of cursors. */ /** An alias of list of cursors. */
typedef std::list<Cursor*> CursorList; typedef std::list<Cursor*> CursorList;
/** An alias of list of transaction logs. */ /** An alias of list of transaction logs. */
skipping to change at line 71 skipping to change at line 71
/** The mininum number of buckets to use mmap. */ /** The mininum number of buckets to use mmap. */
static const size_t ZMAPBNUM = 32768; static const size_t ZMAPBNUM = 32768;
/** The maximum size of each key. */ /** The maximum size of each key. */
static const uint32_t KSIZMAX = 0xfffff; static const uint32_t KSIZMAX = 0xfffff;
/** The size of the record buffer. */ /** The size of the record buffer. */
static const size_t RECBUFSIZ = 48; static const size_t RECBUFSIZ = 48;
/** The size of the opaque buffer. */ /** The size of the opaque buffer. */
static const size_t OPAQUESIZ = 16; static const size_t OPAQUESIZ = 16;
/** The threshold of busy loop and sleep for locking. */ /** The threshold of busy loop and sleep for locking. */
static const uint32_t LOCKBUSYLOOP = 8192; static const uint32_t LOCKBUSYLOOP = 8192;
public: public:
/** /**
* Cursor to indicate a record. * Cursor to indicate a record.
*/ */
class Cursor : public BasicDB::Cursor { class Cursor : public BasicDB::Cursor {
friend class CacheDB; friend class CacheDB;
public: public:
/** /**
* Constructor. * Constructor.
* @param db the container database object. * @param db the container database object.
*/ */
explicit Cursor(CacheDB* db) : db_(db), sidx_(-1), rec_(NULL) { explicit Cursor(CacheDB* db) : db_(db), sidx_(-1), rec_(NULL) {
_assert_(db); _assert_(db);
ScopedSpinRWLock lock(&db_->mlock_, true); ScopedSpinRWLock lock(&db_->mlock_, true);
db_->curs_.push_back(this); db_->curs_.push_back(this);
} }
/** /**
skipping to change at line 320 skipping to change at line 320
return false; return false;
} }
/** /**
* Get the database object. * Get the database object.
* @return the database object. * @return the database object.
*/ */
CacheDB* db() { CacheDB* db() {
_assert_(true); _assert_(true);
return db_; return db_;
} }
private: private:
/** /**
* Step the cursor to the next record. * Step the cursor to the next record.
* @return true on success, or false on failure. * @return true on success, or false on failure.
*/ */
bool step_impl() { bool step_impl() {
_assert_(true); _assert_(true);
rec_ = rec_->next; rec_ = rec_->next;
if (!rec_) { if (!rec_) {
for (int32_t i = sidx_ + 1; i < SLOTNUM; i++) { for (int32_t i = sidx_ + 1; i < SLOTNUM; i++) {
Slot* slot = db_->slots_ + i; Slot* slot = db_->slots_ + i;
skipping to change at line 374 skipping to change at line 374
* Status flags. * Status flags.
*/ */
enum Flag { enum Flag {
FOPEN = 1 << 0, ///< dummy for compatibility FOPEN = 1 << 0, ///< dummy for compatibility
FFATAL = 1 << 1 ///< dummy for compatibility FFATAL = 1 << 1 ///< dummy for compatibility
}; };
/** /**
* Default constructor. * Default constructor.
*/ */
explicit CacheDB() : explicit CacheDB() :
mlock_(), flock_(), error_(), logger_(NULL), logkinds_(0), mtrigger_(NU mlock_(), flock_(), error_(), logger_(NULL), logkinds_(0), mtrigger_(
LL), NULL),
omode_(0), curs_(), path_(""), type_(TYPECACHE), omode_(0), curs_(), path_(""), type_(TYPECACHE),
opts_(0), bnum_(DEFBNUM), capcnt_(-1), capsiz_(-1), opts_(0), bnum_(DEFBNUM), capcnt_(-1), capsiz_(-1),
opaque_(), embcomp_(ZLIBRAWCOMP), comp_(NULL), slots_(), tran_(false) { opaque_(), embcomp_(ZLIBRAWCOMP), comp_(NULL), slots_(), tran_(false)
{
_assert_(true); _assert_(true);
} }
/** /**
* Destructor. * Destructor.
* @note If the database is not closed, it is closed implicitly. * @note If the database is not closed, it is closed implicitly.
*/ */
virtual ~CacheDB() { virtual ~CacheDB() {
_assert_(true); _assert_(true);
if (omode_ != 0) close(); if (omode_ != 0) close();
if (!curs_.empty()) { if (!curs_.empty()) {
skipping to change at line 589 skipping to change at line 589
* @param func the function name of the program source code. * @param func the function name of the program source code.
* @param code an error code. * @param code an error code.
* @param message a supplement message. * @param message a supplement message.
*/ */
void set_error(const char* file, int32_t line, const char* func, void set_error(const char* file, int32_t line, const char* func,
Error::Code code, const char* message) { Error::Code code, const char* message) {
_assert_(file && line > 0 && func && message); _assert_(file && line > 0 && func && message);
error_->set(code, message); error_->set(code, message);
if (logger_) { if (logger_) {
Logger::Kind kind = code == Error::BROKEN || code == Error::SYSTEM ? Logger::Kind kind = code == Error::BROKEN || code == Error::SYSTEM ?
Logger::ERROR : Logger::INFO; Logger::ERROR : Logger::INFO;
if (kind & logkinds_) if (kind & logkinds_)
report(file, line, func, kind, "%d: %s: %s", code, Error::codename( code), message); report(file, line, func, kind, "%d: %s: %s", code, Error::codename( code), message);
} }
} }
/** /**
* Open a database file. * Open a database file.
* @param path the path of a database file. * @param path the path of a database file.
* @param mode the connection mode. CacheDB::OWRITER as a writer, CacheD B::OREADER as a * @param mode the connection mode. CacheDB::OWRITER as a writer, CacheD B::OREADER as a
* reader. The following may be added to the writer mode by bitwise-or: CacheDB::OCREATE, * reader. The following may be added to the writer mode by bitwise-or: CacheDB::OCREATE,
* which means it creates a new database if the file does not exist, Cach eDB::OTRUNCATE, which * which means it creates a new database if the file does not exist, Cach eDB::OTRUNCATE, which
skipping to change at line 1056 skipping to change at line 1056
if (omode_ == 0) { if (omode_ == 0) {
set_error(_KCCODELINE_, Error::INVALID, "not opened"); set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false; return false;
} }
if (!(omode_ & OWRITER)) { if (!(omode_ & OWRITER)) {
set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); set_error(_KCCODELINE_, Error::NOPERM, "permission denied");
return false; return false;
} }
return true; return true;
} }
protected: protected:
/** /**
* Report a message for debugging. * Report a message for debugging.
* @param file the file name of the program source code. * @param file the file name of the program source code.
* @param line the line number of the program source code. * @param line the line number of the program source code.
* @param func the function name of the program source code. * @param func the function name of the program source code.
* @param kind the kind of the event. Logger::DEBUG for debugging, Logge r::INFO for normal * @param kind the kind of the event. Logger::DEBUG for debugging, Logge r::INFO for normal
* information, Logger::WARN for warning, and Logger::ERROR for fatal err or. * information, Logger::WARN for warning, and Logger::ERROR for fatal err or.
* @param format the printf-like format string. * @param format the printf-like format string.
* @param ... used according to the format string. * @param ... used according to the format string.
*/ */
skipping to change at line 1262 skipping to change at line 1262
*/ */
bool reorganized() { bool reorganized() {
_assert_(true); _assert_(true);
ScopedSpinRWLock lock(&mlock_, false); ScopedSpinRWLock lock(&mlock_, false);
if (omode_ == 0) { if (omode_ == 0) {
set_error(_KCCODELINE_, Error::INVALID, "not opened"); set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false; return false;
} }
return false; return false;
} }
private: private:
/** /**
* Set the power of the alignment of record size. * Set the power of the alignment of record size.
* @note This is a dummy implementation for compatibility. * @note This is a dummy implementation for compatibility.
*/ */
bool tune_alignment(int8_t apow) { bool tune_alignment(int8_t apow) {
return true; return true;
} }
/** /**
* Set the power of the capacity of the free block pool. * Set the power of the capacity of the free block pool.
* @note This is a dummy implementation for compatibility. * @note This is a dummy implementation for compatibility.
skipping to change at line 1340 skipping to change at line 1340
int64_t msiz() { int64_t msiz() {
return 0; return 0;
} }
/** /**
* Get the unit step number of auto defragmentation. * Get the unit step number of auto defragmentation.
* @note This is a dummy implementation for compatibility. * @note This is a dummy implementation for compatibility.
*/ */
int64_t dfunit() { int64_t dfunit() {
return 0; return 0;
} }
private: private:
/** /**
* Record data. * Record data.
*/ */
struct Record { struct Record {
uint32_t ksiz; ///< size of the key uint32_t ksiz; ///< size of the key
uint32_t vsiz; ///< size of the value uint32_t vsiz; ///< size of the value
Record* left; ///< left child record Record* left; ///< left child record
Record* right; ///< right child record Record* right; ///< right child record
Record* prev; ///< privious record Record* prev; ///< privious record
Record* next; ///< next record Record* next; ///< next record
}; };
/** /**
* Transaction log. * Transaction log.
*/ */
struct TranLog { struct TranLog {
bool full; ///< flag whether full bool full; ///< flag whether full
std::string key; ///< old key std::string key; ///< old key
std::string value; ///< old value std::string value; ///< old value
/** constructor for a full record */ /** constructor for a full record */
explicit TranLog(const char* kbuf, size_t ksiz, const char* vbuf, size_ t vsiz) : explicit TranLog(const char* kbuf, size_t ksiz, const char* vbuf, size_ t vsiz) :
full(true), key(kbuf, ksiz), value(vbuf, vsiz) { full(true), key(kbuf, ksiz), value(vbuf, vsiz) {
_assert_(true); _assert_(true);
} }
/** constructor for an empty record */ /** constructor for an empty record */
explicit TranLog(const char* kbuf, size_t ksiz) : full(false), key(kbuf , ksiz) { explicit TranLog(const char* kbuf, size_t ksiz) : full(false), key(kbuf , ksiz) {
_assert_(true); _assert_(true);
} }
}; };
/** /**
* Slot table. * Slot table.
*/ */
skipping to change at line 1389 skipping to change at line 1389
Record* last; ///< last record Record* last; ///< last record
size_t count; ///< number of records size_t count; ///< number of records
size_t size; ///< total size of records size_t size; ///< total size of records
TranLogList trlogs; ///< transaction logs TranLogList trlogs; ///< transaction logs
size_t trsize; ///< size before transaction size_t trsize; ///< size before transaction
}; };
/** /**
* Repeating visitor. * Repeating visitor.
*/ */
class Repeater : public Visitor { class Repeater : public Visitor {
public: public:
/** constructor */ /** constructor */
explicit Repeater(const char* vbuf, size_t vsiz) : vbuf_(vbuf), vsiz_(v siz) {} explicit Repeater(const char* vbuf, size_t vsiz) : vbuf_(vbuf), vsiz_(v siz) {}
private: private:
/** process a full record */ /** process a full record */
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
_assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp ); _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp );
*sp = vsiz_; *sp = vsiz_;
return vbuf_; return vbuf_;
} }
const char* vbuf_; ///< region of the value const char* vbuf_; ///< region of the value
size_t vsiz_; ///< size of the value size_t vsiz_; ///< size of the value
}; };
/** /**
* Setting visitor. * Setting visitor.
*/ */
class Setter : public Visitor { class Setter : public Visitor {
public: public:
/** constructor */ /** constructor */
explicit Setter(const char* vbuf, size_t vsiz) : vbuf_(vbuf), vsiz_(vsi z) {} explicit Setter(const char* vbuf, size_t vsiz) : vbuf_(vbuf), vsiz_(vsi z) {}
private: private:
/** process a full record */ /** process a full record */
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
_assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp ); _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp );
*sp = vsiz_; *sp = vsiz_;
return vbuf_; return vbuf_;
} }
/** process an empty record */ /** process an empty record */
const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) {
_assert_(kbuf && ksiz <= MEMMAXSIZ && sp); _assert_(kbuf && ksiz <= MEMMAXSIZ && sp);
*sp = vsiz_; *sp = vsiz_;
return vbuf_; return vbuf_;
} }
const char* vbuf_; ///< region of the value const char* vbuf_; ///< region of the value
size_t vsiz_; ///< size of the value size_t vsiz_; ///< size of the value
}; };
/** /**
* Removing visitor. * Removing visitor.
*/ */
class Remover : public Visitor { class Remover : public Visitor {
private: private:
/** visit a record */ /** visit a record */
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
_assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp ); _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp );
return REMOVE; return REMOVE;
} }
}; };
/** /**
* Scoped visitor. * Scoped visitor.
*/ */
class ScopedVisitor { class ScopedVisitor {
public: public:
/** constructor */ /** constructor */
explicit ScopedVisitor(Visitor* visitor) : visitor_(visitor) { explicit ScopedVisitor(Visitor* visitor) : visitor_(visitor) {
_assert_(visitor); _assert_(visitor);
visitor_->visit_before(); visitor_->visit_before();
} }
/** destructor */ /** destructor */
~ScopedVisitor() { ~ScopedVisitor() {
_assert_(true); _assert_(true);
visitor_->visit_after(); visitor_->visit_after();
} }
private: private:
Visitor* visitor_; ///< visitor Visitor* visitor_; ///< visitor
}; };
/** /**
* Accept a visitor to a record. * Accept a visitor to a record.
* @param slot the slot of the record. * @param slot the slot of the record.
* @param hash the hash value of the key. * @param hash the hash value of the key.
* @param kbuf the pointer to the key region. * @param kbuf the pointer to the key region.
* @param ksiz the size of the key region. * @param ksiz the size of the key region.
* @param visitor a visitor object. * @param visitor a visitor object.
* @param comp the data compressor. * @param comp the data compressor.
skipping to change at line 1798 skipping to change at line 1798
return hashmurmur(kbuf, ksiz); return hashmurmur(kbuf, ksiz);
} }
/** /**
* Fold a hash value into a small number. * Fold a hash value into a small number.
* @param hash the hash number. * @param hash the hash number.
* @return the result number. * @return the result number.
*/ */
uint32_t fold_hash(uint64_t hash) { uint32_t fold_hash(uint64_t hash) {
_assert_(true); _assert_(true);
return ((hash & 0xffffffff00000000ULL) >> 32) ^ ((hash & 0x0000ffffffff 0000ULL) >> 16) ^ return ((hash & 0xffffffff00000000ULL) >> 32) ^ ((hash & 0x0000ffffffff 0000ULL) >> 16) ^
((hash & 0x000000000000ffffULL) << 16) ^ ((hash & 0x00000000ffff0000U LL) >> 0); ((hash & 0x000000000000ffffULL) << 16) ^ ((hash & 0x00000000ffff000 0ULL) >> 0);
} }
/** /**
* Compare two keys in lexical order. * Compare two keys in lexical order.
* @param abuf one key. * @param abuf one key.
* @param asiz the size of the one key. * @param asiz the size of the one key.
* @param bbuf the other key. * @param bbuf the other key.
* @param bsiz the size of the other key. * @param bsiz the size of the other key.
* @return positive if the former is big, or negative if the latter is bi g, or 0 if both are * @return positive if the former is big, or negative if the latter is bi g, or 0 if both are
* equivalent. * equivalent.
*/ */
 End of changes. 19 change blocks. 
23 lines changed or deleted 24 lines changed or added


 kccompare.h   kccompare.h 
skipping to change at line 27 skipping to change at line 27
#include <kccommon.h> #include <kccommon.h>
#include <kcutil.h> #include <kcutil.h>
namespace kyotocabinet { // common namespace namespace kyotocabinet { // common namespace
/** /**
* Interfrace of comparator of record keys. * Interfrace of comparator of record keys.
*/ */
class Comparator { class Comparator {
public: public:
/** /**
* Destructor. * Destructor.
*/ */
virtual ~Comparator() {} virtual ~Comparator() {}
/** /**
* Compare two keys. * Compare two keys.
* @param akbuf the pointer to the region of one key. * @param akbuf the pointer to the region of one key.
* @param aksiz the size of the region of one key. * @param aksiz the size of the region of one key.
* @param bkbuf the pointer to the region of the other key. * @param bkbuf the pointer to the region of the other key.
* @param bksiz the size of the region of the other key. * @param bksiz the size of the region of the other key.
* @return positive if the former is big, negative if the latter is big, 0 if both are * @return positive if the former is big, negative if the latter is big, 0 if both are
* equivalent. * equivalent.
*/ */
virtual int32_t compare(const char* akbuf, size_t aksiz, const char* bkbu f, size_t bksiz) = 0; virtual int32_t compare(const char* akbuf, size_t aksiz, const char* bkbu f, size_t bksiz) = 0;
}; };
/** /**
* Comparator in the lexical order. * Comparator in the lexical order.
*/ */
class LexicalComparator : public Comparator { class LexicalComparator : public Comparator {
public: public:
explicit LexicalComparator() {} explicit LexicalComparator() {}
int32_t compare(const char* akbuf, size_t aksiz, const char* bkbuf, size_ t bksiz) { int32_t compare(const char* akbuf, size_t aksiz, const char* bkbuf, size_ t bksiz) {
_assert_(akbuf && bkbuf); _assert_(akbuf && bkbuf);
size_t msiz = aksiz < bksiz ? aksiz : bksiz; size_t msiz = aksiz < bksiz ? aksiz : bksiz;
for (size_t i = 0; i < msiz; i++) { for (size_t i = 0; i < msiz; i++) {
if (((uint8_t*)akbuf)[i] != ((uint8_t*)bkbuf)[i]) if (((uint8_t*)akbuf)[i] != ((uint8_t*)bkbuf)[i])
return ((uint8_t*)akbuf)[i] - ((uint8_t*)bkbuf)[i]; return ((uint8_t*)akbuf)[i] - ((uint8_t*)bkbuf)[i];
} }
return (int32_t)aksiz - (int32_t)bksiz; return (int32_t)aksiz - (int32_t)bksiz;
} }
}; };
/** /**
* Comparator in the lexical descending order. * Comparator in the lexical descending order.
*/ */
class LexicalDescendingComparator : public Comparator { class LexicalDescendingComparator : public Comparator {
public: public:
explicit LexicalDescendingComparator() : comp_() {} explicit LexicalDescendingComparator() : comp_() {}
int32_t compare(const char* akbuf, size_t aksiz, const char* bkbuf, size_ t bksiz) { int32_t compare(const char* akbuf, size_t aksiz, const char* bkbuf, size_ t bksiz) {
return -comp_.compare(akbuf, aksiz, bkbuf, bksiz); return -comp_.compare(akbuf, aksiz, bkbuf, bksiz);
} }
private: private:
LexicalComparator comp_; LexicalComparator comp_;
}; };
/** /**
* Comparator in the decimal order. * Comparator in the decimal order.
*/ */
class DecimalComparator : public Comparator { class DecimalComparator : public Comparator {
public: public:
explicit DecimalComparator() {} explicit DecimalComparator() {}
int32_t compare(const char* akbuf, size_t aksiz, const char* bkbuf, size_ t bksiz) { int32_t compare(const char* akbuf, size_t aksiz, const char* bkbuf, size_ t bksiz) {
_assert_(akbuf && bkbuf); _assert_(akbuf && bkbuf);
const int32_t LDBLCOLMAX = 16; const int32_t LDBLCOLMAX = 16;
const unsigned char* arp = (unsigned char*)akbuf; const unsigned char* arp = (unsigned char*)akbuf;
int32_t alen = aksiz; int32_t alen = aksiz;
while (alen > 0 && (*arp <= ' ' || *arp == 0x7f)) { while (alen > 0 && (*arp <= ' ' || *arp == 0x7f)) {
arp++; arp++;
alen--; alen--;
} }
skipping to change at line 171 skipping to change at line 171
LexicalComparator lexcomp; LexicalComparator lexcomp;
int32_t rv = lexcomp.compare(akbuf, aksiz, bkbuf, bksiz); int32_t rv = lexcomp.compare(akbuf, aksiz, bkbuf, bksiz);
return rv; return rv;
} }
}; };
/** /**
* Comparator in the decimal descending order. * Comparator in the decimal descending order.
*/ */
class DecimalDescendingComparator : public Comparator { class DecimalDescendingComparator : public Comparator {
public: public:
explicit DecimalDescendingComparator() : comp_() {} explicit DecimalDescendingComparator() : comp_() {}
int32_t compare(const char* akbuf, size_t aksiz, const char* bkbuf, size_ t bksiz) { int32_t compare(const char* akbuf, size_t aksiz, const char* bkbuf, size_ t bksiz) {
return -comp_.compare(akbuf, aksiz, bkbuf, bksiz); return -comp_.compare(akbuf, aksiz, bkbuf, bksiz);
} }
private: private:
DecimalComparator comp_; DecimalComparator comp_;
}; };
/** /**
* Prepared pointer of the comparator in the lexical order. * Prepared pointer of the comparator in the lexical order.
*/ */
extern LexicalComparator* const LEXICALCOMP; extern LexicalComparator* const LEXICALCOMP;
/** /**
* Prepared pointer of the comparator in the lexical descending order. * Prepared pointer of the comparator in the lexical descending order.
 End of changes. 7 change blocks. 
7 lines changed or deleted 7 lines changed or added


 kccompress.h   kccompress.h 
skipping to change at line 28 skipping to change at line 28
#include <kccommon.h> #include <kccommon.h>
#include <kcutil.h> #include <kcutil.h>
#include <kcthread.h> #include <kcthread.h>
namespace kyotocabinet { // common namespace namespace kyotocabinet { // common namespace
/** /**
* Interfrace of data compression and decompression. * Interfrace of data compression and decompression.
*/ */
class Compressor { class Compressor {
public: public:
/** /**
* Destructor. * Destructor.
*/ */
virtual ~Compressor() {} virtual ~Compressor() {}
/** /**
* Compress a serial data. * Compress a serial data.
* @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.
skipping to change at line 63 skipping to change at line 63
* 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.
*/ */
virtual char* decompress(const void* buf, size_t size, size_t* sp) = 0; virtual char* decompress(const void* buf, size_t size, size_t* sp) = 0;
}; };
/** /**
* ZLIB compressor. * ZLIB compressor.
*/ */
class ZLIB { class ZLIB {
public: public:
/** /**
* 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.
skipping to change at line 112 skipping to change at line 112
* @param seed the cyclic seed value. * @param seed the cyclic seed value.
* @return the CRC32 checksum. * @return the CRC32 checksum.
*/ */
static uint32_t calculate_crc(const void* buf, size_t size, uint32_t seed = 0); static uint32_t calculate_crc(const void* buf, size_t size, uint32_t seed = 0);
}; };
/** /**
* LZO compressor. * LZO compressor.
*/ */
class LZO { class LZO {
public: public:
/** /**
* Compression modes. * Compression modes.
*/ */
enum Mode { enum Mode {
RAW, ///< without any checksum RAW, ///< without any checksum
CRC ///< with CRC32 checksum CRC ///< with CRC32 checksum
}; };
/** /**
* Compress a serial data. * Compress a serial data.
* @param buf the input buffer. * @param buf the input buffer.
skipping to change at line 160 skipping to change at line 160
* @param seed the cyclic seed value. * @param seed the cyclic seed value.
* @return the CRC32 checksum. * @return the CRC32 checksum.
*/ */
static uint32_t calculate_crc(const void* buf, size_t size, uint32_t seed = 0); static uint32_t calculate_crc(const void* buf, size_t size, uint32_t seed = 0);
}; };
/** /**
* LZMA compressor. * LZMA compressor.
*/ */
class LZMA { class LZMA {
public: public:
/** /**
* Compression modes. * Compression modes.
*/ */
enum Mode { enum Mode {
RAW, ///< without any checksum RAW, ///< without any checksum
CRC, ///< with CRC32 checksum CRC, ///< with CRC32 checksum
SHA ///< with SHA256 checksum SHA ///< with SHA256 checksum
}; };
/** /**
* Compress a serial data. * Compress a serial data.
skipping to change at line 210 skipping to change at line 210
* @return the CRC32 checksum. * @return the CRC32 checksum.
*/ */
static uint32_t calculate_crc(const void* buf, size_t size, uint32_t seed = 0); static uint32_t calculate_crc(const void* buf, size_t size, uint32_t seed = 0);
}; };
/** /**
* Compressor with ZLIB. * Compressor with ZLIB.
*/ */
template <ZLIB::Mode MODE> template <ZLIB::Mode MODE>
class ZLIBCompressor : public Compressor { class ZLIBCompressor : public Compressor {
private: private:
/** /**
* Compress a serial data. * 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 && size <= MEMMAXSIZ && sp); _assert_(buf && size <= MEMMAXSIZ && sp);
return ZLIB::compress(buf, size, sp, MODE); return ZLIB::compress(buf, size, sp, MODE);
} }
/** /**
* Decompress a serial data. * Decompress a serial data.
*/ */
skipping to change at line 232 skipping to change at line 232
_assert_(buf && size <= MEMMAXSIZ && sp); _assert_(buf && size <= MEMMAXSIZ && sp);
return ZLIB::decompress(buf, size, sp, MODE); return ZLIB::decompress(buf, size, sp, MODE);
} }
}; };
/** /**
* Compressor with LZO. * Compressor with LZO.
*/ */
template <LZO::Mode MODE> template <LZO::Mode MODE>
class LZOCompressor : public Compressor { class LZOCompressor : public Compressor {
private: private:
/** /**
* Compress a serial data. * 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 && size <= MEMMAXSIZ && sp); _assert_(buf && size <= MEMMAXSIZ && sp);
return LZO::compress(buf, size, sp, MODE); return LZO::compress(buf, size, sp, MODE);
} }
/** /**
* Decompress a serial data. * Decompress a serial data.
*/ */
skipping to change at line 254 skipping to change at line 254
_assert_(buf && size <= MEMMAXSIZ && sp); _assert_(buf && size <= MEMMAXSIZ && sp);
return LZO::decompress(buf, size, sp, MODE); return LZO::decompress(buf, size, sp, MODE);
} }
}; };
/** /**
* Compressor with LZMA. * Compressor with LZMA.
*/ */
template <LZMA::Mode MODE> template <LZMA::Mode MODE>
class LZMACompressor : public Compressor { class LZMACompressor : public Compressor {
private: private:
/** /**
* Compress a serial data. * 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 && size <= MEMMAXSIZ && sp); _assert_(buf && size <= MEMMAXSIZ && sp);
return LZMA::compress(buf, size, sp, MODE); return LZMA::compress(buf, size, sp, MODE);
} }
/** /**
* Decompress a serial data. * 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 && size <= MEMMAXSIZ && sp); _assert_(buf && size <= MEMMAXSIZ && sp);
return LZMA::decompress(buf, size, sp, MODE); return LZMA::decompress(buf, size, sp, MODE);
} }
}; };
/** /**
* Compressor with the Arcfour cipher. * Compressor with the Arcfour cipher.
*/ */
class ArcfourCompressor : public Compressor { class ArcfourCompressor : public Compressor {
public: public:
/** /**
* Constructor. * Constructor.
*/ */
ArcfourCompressor() : kbuf_(NULL), ksiz_(0), comp_(NULL), salt_(0), cycle _(false) { ArcfourCompressor() : kbuf_(NULL), ksiz_(0), comp_(NULL), salt_(0), cycle _(false) {
_assert_(true); _assert_(true);
kbuf_ = new char[1]; kbuf_ = new char[1];
ksiz_ = 0; ksiz_ = 0;
} }
/** /**
* Destructor. * Destructor.
skipping to change at line 320 skipping to change at line 320
comp_ = comp; comp_ = comp;
} }
/** /**
* Begin the cycle of ciper salt. * Begin the cycle of ciper salt.
* @param salt the additional cipher salt. * @param salt the additional cipher salt.
*/ */
void begin_cycle(uint64_t salt = 0) { void begin_cycle(uint64_t salt = 0) {
salt_ = salt; salt_ = salt;
cycle_ = true; cycle_ = true;
} }
private: private:
/** /**
* Compress a serial data. * 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 && size <= MEMMAXSIZ && sp); _assert_(buf && size <= MEMMAXSIZ && sp);
uint64_t salt = cycle_ ? salt_.add(1) : 0; uint64_t salt = cycle_ ? salt_.add(1) : 0;
char kbuf[NUMBUFSIZ*2]; char kbuf[NUMBUFSIZ*2];
writefixnum(kbuf, salt, sizeof(salt)); writefixnum(kbuf, salt, sizeof(salt));
std::memcpy(kbuf + sizeof(salt), kbuf_, ksiz_); std::memcpy(kbuf + sizeof(salt), kbuf_, ksiz_);
char* tbuf = NULL; char* tbuf = NULL;
 End of changes. 9 change blocks. 
9 lines changed or deleted 9 lines changed or added


 kcdb.h   kcdb.h 
skipping to change at line 35 skipping to change at line 35
#define KCDBSSMAGICDATA "KCSS\n" ///< The magic data of the snapsho t file #define KCDBSSMAGICDATA "KCSS\n" ///< The magic data of the snapsho t file
namespace kyotocabinet { // common namespace namespace kyotocabinet { // common namespace
/** /**
* Interface of database abstraction. * Interface of database abstraction.
* @note This class is an abstract class to prescribe the interface of reco rd access. * @note This class is an abstract class to prescribe the interface of reco rd access.
*/ */
class DB { class DB {
public: public:
/** /**
* Interface to access a record. * Interface to access a record.
*/ */
class Visitor { class Visitor {
public: public:
/** Special pointer for no operation. */ /** Special pointer for no operation. */
static const char* const NOP; static const char* const NOP;
/** Special pointer to remove the record. */ /** Special pointer to remove the record. */
static const char* const REMOVE; static const char* const REMOVE;
/** /**
* Destructor. * Destructor.
*/ */
virtual ~Visitor() { virtual ~Visitor() {
_assert_(true); _assert_(true);
} }
skipping to change at line 97 skipping to change at line 97
* Postprocess the main operations. * Postprocess the main operations.
*/ */
virtual void visit_after() { virtual void visit_after() {
_assert_(true); _assert_(true);
} }
}; };
/** /**
* Interface of cursor to indicate a record. * Interface of cursor to indicate a record.
*/ */
class Cursor { class Cursor {
public: public:
/** /**
* Destructor. * Destructor.
*/ */
virtual ~Cursor() { virtual ~Cursor() {
_assert_(true); _assert_(true);
} }
/** /**
* Accept a visitor to the current record. * Accept a visitor to the current record.
* @param visitor a visitor object. * @param visitor a visitor object.
* @param writable true for writable operation, or false for read-only operation. * @param writable true for writable operation, or false for read-only operation.
skipping to change at line 463 skipping to change at line 463
* @note This class is an abstract class to prescribe the interface of file operations and * @note This class is an abstract class to prescribe the interface of file operations and
* provide mix-in methods. This class can be inherited but overwriting met hods is forbidden. * provide mix-in methods. This class can be inherited but overwriting met hods is forbidden.
* Before every database operation, it is necessary to call the BasicDB::op en method in order to * Before every database operation, it is necessary to call the BasicDB::op en method in order to
* open a database file and connect the database object to it. To avoid da ta missing or * open a database file and connect the database object to it. To avoid da ta missing or
* corruption, it is important to close every database file by the BasicDB: :close method when the * corruption, it is important to close every database file by the BasicDB: :close method when the
* database is no longer in use. It is forbidden for multible database obj ects in a process to * database is no longer in use. It is forbidden for multible database obj ects in a process to
* open the same database at the same time. It is forbidden to share a dat abase object with * open the same database at the same time. It is forbidden to share a dat abase object with
* child processes. * child processes.
*/ */
class BasicDB : public DB { class BasicDB : public DB {
public: public:
class Cursor; class Cursor;
class Error; class Error;
class ProgressChecker; class ProgressChecker;
class FileProcessor; class FileProcessor;
class Logger; class Logger;
class MetaTrigger; class MetaTrigger;
private: private:
/** The size of the IO buffer. */ /** The size of the IO buffer. */
static const size_t IOBUFSIZ = 8192; static const size_t IOBUFSIZ = 8192;
public: public:
/** /**
* Database types. * Database types.
*/ */
enum Type { enum Type {
TYPEVOID = 0x00, ///< void database TYPEVOID = 0x00, ///< void database
TYPEPHASH = 0x10, ///< prototype hash database TYPEPHASH = 0x10, ///< prototype hash database
TYPEPTREE = 0x11, ///< prototype tree database TYPEPTREE = 0x11, ///< prototype tree database
TYPESTASH = 0x18, ///< stash database TYPESTASH = 0x18, ///< stash database
TYPECACHE = 0x20, ///< cache hash database TYPECACHE = 0x20, ///< cache hash database
TYPEGRASS = 0x21, ///< cache tree database TYPEGRASS = 0x21, ///< cache tree database
TYPEHASH = 0x30, ///< file hash database TYPEHASH = 0x30, ///< file hash database
TYPETREE = 0x31, ///< file tree database TYPETREE = 0x31, ///< file tree database
TYPEDIR = 0x40, ///< directory hash database TYPEDIR = 0x40, ///< directory hash database
TYPEFOREST = 0x41, ///< directory tree database TYPEFOREST = 0x41, ///< directory tree database
TYPEMISC = 0x80 ///< miscellaneous database TYPEMISC = 0x80 ///< miscellaneous database
}; };
/** /**
* Interface of cursor to indicate a record. * Interface of cursor to indicate a record.
*/ */
class Cursor : public DB::Cursor { class Cursor : public DB::Cursor {
public: public:
/** /**
* Destructor. * Destructor.
*/ */
virtual ~Cursor() { virtual ~Cursor() {
_assert_(true); _assert_(true);
} }
/** /**
* Set the value of the current record. * Set the value of the current record.
* @param vbuf the pointer to the value region. * @param vbuf the pointer to the value region.
* @param vsiz the size of the value region. * @param vsiz the size of the value region.
* @param step true to move the cursor to the next record, or false for no move. * @param step true to move the cursor to the next record, or false for no move.
* @return true on success, or false on failure. * @return true on success, or false on failure.
*/ */
bool set_value(const char* vbuf, size_t vsiz, bool step = false) { bool set_value(const char* vbuf, size_t vsiz, bool step = false) {
_assert_(vbuf && vsiz <= MEMMAXSIZ); _assert_(vbuf && vsiz <= MEMMAXSIZ);
class VisitorImpl : public Visitor { class VisitorImpl : public Visitor {
public: public:
explicit VisitorImpl(const char* vbuf, size_t vsiz) : explicit VisitorImpl(const char* vbuf, size_t vsiz) :
vbuf_(vbuf), vsiz_(vsiz), ok_(false) {} vbuf_(vbuf), vsiz_(vsiz), ok_(false) {}
bool ok() const { bool ok() const {
return ok_; return ok_;
} }
private: private:
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
ok_ = true; ok_ = true;
*sp = vsiz_; *sp = vsiz_;
return vbuf_; return vbuf_;
} }
const char* vbuf_; const char* vbuf_;
size_t vsiz_; size_t vsiz_;
bool ok_; bool ok_;
}; };
skipping to change at line 551 skipping to change at line 551
} }
/** /**
* Remove the current record. * Remove the current record.
* @return true on success, or false on failure. * @return true on success, or false on failure.
* @note If no record corresponds to the key, false is returned. The c ursor is moved to the * @note If no record corresponds to the key, false is returned. The c ursor is moved to the
* next record implicitly. * next record implicitly.
*/ */
bool remove() { bool remove() {
_assert_(true); _assert_(true);
class VisitorImpl : public Visitor { class VisitorImpl : public Visitor {
public: public:
explicit VisitorImpl() : ok_(false) {} explicit VisitorImpl() : ok_(false) {}
bool ok() const { bool ok() const {
return ok_; return ok_;
} }
private: private:
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
ok_ = true; ok_ = true;
return REMOVE; return REMOVE;
} }
bool ok_; bool ok_;
}; };
VisitorImpl visitor; VisitorImpl visitor;
if (!accept(&visitor, true, false)) return false; if (!accept(&visitor, true, false)) return false;
if (!visitor.ok()) return false; if (!visitor.ok()) return false;
skipping to change at line 584 skipping to change at line 584
* @return the pointer to the key region of the current record, or NULL on failure. * @return the pointer to the key region of the current record, or NULL on failure.
* @note If the cursor is invalidated, NULL is returned. Because an ad ditional zero * @note If the cursor is invalidated, NULL is returned. Because an ad ditional zero
* code is appended at the end of the region of the return value, the r eturn value can be * code is appended at the end of the region of the return value, the r eturn value can be
* treated as a C-style string. Because the region of the return value is allocated with the * treated as a C-style string. Because the region of the return value is allocated with the
* the new[] operator, it should be released with the delete[] operator when it is no longer * the new[] operator, it should be released with the delete[] operator when it is no longer
* in use. * in use.
*/ */
char* get_key(size_t* sp, bool step = false) { char* get_key(size_t* sp, bool step = false) {
_assert_(sp); _assert_(sp);
class VisitorImpl : public Visitor { class VisitorImpl : public Visitor {
public: public:
explicit VisitorImpl() : kbuf_(NULL), ksiz_(0) {} explicit VisitorImpl() : kbuf_(NULL), ksiz_(0) {}
char* pop(size_t* sp) { char* pop(size_t* sp) {
*sp = ksiz_; *sp = ksiz_;
return kbuf_; return kbuf_;
} }
void clear() { void clear() {
delete[] kbuf_; delete[] kbuf_;
} }
private: private:
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
kbuf_ = new char[ksiz+1]; kbuf_ = new char[ksiz+1];
std::memcpy(kbuf_, kbuf, ksiz); std::memcpy(kbuf_, kbuf, ksiz);
kbuf_[ksiz] = '\0'; kbuf_[ksiz] = '\0';
ksiz_ = ksiz; ksiz_ = ksiz;
return NOP; return NOP;
} }
char* kbuf_; char* kbuf_;
size_t ksiz_; size_t ksiz_;
skipping to change at line 650 skipping to change at line 650
* @return the pointer to the value region of the current record, or NU LL on failure. * @return the pointer to the value region of the current record, or NU LL on failure.
* @note If the cursor is invalidated, NULL is returned. Because an ad ditional zero * @note If the cursor is invalidated, NULL is returned. Because an ad ditional zero
* code is appended at the end of the region of the return value, the r eturn value can be * code is appended at the end of the region of the return value, the r eturn value can be
* treated as a C-style string. Because the region of the return value is allocated with the * treated as a C-style string. Because the region of the return value is allocated with the
* the new[] operator, it should be released with the delete[] operator when it is no longer * the new[] operator, it should be released with the delete[] operator when it is no longer
* in use. * in use.
*/ */
char* get_value(size_t* sp, bool step = false) { char* get_value(size_t* sp, bool step = false) {
_assert_(sp); _assert_(sp);
class VisitorImpl : public Visitor { class VisitorImpl : public Visitor {
public: public:
explicit VisitorImpl() : vbuf_(NULL), vsiz_(0) {} explicit VisitorImpl() : vbuf_(NULL), vsiz_(0) {}
char* pop(size_t* sp) { char* pop(size_t* sp) {
*sp = vsiz_; *sp = vsiz_;
return vbuf_; return vbuf_;
} }
void clear() { void clear() {
delete[] vbuf_; delete[] vbuf_;
} }
private: private:
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
vbuf_ = new char[vsiz+1]; vbuf_ = new char[vsiz+1];
std::memcpy(vbuf_, vbuf, vsiz); std::memcpy(vbuf_, vbuf, vsiz);
vbuf_[vsiz] = '\0'; vbuf_[vsiz] = '\0';
vsiz_ = vsiz; vsiz_ = vsiz;
return NOP; return NOP;
} }
char* vbuf_; char* vbuf_;
size_t vsiz_; size_t vsiz_;
skipping to change at line 719 skipping to change at line 719
* @param step true to move the cursor to the next record, or false for no move. * @param step true to move the cursor to the next record, or false for no move.
* @return the pointer to the key region, or NULL on failure. * @return the pointer to the key region, or NULL on failure.
* @note If the cursor is invalidated, NULL is returned. Because an ad ditional zero code is * @note If the cursor is invalidated, NULL is returned. Because an ad ditional zero code is
* appended at the end of each region of the key and the value, each re gion can be treated * appended at the end of each region of the key and the value, each re gion can be treated
* as a C-style string. The return value should be deleted explicitly by the caller with * as a C-style string. The return value should be deleted explicitly by the caller with
* the detele[] operator. * the detele[] operator.
*/ */
char* get(size_t* ksp, const char** vbp, size_t* vsp, bool step = false ) { char* get(size_t* ksp, const char** vbp, size_t* vsp, bool step = false ) {
_assert_(ksp && vbp && vsp); _assert_(ksp && vbp && vsp);
class VisitorImpl : public Visitor { class VisitorImpl : public Visitor {
public: public:
explicit VisitorImpl() : kbuf_(NULL), ksiz_(0), vbuf_(NULL), vsiz_( 0) {} explicit VisitorImpl() : kbuf_(NULL), ksiz_(0), vbuf_(NULL), vsiz_( 0) {}
char* pop(size_t* ksp, const char** vbp, size_t* vsp) { char* pop(size_t* ksp, const char** vbp, size_t* vsp) {
*ksp = ksiz_; *ksp = ksiz_;
*vbp = vbuf_; *vbp = vbuf_;
*vsp = vsiz_; *vsp = vsiz_;
return kbuf_; return kbuf_;
} }
void clear() { void clear() {
delete[] kbuf_; delete[] kbuf_;
} }
private: private:
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
size_t rsiz = ksiz + 1 + vsiz + 1; size_t rsiz = ksiz + 1 + vsiz + 1;
kbuf_ = new char[rsiz]; kbuf_ = new char[rsiz];
std::memcpy(kbuf_, kbuf, ksiz); std::memcpy(kbuf_, kbuf, ksiz);
kbuf_[ksiz] = '\0'; kbuf_[ksiz] = '\0';
ksiz_ = ksiz; ksiz_ = ksiz;
vbuf_ = kbuf_ + ksiz + 1; vbuf_ = kbuf_ + ksiz + 1;
std::memcpy(vbuf_, vbuf, vsiz); std::memcpy(vbuf_, vbuf, vsiz);
vbuf_[vsiz] = '\0'; vbuf_[vsiz] = '\0';
skipping to change at line 767 skipping to change at line 767
return visitor.pop(ksp, vbp, vsp); return visitor.pop(ksp, vbp, vsp);
} }
/** /**
* Get a pair of the key and the value of the current record. * Get a pair of the key and the value of the current record.
* @note Equal to the original Cursor::get method except that parameter s are strings * @note Equal to the original Cursor::get method except that parameter s are strings
* to contain the result and the return value is bool for success. * to contain the result and the return value is bool for success.
*/ */
bool get(std::string* key, std::string* value, bool step = false) { bool get(std::string* key, std::string* value, bool step = false) {
_assert_(key && value); _assert_(key && value);
class VisitorImpl : public Visitor { class VisitorImpl : public Visitor {
public: public:
explicit VisitorImpl(std::string* key, std::string* value) : explicit VisitorImpl(std::string* key, std::string* value) :
key_(key), value_(value), ok_(false) {} key_(key), value_(value), ok_(false) {}
bool ok() { bool ok() {
return ok_; return ok_;
} }
private: private:
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
key_->clear(); key_->clear();
key_->append(kbuf, ksiz); key_->append(kbuf, ksiz);
value_->clear(); value_->clear();
value_->append(vbuf, vsiz); value_->append(vbuf, vsiz);
ok_ = true; ok_ = true;
return NOP; return NOP;
} }
std::string* key_; std::string* key_;
skipping to change at line 809 skipping to change at line 809
*/ */
Error error() { Error error() {
_assert_(true); _assert_(true);
return db()->error(); return db()->error();
} }
}; };
/** /**
* Error data. * Error data.
*/ */
class Error { class Error {
public: public:
/** /**
* Error codes. * Error codes.
*/ */
enum Code { enum Code {
SUCCESS, ///< success SUCCESS, ///< success
NOIMPL, ///< not implemented NOIMPL, ///< not implemented
INVALID, ///< invalid operation INVALID, ///< invalid operation
NOREPOS, ///< no repository NOREPOS, ///< no repository
NOPERM, ///< no permission NOPERM, ///< no permission
BROKEN, ///< broken file BROKEN, ///< broken file
skipping to change at line 928 skipping to change at line 928
message_ = right.message_; message_ = right.message_;
return *this; return *this;
} }
/** /**
* Cast operator to integer. * Cast operator to integer.
* @return the error code. * @return the error code.
*/ */
operator int32_t() const { operator int32_t() const {
return code_; return code_;
} }
private: private:
/** The error code. */ /** The error code. */
Code code_; Code code_;
/** The supplement message. */ /** The supplement message. */
const char* message_; const char* message_;
}; };
/** /**
* Interface to check progress status of long process. * Interface to check progress status of long process.
*/ */
class ProgressChecker { class ProgressChecker {
public: public:
/** /**
* Destructor. * Destructor.
*/ */
virtual ~ProgressChecker() { virtual ~ProgressChecker() {
_assert_(true); _assert_(true);
} }
/** /**
* Check the progress status. * Check the progress status.
* @param name the name of the process. * @param name the name of the process.
* @param message a supplement message. * @param message a supplement message.
skipping to change at line 960 skipping to change at line 960
* @param allcnt the estimation count of all steps of the progress, or -1 if not applicable. * @param allcnt the estimation count of all steps of the progress, or -1 if not applicable.
* @return true to continue the process, or false to stop the process. * @return true to continue the process, or false to stop the process.
*/ */
virtual bool check(const char* name, const char* message, virtual bool check(const char* name, const char* message,
int64_t curcnt, int64_t allcnt) = 0; int64_t curcnt, int64_t allcnt) = 0;
}; };
/** /**
* Interface to process the database file. * Interface to process the database file.
*/ */
class FileProcessor { class FileProcessor {
public: public:
/** /**
* Destructor. * Destructor.
*/ */
virtual ~FileProcessor() { virtual ~FileProcessor() {
_assert_(true); _assert_(true);
} }
/** /**
* Process the database file. * Process the database file.
* @param path the path of the database file. * @param path the path of the database file.
* @param count the number of records. A negative value means omission . * @param count the number of records. A negative value means omission .
* @param size the size of the available region. A negative value mean s omission. * @param size the size of the available region. A negative value mean s omission.
* @return true on success, or false on failure. * @return true on success, or false on failure.
*/ */
virtual bool process(const std::string& path, int64_t count, int64_t si ze) = 0; virtual bool process(const std::string& path, int64_t count, int64_t si ze) = 0;
}; };
/** /**
* Interface to log internal information and errors. * Interface to log internal information and errors.
*/ */
class Logger { class Logger {
public: public:
/** /**
* Event kinds. * Event kinds.
*/ */
enum Kind { enum Kind {
DEBUG = 1 << 0, ///< debugging DEBUG = 1 << 0, ///< debugging
INFO = 1 << 1, ///< normal information INFO = 1 << 1, ///< normal information
WARN = 1 << 2, ///< warning WARN = 1 << 2, ///< warning
ERROR = 1 << 3 ///< error ERROR = 1 << 3 ///< error
}; };
/** /**
skipping to change at line 1012 skipping to change at line 1012
* information, Logger::WARN for warning, and Logger::ERROR for fatal e rror. * information, Logger::WARN for warning, and Logger::ERROR for fatal e rror.
* @param message the supplement message. * @param message the supplement message.
*/ */
virtual void log(const char* file, int32_t line, const char* func, Kind kind, virtual void log(const char* file, int32_t line, const char* func, Kind kind,
const char* message) = 0; const char* message) = 0;
}; };
/** /**
* Interface to trigger meta database operations. * Interface to trigger meta database operations.
*/ */
class MetaTrigger { class MetaTrigger {
public: public:
/** /**
* Event kinds. * Event kinds.
*/ */
enum Kind { enum Kind {
OPEN, ///< opening OPEN, ///< opening
CLOSE, ///< closing CLOSE, ///< closing
CLEAR, ///< clearing CLEAR, ///< clearing
ITERATE, ///< iteration ITERATE, ///< iteration
SYNCHRONIZE, ///< synchronization SYNCHRONIZE, ///< synchronization
OCCUPY, ///< occupation OCCUPY, ///< occupation
skipping to change at line 1161 skipping to change at line 1161
virtual bool occupy(bool writable = true, FileProcessor* proc = NULL) = 0 ; virtual bool occupy(bool writable = true, FileProcessor* proc = NULL) = 0 ;
/** /**
* Create a copy of the database file. * Create a copy of the database file.
* @param dest the path of the destination file. * @param dest the path of the destination file.
* @param checker a progress checker object. If it is NULL, no checking is performed. * @param checker a progress checker object. If it is NULL, no checking is performed.
* @return true on success, or false on failure. * @return true on success, or false on failure.
*/ */
bool copy(const std::string& dest, ProgressChecker* checker = NULL) { bool copy(const std::string& dest, ProgressChecker* checker = NULL) {
_assert_(true); _assert_(true);
class FileProcessorImpl : public FileProcessor { class FileProcessorImpl : public FileProcessor {
public: public:
explicit FileProcessorImpl(const std::string& dest, ProgressChecker* checker, explicit FileProcessorImpl(const std::string& dest, ProgressChecker* checker,
BasicDB* db) : BasicDB* db) :
dest_(dest), checker_(checker), db_(db) {} dest_(dest), checker_(checker), db_(db) {}
private: private:
bool process(const std::string& path, int64_t count, int64_t size) { bool process(const std::string& path, int64_t count, int64_t size) {
File::Status sbuf; File::Status sbuf;
if (!File::status(path, &sbuf)) return false; if (!File::status(path, &sbuf)) return false;
if (sbuf.isdir) { if (sbuf.isdir) {
if (!File::make_directory(dest_)) return false; if (!File::make_directory(dest_)) return false;
bool err = false; bool err = false;
DirStream dir; DirStream dir;
if (dir.open(path)) { if (dir.open(path)) {
if (checker_ && !checker_->check("copy", "beginning", 0, -1)) { if (checker_ && !checker_->check("copy", "beginning", 0, -1)) {
db_->set_error(_KCCODELINE_, Error::LOGIC, "checker failed"); db_->set_error(_KCCODELINE_, Error::LOGIC, "checker failed");
skipping to change at line 1307 skipping to change at line 1307
* @param ksiz the size of the key region. * @param ksiz the size of the key region.
* @param vbuf the pointer to the value region. * @param vbuf the pointer to the value region.
* @param vsiz the size of the value region. * @param vsiz the size of the value region.
* @return true on success, or false on failure. * @return true on success, or false on failure.
* @note If no record corresponds to the key, a new record is created. I f the corresponding * @note If no record corresponds to the key, a new record is created. I f the corresponding
* record exists, the value is overwritten. * record exists, the value is overwritten.
*/ */
bool set(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) { bool set(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) {
_assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ); _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ);
class VisitorImpl : public Visitor { class VisitorImpl : public Visitor {
public: public:
explicit VisitorImpl(const char* vbuf, size_t vsiz) : vbuf_(vbuf), vs iz_(vsiz) {} explicit VisitorImpl(const char* vbuf, size_t vsiz) : vbuf_(vbuf), vs iz_(vsiz) {}
private: private:
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
*sp = vsiz_; *sp = vsiz_;
return vbuf_; return vbuf_;
} }
const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) {
*sp = vsiz_; *sp = vsiz_;
return vbuf_; return vbuf_;
} }
const char* vbuf_; const char* vbuf_;
skipping to change at line 1347 skipping to change at line 1347
* @param ksiz the size of the key region. * @param ksiz the size of the key region.
* @param vbuf the pointer to the value region. * @param vbuf the pointer to the value region.
* @param vsiz the size of the value region. * @param vsiz the size of the value region.
* @return true on success, or false on failure. * @return true on success, or false on failure.
* @note If no record corresponds to the key, a new record is created. I f the corresponding * @note If no record corresponds to the key, a new record is created. I f the corresponding
* record exists, the record is not modified and false is returned. * record exists, the record is not modified and false is returned.
*/ */
bool add(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) { bool add(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) {
_assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ); _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ);
class VisitorImpl : public Visitor { class VisitorImpl : public Visitor {
public: public:
explicit VisitorImpl(const char* vbuf, size_t vsiz) : explicit VisitorImpl(const char* vbuf, size_t vsiz) :
vbuf_(vbuf), vsiz_(vsiz), ok_(false) {} vbuf_(vbuf), vsiz_(vsiz), ok_(false) {}
bool ok() const { bool ok() const {
return ok_; return ok_;
} }
private: private:
const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) {
ok_ = true; ok_ = true;
*sp = vsiz_; *sp = vsiz_;
return vbuf_; return vbuf_;
} }
const char* vbuf_; const char* vbuf_;
size_t vsiz_; size_t vsiz_;
bool ok_; bool ok_;
}; };
VisitorImpl visitor(vbuf, vsiz); VisitorImpl visitor(vbuf, vsiz);
skipping to change at line 1392 skipping to change at line 1392
* @param ksiz the size of the key region. * @param ksiz the size of the key region.
* @param vbuf the pointer to the value region. * @param vbuf the pointer to the value region.
* @param vsiz the size of the value region. * @param vsiz the size of the value region.
* @return true on success, or false on failure. * @return true on success, or false on failure.
* @note If no record corresponds to the key, no new record is created an d false is returned. * @note If no record corresponds to the key, no new record is created an d false is returned.
* If the corresponding record exists, the value is modified. * If the corresponding record exists, the value is modified.
*/ */
bool replace(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz ) { bool replace(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz ) {
_assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ); _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ);
class VisitorImpl : public Visitor { class VisitorImpl : public Visitor {
public: public:
explicit VisitorImpl(const char* vbuf, size_t vsiz) : explicit VisitorImpl(const char* vbuf, size_t vsiz) :
vbuf_(vbuf), vsiz_(vsiz), ok_(false) {} vbuf_(vbuf), vsiz_(vsiz), ok_(false) {}
bool ok() const { bool ok() const {
return ok_; return ok_;
} }
private: private:
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
ok_ = true; ok_ = true;
*sp = vsiz_; *sp = vsiz_;
return vbuf_; return vbuf_;
} }
const char* vbuf_; const char* vbuf_;
size_t vsiz_; size_t vsiz_;
bool ok_; bool ok_;
}; };
skipping to change at line 1438 skipping to change at line 1438
* @param ksiz the size of the key region. * @param ksiz the size of the key region.
* @param vbuf the pointer to the value region. * @param vbuf the pointer to the value region.
* @param vsiz the size of the value region. * @param vsiz the size of the value region.
* @return true on success, or false on failure. * @return true on success, or false on failure.
* @note If no record corresponds to the key, a new record is created. I f the corresponding * @note If no record corresponds to the key, a new record is created. I f the corresponding
* record exists, the given value is appended at the end of the existing value. * record exists, the given value is appended at the end of the existing value.
*/ */
bool append(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) { bool append(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) {
_assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ); _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ);
class VisitorImpl : public Visitor { class VisitorImpl : public Visitor {
public: public:
explicit VisitorImpl(const char* vbuf, size_t vsiz) : explicit VisitorImpl(const char* vbuf, size_t vsiz) :
vbuf_(vbuf), vsiz_(vsiz), nbuf_(NULL) {} vbuf_(vbuf), vsiz_(vsiz), nbuf_(NULL) {}
~VisitorImpl() { ~VisitorImpl() {
if (nbuf_) delete[] nbuf_; if (nbuf_) delete[] nbuf_;
} }
private: private:
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
size_t nsiz = vsiz + vsiz_; size_t nsiz = vsiz + vsiz_;
nbuf_ = new char[nsiz]; nbuf_ = new char[nsiz];
std::memcpy(nbuf_, vbuf, vsiz); std::memcpy(nbuf_, vbuf, vsiz);
std::memcpy(nbuf_ + vsiz, vbuf_, vsiz_); std::memcpy(nbuf_ + vsiz, vbuf_, vsiz_);
*sp = nsiz; *sp = nsiz;
return nbuf_; return nbuf_;
} }
const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) {
skipping to change at line 1488 skipping to change at line 1488
* @param num the additional number. * @param num the additional number.
* @return the result value, or kyotocabinet::INT64MIN on failure. * @return the result value, or kyotocabinet::INT64MIN on failure.
* @note If no record corresponds to the key, a new record is created wit h the initial value * @note If no record corresponds to the key, a new record is created wit h the initial value
* set by the additional value. The value is serialized as an 8-byte bin ary integer in * set by the additional value. The value is serialized as an 8-byte bin ary integer in
* big-endian order, not a decimal string. If existing value is not 8-by te, this function * big-endian order, not a decimal string. If existing value is not 8-by te, this function
* fails. * fails.
*/ */
int64_t increment(const char* kbuf, size_t ksiz, int64_t num) { int64_t increment(const char* kbuf, size_t ksiz, int64_t num) {
_assert_(kbuf && ksiz <= MEMMAXSIZ); _assert_(kbuf && ksiz <= MEMMAXSIZ);
class VisitorImpl : public Visitor { class VisitorImpl : public Visitor {
public: public:
explicit VisitorImpl(int64_t num) : num_(num), big_(0) {} explicit VisitorImpl(int64_t num) : num_(num), big_(0) {}
int64_t num() { int64_t num() {
return num_; return num_;
} }
private: private:
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
if (vsiz != sizeof(num_)) { if (vsiz != sizeof(num_)) {
num_ = INT64MIN; num_ = INT64MIN;
return NOP; return NOP;
} }
int64_t onum; int64_t onum;
std::memcpy(&onum, vbuf, vsiz); std::memcpy(&onum, vbuf, vsiz);
onum = ntoh64(onum); onum = ntoh64(onum);
if (num_ == 0) { if (num_ == 0) {
skipping to change at line 1551 skipping to change at line 1551
* @param num the additional number. * @param num the additional number.
* @return the result value, or Not-a-number on failure. * @return the result value, or Not-a-number on failure.
* @note If no record corresponds to the key, a new record is created wit h the initial value * @note If no record corresponds to the key, a new record is created wit h the initial value
* set by the additional value. The value is serialized as an 16-byte bi nary fixed-point * set by the additional value. The value is serialized as an 16-byte bi nary fixed-point
* number in big-endian order, not a decimal string. If existing value i s not 16-byte, this * number in big-endian order, not a decimal string. If existing value i s not 16-byte, this
* function fails. * function fails.
*/ */
double increment_double(const char* kbuf, size_t ksiz, double num) { double increment_double(const char* kbuf, size_t ksiz, double num) {
_assert_(kbuf && ksiz <= MEMMAXSIZ); _assert_(kbuf && ksiz <= MEMMAXSIZ);
class VisitorImpl : public Visitor { class VisitorImpl : public Visitor {
public: public:
explicit VisitorImpl(double num) : DECUNIT(1000000000000000LL), num_( num), buf_() {} explicit VisitorImpl(double num) : DECUNIT(1000000000000000LL), num_( num), buf_() {}
double num() { double num() {
return num_; return num_;
} }
private: private:
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
if (vsiz != sizeof(buf_)) { if (vsiz != sizeof(buf_)) {
num_ = nan(); num_ = nan();
return NOP; return NOP;
} }
int64_t linteg, lfract; int64_t linteg, lfract;
std::memcpy(&linteg, vbuf, sizeof(linteg)); std::memcpy(&linteg, vbuf, sizeof(linteg));
linteg = ntoh64(linteg); linteg = ntoh64(linteg);
std::memcpy(&lfract, vbuf + sizeof(linteg), sizeof(lfract)); std::memcpy(&lfract, vbuf + sizeof(linteg), sizeof(lfract));
skipping to change at line 1665 skipping to change at line 1665
* @param ovbuf the pointer to the old value region. NULL means that no record corresponds. * @param ovbuf the pointer to the old value region. NULL means that no record corresponds.
* @param ovsiz the size of the old value region. * @param ovsiz the size of the old value region.
* @param nvbuf the pointer to the new value region. NULL means that the record is removed. * @param nvbuf the pointer to the new value region. NULL means that the record is removed.
* @param nvsiz the size of new old value region. * @param nvsiz the size of new old value region.
* @return true on success, or false on failure. * @return true on success, or false on failure.
*/ */
bool cas(const char* kbuf, size_t ksiz, bool cas(const char* kbuf, size_t ksiz,
const char* ovbuf, size_t ovsiz, const char* nvbuf, size_t nvsiz ) { const char* ovbuf, size_t ovsiz, const char* nvbuf, size_t nvsiz ) {
_assert_(kbuf && ksiz <= MEMMAXSIZ); _assert_(kbuf && ksiz <= MEMMAXSIZ);
class VisitorImpl : public Visitor { class VisitorImpl : public Visitor {
public: public:
explicit VisitorImpl(const char* ovbuf, size_t ovsiz, const char* nvb uf, size_t nvsiz) : explicit VisitorImpl(const char* ovbuf, size_t ovsiz, const char* nvb uf, size_t nvsiz) :
ovbuf_(ovbuf), ovsiz_(ovsiz), nvbuf_(nvbuf), nvsiz_(nvsiz), ok_(fal se) {} ovbuf_(ovbuf), ovsiz_(ovsiz), nvbuf_(nvbuf), nvsiz_(nvsiz), ok_(f alse) {}
bool ok() const { bool ok() const {
return ok_; return ok_;
} }
private: private:
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
if (!ovbuf_ || vsiz != ovsiz_ || std::memcmp(vbuf, ovbuf_, vsiz)) r eturn NOP; if (!ovbuf_ || vsiz != ovsiz_ || std::memcmp(vbuf, ovbuf_, vsiz)) r eturn NOP;
ok_ = true; ok_ = true;
if (!nvbuf_) return REMOVE; if (!nvbuf_) return REMOVE;
*sp = nvsiz_; *sp = nvsiz_;
return nvbuf_; return nvbuf_;
} }
const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) {
if (ovbuf_) return NOP; if (ovbuf_) return NOP;
skipping to change at line 1721 skipping to change at line 1721
/** /**
* Remove a record. * Remove a record.
* @param kbuf the pointer to the key region. * @param kbuf the pointer to the key region.
* @param ksiz the size of the key region. * @param ksiz the size of the key region.
* @return true on success, or false on failure. * @return true on success, or false on failure.
* @note If no record corresponds to the key, false is returned. * @note If no record corresponds to the key, false is returned.
*/ */
bool remove(const char* kbuf, size_t ksiz) { bool remove(const char* kbuf, size_t ksiz) {
_assert_(kbuf && ksiz <= MEMMAXSIZ); _assert_(kbuf && ksiz <= MEMMAXSIZ);
class VisitorImpl : public Visitor { class VisitorImpl : public Visitor {
public: public:
explicit VisitorImpl() : ok_(false) {} explicit VisitorImpl() : ok_(false) {}
bool ok() const { bool ok() const {
return ok_; return ok_;
} }
private: private:
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
ok_ = true; ok_ = true;
return REMOVE; return REMOVE;
} }
bool ok_; bool ok_;
}; };
VisitorImpl visitor; VisitorImpl visitor;
if (!accept(kbuf, ksiz, &visitor, true)) return false; if (!accept(kbuf, ksiz, &visitor, true)) return false;
if (!visitor.ok()) { if (!visitor.ok()) {
skipping to change at line 1766 skipping to change at line 1766
* @return the pointer to the value region of the corresponding record, o r NULL on failure. * @return the pointer to the value region of the corresponding record, o r NULL on failure.
* @note If no record corresponds to the key, NULL is returned. Because an additional zero * @note If no record corresponds to the key, NULL is returned. Because an additional zero
* code is appended at the end of the region of the return value, the ret urn value can be * code is appended at the end of the region of the return value, the ret urn value can be
* treated as a C-style string. Because the region of the return value i s allocated with the * treated as a C-style string. Because the region of the return value i s allocated with the
* the new[] operator, it should be released with the delete[] operator w hen it is no longer * the new[] operator, it should be released with the delete[] operator w hen it is no longer
* in use. * in use.
*/ */
char* get(const char* kbuf, size_t ksiz, size_t* sp) { char* get(const char* kbuf, size_t ksiz, size_t* sp) {
_assert_(kbuf && ksiz <= MEMMAXSIZ && sp); _assert_(kbuf && ksiz <= MEMMAXSIZ && sp);
class VisitorImpl : public Visitor { class VisitorImpl : public Visitor {
public: public:
explicit VisitorImpl() : vbuf_(NULL), vsiz_(0) {} explicit VisitorImpl() : vbuf_(NULL), vsiz_(0) {}
char* pop(size_t* sp) { char* pop(size_t* sp) {
*sp = vsiz_; *sp = vsiz_;
return vbuf_; return vbuf_;
} }
private: private:
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
vbuf_ = new char[vsiz+1]; vbuf_ = new char[vsiz+1];
std::memcpy(vbuf_, vbuf, vsiz); std::memcpy(vbuf_, vbuf, vsiz);
vbuf_[vsiz] = '\0'; vbuf_[vsiz] = '\0';
vsiz_ = vsiz; vsiz_ = vsiz;
return NOP; return NOP;
} }
char* vbuf_; char* vbuf_;
size_t vsiz_; size_t vsiz_;
skipping to change at line 1827 skipping to change at line 1827
* @param kbuf the pointer to the key region. * @param kbuf the pointer to the key region.
* @param ksiz the size of the key region. * @param ksiz the size of the key region.
* @param vbuf the pointer to the buffer into which the value of the corr esponding record is * @param vbuf the pointer to the buffer into which the value of the corr esponding record is
* written. * written.
* @param max the size of the buffer. * @param max the size of the buffer.
* @return the size of the value, or -1 on failure. * @return the size of the value, or -1 on failure.
*/ */
int32_t get(const char* kbuf, size_t ksiz, char* vbuf, size_t max) { int32_t get(const char* kbuf, size_t ksiz, char* vbuf, size_t max) {
_assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf); _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf);
class VisitorImpl : public Visitor { class VisitorImpl : public Visitor {
public: public:
explicit VisitorImpl(char* vbuf, size_t max) : vbuf_(vbuf), max_(max) , vsiz_(-1) {} explicit VisitorImpl(char* vbuf, size_t max) : vbuf_(vbuf), max_(max) , vsiz_(-1) {}
int32_t vsiz() { int32_t vsiz() {
return vsiz_; return vsiz_;
} }
private: private:
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
vsiz_ = vsiz; vsiz_ = vsiz;
size_t max = vsiz < max_ ? vsiz : max_; size_t max = vsiz < max_ ? vsiz : max_;
std::memcpy(vbuf_, vbuf, max); std::memcpy(vbuf_, vbuf, max);
return NOP; return NOP;
} }
char* vbuf_; char* vbuf_;
size_t max_; size_t max_;
int32_t vsiz_; int32_t vsiz_;
skipping to change at line 1871 skipping to change at line 1871
if (atomic) { if (atomic) {
std::vector<std::string> keys; std::vector<std::string> keys;
keys.reserve(recs.size()); keys.reserve(recs.size());
std::map<std::string, std::string>::const_iterator rit = recs.begin() ; std::map<std::string, std::string>::const_iterator rit = recs.begin() ;
std::map<std::string, std::string>::const_iterator ritend = recs.end( ); std::map<std::string, std::string>::const_iterator ritend = recs.end( );
while (rit != ritend) { while (rit != ritend) {
keys.push_back(rit->first); keys.push_back(rit->first);
++rit; ++rit;
} }
class VisitorImpl : public Visitor { class VisitorImpl : public Visitor {
public: public:
explicit VisitorImpl(const std::map<std::string, std::string>& recs ) : recs_(recs) {} explicit VisitorImpl(const std::map<std::string, std::string>& recs ) : recs_(recs) {}
private: private:
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
std::map<std::string, std::string>::const_iterator rit = std::map<std::string, std::string>::const_iterator rit =
recs_.find(std::string(kbuf, ksiz)); recs_.find(std::string(kbuf, ksiz));
if (rit == recs_.end()) return NOP; if (rit == recs_.end()) return NOP;
*sp = rit->second.size(); *sp = rit->second.size();
return rit->second.data(); return rit->second.data();
} }
const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) {
std::map<std::string, std::string>::const_iterator rit = std::map<std::string, std::string>::const_iterator rit =
recs_.find(std::string(kbuf, ksiz)); recs_.find(std::string(kbuf, ksiz));
if (rit == recs_.end()) return NOP; if (rit == recs_.end()) return NOP;
*sp = rit->second.size(); *sp = rit->second.size();
return rit->second.data(); return rit->second.data();
} }
const std::map<std::string, std::string>& recs_; const std::map<std::string, std::string>& recs_;
}; };
VisitorImpl visitor(recs); VisitorImpl visitor(recs);
if (!accept_bulk(keys, &visitor, true)) return -1; if (!accept_bulk(keys, &visitor, true)) return -1;
return keys.size(); return keys.size();
} }
skipping to change at line 1914 skipping to change at line 1914
/** /**
* Remove records at once. * Remove records at once.
* @param keys the keys of the records to remove. * @param keys the keys of the records to remove.
* @param atomic true to perform all operations atomically, or false for non-atomic operations. * @param atomic true to perform all operations atomically, or false for non-atomic operations.
* @return the number of removed records, or -1 on failure. * @return the number of removed records, or -1 on failure.
*/ */
int64_t remove_bulk(const std::vector<std::string>& keys, bool atomic = t rue) { int64_t remove_bulk(const std::vector<std::string>& keys, bool atomic = t rue) {
_assert_(true); _assert_(true);
if (atomic) { if (atomic) {
class VisitorImpl : public Visitor { class VisitorImpl : public Visitor {
public: public:
explicit VisitorImpl() : cnt_(0) {} explicit VisitorImpl() : cnt_(0) {}
int64_t cnt() const { int64_t cnt() const {
return cnt_; return cnt_;
} }
private: private:
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
cnt_++; cnt_++;
return REMOVE; return REMOVE;
} }
int64_t cnt_; int64_t cnt_;
}; };
VisitorImpl visitor; VisitorImpl visitor;
if (!accept_bulk(keys, &visitor, true)) return -1; if (!accept_bulk(keys, &visitor, true)) return -1;
return visitor.cnt(); return visitor.cnt();
skipping to change at line 1956 skipping to change at line 1956
* @param keys the keys of the records to retrieve. * @param keys the keys of the records to retrieve.
* @param recs a string map to contain the retrieved records. * @param recs a string map to contain the retrieved records.
* @param atomic true to perform all operations atomically, or false for non-atomic operations. * @param atomic true to perform all operations atomically, or false for non-atomic operations.
* @return the number of retrieved records, or -1 on failure. * @return the number of retrieved records, or -1 on failure.
*/ */
int64_t get_bulk(const std::vector<std::string>& keys, int64_t get_bulk(const std::vector<std::string>& keys,
std::map<std::string, std::string>* recs, bool atomic = true) { std::map<std::string, std::string>* recs, bool atomic = true) {
_assert_(recs); _assert_(recs);
if (atomic) { if (atomic) {
class VisitorImpl : public Visitor { class VisitorImpl : public Visitor {
public: public:
explicit VisitorImpl(std::map<std::string, std::string>* recs) : re cs_(recs) {} explicit VisitorImpl(std::map<std::string, std::string>* recs) : re cs_(recs) {}
private: private:
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
(*recs_)[std::string(kbuf, ksiz)] = std::string(vbuf, vsiz); (*recs_)[std::string(kbuf, ksiz)] = std::string(vbuf, vsiz);
return NOP; return NOP;
} }
std::map<std::string, std::string>* recs_; std::map<std::string, std::string>* recs_;
}; };
VisitorImpl visitor(recs); VisitorImpl visitor(recs);
if (!accept_bulk(keys, &visitor, false)) return -1; if (!accept_bulk(keys, &visitor, false)) return -1;
return recs->size(); return recs->size();
skipping to change at line 1998 skipping to change at line 1998
* @param checker a progress checker object. If it is NULL, no checking is performed. * @param checker a progress checker object. If it is NULL, no checking is performed.
* @return true on success, or false on failure. * @return true on success, or false on failure.
*/ */
bool dump_snapshot(std::ostream* dest, ProgressChecker* checker = NULL) { bool dump_snapshot(std::ostream* dest, ProgressChecker* checker = NULL) {
_assert_(dest); _assert_(dest);
if (dest->fail()) { if (dest->fail()) {
set_error(_KCCODELINE_, Error::INVALID, "invalid stream"); set_error(_KCCODELINE_, Error::INVALID, "invalid stream");
return false; return false;
} }
class VisitorImpl : public Visitor { class VisitorImpl : public Visitor {
public: public:
explicit VisitorImpl(std::ostream* dest) : dest_(dest), stack_() {} explicit VisitorImpl(std::ostream* dest) : dest_(dest), stack_() {}
private: private:
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
char* wp = stack_; char* wp = stack_;
*(wp++) = 0x00; *(wp++) = 0x00;
wp += writevarnum(wp, ksiz); wp += writevarnum(wp, ksiz);
wp += writevarnum(wp, vsiz); wp += writevarnum(wp, vsiz);
dest_->write(stack_, wp - stack_); dest_->write(stack_, wp - stack_);
dest_->write(kbuf, ksiz); dest_->write(kbuf, ksiz);
dest_->write(vbuf, vsiz); dest_->write(vbuf, vsiz);
return NOP; return NOP;
 End of changes. 63 change blocks. 
64 lines changed or deleted 64 lines changed or added


 kcdbext.h   kcdbext.h 
skipping to change at line 43 skipping to change at line 43
#include <kcpolydb.h> #include <kcpolydb.h>
namespace kyotocabinet { // common namespace namespace kyotocabinet { // common namespace
/** /**
* MapReduce framework. * MapReduce framework.
* @note Although this framework is not distributed or concurrent, it is us eful for aggregate * @note Although this framework is not distributed or concurrent, it is us eful for aggregate
* calculation with less CPU loading and less memory usage. * calculation with less CPU loading and less memory usage.
*/ */
class MapReduce { class MapReduce {
public: public:
class MapEmitter; class MapEmitter;
class ValueIterator; class ValueIterator;
private: private:
class MapVisitor; class MapVisitor;
struct MergeLine; struct MergeLine;
/** An alias of vector of loaded values. */ /** An alias of vector of loaded values. */
typedef std::vector<std::string> Values; typedef std::vector<std::string> Values;
/** The default number of temporary databases. */ /** The default number of temporary databases. */
static const size_t MRDEFDBNUM = 8; static const size_t MRDEFDBNUM = 8;
/** The maxinum number of temporary databases. */ /** The maxinum number of temporary databases. */
static const size_t MRMAXDBNUM = 256; static const size_t MRMAXDBNUM = 256;
/** The default cache limit. */ /** The default cache limit. */
static const int64_t MRDEFCLIM = 512LL << 20; static const int64_t MRDEFCLIM = 512LL << 20;
/** The default cache bucket numer. */ /** The default cache bucket numer. */
static const int64_t MRDEFCBNUM = 1048583LL; static const int64_t MRDEFCBNUM = 1048583LL;
/** The bucket number of temprary databases. */ /** The bucket number of temprary databases. */
static const int64_t MRDBBNUM = 512LL << 10; static const int64_t MRDBBNUM = 512LL << 10;
/** The page size of temprary databases. */ /** The page size of temprary databases. */
static const int32_t MRDBPSIZ = 32768; static const int32_t MRDBPSIZ = 32768;
/** The mapped size of temprary databases. */ /** The mapped size of temprary databases. */
static const int64_t MRDBMSIZ = 516LL * 4096; static const int64_t MRDBMSIZ = 516LL * 4096;
/** The page cache capacity of temprary databases. */ /** The page cache capacity of temprary databases. */
static const int64_t MRDBPCCAP = 16LL << 20; static const int64_t MRDBPCCAP = 16LL << 20;
public: public:
/** /**
* Data emitter for the mapper. * Data emitter for the mapper.
*/ */
class MapEmitter { class MapEmitter {
friend class MapReduce; friend class MapReduce;
friend class MapReduce::MapVisitor; friend class MapReduce::MapVisitor;
public: public:
/** /**
* Emit a record from the mapper. * Emit a record from the mapper.
* @param kbuf the pointer to the key region. * @param kbuf the pointer to the key region.
* @param ksiz the size of the key region. * @param ksiz the size of the key region.
* @param vbuf the pointer to the value region. * @param vbuf the pointer to the value region.
* @param vsiz the size of the value region. * @param vsiz the size of the value region.
* @return true on success, or false on failure. * @return true on success, or false on failure.
*/ */
bool emit(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) { bool emit(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) {
_assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ); _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ);
skipping to change at line 97 skipping to change at line 97
char stack[NUMBUFSIZ*4]; char stack[NUMBUFSIZ*4];
char* rbuf = rsiz > sizeof(stack) ? new char[rsiz] : stack; char* rbuf = rsiz > sizeof(stack) ? new char[rsiz] : stack;
char* wp = rbuf; char* wp = rbuf;
wp += writevarnum(rbuf, vsiz); wp += writevarnum(rbuf, vsiz);
std::memcpy(wp, vbuf, vsiz); std::memcpy(wp, vbuf, vsiz);
mr_->cache_->append(kbuf, ksiz, rbuf, rsiz); mr_->cache_->append(kbuf, ksiz, rbuf, rsiz);
if (rbuf != stack) delete[] rbuf; if (rbuf != stack) delete[] rbuf;
mr_->csiz_ += rsiz; mr_->csiz_ += rsiz;
return !err; return !err;
} }
private: private:
/** /**
* Default constructor. * Default constructor.
*/ */
explicit MapEmitter(MapReduce* mr) : mr_(mr) { explicit MapEmitter(MapReduce* mr) : mr_(mr) {
_assert_(true); _assert_(true);
} }
/** /**
* Destructor. * Destructor.
*/ */
~MapEmitter() { ~MapEmitter() {
skipping to change at line 122 skipping to change at line 122
/** Dummy Operator to forbid the use. */ /** Dummy Operator to forbid the use. */
MapEmitter& operator =(const MapEmitter&); MapEmitter& operator =(const MapEmitter&);
/** The owner object. */ /** The owner object. */
MapReduce* mr_; MapReduce* mr_;
}; };
/** /**
* Value iterator for the reducer. * Value iterator for the reducer.
*/ */
class ValueIterator { class ValueIterator {
friend class MapReduce; friend class MapReduce;
public: public:
/** /**
* Get the next value. * Get the next value.
* @param sp the pointer to the variable into which the size of the reg ion of the return * @param sp the pointer to the variable into which the size of the reg ion of the return
* value is assigned. * value is assigned.
* @return the pointer to the next value region, or NULL if no value re mains. * @return the pointer to the next value region, or NULL if no value re mains.
*/ */
const char* next(size_t* sp) { const char* next(size_t* sp) {
_assert_(sp); _assert_(sp);
if (!vptr_) { if (!vptr_) {
if (vit_ == vend_) return NULL; if (vit_ == vend_) return NULL;
skipping to change at line 148 skipping to change at line 148
size_t step = readvarnum(vptr_, vsiz_, &vsiz); size_t step = readvarnum(vptr_, vsiz_, &vsiz);
vptr_ += step; vptr_ += step;
vsiz_ -= step; vsiz_ -= step;
const char* vbuf = vptr_; const char* vbuf = vptr_;
*sp = vsiz; *sp = vsiz;
vptr_ += vsiz; vptr_ += vsiz;
vsiz_ -= vsiz; vsiz_ -= vsiz;
if (vsiz_ < 1) vptr_ = NULL; if (vsiz_ < 1) vptr_ = NULL;
return vbuf; return vbuf;
} }
private: private:
/** /**
* Default constructor. * Default constructor.
*/ */
explicit ValueIterator(Values::const_iterator vit, Values::const_iterat or vend) : explicit ValueIterator(Values::const_iterator vit, Values::const_iterat or vend) :
vit_(vit), vend_(vend), vptr_(NULL), vsiz_(0) { vit_(vit), vend_(vend), vptr_(NULL), vsiz_(0) {
_assert_(true); _assert_(true);
} }
/** /**
* Destructor. * Destructor.
*/ */
~ValueIterator() { ~ValueIterator() {
_assert_(true); _assert_(true);
} }
/** Dummy constructor to forbid the use. */ /** Dummy constructor to forbid the use. */
ValueIterator(const ValueIterator&); ValueIterator(const ValueIterator&);
skipping to change at line 186 skipping to change at line 186
* Execution options. * Execution options.
*/ */
enum Option { enum Option {
XNOLOCK = 1 << 0, ///< avoid locking against update operations XNOLOCK = 1 << 0, ///< avoid locking against update operations
XNOCOMP = 1 << 1 ///< avoid compression of temporar y databases XNOCOMP = 1 << 1 ///< avoid compression of temporar y databases
}; };
/** /**
* Default constructor. * Default constructor.
*/ */
explicit MapReduce() : explicit MapReduce() :
rcomp_(NULL), tmpdbs_(NULL), dbnum_(MRDEFDBNUM), dbclock_(0), keyclock_ rcomp_(NULL), tmpdbs_(NULL), dbnum_(MRDEFDBNUM), dbclock_(0), keycloc
(0), k_(0),
cache_(NULL), csiz_(0), clim_(MRDEFCLIM), cbnum_(MRDEFCBNUM) { cache_(NULL), csiz_(0), clim_(MRDEFCLIM), cbnum_(MRDEFCBNUM) {
_assert_(true); _assert_(true);
} }
/** /**
* Destructor. * Destructor.
*/ */
virtual ~MapReduce() { virtual ~MapReduce() {
_assert_(true); _assert_(true);
} }
/** /**
* Map a record data. * Map a record data.
skipping to change at line 323 skipping to change at line 323
return false; return false;
} }
if (!logf("prepare", "started to open temporary databases under %s", tmppath.c_str())) if (!logf("prepare", "started to open temporary databases under %s", tmppath.c_str()))
err = true; err = true;
stime = time(); stime = time();
uint32_t pid = getpid() & UINT16MAX; uint32_t pid = getpid() & UINT16MAX;
uint32_t tid = Thread::hash() & UINT16MAX; uint32_t tid = Thread::hash() & UINT16MAX;
uint32_t ts = time() * 1000; uint32_t ts = time() * 1000;
for (size_t i = 0; i < dbnum_; i++) { for (size_t i = 0; i < dbnum_; i++) {
std::string childpath = std::string childpath =
strprintf("%s%cmr-%04x-%04x-%08x-%03d%ckct", strprintf("%s%cmr-%04x-%04x-%08x-%03d%ckct",
tmppath.c_str(), File::PATHCHR, pid, tid, ts, (int)(i + tmppath.c_str(), File::PATHCHR, pid, tid, ts, (int)(i
1), File::EXTCHR); + 1), File::EXTCHR);
TreeDB* tdb = new TreeDB; TreeDB* tdb = new TreeDB;
int32_t myopts = TreeDB::TSMALL | TreeDB::TLINEAR; int32_t myopts = TreeDB::TSMALL | TreeDB::TLINEAR;
if (!(opts & XNOCOMP)) myopts |= TreeDB::TCOMPRESS; if (!(opts & XNOCOMP)) myopts |= TreeDB::TCOMPRESS;
tdb->tune_options(myopts); tdb->tune_options(myopts);
tdb->tune_buckets(MRDBBNUM); tdb->tune_buckets(MRDBBNUM);
tdb->tune_page(MRDBPSIZ); tdb->tune_page(MRDBPSIZ);
tdb->tune_map(MRDBMSIZ); tdb->tune_map(MRDBMSIZ);
tdb->tune_page_cache(MRDBPCCAP); tdb->tune_page_cache(MRDBPCCAP);
tdb->tune_comparator(rcomp_); tdb->tune_comparator(rcomp_);
if (!tdb->open(childpath, TreeDB::OWRITER | TreeDB::OCREATE | TreeD B::OTRUNCATE)) { if (!tdb->open(childpath, TreeDB::OWRITER | TreeDB::OCREATE | TreeD B::OTRUNCATE)) {
skipping to change at line 413 skipping to change at line 413
* @param cbnum the bucket number of the internal cache. * @param cbnum the bucket number of the internal cache.
*/ */
void tune_storage(int32_t dbnum, int64_t clim, int64_t cbnum) { void tune_storage(int32_t dbnum, int64_t clim, int64_t cbnum) {
_assert_(true); _assert_(true);
dbnum_ = dbnum > 0 ? dbnum : MRDEFDBNUM; dbnum_ = dbnum > 0 ? dbnum : MRDEFDBNUM;
if (dbnum_ > MRMAXDBNUM) dbnum_ = MRMAXDBNUM; if (dbnum_ > MRMAXDBNUM) dbnum_ = MRMAXDBNUM;
clim_ = clim > 0 ? clim : MRDEFCLIM; clim_ = clim > 0 ? clim : MRDEFCLIM;
cbnum_ = cbnum > 0 ? cbnum : MRDEFCBNUM; cbnum_ = cbnum > 0 ? cbnum : MRDEFCBNUM;
if (cbnum_ > INT16MAX) cbnum_ = nearbyprime(cbnum_); if (cbnum_ > INT16MAX) cbnum_ = nearbyprime(cbnum_);
} }
private: private:
/** /**
* Checker for the map process. * Checker for the map process.
*/ */
class MapChecker : public BasicDB::ProgressChecker { class MapChecker : public BasicDB::ProgressChecker {
public: public:
/** constructor */ /** constructor */
explicit MapChecker() : stop_(false) {} explicit MapChecker() : stop_(false) {}
/** stop the process */ /** stop the process */
void stop() { void stop() {
stop_ = true; stop_ = true;
} }
/** check whether stopped */ /** check whether stopped */
bool stopped() { bool stopped() {
return stop_; return stop_;
} }
private: private:
/** check whether stopped */ /** check whether stopped */
bool check(const char* name, const char* message, int64_t curcnt, int64 _t allcnt) { bool check(const char* name, const char* message, int64_t curcnt, int64 _t allcnt) {
return !stop_; return !stop_;
} }
bool stop_; ///< flag for stop bool stop_; ///< flag for stop
}; };
/** /**
* Visitor for the map process. * Visitor for the map process.
*/ */
class MapVisitor : public BasicDB::Visitor { class MapVisitor : public BasicDB::Visitor {
public: public:
/** constructor */ /** constructor */
explicit MapVisitor(MapReduce* mr, MapChecker* checker, int64_t scale) : explicit MapVisitor(MapReduce* mr, MapChecker* checker, int64_t scale) :
mr_(mr), checker_(checker), emitter_(mr), scale_(scale), mr_(mr), checker_(checker), emitter_(mr), scale_(scale),
stime_(0), err_(false) {} stime_(0), err_(false) {}
/** get the error flag */ /** get the error flag */
bool error() { bool error() {
return err_; return err_;
} }
/** preprocess the mappter */ /** preprocess the mappter */
void visit_before() { void visit_before() {
if (!mr_->preprocess()) err_ = true; if (!mr_->preprocess()) err_ = true;
stime_ = time(); stime_ = time();
mr_->dbclock_ = 0; mr_->dbclock_ = 0;
mr_->keyclock_ = 0; mr_->keyclock_ = 0;
skipping to change at line 471 skipping to change at line 471
void visit_after() { void visit_after() {
if (mr_->cache_->count() > 0 && !mr_->flush_cache()) err_ = true; if (mr_->cache_->count() > 0 && !mr_->flush_cache()) err_ = true;
delete mr_->cache_; delete mr_->cache_;
if (!mr_->midprocess()) err_ = true; if (!mr_->midprocess()) err_ = true;
double etime = time(); double etime = time();
if (!mr_->logf("map", "the map process finished: time=%.6f", etime - stime_)) if (!mr_->logf("map", "the map process finished: time=%.6f", etime - stime_))
err_ = true; err_ = true;
if (!err_ && !mr_->execute_reduce()) err_ = true; if (!err_ && !mr_->execute_reduce()) err_ = true;
if (!mr_->postprocess()) err_ = true; if (!mr_->postprocess()) err_ = true;
} }
private: private:
/** visit a record */ /** visit a record */
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
if (!mr_->map(kbuf, ksiz, vbuf, vsiz, &emitter_)) { if (!mr_->map(kbuf, ksiz, vbuf, vsiz, &emitter_)) {
checker_->stop(); checker_->stop();
err_ = true; err_ = true;
} }
if (mr_->csiz_ >= mr_->clim_ && !mr_->flush_cache()) { if (mr_->csiz_ >= mr_->clim_ && !mr_->flush_cache()) {
checker_->stop(); checker_->stop();
err_ = true; err_ = true;
 End of changes. 16 change blocks. 
21 lines changed or deleted 21 lines changed or added


 kcdirdb.h   kcdirdb.h 
skipping to change at line 52 skipping to change at line 52
* @note This class is a concrete class to operate a hash database in a dir ectory. This class * @note This class is a concrete class to operate a hash database in a dir ectory. This class
* can be inherited but overwriting methods is forbidden. Before every dat abase operation, it is * can be inherited but overwriting methods is forbidden. Before every dat abase operation, it is
* necessary to call the TreeDB::open method in order to open a database fi le and connect the * necessary to call the TreeDB::open method in order to open a database fi le and connect the
* database object to it. To avoid data missing or corruption, it is impor tant to close every * database object to it. To avoid data missing or corruption, it is impor tant to close every
* database file by the TreeDB::close method when the database is no longer in use. It is * database file by the TreeDB::close method when the database is no longer in use. It is
* forbidden for multible database objects in a process to open the same da tabase at the same * forbidden for multible database objects in a process to open the same da tabase at the same
* time. It is forbidden to share a database object with child processes. * time. It is forbidden to share a database object with child processes.
*/ */
class DirDB : public BasicDB { class DirDB : public BasicDB {
friend class PlantDB<DirDB, BasicDB::TYPEFOREST>; friend class PlantDB<DirDB, BasicDB::TYPEFOREST>;
public: public:
class Cursor; class Cursor;
private: private:
struct Record; struct Record;
class ScopedVisitor; class ScopedVisitor;
/** An alias of list of cursors. */ /** An alias of list of cursors. */
typedef std::list<Cursor*> CursorList; typedef std::list<Cursor*> CursorList;
/** An alias of vector of strings. */ /** An alias of vector of strings. */
typedef std::vector<std::string> StringVector; typedef std::vector<std::string> StringVector;
/** The size of the meta data buffer. */ /** The size of the meta data buffer. */
static const int64_t METABUFSIZ = 128; static const int64_t METABUFSIZ = 128;
/** The magic data for record. */ /** The magic data for record. */
static const uint8_t RECMAGIC = 0xcc; static const uint8_t RECMAGIC = 0xcc;
/** The number of slots of the record lock. */ /** The number of slots of the record lock. */
static const int32_t RLOCKSLOT = 2048; static const int32_t RLOCKSLOT = 2048;
/** The unit size of a record. */ /** The unit size of a record. */
static const int32_t RECUNITSIZ = 32; static const int32_t RECUNITSIZ = 32;
/** The size of the opaque buffer. */ /** The size of the opaque buffer. */
static const size_t OPAQUESIZ = 16; static const size_t OPAQUESIZ = 16;
/** The threshold of busy loop and sleep for locking. */ /** The threshold of busy loop and sleep for locking. */
static const uint32_t LOCKBUSYLOOP = 8192; static const uint32_t LOCKBUSYLOOP = 8192;
public: public:
/** /**
* Cursor to indicate a record. * Cursor to indicate a record.
*/ */
class Cursor : public BasicDB::Cursor { class Cursor : public BasicDB::Cursor {
friend class DirDB; friend class DirDB;
public: public:
/** /**
* Constructor. * Constructor.
* @param db the container database object. * @param db the container database object.
*/ */
explicit Cursor(DirDB* db) : db_(db), dir_(), alive_(false), name_("") { explicit Cursor(DirDB* db) : db_(db), dir_(), alive_(false), name_("") {
_assert_(db); _assert_(db);
ScopedSpinRWLock lock(&db_->mlock_, true); ScopedSpinRWLock lock(&db_->mlock_, true);
db_->curs_.push_back(this); db_->curs_.push_back(this);
} }
/** /**
skipping to change at line 330 skipping to change at line 330
return false; return false;
} }
/** /**
* Get the database object. * Get the database object.
* @return the database object. * @return the database object.
*/ */
DirDB* db() { DirDB* db() {
_assert_(true); _assert_(true);
return db_; return db_;
} }
private: private:
/** /**
* Disable the cursor. * Disable the cursor.
* @return true on success, or false on failure. * @return true on success, or false on failure.
*/ */
bool disable() { bool disable() {
bool err = false; bool err = false;
if (!dir_.close()) { if (!dir_.close()) {
db_->set_error(_KCCODELINE_, Error::SYSTEM, "closing a directory fa iled"); db_->set_error(_KCCODELINE_, Error::SYSTEM, "closing a directory fa iled");
err = true; err = true;
} }
skipping to change at line 376 skipping to change at line 376
* Status flags. * Status flags.
*/ */
enum Flag { enum Flag {
FOPEN = 1 << 0, ///< dummy for compatibility FOPEN = 1 << 0, ///< dummy for compatibility
FFATAL = 1 << 1 ///< dummy for compatibility FFATAL = 1 << 1 ///< dummy for compatibility
}; };
/** /**
* Default constructor. * Default constructor.
*/ */
explicit DirDB() : explicit DirDB() :
mlock_(), rlock_(RLOCKSLOT), error_(), logger_(NULL), logkinds_(0), mtr mlock_(), rlock_(RLOCKSLOT), error_(),
igger_(NULL), logger_(NULL), logkinds_(0), mtrigger_(NULL),
omode_(0), writer_(false), autotran_(false), autosync_(false), recov_(f omode_(0), writer_(false), autotran_(false), autosync_(false),
alse), reorg_(false), recov_(false), reorg_(false),
file_(), curs_(), path_(""), file_(), curs_(), path_(""),
libver_(LIBVER), librev_(LIBREV), fmtver_(FMTVER), chksum_(0), type_(TY libver_(LIBVER), librev_(LIBREV), fmtver_(FMTVER), chksum_(0), type_(
PEDIR), TYPEDIR),
flags_(0), opts_(0), count_(0), size_(0), opaque_(), embcomp_(ZLIBRAWCO flags_(0), opts_(0), count_(0), size_(0), opaque_(), embcomp_(ZLIBRAW
MP), comp_(NULL), COMP), comp_(NULL),
tran_(false), trhard_(false), trcount_(0), trsize_(0), walpath_(""), tm tran_(false), trhard_(false), trcount_(0), trsize_(0), walpath_(""),
ppath_("") { tmppath_("") {
_assert_(true); _assert_(true);
} }
/** /**
* Destructor. * Destructor.
* @note If the database is not closed, it is closed implicitly. * @note If the database is not closed, it is closed implicitly.
*/ */
virtual ~DirDB() { virtual ~DirDB() {
_assert_(true); _assert_(true);
if (omode_ != 0) close(); if (omode_ != 0) close();
if (!curs_.empty()) { if (!curs_.empty()) {
skipping to change at line 550 skipping to change at line 552
* @param code an error code. * @param code an error code.
* @param message a supplement message. * @param message a supplement message.
*/ */
void set_error(const char* file, int32_t line, const char* func, void set_error(const char* file, int32_t line, const char* func,
Error::Code code, const char* message) { Error::Code code, const char* message) {
_assert_(file && line > 0 && func && message); _assert_(file && line > 0 && func && message);
error_->set(code, message); error_->set(code, message);
if (code == Error::BROKEN || code == Error::SYSTEM) flags_ |= FFATAL; if (code == Error::BROKEN || code == Error::SYSTEM) flags_ |= FFATAL;
if (logger_) { if (logger_) {
Logger::Kind kind = code == Error::BROKEN || code == Error::SYSTEM ? Logger::Kind kind = code == Error::BROKEN || code == Error::SYSTEM ?
Logger::ERROR : Logger::INFO; Logger::ERROR : Logger::INFO;
if (kind & logkinds_) if (kind & logkinds_)
report(file, line, func, kind, "%d: %s: %s", code, Error::codename( code), message); report(file, line, func, kind, "%d: %s: %s", code, Error::codename( code), message);
} }
} }
/** /**
* Open a database file. * Open a database file.
* @param path the path of a database file. * @param path the path of a database file.
* @param mode the connection mode. DirDB::OWRITER as a writer, DirDB::O READER as a * @param mode the connection mode. DirDB::OWRITER as a writer, DirDB::O READER as a
* reader. The following may be added to the writer mode by bitwise-or: DirDB::OCREATE, * reader. The following may be added to the writer mode by bitwise-or: DirDB::OCREATE,
* which means it creates a new database if the file does not exist, DirD B::OTRUNCATE, which * which means it creates a new database if the file does not exist, DirD B::OTRUNCATE, which
skipping to change at line 1188 skipping to change at line 1190
*/ */
uint8_t flags() { uint8_t flags() {
_assert_(true); _assert_(true);
ScopedSpinRWLock lock(&mlock_, false); ScopedSpinRWLock lock(&mlock_, false);
if (omode_ == 0) { if (omode_ == 0) {
set_error(_KCCODELINE_, Error::INVALID, "not opened"); set_error(_KCCODELINE_, Error::INVALID, "not opened");
return 0; return 0;
} }
return 0; return 0;
} }
protected: protected:
/** /**
* Report a message for debugging. * Report a message for debugging.
* @param file the file name of the program source code. * @param file the file name of the program source code.
* @param line the line number of the program source code. * @param line the line number of the program source code.
* @param func the function name of the program source code. * @param func the function name of the program source code.
* @param kind the kind of the event. Logger::DEBUG for debugging, Logge r::INFO for normal * @param kind the kind of the event. Logger::DEBUG for debugging, Logge r::INFO for normal
* information, Logger::WARN for warning, and Logger::ERROR for fatal err or. * information, Logger::WARN for warning, and Logger::ERROR for fatal err or.
* @param format the printf-like format string. * @param format the printf-like format string.
* @param ... used according to the format string. * @param ... used according to the format string.
*/ */
skipping to change at line 1394 skipping to change at line 1396
*/ */
bool reorganized() { bool reorganized() {
_assert_(true); _assert_(true);
ScopedSpinRWLock lock(&mlock_, false); ScopedSpinRWLock lock(&mlock_, false);
if (omode_ == 0) { if (omode_ == 0) {
set_error(_KCCODELINE_, Error::INVALID, "not opened"); set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false; return false;
} }
return reorg_; return reorg_;
} }
private: private:
/** /**
* Set the power of the alignment of record size. * Set the power of the alignment of record size.
* @note This is a dummy implementation for compatibility. * @note This is a dummy implementation for compatibility.
*/ */
bool tune_alignment(int8_t apow) { bool tune_alignment(int8_t apow) {
return true; return true;
} }
/** /**
* Set the power of the capacity of the free block pool. * Set the power of the capacity of the free block pool.
* @note This is a dummy implementation for compatibility. * @note This is a dummy implementation for compatibility.
skipping to change at line 1472 skipping to change at line 1474
int64_t msiz() { int64_t msiz() {
return 0; return 0;
} }
/** /**
* Get the unit step number of auto defragmentation. * Get the unit step number of auto defragmentation.
* @note This is a dummy implementation for compatibility. * @note This is a dummy implementation for compatibility.
*/ */
int64_t dfunit() { int64_t dfunit() {
return 0; return 0;
} }
private: private:
/** /**
* Record data. * Record data.
*/ */
struct Record { struct Record {
char* rbuf; ///< record buffer char* rbuf; ///< record buffer
size_t rsiz; ///< record size size_t rsiz; ///< record size
const char* kbuf; ///< key buffer const char* kbuf; ///< key buffer
size_t ksiz; ///< key size size_t ksiz; ///< key size
const char* vbuf; ///< value buffer const char* vbuf; ///< value buffer
size_t vsiz; ///< value size size_t vsiz; ///< value size
}; };
/** /**
* Scoped visitor. * Scoped visitor.
*/ */
class ScopedVisitor { class ScopedVisitor {
public: public:
/** constructor */ /** constructor */
explicit ScopedVisitor(Visitor* visitor) : visitor_(visitor) { explicit ScopedVisitor(Visitor* visitor) : visitor_(visitor) {
_assert_(visitor); _assert_(visitor);
visitor_->visit_before(); visitor_->visit_before();
} }
/** destructor */ /** destructor */
~ScopedVisitor() { ~ScopedVisitor() {
_assert_(true); _assert_(true);
visitor_->visit_after(); visitor_->visit_after();
} }
private: private:
Visitor* visitor_; ///< visitor Visitor* visitor_; ///< visitor
}; };
/** /**
* Dump the magic data into the file. * Dump the magic data into the file.
* @return true on success, or false on failure. * @return true on success, or false on failure.
*/ */
bool dump_magic() { bool dump_magic() {
_assert_(true); _assert_(true);
const std::string& buf = format_magic(count_, size_); const std::string& buf = format_magic(count_, size_);
if (!file_.write(0, buf.c_str(), buf.size())) { if (!file_.write(0, buf.c_str(), buf.size())) {
 End of changes. 12 change blocks. 
22 lines changed or deleted 22 lines changed or added


 kcfile.h   kcfile.h 
skipping to change at line 28 skipping to change at line 28
#include <kccommon.h> #include <kccommon.h>
#include <kcutil.h> #include <kcutil.h>
#include <kcthread.h> #include <kcthread.h>
namespace kyotocabinet { // common namespace namespace kyotocabinet { // common namespace
/** /**
* Filesystem abstraction. * Filesystem abstraction.
*/ */
class File { class File {
public: public:
struct Status; struct Status;
public: public:
/** Path delimiter character. */ /** Path delimiter character. */
static const char PATHCHR; static const char PATHCHR;
/** Path delimiter string. */ /** Path delimiter string. */
static const char* const PATHSTR; static const char* const PATHSTR;
/** Extension delimiter character. */ /** Extension delimiter character. */
static const char EXTCHR; static const char EXTCHR;
/** Extension delimiter string. */ /** Extension delimiter string. */
static const char* const EXTSTR; static const char* const EXTSTR;
/** Current directory string. */ /** Current directory string. */
static const char* const CDIRSTR; static const char* const CDIRSTR;
skipping to change at line 331 skipping to change at line 331
* 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. * Synchronize the whole of the file system with the device.
* @return true on success, or false on failure. * @return true on success, or false on failure.
*/ */
static bool synchronize_whole(); 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. * Directory stream abstraction.
*/ */
class DirStream { class DirStream {
public: public:
/** /**
* Default constructor. * Default constructor.
*/ */
explicit DirStream(); explicit DirStream();
/** /**
* Destructor. * Destructor.
* @note If the file is not closed, it is closed implicitly. * @note If the file is not closed, it is closed implicitly.
*/ */
~DirStream(); ~DirStream();
/** /**
skipping to change at line 371 skipping to change at line 371
* Close the file. * Close the file.
* @return true on success, or false on failure. * @return true on success, or false on failure.
*/ */
bool close(); bool close();
/** /**
* Read the next file in the directory. * Read the next file in the directory.
* @param path a string to store the file path. * @param path a string to store the file path.
* @return true on success, or false on failure. * @return true on success, or false on failure.
*/ */
bool read(std::string* path); bool read(std::string* path);
private: private:
/** Dummy constructor to forbid the use. */ /** Dummy constructor to forbid the use. */
DirStream(const DirStream&); DirStream(const DirStream&);
/** Dummy Operator to forbid the use. */ /** Dummy Operator to forbid the use. */
DirStream& operator =(const DirStream&); DirStream& operator =(const DirStream&);
/** Opaque pointer. */ /** Opaque pointer. */
void* opq_; void* opq_;
}; };
} // common namespace } // common namespace
 End of changes. 5 change blocks. 
5 lines changed or deleted 5 lines changed or added


 kchashdb.h   kchashdb.h 
skipping to change at line 47 skipping to change at line 47
* @note This class is a concrete class to operate a hash database on a fil e. This class can be * @note This class is a concrete class to operate a hash database on a fil e. This class can be
* inherited but overwriting methods is forbidden. Before every database o peration, it is * inherited but overwriting methods is forbidden. Before every database o peration, it is
* necessary to call the HashDB::open method in order to open a database fi le and connect the * necessary to call the HashDB::open method in order to open a database fi le and connect the
* database object to it. To avoid data missing or corruption, it is impor tant to close every * database object to it. To avoid data missing or corruption, it is impor tant to close every
* database file by the HashDB::close method when the database is no longer in use. It is * database file by the HashDB::close method when the database is no longer in use. It is
* forbidden for multible database objects in a process to open the same da tabase at the same * forbidden for multible database objects in a process to open the same da tabase at the same
* time. It is forbidden to share a database object with child processes. * time. It is forbidden to share a database object with child processes.
*/ */
class HashDB : public BasicDB { class HashDB : public BasicDB {
friend class PlantDB<HashDB, BasicDB::TYPETREE>; friend class PlantDB<HashDB, BasicDB::TYPETREE>;
public: public:
class Cursor; class Cursor;
private: private:
struct Record; struct Record;
struct FreeBlock; struct FreeBlock;
struct FreeBlockComparator; struct FreeBlockComparator;
class Repeater; class Repeater;
class ScopedVisitor; class ScopedVisitor;
/** An alias of set of free blocks. */ /** An alias of set of free blocks. */
typedef std::set<FreeBlock> FBP; typedef std::set<FreeBlock> FBP;
/** An alias of list of cursors. */ /** An alias of list of cursors. */
typedef std::list<Cursor*> CursorList; typedef std::list<Cursor*> CursorList;
/** The offset of the library version. */ /** The offset of the library version. */
skipping to change at line 125 skipping to change at line 125
/** The magic data for free block. */ /** The magic data for free block. */
static const uint8_t FBMAGIC = 0xdd; static const uint8_t FBMAGIC = 0xdd;
/** The maximum unit of auto defragmentation. */ /** The maximum unit of auto defragmentation. */
static const int32_t DFRGMAX = 512; static const int32_t DFRGMAX = 512;
/** The coefficient of auto defragmentation. */ /** The coefficient of auto defragmentation. */
static const int32_t DFRGCEF = 2; static const int32_t DFRGCEF = 2;
/** The checking width for record salvage. */ /** The checking width for record salvage. */
static const int64_t SLVGWIDTH = 1LL << 20; static const int64_t SLVGWIDTH = 1LL << 20;
/** The threshold of busy loop and sleep for locking. */ /** The threshold of busy loop and sleep for locking. */
static const uint32_t LOCKBUSYLOOP = 8192; static const uint32_t LOCKBUSYLOOP = 8192;
public: public:
/** /**
* Cursor to indicate a record. * Cursor to indicate a record.
*/ */
class Cursor : public BasicDB::Cursor { class Cursor : public BasicDB::Cursor {
friend class HashDB; friend class HashDB;
public: public:
/** /**
* Constructor. * Constructor.
* @param db the container database object. * @param db the container database object.
*/ */
explicit Cursor(HashDB* db) : db_(db), off_(0), end_(0) { explicit Cursor(HashDB* db) : db_(db), off_(0), end_(0) {
_assert_(db); _assert_(db);
ScopedSpinRWLock lock(&db_->mlock_, true); ScopedSpinRWLock lock(&db_->mlock_, true);
db_->curs_.push_back(this); db_->curs_.push_back(this);
} }
/** /**
skipping to change at line 326 skipping to change at line 326
while (off > 0) { while (off > 0) {
rec.off = off; rec.off = off;
if (!db_->read_record(&rec, rbuf)) return false; if (!db_->read_record(&rec, rbuf)) return false;
if (rec.psiz == UINT16MAX) { if (rec.psiz == UINT16MAX) {
db_->set_error(_KCCODELINE_, Error::BROKEN, "free block in the ch ain"); db_->set_error(_KCCODELINE_, Error::BROKEN, "free block in the ch ain");
db_->report(_KCCODELINE_, Logger::WARN, "psiz=%lld off=%lld fsiz= %lld", db_->report(_KCCODELINE_, Logger::WARN, "psiz=%lld off=%lld fsiz= %lld",
(long long)db_->psiz_, (long long)rec.off, (long long )db_->file_.size()); (long long)db_->psiz_, (long long)rec.off, (long long )db_->file_.size());
return false; return false;
} }
uint32_t tpivot = db_->linear_ ? pivot : uint32_t tpivot = db_->linear_ ? pivot :
db_->fold_hash(db_->hash_record(rec.kbuf, rec.ksiz)); db_->fold_hash(db_->hash_record(rec.kbuf, rec.ksiz));
if (pivot > tpivot) { if (pivot > tpivot) {
delete[] rec.bbuf; delete[] rec.bbuf;
off = rec.left; off = rec.left;
} else if (pivot < tpivot) { } else if (pivot < tpivot) {
delete[] rec.bbuf; delete[] rec.bbuf;
off = rec.right; off = rec.right;
} else { } else {
int32_t kcmp = db_->compare_keys(kbuf, ksiz, rec.kbuf, rec.ksiz); int32_t kcmp = db_->compare_keys(kbuf, ksiz, rec.kbuf, rec.ksiz);
if (db_->linear_ && kcmp != 0) kcmp = 1; if (db_->linear_ && kcmp != 0) kcmp = 1;
if (kcmp > 0) { if (kcmp > 0) {
skipping to change at line 450 skipping to change at line 450
return false; return false;
} }
/** /**
* Get the database object. * Get the database object.
* @return the database object. * @return the database object.
*/ */
HashDB* db() { HashDB* db() {
_assert_(true); _assert_(true);
return db_; return db_;
} }
private: private:
/** /**
* Step the cursor to the next record. * Step the cursor to the next record.
* @param rec the record structure. * @param rec the record structure.
* @param rbuf the working buffer. * @param rbuf the working buffer.
* @param skip the number of skipping blocks. * @param skip the number of skipping blocks.
* @return true on success, or false on failure. * @return true on success, or false on failure.
*/ */
bool step_impl(Record* rec, char* rbuf, int64_t skip) { bool step_impl(Record* rec, char* rbuf, int64_t skip) {
_assert_(rec && rbuf && skip >= 0); _assert_(rec && rbuf && skip >= 0);
if (off_ >= end_) { if (off_ >= end_) {
skipping to change at line 512 skipping to change at line 512
* Status flags. * Status flags.
*/ */
enum Flag { enum Flag {
FOPEN = 1 << 0, ///< whether opened FOPEN = 1 << 0, ///< whether opened
FFATAL = 1 << 1 ///< whether with fatal error FFATAL = 1 << 1 ///< whether with fatal error
}; };
/** /**
* Default constructor. * Default constructor.
*/ */
explicit HashDB() : explicit HashDB() :
mlock_(), rlock_(RLOCKSLOT), flock_(), atlock_(), error_(), mlock_(), rlock_(RLOCKSLOT), flock_(), atlock_(), error_(),
logger_(NULL), logkinds_(0), mtrigger_(NULL), logger_(NULL), logkinds_(0), mtrigger_(NULL),
omode_(0), writer_(false), autotran_(false), autosync_(false), reorg_(f omode_(0), writer_(false), autotran_(false), autosync_(false),
alse), trim_(false), reorg_(false), trim_(false),
file_(), fbp_(), curs_(), path_(""), file_(), fbp_(), curs_(), path_(""),
libver_(0), librev_(0), fmtver_(0), chksum_(0), type_(TYPEHASH), libver_(0), librev_(0), fmtver_(0), chksum_(0), type_(TYPEHASH),
apow_(DEFAPOW), fpow_(DEFFPOW), opts_(0), bnum_(DEFBNUM), apow_(DEFAPOW), fpow_(DEFFPOW), opts_(0), bnum_(DEFBNUM),
flags_(0), flagopen_(false), count_(0), lsiz_(0), psiz_(0), opaque_(), flags_(0), flagopen_(false), count_(0), lsiz_(0), psiz_(0), opaque_()
msiz_(DEFMSIZ), dfunit_(0), embcomp_(ZLIBRAWCOMP), ,
align_(0), fbpnum_(0), width_(0), linear_(false), msiz_(DEFMSIZ), dfunit_(0), embcomp_(ZLIBRAWCOMP),
comp_(NULL), rhsiz_(0), boff_(0), roff_(0), dfcur_(0), frgcnt_(0), align_(0), fbpnum_(0), width_(0), linear_(false),
tran_(false), trhard_(false), trfbp_(), trcount_(0), trsize_(0) { comp_(NULL), rhsiz_(0), boff_(0), roff_(0), dfcur_(0), frgcnt_(0),
tran_(false), trhard_(false), trfbp_(), trcount_(0), trsize_(0) {
_assert_(true); _assert_(true);
} }
/** /**
* Destructor. * Destructor.
* @note If the database is not closed, it is closed implicitly. * @note If the database is not closed, it is closed implicitly.
*/ */
virtual ~HashDB() { virtual ~HashDB() {
_assert_(true); _assert_(true);
if (omode_ != 0) close(); if (omode_ != 0) close();
if (!curs_.empty()) { if (!curs_.empty()) {
skipping to change at line 742 skipping to change at line 743
* @param code an error code. * @param code an error code.
* @param message a supplement message. * @param message a supplement message.
*/ */
void set_error(const char* file, int32_t line, const char* func, void set_error(const char* file, int32_t line, const char* func,
Error::Code code, const char* message) { Error::Code code, const char* message) {
_assert_(file && line > 0 && func && message); _assert_(file && line > 0 && func && message);
error_->set(code, message); error_->set(code, message);
if (code == Error::BROKEN || code == Error::SYSTEM) flags_ |= FFATAL; if (code == Error::BROKEN || code == Error::SYSTEM) flags_ |= FFATAL;
if (logger_) { if (logger_) {
Logger::Kind kind = code == Error::BROKEN || code == Error::SYSTEM ? Logger::Kind kind = code == Error::BROKEN || code == Error::SYSTEM ?
Logger::ERROR : Logger::INFO; Logger::ERROR : Logger::INFO;
if (kind & logkinds_) if (kind & logkinds_)
report(file, line, func, kind, "%d: %s: %s", code, Error::codename( code), message); report(file, line, func, kind, "%d: %s: %s", code, Error::codename( code), message);
} }
} }
/** /**
* Open a database file. * Open a database file.
* @param path the path of a database file. * @param path the path of a database file.
* @param mode the connection mode. HashDB::OWRITER as a writer, HashDB: :OREADER as a * @param mode the connection mode. HashDB::OWRITER as a writer, HashDB: :OREADER as a
* reader. The following may be added to the writer mode by bitwise-or: HashDB::OCREATE, * reader. The following may be added to the writer mode by bitwise-or: HashDB::OCREATE,
* which means it creates a new database if the file does not exist, Hash DB::OTRUNCATE, which * which means it creates a new database if the file does not exist, Hash DB::OTRUNCATE, which
skipping to change at line 1427 skipping to change at line 1428
*/ */
uint8_t flags() { uint8_t flags() {
_assert_(true); _assert_(true);
ScopedSpinRWLock lock(&mlock_, false); ScopedSpinRWLock lock(&mlock_, false);
if (omode_ == 0) { if (omode_ == 0) {
set_error(_KCCODELINE_, Error::INVALID, "not opened"); set_error(_KCCODELINE_, Error::INVALID, "not opened");
return 0; return 0;
} }
return flags_; return flags_;
} }
protected: protected:
/** /**
* Report a message for debugging. * Report a message for debugging.
* @param file the file name of the program source code. * @param file the file name of the program source code.
* @param line the line number of the program source code. * @param line the line number of the program source code.
* @param func the function name of the program source code. * @param func the function name of the program source code.
* @param kind the kind of the event. Logger::DEBUG for debugging, Logge r::INFO for normal * @param kind the kind of the event. Logger::DEBUG for debugging, Logge r::INFO for normal
* information, Logger::WARN for warning, and Logger::ERROR for fatal err or. * information, Logger::WARN for warning, and Logger::ERROR for fatal err or.
* @param format the printf-like format string. * @param format the printf-like format string.
* @param ... used according to the format string. * @param ... used according to the format string.
*/ */
skipping to change at line 1698 skipping to change at line 1699
*/ */
bool reorganized() { bool reorganized() {
_assert_(true); _assert_(true);
ScopedSpinRWLock lock(&mlock_, false); ScopedSpinRWLock lock(&mlock_, false);
if (omode_ == 0) { if (omode_ == 0) {
set_error(_KCCODELINE_, Error::INVALID, "not opened"); set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false; return false;
} }
return reorg_; return reorg_;
} }
private: private:
/** /**
* Record data. * Record data.
*/ */
struct Record { struct Record {
int64_t off; ///< offset int64_t off; ///< offset
size_t rsiz; ///< whole size size_t rsiz; ///< whole size
size_t psiz; ///< size of the padding size_t psiz; ///< size of the padding
size_t ksiz; ///< size of the key size_t ksiz; ///< size of the key
size_t vsiz; ///< size of the value size_t vsiz; ///< size of the value
int64_t left; ///< address of the left child rec ord int64_t left; ///< address of the left child rec ord
skipping to change at line 1743 skipping to change at line 1744
/** comparing operator */ /** comparing operator */
bool operator ()(const FreeBlock& a, const FreeBlock& b) const { bool operator ()(const FreeBlock& a, const FreeBlock& b) const {
_assert_(true); _assert_(true);
return a.off < b.off; return a.off < b.off;
} }
}; };
/** /**
* Repeating visitor. * Repeating visitor.
*/ */
class Repeater : public Visitor { class Repeater : public Visitor {
public: public:
/** constructor */ /** constructor */
explicit Repeater(const char* vbuf, size_t vsiz) : vbuf_(vbuf), vsiz_(v siz) { explicit Repeater(const char* vbuf, size_t vsiz) : vbuf_(vbuf), vsiz_(v siz) {
_assert_(vbuf); _assert_(vbuf);
} }
private: private:
/** visit a record */ /** visit a record */
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
_assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp ); _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp );
*sp = vsiz_; *sp = vsiz_;
return vbuf_; return vbuf_;
} }
const char* vbuf_; const char* vbuf_;
size_t vsiz_; size_t vsiz_;
}; };
/** /**
* Scoped visitor. * Scoped visitor.
*/ */
class ScopedVisitor { class ScopedVisitor {
public: public:
/** constructor */ /** constructor */
explicit ScopedVisitor(Visitor* visitor) : visitor_(visitor) { explicit ScopedVisitor(Visitor* visitor) : visitor_(visitor) {
_assert_(visitor); _assert_(visitor);
visitor_->visit_before(); visitor_->visit_before();
} }
/** destructor */ /** destructor */
~ScopedVisitor() { ~ScopedVisitor() {
_assert_(true); _assert_(true);
visitor_->visit_after(); visitor_->visit_after();
} }
private: private:
Visitor* visitor_; ///< visitor Visitor* visitor_; ///< visitor
}; };
/** /**
* Accept a visitor to a record. * Accept a visitor to a record.
* @param kbuf the pointer to the key region. * @param kbuf the pointer to the key region.
* @param ksiz the size of the key region. * @param ksiz the size of the key region.
* @param visitor a visitor object. * @param visitor a visitor object.
* @param bidx the bucket index. * @param bidx the bucket index.
* @param pivot the second hash value. * @param pivot the second hash value.
@ @param isiter true for iterator use, or false for direct use. @ @param isiter true for iterator use, or false for direct use.
skipping to change at line 2346 skipping to change at line 2347
} }
return true; return true;
} }
/** /**
* Calculate meta data with saved ones. * Calculate meta data with saved ones.
*/ */
void calc_meta() { void calc_meta() {
_assert_(true); _assert_(true);
align_ = 1 << apow_; align_ = 1 << apow_;
fbpnum_ = fpow_ > 0 ? 1 << fpow_ : 0; fbpnum_ = fpow_ > 0 ? 1 << fpow_ : 0;
//width_ = (opts_ & TSMALL) ? WIDTHSMALL : WIDTHLARGE;
width_ = (opts_ & TSMALL) ? sizeof(uint32_t) : sizeof(uint32_t) + 2; width_ = (opts_ & TSMALL) ? sizeof(uint32_t) : sizeof(uint32_t) + 2;
linear_ = (opts_ & TLINEAR) ? true : false; linear_ = (opts_ & TLINEAR) ? true : false;
comp_ = (opts_ & TCOMPRESS) ? embcomp_ : NULL; comp_ = (opts_ & TCOMPRESS) ? embcomp_ : NULL;
rhsiz_ = sizeof(uint16_t) + sizeof(uint8_t) * 2; rhsiz_ = sizeof(uint16_t) + sizeof(uint8_t) * 2;
rhsiz_ += linear_ ? width_ : width_ * 2; rhsiz_ += linear_ ? width_ : width_ * 2;
boff_ = HEADSIZ + FBPWIDTH * fbpnum_; boff_ = HEADSIZ + FBPWIDTH * fbpnum_;
if (fbpnum_ > 0) boff_ += width_ * 2 + sizeof(uint8_t) * 2; if (fbpnum_ > 0) boff_ += width_ * 2 + sizeof(uint8_t) * 2;
roff_ = boff_ + width_ * bnum_; roff_ = boff_ + width_ * bnum_;
int64_t rem = roff_ % align_; int64_t rem = roff_ % align_;
if (rem > 0) roff_ += align_ - rem; if (rem > 0) roff_ += align_ - rem;
dfcur_ = roff_; dfcur_ = roff_;
skipping to change at line 2713 skipping to change at line 2712
return hashmurmur(kbuf, ksiz); return hashmurmur(kbuf, ksiz);
} }
/** /**
* Fold a hash value into a small number. * Fold a hash value into a small number.
* @param hash the hash number. * @param hash the hash number.
* @return the result number. * @return the result number.
*/ */
uint32_t fold_hash(uint64_t hash) { uint32_t fold_hash(uint64_t hash) {
_assert_(true); _assert_(true);
return (((hash & 0xffff000000000000ULL) >> 48) | ((hash & 0x0000ffff000 00000ULL) >> 16)) ^ return (((hash & 0xffff000000000000ULL) >> 48) | ((hash & 0x0000ffff000 00000ULL) >> 16)) ^
(((hash & 0x000000000000ffffULL) << 16) | ((hash & 0x00000000ffff0000 ULL) >> 16)); (((hash & 0x000000000000ffffULL) << 16) | ((hash & 0x00000000ffff00 00ULL) >> 16));
} }
/** /**
* Compare two keys in lexical order. * Compare two keys in lexical order.
* @param abuf one key. * @param abuf one key.
* @param asiz the size of the one key. * @param asiz the size of the one key.
* @param bbuf the other key. * @param bbuf the other key.
* @param bsiz the size of the other key. * @param bsiz the size of the other key.
* @return positive if the former is big, or negative if the latter is bi g, or 0 if both are * @return positive if the former is big, or negative if the latter is bi g, or 0 if both are
* equivalent. * equivalent.
*/ */
 End of changes. 17 change blocks. 
28 lines changed or deleted 27 lines changed or added


 kclangc.h   kclangc.h 
skipping to change at line 51 skipping to change at line 51
#include <stdint.h> #include <stdint.h>
/** /**
* C wrapper of polymorphic database. * C wrapper of polymorphic database.
*/ */
typedef union { typedef union {
void* db; /**< dummy member */ void* db; /**< dummy member */
} KCDB; } KCDB;
/** /**
* C wrapper of polymorphic cursor.
*/
typedef union {
void* cur; /**< dummy member */
} KCCUR;
/**
* Binary string of byte array. * Binary string of byte array.
*/ */
typedef struct { typedef struct {
char* buf; /**< pointer to the data region */ char* buf; /**< pointer to the data region */
size_t size; /**< size of the data region */ size_t size; /**< size of the data region */
} KCSTR; } KCSTR;
/** /**
* Key-Value record. * Key-Value record.
*/ */
skipping to change at line 155 skipping to change at line 162
* Call back function to process the database file. * Call back function to process the database file.
* @param path the path of the database file. * @param path the path of the database file.
* @param count the number of records. * @param count the number of records.
* @param size the size of the available region. * @param size the size of the available region.
* @param opq an opaque pointer. * @param opq an opaque pointer.
* @return true on success, or false on failure. * @return true on success, or false on failure.
*/ */
typedef int32_t (*KCFILEPROC)(const char* path, int64_t count, int64_t size , void* opq); typedef int32_t (*KCFILEPROC)(const char* path, int64_t count, int64_t size , void* opq);
/** /**
* C wrapper of polymorphic cursor.
*/
typedef union {
void* cur; /**< dummy member */
} KCCUR;
/**
* Allocate a region on memory. * Allocate a region on memory.
* @param size the size of the region. * @param size the size of the region.
* @return the pointer to the allocated region. The region of the return v alue should be * @return the pointer to the allocated region. The region of the return v alue should be
* released with the kcfree function when it is no longer in use. * released with the kcfree function when it is no longer in use.
*/ */
void* kcmalloc(size_t size); void* kcmalloc(size_t size);
/** /**
* Release a region allocated in the library. * Release a region allocated in the library.
* @param ptr the pointer to the region. * @param ptr the pointer to the region.
skipping to change at line 254 skipping to change at line 254
int32_t kcchkinf(double num); int32_t kcchkinf(double num);
/** /**
* Get the readable string of an error code. * Get the readable string of an error code.
* @param code the error code. * @param code the error code.
* @return the readable string of the error code. * @return the readable string of the error code.
*/ */
const char* kcecodename(int32_t code); const char* kcecodename(int32_t code);
/** /**
* Create a database object. * Create a polymorphic database object.
* @return the created database object. * @return the created database object.
* @note The object of the return value should be released with the kcdbdel function when it is * @note The object of the return value should be released with the kcdbdel function when it is
* no longer in use. * no longer in use.
*/ */
KCDB* kcdbnew(void); KCDB* kcdbnew(void);
/** /**
* Destroy a database object. * Destroy a database object.
* @param db the database object. * @param db the database object.
*/ */
skipping to change at line 698 skipping to change at line 698
* @param srcary an array of the source detabase objects. * @param srcary an array of the source detabase objects.
* @param srcnum the number of the elements of the source array. * @param srcnum the number of the elements of the source array.
* @param mode the merge mode. KCMSET to overwrite the existing value, KCM ADD to keep the * @param mode the merge mode. KCMSET to overwrite the existing value, KCM ADD to keep the
* existing value, KCMREPLACE to modify the existing record only, KCMAPPEND to append the new * existing value, KCMREPLACE to modify the existing record only, KCMAPPEND to append the new
* value. * value.
* @return true on success, or false on failure. * @return true on success, or false on failure.
*/ */
int32_t kcdbmerge(KCDB* db, KCDB** srcary, size_t srcnum, uint32_t mode); int32_t kcdbmerge(KCDB* db, KCDB** srcary, size_t srcnum, uint32_t mode);
/** /**
* Create a cursor object. * Create a polymorphic cursor object.
* @param db a database object. * @param db a database object.
* @return the return value is the created cursor object. * @return the return value is the created cursor object.
* @note The object of the return value should be released with the kccurde l function when it is * @note The object of the return value should be released with the kccurde l function when it is
* no longer in use. * no longer in use.
*/ */
KCCUR* kcdbcursor(KCDB* db); KCCUR* kcdbcursor(KCDB* db);
/** /**
* Destroy a cursor object. * Destroy a cursor object.
* @param cur the cursor object. * @param cur the cursor object.
skipping to change at line 865 skipping to change at line 865
*/ */
int32_t kccurecode(KCCUR* cur); int32_t kccurecode(KCCUR* cur);
/** /**
* Get the supplement message of the last happened error. * Get the supplement message of the last happened error.
* @param cur a cursor object. * @param cur a cursor object.
* @return the supplement message of the last happened error. * @return the supplement message of the last happened error.
*/ */
const char* kccuremsg(KCCUR* cur); const char* kccuremsg(KCCUR* cur);
/**
* C wrapper of memory-saving string hash map.
*/
typedef union {
void* map; /**< dummy member */
} KCMAP;
/**
* C wrapper of iterator of memory-saving string hash map.
*/
typedef union {
void* iter; /**< dummy member */
} KCMAPITER;
/**
* C wrapper of sorter of memory-saving string hash map.
*/
typedef union {
void* iter; /**< dummy member */
} KCMAPSORT;
/**
* Create a string hash map object.
* @param bnum the number of buckets of the hash table. If it is not more
than 0, the default
* setting 31 is specified.
* @return the created map object.
* @note The object of the return value should be released with the kcmapde
l function when it is
* no longer in use.
*/
KCMAP* kcmapnew(size_t bnum);
/**
* Destroy a map object.
* @param map the map object.
*/
void kcmapdel(KCMAP* map);
/**
* Set the value of a record.
* @param map the map object.
* @param kbuf the pointer to the key region.
* @param ksiz the size of the key region.
* @param vbuf the pointer to the value region.
* @param vsiz the size of the value region.
* @note If no record corresponds to the key, a new record is created. If
the corresponding
* record exists, the value is overwritten.
*/
void kcmapset(KCMAP* map, const char* kbuf, size_t ksiz, const char* vbuf,
size_t vsiz);
/**
* Add a record.
* @param map the map object.
* @param kbuf the pointer to the key region.
* @param ksiz the size of the key region.
* @param vbuf the pointer to the value region.
* @param vsiz the size of the value region.
* @return true on success, or false on failure.
* @note If no record corresponds to the key, a new record is created. If
the corresponding
* record exists, the record is not modified and false is returned.
*/
int32_t kcmapadd(KCMAP* map, const char* kbuf, size_t ksiz, const char* vbu
f, size_t vsiz);
/**
* Replace the value of a record.
* @param map the map object.
* @param kbuf the pointer to the key region.
* @param ksiz the size of the key region.
* @param vbuf the pointer to the value region.
* @param vsiz the size of the value region.
* @return true on success, or false on failure.
* @note If no record corresponds to the key, no new record is created and
false is returned.
* If the corresponding record exists, the value is modified.
*/
int32_t kcmapreplace(KCMAP* map, const char* kbuf, size_t ksiz, const char*
vbuf, size_t vsiz);
/**
* Append the value of a record.
* @param map the map object.
* @param kbuf the pointer to the key region.
* @param ksiz the size of the key region.
* @param vbuf the pointer to the value region.
* @param vsiz the size of the value region.
* @note If no record corresponds to the key, a new record is created. If
the corresponding
* record exists, the given value is appended at the end of the existing va
lue.
*/
void kcmapappend(KCMAP* map, const char* kbuf, size_t ksiz, const char* vbu
f, size_t vsiz);
/**
* Remove a record.
* @param map the map object.
* @param kbuf the pointer to the key region.
* @param ksiz the size of the key region.
* @return true on success, or false on failure.
* @note If no record corresponds to the key, false is returned.
*/
int32_t kcmapremove(KCMAP* map, const char* kbuf, size_t ksiz);
/**
* Retrieve the value of a record.
* @param map the map object.
* @param kbuf the pointer to the key region.
* @param ksiz the size of the key region.
* @param sp the pointer to the variable into which the size of the region
of the return
* value is assigned.
* @return the pointer to the value region of the corresponding record, or
NULL on failure.
*/
const char* kcmapget(KCMAP* map, const char* kbuf, size_t ksiz, size_t* sp)
;
/**
* Remove all records.
* @param map the map object.
*/
void kcmapclear(KCMAP* map);
/**
* Get the number of records.
* @param map the map object.
* @return the number of records.
*/
size_t kcmapcount(KCMAP* map);
/**
* Create a string hash map iterator object.
* @param map a map object.
* @return the return value is the created iterator object.
* @note The object of the return value should be released with the kcmapit
erdel function when
* it is no longer in use.
* @note This object will not be invalidated even when the map object is up
dated once.
* However, phantom records may be retrieved if they are removed after crea
tion of each iterator.
*/
KCMAPITER* kcmapiterator(KCMAP* map);
/**
* Destroy an iterator object.
* @param iter the iterator object.
*/
void kcmapiterdel(KCMAPITER* iter);
/**
* Get the key of the current record.
* @param iter the iterator object.
* @param sp the pointer to the variable into which the size of the region
of the return
* value is assigned.
* @return the pointer to the key region of the current record, or NULL on
failure.
*/
const char* kcmapitergetkey(KCMAPITER* iter, size_t* sp);
/**
* Get the value of the current record.
* @param iter the iterator object.
* @param sp the pointer to the variable into which the size of the region
of the return
* value is assigned.
* @return the pointer to the value region of the current record, or NULL o
n failure.
*/
const char* kcmapitergetvalue(KCMAPITER* iter, size_t* sp);
/**
* Get a pair of the key and the value of the current record.
* @param iter the iterator object.
* @param ksp the pointer to the variable into which the size of the region
of the return
* value is assigned.
* @param vbp the pointer to the variable into which the pointer to the val
ue region is
* assigned.
* @param vsp the pointer to the variable into which the size of the value
region is
* assigned.
* @return the pointer to the key region, or NULL on failure.
*/
const char* kcmapiterget(KCMAPITER* iter, size_t* ksp, const char** vbp, si
ze_t* vsp);
/**
* Step the cursor to the next record.
* @param iter the iterator object.
*/
void kcmapiterstep(KCMAPITER* iter);
/**
* Create a string hash map sorter object.
* @param map a map object.
* @return the return value is the created sorter object.
* @note The object of the return value should be released with the kcmapso
rtdel function when
* it is no longer in use.
* @note This object will not be invalidated even when the map object is up
dated once.
* However, phantom records may be retrieved if they are removed after crea
tion of each sorter.
*/
KCMAPSORT* kcmapsorter(KCMAP* map);
/**
* Destroy an sorter object.
* @param sort the sorter object.
*/
void kcmapsortdel(KCMAPSORT* sort);
/**
* Get the key of the current record.
* @param sort the sorter object.
* @param sp the pointer to the variable into which the size of the region
of the return
* value is assigned.
* @return the pointer to the key region of the current record, or NULL on
failure.
*/
const char* kcmapsortgetkey(KCMAPSORT* sort, size_t* sp);
/**
* Get the value of the current record.
* @param sort the sorter object.
* @param sp the pointer to the variable into which the size of the region
of the return
* value is assigned.
* @return the pointer to the value region of the current record, or NULL o
n failure.
*/
const char* kcmapsortgetvalue(KCMAPSORT* sort, size_t* sp);
/**
* Get a pair of the key and the value of the current record.
* @param sort the sorter object.
* @param ksp the pointer to the variable into which the size of the region
of the return
* value is assigned.
* @param vbp the pointer to the variable into which the pointer to the val
ue region is
* assigned.
* @param vsp the pointer to the variable into which the size of the value
region is
* assigned.
* @return the pointer to the key region, or NULL on failure.
*/
const char* kcmapsortget(KCMAPSORT* sort, size_t* ksp, const char** vbp, si
ze_t* vsp);
/**
* Step the cursor to the next record.
* @param sort the sorter object.
*/
void kcmapsortstep(KCMAPSORT* sort);
#if defined(__cplusplus) #if defined(__cplusplus)
} }
#endif #endif
#endif /* duplication check */ #endif /* duplication check */
/* END OF FILE */ /* END OF FILE */
 End of changes. 5 change blocks. 
9 lines changed or deleted 274 lines changed or added


 kcmap.h   kcmap.h 
skipping to change at line 24 skipping to change at line 24
#ifndef _KCMAP_H // duplication check #ifndef _KCMAP_H // duplication check
#define _KCMAP_H #define _KCMAP_H
#include <kccommon.h> #include <kccommon.h>
#include <kcutil.h> #include <kcutil.h>
namespace kyotocabinet { // common namespace namespace kyotocabinet { // common namespace
/** /**
* Memory-saving hash map. * Memory-saving string hash map.
*/ */
class TinyHashMap { class TinyHashMap {
public: public:
class Iterator; class Iterator;
private: private:
struct Record; struct Record;
struct RecordComparator; struct RecordComparator;
/** The default bucket number of hash table. */ /** The default bucket number of hash table. */
static const size_t MAPDEFBNUM = 31; static const size_t MAPDEFBNUM = 31;
/** The mininum number of buckets to use mmap. */ /** The mininum number of buckets to use mmap. */
static const size_t MAPZMAPBNUM = 32768; static const size_t MAPZMAPBNUM = 32768;
public: public:
/** /**
* Iterator of records. * Iterator of records.
*/ */
class Iterator { class Iterator {
friend class TinyHashMap; friend class TinyHashMap;
public: public:
/** /**
* Constructor. * Constructor.
* @param map the container. * @param map the container.
* @note This object will not be invalidated even when the map object i
s updated once.
* However, phantom records may be retrieved if they are removed after
creation of each
* iterator.
*/ */
explicit Iterator(TinyHashMap* map) : map_(map), bidx_(-1), ridx_(0), r ecs_() { explicit Iterator(TinyHashMap* map) : map_(map), bidx_(-1), ridx_(0), r ecs_() {
_assert_(map); _assert_(map);
step(); step();
} }
/** /**
* Destructor. * Destructor.
*/ */
~Iterator() { ~Iterator() {
_assert_(true); _assert_(true);
skipping to change at line 119 skipping to change at line 122
ridx_ = 0; ridx_ = 0;
free_records(); free_records();
while (true) { while (true) {
bidx_++; bidx_++;
if (bidx_ >= (int64_t)map_->bnum_) return; if (bidx_ >= (int64_t)map_->bnum_) return;
read_records(); read_records();
if (recs_.size() > 0) break; if (recs_.size() > 0) break;
} }
} }
} }
private: private:
/** /**
* Read records of the current bucket. * Read records of the current bucket.
*/ */
void read_records() { void read_records() {
char* rbuf = map_->buckets_[bidx_]; char* rbuf = map_->buckets_[bidx_];
while (rbuf) { while (rbuf) {
Record rec(rbuf); Record rec(rbuf);
size_t rsiz = sizeof(rec.child_) + sizevarnum(rec.ksiz_) + rec.ksiz _ + size_t rsiz = sizeof(rec.child_) + sizevarnum(rec.ksiz_) + rec.ksiz _ +
sizevarnum(rec.vsiz_) + rec.vsiz_ + sizevarnum(rec.psiz_); sizevarnum(rec.vsiz_) + rec.vsiz_ + sizevarnum(rec.psiz_);
char* nbuf = new char[rsiz]; char* nbuf = new char[rsiz];
std::memcpy(nbuf, rbuf, rsiz); std::memcpy(nbuf, rbuf, rsiz);
recs_.push_back(nbuf); recs_.push_back(nbuf);
rbuf = rec.child_; rbuf = rec.child_;
} }
} }
/** /**
* Release recources of the current records. * Release recources of the current records.
*/ */
void free_records() { void free_records() {
skipping to change at line 165 skipping to change at line 168
int64_t bidx_; int64_t bidx_;
/** The current record index. */ /** The current record index. */
size_t ridx_; size_t ridx_;
/** The current records. */ /** The current records. */
std::vector<char*> recs_; std::vector<char*> recs_;
}; };
/** /**
* Sorter of records. * Sorter of records.
*/ */
class Sorter { class Sorter {
public: public:
/** /**
* Constructor. * Constructor.
* @param map the container. * @param map the container.
* @note This object will be invalidated when the map object is updated once.
*/ */
explicit Sorter(TinyHashMap* map) : map_(map), ridx_(0), recs_() { explicit Sorter(TinyHashMap* map) : map_(map), ridx_(0), recs_() {
_assert_(map); _assert_(map);
recs_.reserve(map->count_); recs_.reserve(map->count_);
char** buckets = map_->buckets_; char** buckets = map_->buckets_;
size_t bnum = map_->bnum_; size_t bnum = map_->bnum_;
for (size_t i = 0; i < bnum; i++) { for (size_t i = 0; i < bnum; i++) {
char* rbuf = buckets[i]; char* rbuf = buckets[i];
while (rbuf) { while (rbuf) {
Record rec(rbuf); Record rec(rbuf);
skipping to change at line 482 skipping to change at line 486
count_ = 0; count_ = 0;
} }
/** /**
* Get the number of records. * Get the number of records.
* @return the number of records. * @return the number of records.
*/ */
size_t count() { size_t count() {
_assert_(true); _assert_(true);
return count_; return count_;
} }
private: private:
/** /**
* Record data. * Record data.
*/ */
struct Record { struct Record {
/** constructor */ /** constructor */
Record(char* child, const char* kbuf, uint64_t ksiz, Record(char* child, const char* kbuf, uint64_t ksiz,
const char* vbuf, uint64_t vsiz, uint64_t psiz) : const char* vbuf, uint64_t vsiz, uint64_t psiz) :
child_(child), kbuf_(kbuf), ksiz_(ksiz), vbuf_(vbuf), vsiz_(vsiz), ps iz_(psiz) { child_(child), kbuf_(kbuf), ksiz_(ksiz), vbuf_(vbuf), vsiz_(vsiz), psiz_(psiz) {
_assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && ps iz <= MEMMAXSIZ); _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && ps iz <= MEMMAXSIZ);
} }
/** constructor */ /** constructor */
Record(const char* rbuf) : Record(const char* rbuf) :
child_(NULL), kbuf_(NULL), ksiz_(0), vbuf_(NULL), vsiz_(0), psiz_(0) { child_(NULL), kbuf_(NULL), ksiz_(0), vbuf_(NULL), vsiz_(0), psiz_(0 ) {
_assert_(rbuf); _assert_(rbuf);
deserialize(rbuf); deserialize(rbuf);
} }
/** overwrite the buffer */ /** overwrite the buffer */
void overwrite(char* rbuf, const char* vbuf, size_t vsiz, size_t psiz) { void overwrite(char* rbuf, const char* vbuf, size_t vsiz, size_t psiz) {
_assert_(rbuf && vbuf && vsiz <= MEMMAXSIZ && psiz <= MEMMAXSIZ); _assert_(rbuf && vbuf && vsiz <= MEMMAXSIZ && psiz <= MEMMAXSIZ);
char* wp = rbuf + sizeof(child_) + sizevarnum(ksiz_) + ksiz_; char* wp = rbuf + sizeof(child_) + sizevarnum(ksiz_) + ksiz_;
wp += writevarnum(wp, vsiz); wp += writevarnum(wp, vsiz);
std::memcpy(wp, vbuf, vsiz); std::memcpy(wp, vbuf, vsiz);
wp += vsiz; wp += vsiz;
skipping to change at line 541 skipping to change at line 545
std::memcpy(wp, ovbuf, ovsiz); std::memcpy(wp, ovbuf, ovsiz);
wp += ovsiz; wp += ovsiz;
std::memcpy(wp, nvbuf, nvsiz); std::memcpy(wp, nvbuf, nvsiz);
wp += nvsiz; wp += nvsiz;
writevarnum(wp, psiz); writevarnum(wp, psiz);
} }
/** serialize data into a buffer */ /** serialize data into a buffer */
char* serialize() { char* serialize() {
_assert_(true); _assert_(true);
uint64_t rsiz = sizeof(child_) + sizevarnum(ksiz_) + ksiz_ + sizevarn um(vsiz_) + vsiz_ + uint64_t rsiz = sizeof(child_) + sizevarnum(ksiz_) + ksiz_ + sizevarn um(vsiz_) + vsiz_ +
sizevarnum(psiz_) + psiz_; sizevarnum(psiz_) + psiz_;
char* rbuf = new char[rsiz]; char* rbuf = new char[rsiz];
char* wp = rbuf; char* wp = rbuf;
*(char**)wp = child_; *(char**)wp = child_;
wp += sizeof(child_); wp += sizeof(child_);
wp += writevarnum(wp, ksiz_); wp += writevarnum(wp, ksiz_);
std::memcpy(wp, kbuf_, ksiz_); std::memcpy(wp, kbuf_, ksiz_);
wp += ksiz_; wp += ksiz_;
wp += writevarnum(wp, vsiz_); wp += writevarnum(wp, vsiz_);
std::memcpy(wp, vbuf_, vsiz_); std::memcpy(wp, vbuf_, vsiz_);
wp += vsiz_; wp += vsiz_;
skipping to change at line 662 skipping to change at line 666
/** /**
* Doubly-linked hash map. * Doubly-linked hash map.
* @param KEY the key type. * @param KEY the key type.
* @param VALUE the value type. * @param VALUE the value type.
* @param HASH the hash functor. * @param HASH the hash functor.
* @param EQUALTO the equality checking functor. * @param EQUALTO the equality checking functor.
*/ */
template <class KEY, class VALUE, template <class KEY, class VALUE,
class HASH = std::hash<KEY>, class EQUALTO = std::equal_to<KEY> > class HASH = std::hash<KEY>, class EQUALTO = std::equal_to<KEY> >
class LinkedHashMap { class LinkedHashMap {
public: public:
class Iterator; class Iterator;
private: private:
struct Record; struct Record;
/** The default bucket number of hash table. */ /** The default bucket number of hash table. */
static const size_t MAPDEFBNUM = 31; static const size_t MAPDEFBNUM = 31;
/** The mininum number of buckets to use mmap. */ /** The mininum number of buckets to use mmap. */
static const size_t MAPZMAPBNUM = 32768; static const size_t MAPZMAPBNUM = 32768;
public: public:
/** /**
* Iterator of records. * Iterator of records.
*/ */
class Iterator { class Iterator {
friend class LinkedHashMap; friend class LinkedHashMap;
public: public:
/** /**
* Copy constructor. * Copy constructor.
* @param src the source object. * @param src the source object.
*/ */
Iterator(const Iterator& src) : map_(src.map_), rec_(src.rec_) { Iterator(const Iterator& src) : map_(src.map_), rec_(src.rec_) {
_assert_(true); _assert_(true);
} }
/** /**
* Get the key. * Get the key.
*/ */
skipping to change at line 774 skipping to change at line 778
Iterator operator --(int) { Iterator operator --(int) {
_assert_(true); _assert_(true);
Iterator old(*this); Iterator old(*this);
if (rec_) { if (rec_) {
rec_ = rec_->prev; rec_ = rec_->prev;
} else { } else {
rec_ = map_->last_; rec_ = map_->last_;
} }
return old; return old;
} }
private: private:
/** /**
* Constructor. * Constructor.
* @param map the container. * @param map the container.
* @param rec the pointer to the current record. * @param rec the pointer to the current record.
*/ */
explicit Iterator(LinkedHashMap* map, Record* rec) : map_(map), rec_(re c) { explicit Iterator(LinkedHashMap* map, Record* rec) : map_(map), rec_(re c) {
_assert_(map); _assert_(map);
} }
/** The container. */ /** The container. */
LinkedHashMap* map_; LinkedHashMap* map_;
skipping to change at line 800 skipping to change at line 804
*/ */
enum MoveMode { enum MoveMode {
MCURRENT, ///< keep the current position MCURRENT, ///< keep the current position
MFIRST, ///< move to the first MFIRST, ///< move to the first
MLAST ///< move to the last MLAST ///< move to the last
}; };
/** /**
* Default constructor. * Default constructor.
*/ */
explicit LinkedHashMap() : explicit LinkedHashMap() :
buckets_(NULL), bnum_(MAPDEFBNUM), first_(NULL), last_(NULL), count_(0) { buckets_(NULL), bnum_(MAPDEFBNUM), first_(NULL), last_(NULL), count_( 0) {
_assert_(true); _assert_(true);
initialize(); initialize();
} }
/** /**
* Constructor. * Constructor.
* @param bnum the number of buckets of the hash table. * @param bnum the number of buckets of the hash table.
*/ */
explicit LinkedHashMap(size_t bnum) : explicit LinkedHashMap(size_t bnum) :
buckets_(NULL), bnum_(bnum), first_(NULL), last_(NULL), count_(0) { buckets_(NULL), bnum_(bnum), first_(NULL), last_(NULL), count_(0) {
_assert_(true); _assert_(true);
if (bnum_ < 1) bnum_ = MAPDEFBNUM; if (bnum_ < 1) bnum_ = MAPDEFBNUM;
initialize(); initialize();
} }
/** /**
* Destructor. * Destructor.
*/ */
~LinkedHashMap() { ~LinkedHashMap() {
_assert_(true); _assert_(true);
destroy(); destroy();
skipping to change at line 1160 skipping to change at line 1164
return last_->key; return last_->key;
} }
/** /**
* Get the reference of the value of the last record. * Get the reference of the value of the last record.
* @return the reference of the value of the last record. * @return the reference of the value of the last record.
*/ */
VALUE& last_value() { VALUE& last_value() {
_assert_(true); _assert_(true);
return last_->value; return last_->value;
} }
private: private:
/** /**
* Record data. * Record data.
*/ */
struct Record { struct Record {
KEY key; ///< key KEY key; ///< key
VALUE value; ///< value VALUE value; ///< value
Record* child; ///< child record Record* child; ///< child record
Record* prev; ///< previous record Record* prev; ///< previous record
Record* next; ///< next record Record* next; ///< next record
/** constructor */ /** constructor */
explicit Record(const KEY& k, const VALUE& v) : explicit Record(const KEY& k, const VALUE& v) :
key(k), value(v), child(NULL), prev(NULL), next(NULL) { key(k), value(v), child(NULL), prev(NULL), next(NULL) {
_assert_(true); _assert_(true);
} }
}; };
/** /**
* Initialize fields. * Initialize fields.
*/ */
void initialize() { void initialize() {
_assert_(true); _assert_(true);
if (bnum_ >= MAPZMAPBNUM) { if (bnum_ >= MAPZMAPBNUM) {
buckets_ = (Record**)mapalloc(sizeof(*buckets_) * bnum_); buckets_ = (Record**)mapalloc(sizeof(*buckets_) * bnum_);
 End of changes. 23 change blocks. 
21 lines changed or deleted 27 lines changed or added


 kcplantdb.h   kcplantdb.h 
skipping to change at line 50 skipping to change at line 50
* TreeDB is the instance of the file tree database. The class ForestDB is the instance of the * TreeDB is the instance of the file tree database. The class ForestDB is the instance of the
* directory tree database. Before every database operation, it is necessa ry to call the * directory tree database. Before every database operation, it is necessa ry to call the
* BasicDB::open method in order to open a database file and connect the da tabase object to it. * BasicDB::open method in order to open a database file and connect the da tabase object to it.
* To avoid data missing or corruption, it is important to close every data base file by the * To avoid data missing or corruption, it is important to close every data base file by the
* BasicDB::close method when the database is no longer in use. It is forb idden for multible * BasicDB::close method when the database is no longer in use. It is forb idden for multible
* database objects in a process to open the same database at the same time . It is forbidden to * database objects in a process to open the same database at the same time . It is forbidden to
* share a database object with child processes. * share a database object with child processes.
*/ */
template <class BASEDB, uint8_t DBTYPE> template <class BASEDB, uint8_t DBTYPE>
class PlantDB : public BasicDB { class PlantDB : public BasicDB {
public: public:
class Cursor; class Cursor;
private: private:
struct Record; struct Record;
struct RecordComparator; struct RecordComparator;
struct LeafNode; struct LeafNode;
struct Link; struct Link;
struct LinkComparator; struct LinkComparator;
struct InnerNode; struct InnerNode;
struct LeafSlot; struct LeafSlot;
struct InnerSlot; struct InnerSlot;
class ScopedVisitor; class ScopedVisitor;
/** An alias of array of records. */ /** An alias of array of records. */
skipping to change at line 112 skipping to change at line 112
/** The base ID number for inner nodes. */ /** The base ID number for inner nodes. */
static const int64_t INIDBASE = 1LL << 48; static const int64_t INIDBASE = 1LL << 48;
/** The minimum number of links in each inner node. */ /** The minimum number of links in each inner node. */
static const size_t INLINKMIN = 8; static const size_t INLINKMIN = 8;
/** The maximum level of B+ tree. */ /** The maximum level of B+ tree. */
static const int32_t LEVELMAX = 16; static const int32_t LEVELMAX = 16;
/** The number of cached nodes for auto transaction. */ /** The number of cached nodes for auto transaction. */
static const int32_t ATRANCNUM = 256; static const int32_t ATRANCNUM = 256;
/** The threshold of busy loop and sleep for locking. */ /** The threshold of busy loop and sleep for locking. */
static const uint32_t LOCKBUSYLOOP = 8192; static const uint32_t LOCKBUSYLOOP = 8192;
public: public:
/** /**
* Cursor to indicate a record. * Cursor to indicate a record.
*/ */
class Cursor : public BasicDB::Cursor { class Cursor : public BasicDB::Cursor {
friend class PlantDB; friend class PlantDB;
public: public:
/** /**
* Constructor. * Constructor.
* @param db the container database object. * @param db the container database object.
*/ */
explicit Cursor(PlantDB* db) : db_(db), stack_(), kbuf_(NULL), ksiz_(0) , lid_(0) { explicit Cursor(PlantDB* db) : db_(db), stack_(), kbuf_(NULL), ksiz_(0) , lid_(0) {
_assert_(db); _assert_(db);
ScopedSpinRWLock lock(&db_->mlock_, true); ScopedSpinRWLock lock(&db_->mlock_, true);
db_->curs_.push_back(this); db_->curs_.push_back(this);
} }
/** /**
skipping to change at line 356 skipping to change at line 356
return !err; return !err;
} }
/** /**
* Get the database object. * Get the database object.
* @return the database object. * @return the database object.
*/ */
PlantDB* db() { PlantDB* db() {
_assert_(true); _assert_(true);
return db_; return db_;
} }
private: private:
/** /**
* Clear the position. * Clear the position.
*/ */
void clear_position() { void clear_position() {
_assert_(true); _assert_(true);
if (kbuf_ != stack_) delete[] kbuf_; if (kbuf_ != stack_) delete[] kbuf_;
kbuf_ = NULL; kbuf_ = NULL;
lid_ = 0; lid_ = 0;
} }
/** /**
skipping to change at line 935 skipping to change at line 935
* Status flags. * Status flags.
*/ */
enum Flag { enum Flag {
FOPEN = BASEDB::FOPEN, ///< whether opened FOPEN = BASEDB::FOPEN, ///< whether opened
FFATAL = BASEDB::FFATAL ///< whether with fatal error FFATAL = BASEDB::FFATAL ///< whether with fatal error
}; };
/** /**
* Default constructor. * Default constructor.
*/ */
explicit PlantDB() : explicit PlantDB() :
mlock_(), mtrigger_(NULL), omode_(0), writer_(false), autotran_(false), mlock_(), mtrigger_(NULL), omode_(0), writer_(false), autotran_(false
autosync_(false), ), autosync_(false),
db_(), curs_(), apow_(DEFAPOW), fpow_(DEFFPOW), opts_(0), bnum_(DEFBNUM db_(), curs_(), apow_(DEFAPOW), fpow_(DEFFPOW), opts_(0), bnum_(DEFBN
), UM),
psiz_(DEFPSIZ), pccap_(DEFPCCAP), psiz_(DEFPSIZ), pccap_(DEFPCCAP),
root_(0), first_(0), last_(0), lcnt_(0), icnt_(0), count_(0), cusage_(0 root_(0), first_(0), last_(0), lcnt_(0), icnt_(0), count_(0), cusage_
), (0),
lslots_(), islots_(), reccomp_(), linkcomp_(), lslots_(), islots_(), reccomp_(), linkcomp_(),
tran_(false), trclock_(0), trlcnt_(0), trcount_(0) { tran_(false), trclock_(0), trlcnt_(0), trcount_(0) {
_assert_(true); _assert_(true);
} }
/** /**
* Destructor. * Destructor.
* @note If the database is not closed, it is closed implicitly. * @note If the database is not closed, it is closed implicitly.
*/ */
virtual ~PlantDB() { virtual ~PlantDB() {
_assert_(true); _assert_(true);
if (omode_ != 0) close(); if (omode_ != 0) close();
if (!curs_.empty()) { if (!curs_.empty()) {
skipping to change at line 1498 skipping to change at line 1498
} }
if (!flush_inner_cache(true)) err = true; if (!flush_inner_cache(true)) err = true;
if (checker && !checker->check("synchronize", "dumping the meta data" , -1, -1)) { if (checker && !checker->check("synchronize", "dumping the meta data" , -1, -1)) {
set_error(_KCCODELINE_, Error::LOGIC, "checker failed"); set_error(_KCCODELINE_, Error::LOGIC, "checker failed");
mlock_.unlock(); mlock_.unlock();
return false; return false;
} }
if (!dump_meta()) err = true; if (!dump_meta()) err = true;
} }
class Wrapper : public FileProcessor { class Wrapper : public FileProcessor {
public: public:
Wrapper(FileProcessor* proc, int64_t count) : proc_(proc), count_(cou nt) {} Wrapper(FileProcessor* proc, int64_t count) : proc_(proc), count_(cou nt) {}
private: private:
bool process(const std::string& path, int64_t count, int64_t size) { bool process(const std::string& path, int64_t count, int64_t size) {
if (proc_) return proc_->process(path, count_, size); if (proc_) return proc_->process(path, count_, size);
return true; return true;
} }
FileProcessor* proc_; FileProcessor* proc_;
int64_t count_; int64_t count_;
} wrapper(proc, count_); } wrapper(proc, count_);
if (!db_.synchronize(hard, &wrapper, checker)) err = true; if (!db_.synchronize(hard, &wrapper, checker)) err = true;
trigger_meta(MetaTrigger::SYNCHRONIZE, "synchronize"); trigger_meta(MetaTrigger::SYNCHRONIZE, "synchronize");
mlock_.unlock(); mlock_.unlock();
skipping to change at line 2018 skipping to change at line 2018
*/ */
Comparator* rcomp() { Comparator* rcomp() {
_assert_(true); _assert_(true);
ScopedSpinRWLock lock(&mlock_, true); ScopedSpinRWLock lock(&mlock_, true);
if (omode_ == 0) { if (omode_ == 0) {
set_error(_KCCODELINE_, Error::INVALID, "not opened"); set_error(_KCCODELINE_, Error::INVALID, "not opened");
return 0; return 0;
} }
return reccomp_.comp; return reccomp_.comp;
} }
protected: protected:
/** /**
* Report a message for debugging. * Report a message for debugging.
* @param file the file name of the program source code. * @param file the file name of the program source code.
* @param line the line number of the program source code. * @param line the line number of the program source code.
* @param func the function name of the program source code. * @param func the function name of the program source code.
* @param kind the kind of the event. Logger::DEBUG for debugging, Logge r::INFO for normal * @param kind the kind of the event. Logger::DEBUG for debugging, Logge r::INFO for normal
* information, Logger::WARN for warning, and Logger::ERROR for fatal err or. * information, Logger::WARN for warning, and Logger::ERROR for fatal err or.
* @param format the printf-like format string. * @param format the printf-like format string.
* @param ... used according to the format string. * @param ... used according to the format string.
*/ */
skipping to change at line 2081 skipping to change at line 2081
* closing, MetaTrigger::CLEAR for clearing, MetaTrigger::ITERATE for ite ration, * closing, MetaTrigger::CLEAR for clearing, MetaTrigger::ITERATE for ite ration,
* MetaTrigger::SYNCHRONIZE for synchronization, MetaTrigger::BEGINTRAN f or beginning * MetaTrigger::SYNCHRONIZE for synchronization, MetaTrigger::BEGINTRAN f or beginning
* transaction, MetaTrigger::COMMITTRAN for committing transaction, MetaT rigger::ABORTTRAN * transaction, MetaTrigger::COMMITTRAN for committing transaction, MetaT rigger::ABORTTRAN
* for aborting transaction, and MetaTrigger::MISC for miscellaneous oper ations. * for aborting transaction, and MetaTrigger::MISC for miscellaneous oper ations.
* @param message the supplement message. * @param message the supplement message.
*/ */
void trigger_meta(MetaTrigger::Kind kind, const char* message) { void trigger_meta(MetaTrigger::Kind kind, const char* message) {
_assert_(message); _assert_(message);
if (mtrigger_) mtrigger_->trigger(kind, message); if (mtrigger_) mtrigger_->trigger(kind, message);
} }
private: private:
/** /**
* Record data. * Record data.
*/ */
struct Record { struct Record {
uint32_t ksiz; ///< size of the key uint32_t ksiz; ///< size of the key
uint32_t vsiz; ///< size of the value uint32_t vsiz; ///< size of the value
}; };
/** /**
* Comparator for records. * Comparator for records.
*/ */
skipping to change at line 2173 skipping to change at line 2173
* Slot cache of inner nodes. * Slot cache of inner nodes.
*/ */
struct InnerSlot { struct InnerSlot {
SpinLock lock; ///< lock SpinLock lock; ///< lock
InnerCache* warm; ///< warm cache InnerCache* warm; ///< warm cache
}; };
/** /**
* Scoped visitor. * Scoped visitor.
*/ */
class ScopedVisitor { class ScopedVisitor {
public: public:
/** constructor */ /** constructor */
explicit ScopedVisitor(Visitor* visitor) : visitor_(visitor) { explicit ScopedVisitor(Visitor* visitor) : visitor_(visitor) {
_assert_(visitor); _assert_(visitor);
visitor_->visit_before(); visitor_->visit_before();
} }
/** destructor */ /** destructor */
~ScopedVisitor() { ~ScopedVisitor() {
_assert_(true); _assert_(true);
visitor_->visit_after(); visitor_->visit_after();
} }
private: private:
Visitor* visitor_; ///< visitor Visitor* visitor_; ///< visitor
}; };
/** /**
* Open the leaf cache. * Open the leaf cache.
*/ */
void create_leaf_cache() { void create_leaf_cache() {
_assert_(true); _assert_(true);
int64_t bnum = bnum_ / SLOTNUM + 1; int64_t bnum = bnum_ / SLOTNUM + 1;
if (bnum < INT8MAX) bnum = INT8MAX; if (bnum < INT8MAX) bnum = INT8MAX;
bnum = nearbyprime(bnum); bnum = nearbyprime(bnum);
skipping to change at line 2419 skipping to change at line 2419
(*np)->hot = true; (*np)->hot = true;
return *np; return *np;
} }
} else { } else {
LeafNode** np = slot->warm->get(id, LeafCache::MLAST); LeafNode** np = slot->warm->get(id, LeafCache::MLAST);
if (np) return *np; if (np) return *np;
} }
char hbuf[NUMBUFSIZ]; char hbuf[NUMBUFSIZ];
size_t hsiz = std::sprintf(hbuf, "%c%llX", LNPREFIX, (long long)id); size_t hsiz = std::sprintf(hbuf, "%c%llX", LNPREFIX, (long long)id);
class VisitorImpl : public DB::Visitor { class VisitorImpl : public DB::Visitor {
public: public:
explicit VisitorImpl() : node_(NULL) {} explicit VisitorImpl() : node_(NULL) {}
LeafNode* pop() { LeafNode* pop() {
return node_; return node_;
} }
private: private:
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
uint64_t prev; uint64_t prev;
size_t step = readvarnum(vbuf, vsiz, &prev); size_t step = readvarnum(vbuf, vsiz, &prev);
if (step < 1) return NOP; if (step < 1) return NOP;
vbuf += step; vbuf += step;
vsiz -= step; vsiz -= step;
uint64_t next; uint64_t next;
step = readvarnum(vbuf, vsiz, &next); step = readvarnum(vbuf, vsiz, &next);
if (step < 1) return NOP; if (step < 1) return NOP;
skipping to change at line 2780 skipping to change at line 2780
InnerNode* load_inner_node(int64_t id) { InnerNode* load_inner_node(int64_t id) {
_assert_(id > 0); _assert_(id > 0);
int32_t sidx = id % SLOTNUM; int32_t sidx = id % SLOTNUM;
InnerSlot* slot = islots_ + sidx; InnerSlot* slot = islots_ + sidx;
ScopedSpinLock lock(&slot->lock); ScopedSpinLock lock(&slot->lock);
InnerNode** np = slot->warm->get(id, InnerCache::MLAST); InnerNode** np = slot->warm->get(id, InnerCache::MLAST);
if (np) return *np; if (np) return *np;
char hbuf[NUMBUFSIZ]; char hbuf[NUMBUFSIZ];
size_t hsiz = std::sprintf(hbuf, "%c%llX", INPREFIX, (long long)(id - I NIDBASE)); size_t hsiz = std::sprintf(hbuf, "%c%llX", INPREFIX, (long long)(id - I NIDBASE));
class VisitorImpl : public DB::Visitor { class VisitorImpl : public DB::Visitor {
public: public:
explicit VisitorImpl() : node_(NULL) {} explicit VisitorImpl() : node_(NULL) {}
InnerNode* pop() { InnerNode* pop() {
return node_; return node_;
} }
private: private:
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
uint64_t heir; uint64_t heir;
size_t step = readvarnum(vbuf, vsiz, &heir); size_t step = readvarnum(vbuf, vsiz, &heir);
if (step < 1) return NOP; if (step < 1) return NOP;
vbuf += step; vbuf += step;
vsiz -= step; vsiz -= step;
InnerNode* node = new InnerNode; InnerNode* node = new InnerNode;
node->size = sizeof(int64_t); node->size = sizeof(int64_t);
node->heir = heir; node->heir = heir;
skipping to change at line 3326 skipping to change at line 3326
} }
/** /**
* Recalculate the count data. * Recalculate the count data.
* @return true on success, or false on failure. * @return true on success, or false on failure.
*/ */
bool recalc_count() { bool recalc_count() {
_assert_(true); _assert_(true);
if (!load_meta()) return false; if (!load_meta()) return false;
bool err = false; bool err = false;
class VisitorImpl : public DB::Visitor { class VisitorImpl : public DB::Visitor {
public: public:
explicit VisitorImpl() : count_(0) {} explicit VisitorImpl() : count_(0) {}
int64_t count() { int64_t count() {
return count_; return count_;
} }
private: private:
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
if (ksiz < 2 || kbuf[0] != LNPREFIX) return NOP; if (ksiz < 2 || kbuf[0] != LNPREFIX) return NOP;
uint64_t prev; uint64_t prev;
size_t step = readvarnum(vbuf, vsiz, &prev); size_t step = readvarnum(vbuf, vsiz, &prev);
if (step < 1) return NOP; if (step < 1) return NOP;
vbuf += step; vbuf += step;
vsiz -= step; vsiz -= step;
uint64_t next; uint64_t next;
step = readvarnum(vbuf, vsiz, &next); step = readvarnum(vbuf, vsiz, &next);
 End of changes. 18 change blocks. 
26 lines changed or deleted 26 lines changed or added


 kcpolydb.h   kcpolydb.h 
skipping to change at line 47 skipping to change at line 47
* Polymorphic database. * Polymorphic database.
* @note This class is a concrete class to operate an arbitrary database wh ose type is determined * @note This class is a concrete class to operate an arbitrary database wh ose type is determined
* in runtime. This class can be inherited but overwriting methods is forb idden. Before every * in runtime. This class can be inherited but overwriting methods is forb idden. Before every
* database operation, it is necessary to call the PolyDB::open method in o rder to open a * database operation, it is necessary to call the PolyDB::open method in o rder to open a
* database file and connect the database object to it. To avoid data miss ing or corruption, it * database file and connect the database object to it. To avoid data miss ing or corruption, it
* is important to close every database file by the PolyDB::close method wh en the database is no * is important to close every database file by the PolyDB::close method wh en the database is no
* longer in use. It is forbidden for multible database objects in a proce ss to open the same * longer in use. It is forbidden for multible database objects in a proce ss to open the same
* database at the same time. It is forbidden to share a database object w ith child processes. * database at the same time. It is forbidden to share a database object w ith child processes.
*/ */
class PolyDB : public BasicDB { class PolyDB : public BasicDB {
public: public:
class Cursor; class Cursor;
private: private:
class StreamLogger; class StreamLogger;
class StreamMetaTrigger; class StreamMetaTrigger;
struct MergeLine; struct MergeLine;
public: public:
/** /**
* Cursor to indicate a record. * Cursor to indicate a record.
*/ */
class Cursor : public BasicDB::Cursor { class Cursor : public BasicDB::Cursor {
friend class PolyDB; friend class PolyDB;
public: public:
/** /**
* Constructor. * Constructor.
* @param db the container database object. * @param db the container database object.
*/ */
explicit Cursor(PolyDB* db) : db_(db), cur_(NULL) { explicit Cursor(PolyDB* db) : db_(db), cur_(NULL) {
_assert_(db); _assert_(db);
if (db_->type_ == TYPEVOID) { if (db_->type_ == TYPEVOID) {
ProtoHashDB tmpdb; ProtoHashDB tmpdb;
cur_ = tmpdb.cursor(); cur_ = tmpdb.cursor();
} else { } else {
skipping to change at line 209 skipping to change at line 209
return cur_->step_back(); return cur_->step_back();
} }
/** /**
* Get the database object. * Get the database object.
* @return the database object. * @return the database object.
*/ */
PolyDB* db() { PolyDB* db() {
_assert_(true); _assert_(true);
return db_; return db_;
} }
private: private:
/** Dummy constructor to forbid the use. */ /** Dummy constructor to forbid the use. */
Cursor(const Cursor&); Cursor(const Cursor&);
/** Dummy Operator to forbid the use. */ /** Dummy Operator to forbid the use. */
Cursor& operator =(const Cursor&); Cursor& operator =(const Cursor&);
/** The inner database. */ /** The inner database. */
PolyDB* db_; PolyDB* db_;
/** The inner cursor. */ /** The inner cursor. */
BasicDB::Cursor* cur_; BasicDB::Cursor* cur_;
}; };
/** /**
skipping to change at line 232 skipping to change at line 232
enum MergeMode { enum MergeMode {
MSET, ///< overwrite the existing value MSET, ///< overwrite the existing value
MADD, ///< keep the existing value MADD, ///< keep the existing value
MREPLACE, ///< modify the existing record on ly MREPLACE, ///< modify the existing record on ly
MAPPEND ///< append the new value MAPPEND ///< append the new value
}; };
/** /**
* Default constructor. * Default constructor.
*/ */
explicit PolyDB() : explicit PolyDB() :
type_(TYPEVOID), db_(NULL), error_(), type_(TYPEVOID), db_(NULL), error_(),
stdlogstrm_(NULL), stdlogger_(NULL), logger_(NULL), logkinds_(0), stdlogstrm_(NULL), stdlogger_(NULL), logger_(NULL), logkinds_(0),
stdmtrgstrm_(NULL), stdmtrigger_(NULL), mtrigger_(NULL), zcomp_(NULL) { stdmtrgstrm_(NULL), stdmtrigger_(NULL), mtrigger_(NULL), zcomp_(NULL)
{
_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 ~PolyDB() { virtual ~PolyDB() {
_assert_(true); _assert_(true);
if (type_ != TYPEVOID) close(); if (type_ != TYPEVOID) close();
delete zcomp_; delete zcomp_;
skipping to change at line 1368 skipping to change at line 1368
*/ */
bool tune_meta_trigger(MetaTrigger* trigger) { bool tune_meta_trigger(MetaTrigger* trigger) {
_assert_(trigger); _assert_(trigger);
if (type_ != TYPEVOID) { if (type_ != TYPEVOID) {
set_error(_KCCODELINE_, Error::INVALID, "already opened"); set_error(_KCCODELINE_, Error::INVALID, "already opened");
return false; return false;
} }
mtrigger_ = trigger; mtrigger_ = trigger;
return true; return true;
} }
private: private:
/** /**
* Stream logger implementation. * Stream logger implementation.
*/ */
class StreamLogger : public Logger { class StreamLogger : public Logger {
public: public:
/** constructor */ /** constructor */
StreamLogger(std::ostream* strm, const char* prefix) : strm_(strm), pre fix_(prefix) {} StreamLogger(std::ostream* strm, const char* prefix) : strm_(strm), pre fix_(prefix) {}
/** print a log message */ /** print a log message */
void log(const char* file, int32_t line, const char* func, Kind kind, void log(const char* file, int32_t line, const char* func, Kind kind,
const char* message) { const char* message) {
_assert_(file && line > 0 && func && message); _assert_(file && line > 0 && func && message);
const char* kstr = "MISC"; const char* kstr = "MISC";
switch (kind) { switch (kind) {
case Logger::DEBUG: kstr = "DEBUG"; break; case Logger::DEBUG: kstr = "DEBUG"; break;
case Logger::INFO: kstr = "INFO"; break; case Logger::INFO: kstr = "INFO"; break;
case Logger::WARN: kstr = "WARN"; break; case Logger::WARN: kstr = "WARN"; break;
case Logger::ERROR: kstr = "ERROR"; break; case Logger::ERROR: kstr = "ERROR"; break;
} }
if (!prefix_.empty()) *strm_ << prefix_ << ": "; if (!prefix_.empty()) *strm_ << prefix_ << ": ";
*strm_ << "[" << kstr << "]: " << file << ": " << line << ": " << fun c << ": " << *strm_ << "[" << kstr << "]: " << file << ": " << line << ": " << fun c << ": " <<
message << std::endl; message << std::endl;
} }
private: private:
std::ostream* strm_; ///< output stream std::ostream* strm_; ///< output stream
std::string prefix_; ///< prefix of each message std::string prefix_; ///< prefix of each message
}; };
/** /**
* Stream meta operation trigger implementation. * Stream meta operation trigger implementation.
*/ */
class StreamMetaTrigger : public MetaTrigger { class StreamMetaTrigger : public MetaTrigger {
public: public:
/** constructor */ /** constructor */
StreamMetaTrigger(std::ostream* strm, const char* prefix) : strm_(strm) , prefix_(prefix) {} StreamMetaTrigger(std::ostream* strm, const char* prefix) : strm_(strm) , prefix_(prefix) {}
/** print a meta operation */ /** print a meta operation */
void trigger(Kind kind, const char* message) { void trigger(Kind kind, const char* message) {
_assert_(message); _assert_(message);
const char* kstr = "unknown"; const char* kstr = "unknown";
switch (kind) { switch (kind) {
case MetaTrigger::OPEN: kstr = "OPEN"; break; case MetaTrigger::OPEN: kstr = "OPEN"; break;
case MetaTrigger::CLOSE: kstr = "CLOSE"; break; case MetaTrigger::CLOSE: kstr = "CLOSE"; break;
case MetaTrigger::CLEAR: kstr = "CLEAR"; break; case MetaTrigger::CLEAR: kstr = "CLEAR"; break;
skipping to change at line 1421 skipping to change at line 1421
case MetaTrigger::SYNCHRONIZE: kstr = "SYNCHRONIZE"; break; case MetaTrigger::SYNCHRONIZE: kstr = "SYNCHRONIZE"; break;
case MetaTrigger::OCCUPY: kstr = "OCCUPY"; break; case MetaTrigger::OCCUPY: kstr = "OCCUPY"; break;
case MetaTrigger::BEGINTRAN: kstr = "BEGINTRAN"; break; case MetaTrigger::BEGINTRAN: kstr = "BEGINTRAN"; break;
case MetaTrigger::COMMITTRAN: kstr = "COMMITTRAN"; break; case MetaTrigger::COMMITTRAN: kstr = "COMMITTRAN"; break;
case MetaTrigger::ABORTTRAN: kstr = "ABORTTRAN"; break; case MetaTrigger::ABORTTRAN: kstr = "ABORTTRAN"; break;
case MetaTrigger::MISC: kstr = "MISC"; break; case MetaTrigger::MISC: kstr = "MISC"; break;
} }
if (!prefix_.empty()) *strm_ << prefix_ << ": "; if (!prefix_.empty()) *strm_ << prefix_ << ": ";
*strm_ << "[" << kstr << "]: " << message << std::endl; *strm_ << "[" << kstr << "]: " << message << std::endl;
} }
private: private:
std::ostream* strm_; ///< output stream std::ostream* strm_; ///< output stream
std::string prefix_; ///< prefix of each message std::string prefix_; ///< prefix of each message
}; };
/** /**
* Front line of a merging list. * Front line of a merging list.
*/ */
struct MergeLine { struct MergeLine {
BasicDB::Cursor* cur; ///< cursor BasicDB::Cursor* cur; ///< cursor
Comparator* comp; ///< comparator Comparator* comp; ///< comparator
char* kbuf; ///< pointer to the key char* kbuf; ///< pointer to the key
 End of changes. 12 change blocks. 
14 lines changed or deleted 15 lines changed or added


 kcprotodb.h   kcprotodb.h 
skipping to change at line 47 skipping to change at line 47
* is forbidden. The class ProtoHashDB is the instance using std::unordere d_map. The class * is forbidden. The class ProtoHashDB is the instance using std::unordere d_map. The class
* ProtoTreeDB is the instance using std::map. Before every database opera tion, it is necessary * ProtoTreeDB is the instance using std::map. Before every database opera tion, it is necessary
* to call the BasicDB::open method in order to open a database file and co nnect the database * to call the BasicDB::open method in order to open a database file and co nnect the database
* object to it. To avoid data missing or corruption, it is important to c lose every database * object to it. To avoid data missing or corruption, it is important to c lose every database
* file by the BasicDB::close method when the database is no longer in use. It is forbidden for * file by the BasicDB::close method when the database is no longer in use. It is forbidden for
* multible database objects in a process to open the same database at the same time. It is * multible database objects in a process to open the same database at the same time. It is
* forbidden to share a database object with child processes. * forbidden to share a database object with child processes.
*/ */
template <class STRMAP, uint8_t DBTYPE> template <class STRMAP, uint8_t DBTYPE>
class ProtoDB : public BasicDB { class ProtoDB : public BasicDB {
public: public:
class Cursor; class Cursor;
private: private:
struct TranLog; struct TranLog;
class ScopedVisitor; class ScopedVisitor;
/** An alias of list of cursors. */ /** An alias of list of cursors. */
typedef std::list<Cursor*> CursorList; typedef std::list<Cursor*> CursorList;
/** An alias of list of transaction logs. */ /** An alias of list of transaction logs. */
typedef std::list<TranLog> TranLogList; typedef std::list<TranLog> TranLogList;
/** The size of the opaque buffer. */ /** The size of the opaque buffer. */
static const size_t OPAQUESIZ = 16; static const size_t OPAQUESIZ = 16;
/** The threshold of busy loop and sleep for locking. */ /** The threshold of busy loop and sleep for locking. */
static const uint32_t LOCKBUSYLOOP = 8192; static const uint32_t LOCKBUSYLOOP = 8192;
public: public:
/** /**
* Cursor to indicate a record. * Cursor to indicate a record.
*/ */
class Cursor : public BasicDB::Cursor { class Cursor : public BasicDB::Cursor {
friend class ProtoDB; friend class ProtoDB;
public: public:
/** /**
* Constructor. * Constructor.
* @param db the container database object. * @param db the container database object.
*/ */
explicit Cursor(ProtoDB* db) : db_(db), it_(db->recs_.end()) { explicit Cursor(ProtoDB* db) : db_(db), it_(db->recs_.end()) {
_assert_(db); _assert_(db);
ScopedSpinRWLock lock(&db_->mlock_, true); ScopedSpinRWLock lock(&db_->mlock_, true);
db_->curs_.push_back(this); db_->curs_.push_back(this);
} }
/** /**
skipping to change at line 317 skipping to change at line 317
return true; return true;
} }
/** /**
* Get the database object. * Get the database object.
* @return the database object. * @return the database object.
*/ */
ProtoDB* db() { ProtoDB* db() {
_assert_(true); _assert_(true);
return db_; return db_;
} }
private: private:
/** /**
* Search for a record. * Search for a record.
*/ */
void search(const std::string& key); void search(const std::string& key);
/** /**
* Place back the inner iterator. * Place back the inner iterator.
* @return true on success, or false on failure. * @return true on success, or false on failure.
*/ */
bool iter_back(); bool iter_back();
/** Dummy constructor to forbid the use. */ /** Dummy constructor to forbid the use. */
skipping to change at line 340 skipping to change at line 340
Cursor& operator =(const Cursor&); Cursor& operator =(const Cursor&);
/** The inner database. */ /** The inner database. */
ProtoDB* db_; ProtoDB* db_;
/** The inner iterator. */ /** The inner iterator. */
typename STRMAP::iterator it_; typename STRMAP::iterator it_;
}; };
/** /**
* Default constructor. * Default constructor.
*/ */
explicit ProtoDB() : explicit ProtoDB() :
mlock_(), error_(), logger_(NULL), logkinds_(0), mtrigger_(NULL), mlock_(), error_(), logger_(NULL), logkinds_(0), mtrigger_(NULL),
omode_(0), recs_(), curs_(), path_(""), size_(0), opaque_(), omode_(0), recs_(), curs_(), path_(""), size_(0), opaque_(),
tran_(false), trlogs_(), trsize_(0) { tran_(false), trlogs_(), trsize_(0) {
_assert_(true); _assert_(true);
map_tune(); map_tune();
} }
/** /**
* Destructor. * Destructor.
* @note If the database is not closed, it is closed implicitly. * @note If the database is not closed, it is closed implicitly.
*/ */
virtual ~ProtoDB() { virtual ~ProtoDB() {
_assert_(true); _assert_(true);
if (omode_ != 0) close(); if (omode_ != 0) close();
skipping to change at line 613 skipping to change at line 613
* @param func the function name of the program source code. * @param func the function name of the program source code.
* @param code an error code. * @param code an error code.
* @param message a supplement message. * @param message a supplement message.
*/ */
void set_error(const char* file, int32_t line, const char* func, void set_error(const char* file, int32_t line, const char* func,
Error::Code code, const char* message) { Error::Code code, const char* message) {
_assert_(file && line > 0 && func && message); _assert_(file && line > 0 && func && message);
error_->set(code, message); error_->set(code, message);
if (logger_) { if (logger_) {
Logger::Kind kind = code == Error::BROKEN || code == Error::SYSTEM ? Logger::Kind kind = code == Error::BROKEN || code == Error::SYSTEM ?
Logger::ERROR : Logger::INFO; Logger::ERROR : Logger::INFO;
if (kind & logkinds_) if (kind & logkinds_)
report(file, line, func, kind, "%d: %s: %s", code, Error::codename( code), message); report(file, line, func, kind, "%d: %s: %s", code, Error::codename( code), message);
} }
} }
/** /**
* Open a database file. * Open a database file.
* @param path the path of a database file. * @param path the path of a database file.
* @param mode the connection mode. BasicDB::OWRITER as a writer, BasicD B::OREADER as a * @param mode the connection mode. BasicDB::OWRITER as a writer, BasicD B::OREADER as a
* reader. The following may be added to the writer mode by bitwise-or: BasicDB::OCREATE, * reader. The following may be added to the writer mode by bitwise-or: BasicDB::OCREATE,
* which means it creates a new database if the file does not exist, Basi cDB::OTRUNCATE, which * which means it creates a new database if the file does not exist, Basi cDB::OTRUNCATE, which
skipping to change at line 1007 skipping to change at line 1007
if (omode_ == 0) { if (omode_ == 0) {
set_error(_KCCODELINE_, Error::INVALID, "not opened"); set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false; return false;
} }
if (!(omode_ & OWRITER)) { if (!(omode_ & OWRITER)) {
set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); set_error(_KCCODELINE_, Error::NOPERM, "permission denied");
return false; return false;
} }
return true; return true;
} }
protected: protected:
/** /**
* Report a message for debugging. * Report a message for debugging.
* @param file the file name of the program source code. * @param file the file name of the program source code.
* @param line the line number of the program source code. * @param line the line number of the program source code.
* @param func the function name of the program source code. * @param func the function name of the program source code.
* @param kind the kind of the event. Logger::DEBUG for debugging, Logge r::INFO for normal * @param kind the kind of the event. Logger::DEBUG for debugging, Logge r::INFO for normal
* information, Logger::WARN for warning, and Logger::ERROR for fatal err or. * information, Logger::WARN for warning, and Logger::ERROR for fatal err or.
* @param format the printf-like format string. * @param format the printf-like format string.
* @param ... used according to the format string. * @param ... used according to the format string.
*/ */
skipping to change at line 1081 skipping to change at line 1081
* closing, MetaTrigger::CLEAR for clearing, MetaTrigger::ITERATE for ite ration, * closing, MetaTrigger::CLEAR for clearing, MetaTrigger::ITERATE for ite ration,
* MetaTrigger::SYNCHRONIZE for synchronization, MetaTrigger::BEGINTRAN f or beginning * MetaTrigger::SYNCHRONIZE for synchronization, MetaTrigger::BEGINTRAN f or beginning
* transaction, MetaTrigger::COMMITTRAN for committing transaction, MetaT rigger::ABORTTRAN * transaction, MetaTrigger::COMMITTRAN for committing transaction, MetaT rigger::ABORTTRAN
* for aborting transaction, and MetaTrigger::MISC for miscellaneous oper ations. * for aborting transaction, and MetaTrigger::MISC for miscellaneous oper ations.
* @param message the supplement message. * @param message the supplement message.
*/ */
void trigger_meta(MetaTrigger::Kind kind, const char* message) { void trigger_meta(MetaTrigger::Kind kind, const char* message) {
_assert_(message); _assert_(message);
if (mtrigger_) mtrigger_->trigger(kind, message); if (mtrigger_) mtrigger_->trigger(kind, message);
} }
private: private:
/** /**
* Transaction log. * Transaction log.
*/ */
struct TranLog { struct TranLog {
bool full; ///< flag whether full bool full; ///< flag whether full
std::string key; ///< old key std::string key; ///< old key
std::string value; ///< old value std::string value; ///< old value
/** constructor for a full record */ /** constructor for a full record */
explicit TranLog(const std::string& pkey, const std::string& pvalue) : explicit TranLog(const std::string& pkey, const std::string& pvalue) :
full(true), key(pkey), value(pvalue) { full(true), key(pkey), value(pvalue) {
_assert_(true); _assert_(true);
} }
/** constructor for an empty record */ /** constructor for an empty record */
explicit TranLog(const std::string& pkey) : full(false), key(pkey) { explicit TranLog(const std::string& pkey) : full(false), key(pkey) {
_assert_(true); _assert_(true);
} }
}; };
/** /**
* Scoped visitor. * Scoped visitor.
*/ */
class ScopedVisitor { class ScopedVisitor {
public: public:
/** constructor */ /** constructor */
explicit ScopedVisitor(Visitor* visitor) : visitor_(visitor) { explicit ScopedVisitor(Visitor* visitor) : visitor_(visitor) {
_assert_(visitor); _assert_(visitor);
visitor_->visit_before(); visitor_->visit_before();
} }
/** destructor */ /** destructor */
~ScopedVisitor() { ~ScopedVisitor() {
_assert_(true); _assert_(true);
visitor_->visit_after(); visitor_->visit_after();
} }
private: private:
Visitor* visitor_; ///< visitor Visitor* visitor_; ///< visitor
}; };
/** /**
* Tune the internal map object. * Tune the internal map object.
*/ */
void map_tune(); void map_tune();
/** Dummy constructor to forbid the use. */ /** Dummy constructor to forbid the use. */
ProtoDB(const ProtoDB&); ProtoDB(const ProtoDB&);
/** Dummy Operator to forbid the use. */ /** Dummy Operator to forbid the use. */
ProtoDB& operator =(const ProtoDB&); ProtoDB& operator =(const ProtoDB&);
 End of changes. 12 change blocks. 
14 lines changed or deleted 14 lines changed or added


 kcregex.h   kcregex.h 
skipping to change at line 27 skipping to change at line 27
#include <kccommon.h> #include <kccommon.h>
#include <kcutil.h> #include <kcutil.h>
namespace kyotocabinet { // common namespace namespace kyotocabinet { // common namespace
/** /**
* Regular expression. * Regular expression.
*/ */
class Regex { class Regex {
public: public:
/** /**
* Options. * Options.
*/ */
enum Option { enum Option {
IGNCASE = 1 << 0, ///< case-insensitive IGNCASE = 1 << 0, ///< case-insensitive
MATCHONLY = 1 << 1, ///< matching only MATCHONLY = 1 << 1, ///< matching only
}; };
/** /**
* Default constructor. * Default constructor.
*/ */
skipping to change at line 97 skipping to change at line 97
* @param opts the optional features by bitwise-or: Regex::IGNCASE for ca se-insensitive * @param opts the optional features by bitwise-or: Regex::IGNCASE for ca se-insensitive
* matching, Regex::MATCHONLY for matching only usage. * matching, Regex::MATCHONLY for matching only usage.
* @return the result string. * @return the result string.
*/ */
static std::string replace(const std::string& str, const std::string& pat tern, static std::string replace(const std::string& str, const std::string& pat tern,
const std::string& alt, uint32_t opts = 0) { const std::string& alt, uint32_t opts = 0) {
Regex regex; Regex regex;
if (!regex.compile(pattern, opts)) return str; if (!regex.compile(pattern, opts)) return str;
return regex.replace(str, alt); return regex.replace(str, alt);
} }
private: private:
/** Dummy constructor to forbid the use. */ /** Dummy constructor to forbid the use. */
Regex(const Regex&); Regex(const Regex&);
/** Dummy Operator to forbid the use. */ /** Dummy Operator to forbid the use. */
Regex& operator =(const Regex&); Regex& operator =(const Regex&);
/** Opaque pointer. */ /** Opaque pointer. */
void* opq_; void* opq_;
}; };
} // common namespace } // common namespace
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 kcstashdb.h   kcstashdb.h 
skipping to change at line 42 skipping to change at line 42
* Economical on-memory hash database. * Economical on-memory hash database.
* @note This class is a concrete class to operate a hash database on memor y. This class can be * @note This class is a concrete class to operate a hash database on memor y. This class can be
* inherited but overwriting methods is forbidden. Before every database o peration, it is * inherited but overwriting methods is forbidden. Before every database o peration, it is
* necessary to call the StashDB::open method in order to open a database f ile and connect the * necessary to call the StashDB::open method in order to open a database f ile and connect the
* database object to it. To avoid data missing or corruption, it is impor tant to close every * database object to it. To avoid data missing or corruption, it is impor tant to close every
* database file by the StashDB::close method when the database is no longe r in use. It is * database file by the StashDB::close method when the database is no longe r in use. It is
* forbidden for multible database objects in a process to open the same da tabase at the same * forbidden for multible database objects in a process to open the same da tabase at the same
* time. It is forbidden to share a database object with child processes. * time. It is forbidden to share a database object with child processes.
*/ */
class StashDB : public BasicDB { class StashDB : public BasicDB {
public: public:
class Cursor; class Cursor;
private: private:
struct Record; struct Record;
struct TranLog; struct TranLog;
class Repeater; class Repeater;
class Setter; class Setter;
class Remover; class Remover;
class ScopedVisitor; class ScopedVisitor;
/** An alias of list of cursors. */ /** An alias of list of cursors. */
typedef std::list<Cursor*> CursorList; typedef std::list<Cursor*> CursorList;
/** An alias of list of transaction logs. */ /** An alias of list of transaction logs. */
typedef std::list<TranLog> TranLogList; typedef std::list<TranLog> TranLogList;
/** The number of slots of the record lock. */ /** The number of slots of the record lock. */
static const int32_t RLOCKSLOT = 1024; static const int32_t RLOCKSLOT = 1024;
/** The default bucket number. */ /** The default bucket number. */
static const size_t DEFBNUM = 1048583LL; static const size_t DEFBNUM = 1048583LL;
/** The size of the opaque buffer. */ /** The size of the opaque buffer. */
static const size_t OPAQUESIZ = 16; static const size_t OPAQUESIZ = 16;
/** The threshold of busy loop and sleep for locking. */ /** The threshold of busy loop and sleep for locking. */
static const uint32_t LOCKBUSYLOOP = 8192; static const uint32_t LOCKBUSYLOOP = 8192;
/** The mininum number of buckets to use mmap. */ /** The mininum number of buckets to use mmap. */
static const size_t MAPZMAPBNUM = 32768; static const size_t MAPZMAPBNUM = 32768;
public: public:
/** /**
* Cursor to indicate a record. * Cursor to indicate a record.
*/ */
class Cursor : public BasicDB::Cursor { class Cursor : public BasicDB::Cursor {
friend class StashDB; friend class StashDB;
public: public:
/** /**
* Constructor. * Constructor.
* @param db the container database object. * @param db the container database object.
*/ */
explicit Cursor(StashDB* db) : db_(db), bidx_(-1), rbuf_(NULL) { explicit Cursor(StashDB* db) : db_(db), bidx_(-1), rbuf_(NULL) {
_assert_(db); _assert_(db);
ScopedSpinRWLock lock(&db_->mlock_, true); ScopedSpinRWLock lock(&db_->mlock_, true);
db_->curs_.push_back(this); db_->curs_.push_back(this);
} }
/** /**
skipping to change at line 274 skipping to change at line 274
return false; return false;
} }
/** /**
* Get the database object. * Get the database object.
* @return the database object. * @return the database object.
*/ */
StashDB* db() { StashDB* db() {
_assert_(true); _assert_(true);
return db_; return db_;
} }
private: private:
/** /**
* Step the cursor to the next record. * Step the cursor to the next record.
* @return true on success, or false on failure. * @return true on success, or false on failure.
*/ */
bool step_impl() { bool step_impl() {
_assert_(true); _assert_(true);
Record rec(rbuf_); Record rec(rbuf_);
rbuf_ = rec.child_; rbuf_ = rec.child_;
if (!rbuf_) { if (!rbuf_) {
while (++bidx_ < (int64_t)db_->bnum_) { while (++bidx_ < (int64_t)db_->bnum_) {
skipping to change at line 311 skipping to change at line 311
StashDB* db_; StashDB* db_;
/** The index of the current bucket. */ /** The index of the current bucket. */
int64_t bidx_; int64_t bidx_;
/** The buffer of the current record. */ /** The buffer of the current record. */
char* rbuf_; char* rbuf_;
}; };
/** /**
* Default constructor. * Default constructor.
*/ */
explicit StashDB() : explicit StashDB() :
mlock_(), rlock_(RLOCKSLOT), flock_(), error_(), mlock_(), rlock_(RLOCKSLOT), flock_(), error_(),
logger_(NULL), logkinds_(0), mtrigger_(NULL), logger_(NULL), logkinds_(0), mtrigger_(NULL),
omode_(0), curs_(), path_(""), bnum_(DEFBNUM), opaque_(), omode_(0), curs_(), path_(""), bnum_(DEFBNUM), opaque_(),
count_(0), size_(0), buckets_(NULL), count_(0), size_(0), buckets_(NULL),
tran_(false), trlogs_(), trcount_(0), trsize_(0) { tran_(false), trlogs_(), trcount_(0), trsize_(0) {
_assert_(true); _assert_(true);
} }
/** /**
* Destructor. * Destructor.
* @note If the database is not closed, it is closed implicitly. * @note If the database is not closed, it is closed implicitly.
*/ */
~StashDB() { ~StashDB() {
_assert_(true); _assert_(true);
if (omode_ != 0) close(); if (omode_ != 0) close();
if (!curs_.empty()) { if (!curs_.empty()) {
skipping to change at line 509 skipping to change at line 509
* @param func the function name of the program source code. * @param func the function name of the program source code.
* @param code an error code. * @param code an error code.
* @param message a supplement message. * @param message a supplement message.
*/ */
void set_error(const char* file, int32_t line, const char* func, void set_error(const char* file, int32_t line, const char* func,
Error::Code code, const char* message) { Error::Code code, const char* message) {
_assert_(file && line > 0 && func && message); _assert_(file && line > 0 && func && message);
error_->set(code, message); error_->set(code, message);
if (logger_) { if (logger_) {
Logger::Kind kind = code == Error::BROKEN || code == Error::SYSTEM ? Logger::Kind kind = code == Error::BROKEN || code == Error::SYSTEM ?
Logger::ERROR : Logger::INFO; Logger::ERROR : Logger::INFO;
if (kind & logkinds_) if (kind & logkinds_)
report(file, line, func, kind, "%d: %s: %s", code, Error::codename( code), message); report(file, line, func, kind, "%d: %s: %s", code, Error::codename( code), message);
} }
} }
/** /**
* Open a database file. * Open a database file.
* @param path the path of a database file. * @param path the path of a database file.
* @param mode the connection mode. StashDB::OWRITER as a writer, StashD B::OREADER as a * @param mode the connection mode. StashDB::OWRITER as a writer, StashD B::OREADER as a
* reader. The following may be added to the writer mode by bitwise-or: StashDB::OCREATE, * reader. The following may be added to the writer mode by bitwise-or: StashDB::OCREATE,
* which means it creates a new database if the file does not exist, Stas hDB::OTRUNCATE, which * which means it creates a new database if the file does not exist, Stas hDB::OTRUNCATE, which
skipping to change at line 928 skipping to change at line 928
if (omode_ == 0) { if (omode_ == 0) {
set_error(_KCCODELINE_, Error::INVALID, "not opened"); set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false; return false;
} }
if (!(omode_ & OWRITER)) { if (!(omode_ & OWRITER)) {
set_error(_KCCODELINE_, Error::NOPERM, "permission denied"); set_error(_KCCODELINE_, Error::NOPERM, "permission denied");
return false; return false;
} }
return true; return true;
} }
protected: protected:
/** /**
* Report a message for debugging. * Report a message for debugging.
* @param file the file name of the program source code. * @param file the file name of the program source code.
* @param line the line number of the program source code. * @param line the line number of the program source code.
* @param func the function name of the program source code. * @param func the function name of the program source code.
* @param kind the kind of the event. Logger::DEBUG for debugging, Logge r::INFO for normal * @param kind the kind of the event. Logger::DEBUG for debugging, Logge r::INFO for normal
* information, Logger::WARN for warning, and Logger::ERROR for fatal err or. * information, Logger::WARN for warning, and Logger::ERROR for fatal err or.
* @param format the printf-like format string. * @param format the printf-like format string.
* @param ... used according to the format string. * @param ... used according to the format string.
*/ */
skipping to change at line 1002 skipping to change at line 1002
* closing, MetaTrigger::CLEAR for clearing, MetaTrigger::ITERATE for ite ration, * closing, MetaTrigger::CLEAR for clearing, MetaTrigger::ITERATE for ite ration,
* MetaTrigger::SYNCHRONIZE for synchronization, MetaTrigger::BEGINTRAN f or beginning * MetaTrigger::SYNCHRONIZE for synchronization, MetaTrigger::BEGINTRAN f or beginning
* transaction, MetaTrigger::COMMITTRAN for committing transaction, MetaT rigger::ABORTTRAN * transaction, MetaTrigger::COMMITTRAN for committing transaction, MetaT rigger::ABORTTRAN
* for aborting transaction, and MetaTrigger::MISC for miscellaneous oper ations. * for aborting transaction, and MetaTrigger::MISC for miscellaneous oper ations.
* @param message the supplement message. * @param message the supplement message.
*/ */
void trigger_meta(MetaTrigger::Kind kind, const char* message) { void trigger_meta(MetaTrigger::Kind kind, const char* message) {
_assert_(message); _assert_(message);
if (mtrigger_) mtrigger_->trigger(kind, message); if (mtrigger_) mtrigger_->trigger(kind, message);
} }
private: private:
/** /**
* Record data. * Record data.
*/ */
struct Record { struct Record {
/** constructor */ /** constructor */
Record(char* child, const char* kbuf, uint64_t ksiz, const char* vbuf, uint64_t vsiz) : Record(char* child, const char* kbuf, uint64_t ksiz, const char* vbuf, uint64_t vsiz) :
child_(child), kbuf_(kbuf), ksiz_(ksiz), vbuf_(vbuf), vsiz_(vsiz) { child_(child), kbuf_(kbuf), ksiz_(ksiz), vbuf_(vbuf), vsiz_(vsiz) {
_assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ); _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ);
} }
/** constructor */ /** constructor */
Record(const char* rbuf) : Record(const char* rbuf) :
child_(NULL), kbuf_(NULL), ksiz_(0), vbuf_(NULL), vsiz_(0) { child_(NULL), kbuf_(NULL), ksiz_(0), vbuf_(NULL), vsiz_(0) {
_assert_(rbuf); _assert_(rbuf);
deserialize(rbuf); deserialize(rbuf);
} }
/** overwrite the buffer */ /** overwrite the buffer */
void overwrite(char* rbuf, const char* vbuf, size_t vsiz) { void overwrite(char* rbuf, const char* vbuf, size_t vsiz) {
_assert_(rbuf && vbuf && vsiz <= MEMMAXSIZ); _assert_(rbuf && vbuf && vsiz <= MEMMAXSIZ);
char* wp = rbuf + sizeof(child_) + sizevarnum(ksiz_) + ksiz_; char* wp = rbuf + sizeof(child_) + sizevarnum(ksiz_) + ksiz_;
wp += writevarnum(wp, vsiz); wp += writevarnum(wp, vsiz);
std::memcpy(wp, vbuf, vsiz); std::memcpy(wp, vbuf, vsiz);
} }
skipping to change at line 1075 skipping to change at line 1075
}; };
/** /**
* Transaction log. * Transaction log.
*/ */
struct TranLog { struct TranLog {
bool full; ///< flag whether full bool full; ///< flag whether full
std::string key; ///< old key std::string key; ///< old key
std::string value; ///< old value std::string value; ///< old value
/** constructor for a full record */ /** constructor for a full record */
explicit TranLog(const char* kbuf, size_t ksiz, const char* vbuf, size_ t vsiz) : explicit TranLog(const char* kbuf, size_t ksiz, const char* vbuf, size_ t vsiz) :
full(true), key(kbuf, ksiz), value(vbuf, vsiz) { full(true), key(kbuf, ksiz), value(vbuf, vsiz) {
_assert_(true); _assert_(true);
} }
/** constructor for an empty record */ /** constructor for an empty record */
explicit TranLog(const char* kbuf, size_t ksiz) : full(false), key(kbuf , ksiz) { explicit TranLog(const char* kbuf, size_t ksiz) : full(false), key(kbuf , ksiz) {
_assert_(true); _assert_(true);
} }
}; };
/** /**
* Repeating visitor. * Repeating visitor.
*/ */
class Repeater : public Visitor { class Repeater : public Visitor {
public: public:
/** constructor */ /** constructor */
explicit Repeater(const char* vbuf, size_t vsiz) : vbuf_(vbuf), vsiz_(v siz) {} explicit Repeater(const char* vbuf, size_t vsiz) : vbuf_(vbuf), vsiz_(v siz) {}
private: private:
/** process a full record */ /** process a full record */
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
_assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp ); _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp );
*sp = vsiz_; *sp = vsiz_;
return vbuf_; return vbuf_;
} }
const char* vbuf_; ///< region of the value const char* vbuf_; ///< region of the value
size_t vsiz_; ///< size of the value size_t vsiz_; ///< size of the value
}; };
/** /**
* Setting visitor. * Setting visitor.
*/ */
class Setter : public Visitor { class Setter : public Visitor {
public: public:
/** constructor */ /** constructor */
explicit Setter(const char* vbuf, size_t vsiz) : vbuf_(vbuf), vsiz_(vsi z) {} explicit Setter(const char* vbuf, size_t vsiz) : vbuf_(vbuf), vsiz_(vsi z) {}
private: private:
/** process a full record */ /** process a full record */
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
_assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp ); _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp );
*sp = vsiz_; *sp = vsiz_;
return vbuf_; return vbuf_;
} }
/** process an empty record */ /** process an empty record */
const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) { const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) {
_assert_(kbuf && ksiz <= MEMMAXSIZ && sp); _assert_(kbuf && ksiz <= MEMMAXSIZ && sp);
*sp = vsiz_; *sp = vsiz_;
return vbuf_; return vbuf_;
} }
const char* vbuf_; ///< region of the value const char* vbuf_; ///< region of the value
size_t vsiz_; ///< size of the value size_t vsiz_; ///< size of the value
}; };
/** /**
* Removing visitor. * Removing visitor.
*/ */
class Remover : public Visitor { class Remover : public Visitor {
private: private:
/** visit a record */ /** visit a record */
const char* visit_full(const char* kbuf, size_t ksiz, const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) { const char* vbuf, size_t vsiz, size_t* sp) {
_assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp ); _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && sp );
return REMOVE; return REMOVE;
} }
}; };
/** /**
* Scoped visitor. * Scoped visitor.
*/ */
class ScopedVisitor { class ScopedVisitor {
public: public:
/** constructor */ /** constructor */
explicit ScopedVisitor(Visitor* visitor) : visitor_(visitor) { explicit ScopedVisitor(Visitor* visitor) : visitor_(visitor) {
_assert_(visitor); _assert_(visitor);
visitor_->visit_before(); visitor_->visit_before();
} }
/** destructor */ /** destructor */
~ScopedVisitor() { ~ScopedVisitor() {
_assert_(true); _assert_(true);
visitor_->visit_after(); visitor_->visit_after();
} }
private: private:
Visitor* visitor_; ///< visitor Visitor* visitor_; ///< visitor
}; };
/** /**
* Accept a visitor to a record. * Accept a visitor to a record.
* @param kbuf the pointer to the key region. * @param kbuf the pointer to the key region.
* @param ksiz the size of the key region. * @param ksiz the size of the key region.
* @param visitor a visitor object. * @param visitor a visitor object.
* @param bidx the bucket index. * @param bidx the bucket index.
*/ */
void accept_impl(const char* kbuf, size_t ksiz, Visitor* visitor, size_t bidx) { void accept_impl(const char* kbuf, size_t ksiz, Visitor* visitor, size_t bidx) {
 End of changes. 19 change blocks. 
23 lines changed or deleted 23 lines changed or added


 kcthread.h   kcthread.h 
skipping to change at line 27 skipping to change at line 27
#include <kccommon.h> #include <kccommon.h>
#include <kcutil.h> #include <kcutil.h>
namespace kyotocabinet { // common namespace namespace kyotocabinet { // common namespace
/** /**
* Threading device. * Threading device.
*/ */
class Thread { class Thread {
public: public:
/** /**
* Default constructor. * Default constructor.
*/ */
explicit Thread(); explicit Thread();
/** /**
* Destructor. * Destructor.
*/ */
virtual ~Thread(); virtual ~Thread();
/** /**
* Perform the concrete process. * Perform the concrete process.
skipping to change at line 75 skipping to change at line 75
* Suspend execution of the current thread. * Suspend execution of the current thread.
* @param sec the interval of the suspension in seconds. * @param sec the interval of the suspension in seconds.
* @return true on success, or false on failure. * @return true on success, or false on failure.
*/ */
static bool sleep(double sec); static bool sleep(double sec);
/** /**
* Get the hash value of the current thread. * Get the hash value of the current thread.
* @return the hash value of the current thread. * @return the hash value of the current thread.
*/ */
static int64_t hash(); static int64_t hash();
private: private:
/** Dummy constructor to forbid the use. */ /** Dummy constructor to forbid the use. */
Thread(const Thread&); Thread(const Thread&);
/** Dummy Operator to forbid the use. */ /** Dummy Operator to forbid the use. */
Thread& operator =(const Thread&); Thread& operator =(const Thread&);
/** Opaque pointer. */ /** Opaque pointer. */
void* opq_; void* opq_;
}; };
/** /**
* Basic mutual exclusion device. * Basic mutual exclusion device.
*/ */
class Mutex { class Mutex {
friend class CondVar; friend class CondVar;
public: public:
/** /**
* Type of the behavior for double locking. * Type of the behavior for double locking.
*/ */
enum Type { enum Type {
FAST, ///< no operation FAST, ///< no operation
ERRORCHECK, ///< check error ERRORCHECK, ///< check error
RECURSIVE ///< allow recursive locking RECURSIVE ///< allow recursive locking
}; };
/** /**
* Default constructor. * Default constructor.
skipping to change at line 130 skipping to change at line 130
/** /**
* Try to get the lock. * Try to get the lock.
* @param sec the interval of the suspension in seconds. * @param sec the interval of the suspension in seconds.
* @return true on success, or false on failure. * @return true on success, or false on failure.
*/ */
bool lock_try(double sec); bool lock_try(double sec);
/** /**
* Release the lock. * Release the lock.
*/ */
void unlock(); void unlock();
private: private:
/** Dummy constructor to forbid the use. */ /** Dummy constructor to forbid the use. */
Mutex(const Mutex&); Mutex(const Mutex&);
/** Dummy Operator to forbid the use. */ /** Dummy Operator to forbid the use. */
Mutex& operator =(const Mutex&); Mutex& operator =(const Mutex&);
/** Opaque pointer. */ /** Opaque pointer. */
void* opq_; void* opq_;
}; };
/** /**
* Scoped mutex device. * Scoped mutex device.
*/ */
class ScopedMutex { class ScopedMutex {
public: public:
/** /**
* Constructor. * Constructor.
* @param mutex a mutex to lock the block. * @param mutex a mutex to lock the block.
*/ */
explicit ScopedMutex(Mutex* mutex) : mutex_(mutex) { explicit ScopedMutex(Mutex* mutex) : mutex_(mutex) {
_assert_(mutex); _assert_(mutex);
mutex_->lock(); mutex_->lock();
} }
/** /**
* Destructor. * Destructor.
*/ */
~ScopedMutex() { ~ScopedMutex() {
_assert_(true); _assert_(true);
mutex_->unlock(); mutex_->unlock();
} }
private: private:
/** Dummy constructor to forbid the use. */ /** Dummy constructor to forbid the use. */
ScopedMutex(const ScopedMutex&); ScopedMutex(const ScopedMutex&);
/** Dummy Operator to forbid the use. */ /** Dummy Operator to forbid the use. */
ScopedMutex& operator =(const ScopedMutex&); ScopedMutex& operator =(const ScopedMutex&);
/** The inner device. */ /** The inner device. */
Mutex* mutex_; Mutex* mutex_;
}; };
/** /**
* Slotted mutex device. * Slotted mutex device.
*/ */
class SlottedMutex { class SlottedMutex {
public: public:
/** /**
* Constructor. * Constructor.
* @param slotnum the number of slots. * @param slotnum the number of slots.
*/ */
explicit SlottedMutex(size_t slotnum); explicit SlottedMutex(size_t slotnum);
/** /**
* Destructor. * Destructor.
*/ */
~SlottedMutex(); ~SlottedMutex();
/** /**
skipping to change at line 200 skipping to change at line 200
*/ */
void unlock(size_t idx); void unlock(size_t idx);
/** /**
* Get the locks of all slots. * Get the locks of all slots.
*/ */
void lock_all(); void lock_all();
/** /**
* Release the locks of all slots. * Release the locks of all slots.
*/ */
void unlock_all(); void unlock_all();
private: private:
/** Opaque pointer. */ /** Opaque pointer. */
void* opq_; void* opq_;
}; };
/** /**
* Lightweight mutual exclusion device. * Lightweight mutual exclusion device.
*/ */
class SpinLock { class SpinLock {
public: public:
/** /**
* Default constructor. * Default constructor.
*/ */
explicit SpinLock(); explicit SpinLock();
/** /**
* Destructor. * Destructor.
*/ */
~SpinLock(); ~SpinLock();
/** /**
* Get the lock. * Get the lock.
skipping to change at line 231 skipping to change at line 231
void lock(); void lock();
/** /**
* Try to get the lock. * Try to get the lock.
* @return true on success, or false on failure. * @return true on success, or false on failure.
*/ */
bool lock_try(); bool lock_try();
/** /**
* Release the lock. * Release the lock.
*/ */
void unlock(); void unlock();
private: private:
/** Dummy constructor to forbid the use. */ /** Dummy constructor to forbid the use. */
SpinLock(const SpinLock&); SpinLock(const SpinLock&);
/** Dummy Operator to forbid the use. */ /** Dummy Operator to forbid the use. */
SpinLock& operator =(const SpinLock&); SpinLock& operator =(const SpinLock&);
/** Opaque pointer. */ /** Opaque pointer. */
void* opq_; void* opq_;
}; };
/** /**
* Scoped spin lock device. * Scoped spin lock device.
*/ */
class ScopedSpinLock { class ScopedSpinLock {
public: public:
/** /**
* Constructor. * Constructor.
* @param spinlock a spin lock to lock the block. * @param spinlock a spin lock to lock the block.
*/ */
explicit ScopedSpinLock(SpinLock* spinlock) : spinlock_(spinlock) { explicit ScopedSpinLock(SpinLock* spinlock) : spinlock_(spinlock) {
_assert_(spinlock); _assert_(spinlock);
spinlock_->lock(); spinlock_->lock();
} }
/** /**
* Destructor. * Destructor.
*/ */
~ScopedSpinLock() { ~ScopedSpinLock() {
_assert_(true); _assert_(true);
spinlock_->unlock(); spinlock_->unlock();
} }
private: private:
/** Dummy constructor to forbid the use. */ /** Dummy constructor to forbid the use. */
ScopedSpinLock(const ScopedSpinLock&); ScopedSpinLock(const ScopedSpinLock&);
/** Dummy Operator to forbid the use. */ /** Dummy Operator to forbid the use. */
ScopedSpinLock& operator =(const ScopedSpinLock&); ScopedSpinLock& operator =(const ScopedSpinLock&);
/** The inner device. */ /** The inner device. */
SpinLock* spinlock_; SpinLock* spinlock_;
}; };
/** /**
* Slotted spin lock devices. * Slotted spin lock devices.
*/ */
class SlottedSpinLock { class SlottedSpinLock {
public: public:
/** /**
* Constructor. * Constructor.
* @param slotnum the number of slots. * @param slotnum the number of slots.
*/ */
explicit SlottedSpinLock(size_t slotnum); explicit SlottedSpinLock(size_t slotnum);
/** /**
* Destructor. * Destructor.
*/ */
~SlottedSpinLock(); ~SlottedSpinLock();
/** /**
skipping to change at line 301 skipping to change at line 301
*/ */
void unlock(size_t idx); void unlock(size_t idx);
/** /**
* Get the locks of all slots. * Get the locks of all slots.
*/ */
void lock_all(); void lock_all();
/** /**
* Release the locks of all slots. * Release the locks of all slots.
*/ */
void unlock_all(); void unlock_all();
private: private:
/** Opaque pointer. */ /** Opaque pointer. */
void* opq_; void* opq_;
}; };
/** /**
* Reader-writer locking device. * Reader-writer locking device.
*/ */
class RWLock { class RWLock {
public: public:
/** /**
* Default constructor. * Default constructor.
*/ */
explicit RWLock(); explicit RWLock();
/** /**
* Destructor. * Destructor.
*/ */
~RWLock(); ~RWLock();
/** /**
* Get the writer lock. * Get the writer lock.
skipping to change at line 341 skipping to change at line 341
void lock_reader(); void lock_reader();
/** /**
* Try to get a reader lock. * Try to get a reader lock.
* @return true on success, or false on failure. * @return true on success, or false on failure.
*/ */
bool lock_reader_try(); bool lock_reader_try();
/** /**
* Release the lock. * Release the lock.
*/ */
void unlock(); void unlock();
private: private:
/** Dummy constructor to forbid the use. */ /** Dummy constructor to forbid the use. */
RWLock(const RWLock&); RWLock(const RWLock&);
/** Dummy Operator to forbid the use. */ /** Dummy Operator to forbid the use. */
RWLock& operator =(const RWLock&); RWLock& operator =(const RWLock&);
/** Opaque pointer. */ /** Opaque pointer. */
void* opq_; void* opq_;
}; };
/** /**
* Scoped reader-writer locking device. * Scoped reader-writer locking device.
*/ */
class ScopedRWLock { class ScopedRWLock {
public: public:
/** /**
* Constructor. * Constructor.
* @param rwlock a rwlock to lock the block. * @param rwlock a rwlock to lock the block.
* @param writer true for writer lock, or false for reader lock. * @param writer true for writer lock, or false for reader lock.
*/ */
explicit ScopedRWLock(RWLock* rwlock, bool writer) : rwlock_(rwlock) { explicit ScopedRWLock(RWLock* rwlock, bool writer) : rwlock_(rwlock) {
_assert_(rwlock); _assert_(rwlock);
if (writer) { if (writer) {
rwlock_->lock_writer(); rwlock_->lock_writer();
} else { } else {
rwlock_->lock_reader(); rwlock_->lock_reader();
} }
} }
/** /**
* Destructor. * Destructor.
*/ */
~ScopedRWLock() { ~ScopedRWLock() {
_assert_(true); _assert_(true);
rwlock_->unlock(); rwlock_->unlock();
} }
private: private:
/** Dummy constructor to forbid the use. */ /** Dummy constructor to forbid the use. */
ScopedRWLock(const ScopedRWLock&); ScopedRWLock(const ScopedRWLock&);
/** Dummy Operator to forbid the use. */ /** Dummy Operator to forbid the use. */
ScopedRWLock& operator =(const ScopedRWLock&); ScopedRWLock& operator =(const ScopedRWLock&);
/** The inner device. */ /** The inner device. */
RWLock* rwlock_; RWLock* rwlock_;
}; };
/** /**
* Slotted reader-writer lock devices. * Slotted reader-writer lock devices.
*/ */
class SlottedRWLock { class SlottedRWLock {
public: public:
/** /**
* Constructor. * Constructor.
* @param slotnum the number of slots. * @param slotnum the number of slots.
*/ */
explicit SlottedRWLock(size_t slotnum); explicit SlottedRWLock(size_t slotnum);
/** /**
* Destructor. * Destructor.
*/ */
~SlottedRWLock(); ~SlottedRWLock();
/** /**
skipping to change at line 425 skipping to change at line 425
*/ */
void lock_writer_all(); void lock_writer_all();
/** /**
* Get the reader locks of all slots. * Get the reader locks of all slots.
*/ */
void lock_reader_all(); void lock_reader_all();
/** /**
* Release the locks of all slots. * Release the locks of all slots.
*/ */
void unlock_all(); void unlock_all();
private: private:
/** Opaque pointer. */ /** Opaque pointer. */
void* opq_; void* opq_;
}; };
/** /**
* Lightweight reader-writer locking device. * Lightweight reader-writer locking device.
*/ */
class SpinRWLock { class SpinRWLock {
public: public:
/** /**
* Default constructor. * Default constructor.
*/ */
explicit SpinRWLock(); explicit SpinRWLock();
/** /**
* Destructor. * Destructor.
*/ */
~SpinRWLock(); ~SpinRWLock();
/** /**
* Get the writer lock. * Get the writer lock.
skipping to change at line 474 skipping to change at line 474
void unlock(); void unlock();
/** /**
* Promote a reader lock to the writer lock. * Promote a reader lock to the writer lock.
* @return true on success, or false on failure. * @return true on success, or false on failure.
*/ */
bool promote(); bool promote();
/** /**
* Demote the writer lock to a reader lock. * Demote the writer lock to a reader lock.
*/ */
void demote(); void demote();
private: private:
/** Dummy constructor to forbid the use. */ /** Dummy constructor to forbid the use. */
SpinRWLock(const SpinRWLock&); SpinRWLock(const SpinRWLock&);
/** Dummy Operator to forbid the use. */ /** Dummy Operator to forbid the use. */
SpinRWLock& operator =(const SpinRWLock&); SpinRWLock& operator =(const SpinRWLock&);
/** Opaque pointer. */ /** Opaque pointer. */
void* opq_; void* opq_;
}; };
/** /**
* Scoped reader-writer locking device. * Scoped reader-writer locking device.
*/ */
class ScopedSpinRWLock { class ScopedSpinRWLock {
public: public:
/** /**
* Constructor. * Constructor.
* @param srwlock a spin rwlock to lock the block. * @param srwlock a spin rwlock to lock the block.
* @param writer true for writer lock, or false for reader lock. * @param writer true for writer lock, or false for reader lock.
*/ */
explicit ScopedSpinRWLock(SpinRWLock* srwlock, bool writer) : srwlock_(sr wlock) { explicit ScopedSpinRWLock(SpinRWLock* srwlock, bool writer) : srwlock_(sr wlock) {
_assert_(srwlock); _assert_(srwlock);
if (writer) { if (writer) {
srwlock_->lock_writer(); srwlock_->lock_writer();
} else { } else {
srwlock_->lock_reader(); srwlock_->lock_reader();
} }
} }
/** /**
* Destructor. * Destructor.
*/ */
~ScopedSpinRWLock() { ~ScopedSpinRWLock() {
_assert_(true); _assert_(true);
srwlock_->unlock(); srwlock_->unlock();
} }
private: private:
/** Dummy constructor to forbid the use. */ /** Dummy constructor to forbid the use. */
ScopedSpinRWLock(const ScopedSpinRWLock&); ScopedSpinRWLock(const ScopedSpinRWLock&);
/** Dummy Operator to forbid the use. */ /** Dummy Operator to forbid the use. */
ScopedSpinRWLock& operator =(const ScopedSpinRWLock&); ScopedSpinRWLock& operator =(const ScopedSpinRWLock&);
/** The inner device. */ /** The inner device. */
SpinRWLock* srwlock_; SpinRWLock* srwlock_;
}; };
/** /**
* Slotted lightweight reader-writer lock devices. * Slotted lightweight reader-writer lock devices.
*/ */
class SlottedSpinRWLock { class SlottedSpinRWLock {
public: public:
/** /**
* Constructor. * Constructor.
* @param slotnum the number of slots. * @param slotnum the number of slots.
*/ */
explicit SlottedSpinRWLock(size_t slotnum); explicit SlottedSpinRWLock(size_t slotnum);
/** /**
* Destructor. * Destructor.
*/ */
~SlottedSpinRWLock(); ~SlottedSpinRWLock();
/** /**
skipping to change at line 558 skipping to change at line 558
*/ */
void lock_writer_all(); void lock_writer_all();
/** /**
* Get the reader locks of all slots. * Get the reader locks of all slots.
*/ */
void lock_reader_all(); void lock_reader_all();
/** /**
* Release the locks of all slots. * Release the locks of all slots.
*/ */
void unlock_all(); void unlock_all();
private: private:
/** Opaque pointer. */ /** Opaque pointer. */
void* opq_; void* opq_;
}; };
/** /**
* Condition variable. * Condition variable.
*/ */
class CondVar { class CondVar {
public: public:
/** /**
* Default constructor. * Default constructor.
*/ */
explicit CondVar(); explicit CondVar();
/** /**
* Destructor. * Destructor.
*/ */
~CondVar(); ~CondVar();
/** /**
* Wait for the signal. * Wait for the signal.
skipping to change at line 598 skipping to change at line 598
/** /**
* Send the wake-up signal to another waiting thread. * Send the wake-up signal to another waiting thread.
* @note The mutex used for the wait method should be locked by the calle r. * @note The mutex used for the wait method should be locked by the calle r.
*/ */
void signal(); void signal();
/** /**
* Send the wake-up signal to all waiting threads. * Send the wake-up signal to all waiting threads.
* @note The mutex used for the wait method should be locked by the calle r. * @note The mutex used for the wait method should be locked by the calle r.
*/ */
void broadcast(); void broadcast();
private: private:
/** Dummy constructor to forbid the use. */ /** Dummy constructor to forbid the use. */
CondVar(const CondVar&); CondVar(const CondVar&);
/** Dummy Operator to forbid the use. */ /** Dummy Operator to forbid the use. */
CondVar& operator =(const CondVar&); CondVar& operator =(const CondVar&);
/** Opaque pointer. */ /** Opaque pointer. */
void* opq_; void* opq_;
}; };
/** /**
* Key of thread specific data. * Key of thread specific data.
*/ */
class TSDKey { class TSDKey {
public: public:
/** /**
* Default constructor. * Default constructor.
*/ */
explicit TSDKey(); explicit TSDKey();
/** /**
* Constructor. * Constructor.
* @param dstr the destructor for the value. * @param dstr the destructor for the value.
*/ */
explicit TSDKey(void (*dstr)(void*)); explicit TSDKey(void (*dstr)(void*));
/** /**
skipping to change at line 635 skipping to change at line 635
/** /**
* Set the value. * Set the value.
* @param ptr an arbitrary pointer. * @param ptr an arbitrary pointer.
*/ */
void set(void* ptr); void set(void* ptr);
/** /**
* Get the value. * Get the value.
* @return the value. * @return the value.
*/ */
void* get() const ; void* get() const ;
private: private:
/** Opaque pointer. */ /** Opaque pointer. */
void* opq_; void* opq_;
}; };
/** /**
* Smart pointer to thread specific data. * Smart pointer to thread specific data.
*/ */
template <class TYPE> template <class TYPE>
class TSD { class TSD {
public: public:
/** /**
* Default constructor. * Default constructor.
*/ */
explicit TSD() : key_(delete_value) { explicit TSD() : key_(delete_value) {
_assert_(true); _assert_(true);
} }
/** /**
* Destructor. * Destructor.
*/ */
~TSD() { ~TSD() {
skipping to change at line 699 skipping to change at line 699
/** /**
* Cast operator to the original type. * Cast operator to the original type.
* @return the copy of the inner object. * @return the copy of the inner object.
*/ */
operator TYPE() const { operator TYPE() const {
_assert_(true); _assert_(true);
TYPE* obj = (TYPE*)key_.get(); TYPE* obj = (TYPE*)key_.get();
if (!obj) return TYPE(); if (!obj) return TYPE();
return *obj; return *obj;
} }
private: private:
/** /**
* Delete the inner object. * Delete the inner object.
* @param obj the inner object. * @param obj the inner object.
*/ */
static void delete_value(void* obj) { static void delete_value(void* obj) {
_assert_(true); _assert_(true);
delete (TYPE*)obj; delete (TYPE*)obj;
} }
/** Dummy constructor to forbid the use. */ /** Dummy constructor to forbid the use. */
TSD(const TSD&); TSD(const TSD&);
/** Dummy Operator to forbid the use. */ /** Dummy Operator to forbid the use. */
TSD& operator =(const TSD&); TSD& operator =(const TSD&);
/** Key of thread specific data. */ /** Key of thread specific data. */
TSDKey key_; TSDKey key_;
}; };
/** /**
* Integer with atomic operations. * Integer with atomic operations.
*/ */
class AtomicInt64 { class AtomicInt64 {
public: public:
/** /**
* Default constructor. * Default constructor.
*/ */
explicit AtomicInt64() : value_(0), lock_() { explicit AtomicInt64() : value_(0), lock_() {
_assert_(true); _assert_(true);
} }
/** /**
* Copy constructor. * Copy constructor.
* @param src the source object. * @param src the source object.
*/ */
skipping to change at line 834 skipping to change at line 834
*/ */
int64_t secure_least(int64_t val) { int64_t secure_least(int64_t val) {
_assert_(true); _assert_(true);
while (true) { while (true) {
int64_t cur = get(); int64_t cur = get();
if (cur >= val) return cur; if (cur >= val) return cur;
if (cas(cur, val)) break; if (cas(cur, val)) break;
} }
return val; return val;
} }
private: private:
/** The value. */ /** The value. */
volatile int64_t value_; volatile int64_t value_;
/** The alternative lock. */ /** The alternative lock. */
mutable SpinLock lock_; mutable SpinLock lock_;
}; };
/** /**
* Task queue device. * Task queue device.
*/ */
class TaskQueue { class TaskQueue {
public: public:
class Task; class Task;
private: private:
class WorkerThread; class WorkerThread;
/** An alias of list of tasks. */ /** An alias of list of tasks. */
typedef std::list<Task*> TaskList; typedef std::list<Task*> TaskList;
public: public:
/** /**
* Interface of a task. * Interface of a task.
*/ */
class Task { class Task {
friend class TaskQueue; friend class TaskQueue;
public: public:
/** /**
* Default constructor. * Default constructor.
*/ */
explicit Task() : id_(0), thid_(0), aborted_(false) { explicit Task() : id_(0), thid_(0), aborted_(false) {
_assert_(true); _assert_(true);
} }
/** /**
* Destructor. * Destructor.
*/ */
virtual ~Task() { virtual ~Task() {
skipping to change at line 895 skipping to change at line 895
return thid_; return thid_;
} }
/** /**
* Check whether the thread is to be aborted. * Check whether the thread is to be aborted.
* @return true if the thread is to be aborted, or false if not. * @return true if the thread is to be aborted, or false if not.
*/ */
bool aborted() { bool aborted() {
_assert_(true); _assert_(true);
return aborted_; return aborted_;
} }
private: private:
/** The task ID number. */ /** The task ID number. */
uint64_t id_; uint64_t id_;
/** The thread ID number. */ /** The thread ID number. */
uint64_t thid_; uint64_t thid_;
/** The flag to be aborted. */ /** The flag to be aborted. */
bool aborted_; bool aborted_;
}; };
/** /**
* Default Constructor. * Default Constructor.
*/ */
skipping to change at line 998 skipping to change at line 998
* Get the number of tasks in the queue. * Get the number of tasks in the queue.
* @return the number of tasks in the queue. * @return the number of tasks in the queue.
*/ */
int64_t count() { int64_t count() {
_assert_(true); _assert_(true);
mutex_.lock(); mutex_.lock();
int64_t count = count_; int64_t count = count_;
mutex_.unlock(); mutex_.unlock();
return count; return count;
} }
private: private:
/** /**
* Implementation of the worker thread. * Implementation of the worker thread.
*/ */
class WorkerThread : public Thread { class WorkerThread : public Thread {
friend class TaskQueue; friend class TaskQueue;
public: public:
explicit WorkerThread() : id_(0), queue_(NULL), aborted_(false) { explicit WorkerThread() : id_(0), queue_(NULL), aborted_(false) {
_assert_(true); _assert_(true);
} }
private: private:
void run() { void run() {
_assert_(true); _assert_(true);
bool empty = false; bool empty = false;
while (true) { while (true) {
queue_->mutex_.lock(); queue_->mutex_.lock();
if (aborted_) { if (aborted_) {
queue_->mutex_.unlock(); queue_->mutex_.unlock();
break; break;
} }
if (empty) queue_->cond_.wait(&queue_->mutex_, 1.0); if (empty) queue_->cond_.wait(&queue_->mutex_, 1.0);
 End of changes. 42 change blocks. 
42 lines changed or deleted 42 lines changed or added


 kcutil.h   kcutil.h 
skipping to change at line 894 skipping to change at line 894
return ((num & 0x00ffU) << 8) | ((num & 0xff00U) >> 8); return ((num & 0x00ffU) << 8) | ((num & 0xff00U) >> 8);
} }
/** /**
* Normalize a 32-bit number in the native order into the network byte orde r. * Normalize a 32-bit number in the native order into the network byte orde r.
*/ */
inline uint32_t hton32(uint32_t num) { inline uint32_t hton32(uint32_t num) {
_assert_(true); _assert_(true);
if (BIGEND) return num; if (BIGEND) return num;
return ((num & 0x000000ffUL) << 24) | ((num & 0x0000ff00UL) << 8) | \ return ((num & 0x000000ffUL) << 24) | ((num & 0x0000ff00UL) << 8) | \
((num & 0x00ff0000UL) >> 8) | ((num & 0xff000000UL) >> 24); ((num & 0x00ff0000UL) >> 8) | ((num & 0xff000000UL) >> 24);
} }
/** /**
* Normalize a 64-bit number in the native order into the network byte orde r. * Normalize a 64-bit number in the native order into the network byte orde r.
*/ */
inline uint64_t hton64(uint64_t num) { inline uint64_t hton64(uint64_t num) {
_assert_(true); _assert_(true);
if (BIGEND) return num; if (BIGEND) return num;
return ((num & 0x00000000000000ffULL) << 56) | ((num & 0x000000000000ff00 ULL) << 40) | return ((num & 0x00000000000000ffULL) << 56) | ((num & 0x000000000000ff00 ULL) << 40) |
((num & 0x0000000000ff0000ULL) << 24) | ((num & 0x00000000ff000000ULL) ((num & 0x0000000000ff0000ULL) << 24) | ((num & 0x00000000ff000000ULL
<< 8) | ) << 8) |
((num & 0x000000ff00000000ULL) >> 8) | ((num & 0x0000ff0000000000ULL) > ((num & 0x000000ff00000000ULL) >> 8) | ((num & 0x0000ff0000000000ULL)
> 24) | >> 24) |
((num & 0x00ff000000000000ULL) >> 40) | ((num & 0xff00000000000000ULL) ((num & 0x00ff000000000000ULL) >> 40) | ((num & 0xff00000000000000ULL
>> 56); ) >> 56);
} }
/** /**
* Denormalize a 16-bit number in the network byte order into the native or der. * Denormalize a 16-bit number in the network byte order into the native or der.
*/ */
inline uint16_t ntoh16(uint16_t num) { inline uint16_t ntoh16(uint16_t num) {
_assert_(true); _assert_(true);
return hton16(num); return hton16(num);
} }
skipping to change at line 1077 skipping to change at line 1077
* Get the hash value by MurMur hashing. * Get the hash value by MurMur hashing.
*/ */
inline uint64_t hashmurmur(const void* buf, size_t size) { inline uint64_t hashmurmur(const void* buf, size_t size) {
_assert_(buf && size <= MEMMAXSIZ); _assert_(buf && size <= MEMMAXSIZ);
const uint64_t mul = 0xc6a4a7935bd1e995ULL; const uint64_t mul = 0xc6a4a7935bd1e995ULL;
const int32_t rtt = 47; const int32_t rtt = 47;
uint64_t hash = 19780211ULL ^ (size * mul); uint64_t hash = 19780211ULL ^ (size * mul);
const unsigned char* rp = (const unsigned char*)buf; const unsigned char* rp = (const unsigned char*)buf;
while (size >= sizeof(uint64_t)) { while (size >= sizeof(uint64_t)) {
uint64_t num = ((uint64_t)rp[0] << 0) | ((uint64_t)rp[1] << 8) | uint64_t num = ((uint64_t)rp[0] << 0) | ((uint64_t)rp[1] << 8) |
((uint64_t)rp[2] << 16) | ((uint64_t)rp[3] << 24) | ((uint64_t)rp[2] << 16) | ((uint64_t)rp[3] << 24) |
((uint64_t)rp[4] << 32) | ((uint64_t)rp[5] << 40) | ((uint64_t)rp[4] << 32) | ((uint64_t)rp[5] << 40) |
((uint64_t)rp[6] << 48) | ((uint64_t)rp[7] << 56); ((uint64_t)rp[6] << 48) | ((uint64_t)rp[7] << 56);
num *= mul; num *= mul;
num ^= num >> rtt; num ^= num >> rtt;
num *= mul; num *= mul;
hash *= mul; hash *= mul;
hash ^= num; hash ^= num;
rp += sizeof(uint64_t); rp += sizeof(uint64_t);
size -= sizeof(uint64_t); size -= sizeof(uint64_t);
} }
switch (size) { switch (size) {
case 7: hash ^= (uint64_t)rp[6] << 48; case 7: hash ^= (uint64_t)rp[6] << 48;
skipping to change at line 1149 skipping to change at line 1149
} else { } else {
*(wp++) = 'a' + num - 10; *(wp++) = 'a' + num - 10;
} }
rp++; rp++;
} }
} else { } else {
*(wp++) = '0'; *(wp++) = '0';
} }
uint64_t hash = hashmurmur(buf, size); uint64_t hash = hashmurmur(buf, size);
rv = (((hash & 0xffff000000000000ULL) >> 48) | ((hash & 0x0000ffff00000 000ULL) >> 16)) ^ rv = (((hash & 0xffff000000000000ULL) >> 48) | ((hash & 0x0000ffff00000 000ULL) >> 16)) ^
(((hash & 0x000000000000ffffULL) << 16) | ((hash & 0x00000000ffff0000 ULL) >> 16)); (((hash & 0x000000000000ffffULL) << 16) | ((hash & 0x00000000ffff00 00ULL) >> 16));
} else { } else {
*(wp++) = 'f' + 1 + (size & 0x0f); *(wp++) = 'f' + 1 + (size & 0x0f);
for (int32_t i = 0; i <= 6; i += 3) { for (int32_t i = 0; i <= 6; i += 3) {
uint32_t num = (rp[i] ^ rp[i+1] ^ rp[i+2] ^ uint32_t num = (rp[i] ^ rp[i+1] ^ rp[i+2] ^
rp[size-i-1] ^ rp[size-i-2] ^ rp[size-i-3]) % 36; rp[size-i-1] ^ rp[size-i-2] ^ rp[size-i-3]) % 36;
if (num < 10) { if (num < 10) {
*(wp++) = '0' + num; *(wp++) = '0' + num;
} else { } else {
*(wp++) = 'a' + num - 10; *(wp++) = 'a' + num - 10;
} }
} }
uint64_t hash = hashmurmur(buf, size); uint64_t hash = hashmurmur(buf, size);
rv = (((hash & 0xffff000000000000ULL) >> 48) | ((hash & 0x0000ffff00000 000ULL) >> 16)) ^ rv = (((hash & 0xffff000000000000ULL) >> 48) | ((hash & 0x0000ffff00000 000ULL) >> 16)) ^
(((hash & 0x000000000000ffffULL) << 16) | ((hash & 0x00000000ffff0000 ULL) >> 16)); (((hash & 0x000000000000ffffULL) << 16) | ((hash & 0x00000000ffff00 00ULL) >> 16));
uint64_t inc = hashfnv(buf, size); uint64_t inc = hashfnv(buf, size);
inc = (((inc & 0xffff000000000000ULL) >> 48) | ((inc & 0x0000ffff000000 00ULL) >> 16)) ^ inc = (((inc & 0xffff000000000000ULL) >> 48) | ((inc & 0x0000ffff000000 00ULL) >> 16)) ^
(((inc & 0x000000000000ffffULL) << 16) | ((inc & 0x00000000ffff0000UL L) >> 16)); (((inc & 0x000000000000ffffULL) << 16) | ((inc & 0x00000000ffff0000 ULL) >> 16));
for (size_t i = 0; i < sizeof(hash); i++) { for (size_t i = 0; i < sizeof(hash); i++) {
uint32_t least = hash >> ((sizeof(hash) - 1) * 8); uint32_t least = hash >> ((sizeof(hash) - 1) * 8);
uint64_t num = least >> 4; uint64_t num = least >> 4;
if (inc & 0x01) num += 0x10; if (inc & 0x01) num += 0x10;
inc = inc >> 1; inc = inc >> 1;
if (num < 10) { if (num < 10) {
*(wp++) = '0' + num; *(wp++) = '0' + num;
} else { } else {
*(wp++) = 'a' + num - 10; *(wp++) = 'a' + num - 10;
} }
 End of changes. 6 change blocks. 
13 lines changed or deleted 13 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/