]*>.*<\/h[1-3]> *$/ {
text = $0
text = strip(text)
text = unescape(text)
text = toupper(text)
printf("\n")
printf(".SH %s\n", text)
}
/ *]*>.*<\/p> *$/ {
text = $0
text = strip(text)
text = gensub("]*>([^<]*)
", "\\\\fB\\1\\\\fR", "g", text)
text = gensub("]*>([^<]*)", "\\\\fI\\1\\\\fR", "g", text)
gsub("<[^>]*>", "", text)
text = unescape(text)
printf(".PP\n")
printf("%s\n", text)
}
/ *
]*> *$/ {
printf(".PP\n")
printf(".RS\n")
}
/ *<\/dl> *$/ {
printf(".RE\n")
}
/ *- ]*>.*<\/dt> *$/ {
text = $0
text = strip(text)
text = gensub("]*>([^<]*)", "\\\\fI\\1\\\\fB", "g", text)
gsub("<[^>]*>", "", text)
gsub("[\\||\\[|\\]]", "\\fR&\\fB", text)
text = unescape(text)
printf(".br\n")
printf("\\fB%s\\fR\n", text)
}
/ *
- ]*>.*<\/dd> *$/ {
text = $0
text = strip(text)
text = gensub("
]*>([^<]*)
", "\\\\fB\\1\\\\fR", "g", text)
text = gensub("]*>([^<]*)", "\\\\fI\\1\\\\fR", "g", text)
gsub("<[^>]*>", "", text)
text = unescape(text)
printf(".RS\n")
printf("%s\n", text)
printf(".RE\n")
}
/ *]*> *$/ {
printf(".PP\n")
printf(".RS\n")
}
/ *<\/ul> *$/ {
printf(".RE\n")
}
/ *- ]*>.*<\/li> *$/ {
text = $0
text = strip(text)
text = gensub("
]*>(.*)
", "\\\\fB\\1\\\\fR", "g", text)
text = gensub("]*>([^<]*)", "\\\\fI\\1\\\\fR", "g", text)
gsub("<[^>]*>", "", text)
text = unescape(text)
printf("%s\n", text)
printf(".br\n")
}
END {
printf("\n")
printf(".SH SEE ALSO\n")
printf(".PP\n")
printf(".BR kcutilmgr (1),\n")
printf(".BR kcutiltest (1)\n")
printf(".PP\n")
printf("Please see\n")
printf(".I http://fallabs.com/kyotocabinet/\n")
printf("for detail.\n")
}
kyotocabinet-1.2.80/man/kclangctest.1 0000644 0001750 0001750 00000003474 11757416060 016455 0 ustar mikio mikio .TH "KCLANGCTEST" 1 "2012-05-24" "Man Page" "Kyoto Cabinet"
.SH NAME
kclangctest \- command line interface to test the C language binding
.SH DESCRIPTION
.PP
The command `\fBkclangctest\fR' is a utility for facility test and performance test of the C language binding. This command is used in the following format. `\fIpath\fR' specifies the path of a database file. `\fIrnum\fR' specifies the number of iterations.
.PP
.RS
.br
\fBkclangctest order \fR[\fB\-rnd\fR]\fB \fR[\fB\-etc\fR]\fB \fR[\fB\-tran\fR]\fB \fR[\fB\-oat\fR|\fB\-onl\fR|\fB\-onl\fR|\fB\-otl\fR|\fB\-onr\fR]\fB \fIpath\fB \fIrnum\fB\fR
.RS
Performs in\-order tests.
.RE
.br
\fBkclangctest index \fR[\fB\-rnd\fR]\fB \fR[\fB\-etc\fR]\fB \fR[\fB\-oat\fR|\fB\-onl\fR|\fB\-onl\fR|\fB\-otl\fR|\fB\-onr\fR]\fB \fIpath\fB \fIrnum\fB\fR
.RS
Performs indexing operations.
.RE
.br
\fBkclangctest map \fR[\fB\-rnd\fR]\fB \fR[\fB\-etc\fR]\fB \fR[\fB\-bnum \fInum\fB\fR]\fB \fIrnum\fB\fR
.RS
Performs test of memory\-saving hash map.
.RE
.br
\fBkclangctest list \fR[\fB\-rnd\fR]\fB \fR[\fB\-etc\fR]\fB \fIrnum\fB\fR
.RS
Performs test of memory\-saving array list.
.RE
.RE
.PP
Options feature the following.
.PP
.RS
\fB\-rnd\fR : performs random test.
.br
\fB\-etc\fR : performs miscellaneous operations.
.br
\fB\-tran\fR : performs transaction.
.br
\fB\-oat\fR : opens the database with the auto transaction option.
.br
\fB\-oas\fR : opens the database with the auto synchronization option.
.br
\fB\-onl\fR : opens the database with the no locking option.
.br
\fB\-otl\fR : opens the database with the try locking option.
.br
\fB\-onr\fR : opens the database with the no auto repair option.
.br
\fB\-bnum \fInum\fR\fR : specifies the number of buckets of the hash table.
.br
.RE
.PP
This command returns 0 on success, another on failure.
.SH SEE ALSO
.PP
.BR kcpolymgr (1),
.BR kcpolytest (1)
kyotocabinet-1.2.80/man/kcforestmgr.1 0000644 0001750 0001750 00000011101 11757416060 016463 0 ustar mikio mikio .TH "KCFORESTMGR" 1 "2012-05-24" "Man Page" "Kyoto Cabinet"
.SH NAME
kcforestmgr \- command line interface to manage the directory tree database
.SH DESCRIPTION
.PP
The command `\fBkcforestmgr\fR' is a utility for test and debugging of the file tree database and its applications. `\fIpath\fR' specifies the path of a database file. `\fIkey\fR' specifies the key of a record. `\fIvalue\fR' specifies the value of a record. `\fIfile\fR' specifies the input/output file.
.PP
.RS
.br
\fBkcforestmgr create \fR[\fB\-otr\fR]\fB \fR[\fB\-onl\fR|\fB\-otl\fR|\fB\-onr\fR]\fB \fR[\fB\-tc\fR]\fB \fR[\fB\-bnum \fInum\fB\fR]\fB \fR[\fB\-psiz \fInum\fB\fR]\fB \fR[\fB\-rcd\fR|\fB\-rcld\fR|\fB\-rcdd\fR]\fB \fIpath\fB\fR
.RS
Creates a database file.
.RE
.br
\fBkcforestmgr inform \fR[\fB\-onl\fR|\fB\-otl\fR|\fB\-onr\fR]\fB \fR[\fB\-st\fR]\fB \fIpath\fB\fR
.RS
Prints status information.
.RE
.br
\fBkcforestmgr set \fR[\fB\-onl\fR|\fB\-otl\fR|\fB\-onr\fR]\fB \fR[\fB\-add\fR|\fB\-app\fR|\fB\-rep\fR|\fB\-inci\fR|\fB\-incd\fR]\fB \fR[\fB\-sx\fR]\fB \fIpath\fB \fIkey\fB \fIvalue\fB\fR
.RS
Stores a record.
.RE
.br
\fBkcforestmgr remove \fR[\fB\-onl\fR|\fB\-otl\fR|\fB\-onr\fR]\fB \fR[\fB\-sx\fR]\fB \fIpath\fB \fIkey\fB\fR
.RS
Removes a record.
.RE
.br
\fBkcforestmgr get \fR[\fB\-onl\fR|\fB\-otl\fR|\fB\-onr\fR]\fB \fR[\fB\-rm\fR]\fB \fR[\fB\-sx\fR]\fB \fR[\fB\-px\fR]\fB \fR[\fB\-pz\fR]\fB \fIpath\fB \fIkey\fB\fR
.RS
Prints the value of a record.
.RE
.br
\fBkcforestmgr list \fR[\fB\-onl\fR|\fB\-otl\fR|\fB\-onr\fR]\fB \fR[\fB\-des\fR]\fB \fR[\fB\-max \fInum\fB\fR]\fB \fR[\fB\-rm\fR]\fB \fR[\fB\-sx\fR]\fB \fR[\fB\-pv\fR]\fB \fR[\fB\-px\fR]\fB \fIpath\fB \fR[\fB\fIkey\fB\fR]\fB\fR
.RS
Prints keys of all records, separated by line feeds.
.RE
.br
\fBkcforestmgr clear \fR[\fB\-onl\fR|\fB\-otl\fR|\fB\-onr\fR]\fB \fIpath\fB\fR
.RS
Removes all records of a database.
.RE
.br
\fBkcforestmgr import \fR[\fB\-onl\fR|\fB\-otl\fR|\fB\-onr\fR]\fB \fR[\fB\-sx\fR]\fB \fIpath\fB \fR[\fB\fIfile\fB\fR]\fB\fR
.RS
Imports records from a TSV file.
.RE
.br
\fBkcforestmgr copy \fR[\fB\-onl\fR|\fB\-otl\fR|\fB\-onr\fR]\fB \fIpath\fB \fIfile\fB\fR
.RS
Copies the whole database.
.RE
.br
\fBkcforestmgr dump \fR[\fB\-onl\fR|\fB\-otl\fR|\fB\-onr\fR]\fB \fIpath\fB \fR[\fB\fIfile\fB\fR]\fB\fR
.RS
Dumps records into a snapshot file.
.RE
.br
\fBkcforestmgr load \fR[\fB\-otr\fR]\fB \fR[\fB\-onl\fR|\fB\-otl\fR|\fB\-onr\fR]\fB \fIpath\fB \fR[\fB\fIfile\fB\fR]\fB\fR
.RS
Loads records from a snapshot file.
.RE
.br
\fBkcforestmgr setbulk \fR[\fB\-onl\fR|\fB\-otl\fR|\fB\-onr\fR]\fB \fIpath\fB \fIkey\fB \fIvalue\fB ...\fR
.RS
Store records at once.
.RE
.br
\fBkcforestmgr removebulk \fR[\fB\-onl\fR|\fB\-otl\fR|\fB\-onr\fR]\fB \fR[\fB\-sx\fR]\fB \fIpath\fB \fIkey\fB ...\fR
.RS
Remove records at once.
.RE
.br
\fBkcforestmgr getbulk \fR[\fB\-onl\fR|\fB\-otl\fR|\fB\-onr\fR]\fB \fR[\fB\-sx\fR]\fB \fR[\fB\-px\fR]\fB \fIpath\fB \fIkey\fB ...\fR
.RS
Retrieve records at once.
.RE
.br
\fBkcforestmgr check \fR[\fB\-onl\fR|\fB\-otl\fR|\fB\-onr\fR]\fB \fIpath\fB\fR
.RS
Checks consistency.
.RE
.RE
.PP
Options feature the following.
.PP
.RS
\fB\-otr\fR : opens the database with the truncation option.
.br
\fB\-onl\fR : opens the database with the no locking option.
.br
\fB\-otl\fR : opens the database with the try locking option.
.br
\fB\-onr\fR : opens the database with the no auto repair option.
.br
\fB\-tc\fR : tunes the database with the compression option.
.br
\fB\-bnum \fInum\fR\fR : specifies the number of buckets of the hash table.
.br
\fB\-psiz \fInum\fR\fR : specifies the size of each page.
.br
\fB\-rcd\fR : use the decimal comparator instead of the lexical one.
.br
\fB\-rcld\fR : use the lexical descending comparator instead of the ascending one.
.br
\fB\-rcdd\fR : use the decimal descending comparator instead of the lexical one.
.br
\fB\-st\fR : prints miscellaneous information.
.br
\fB\-add\fR : performs adding operation.
.br
\fB\-app\fR : performs appending operation.
.br
\fB\-rep\fR : performs replacing operation.
.br
\fB\-inci\fR : performs integer increment operation.
.br
\fB\-incd\fR : performs real number increment operation.
.br
\fB\-sx\fR : the input data is evaluated as a hexadecimal data string.
.br
\fB\-rm\fR : removes the record.
.br
\fB\-px\fR : the output data is converted into a hexadecimal data string.
.br
\fB\-pz\fR : does not append line feed at the end of the output.
.br
\fB\-des\fR : visits records in descending order.
.br
\fB\-max \fInum\fR\fR : specifies the maximum number of shown records.
.br
\fB\-pv\fR : prints values of records also.
.br
.RE
.PP
This command returns 0 on success, another on failure.
.SH SEE ALSO
.PP
.BR kcforesttest (1)
kyotocabinet-1.2.80/man/kcforesttest.1 0000644 0001750 0001750 00000007241 11757416060 016667 0 ustar mikio mikio .TH "KCFORESTTEST" 1 "2012-05-24" "Man Page" "Kyoto Cabinet"
.SH NAME
kcforesttest \- command line interface to test the directory tree database
.SH DESCRIPTION
.PP
The command `\fBkcforesttest\fR' is a utility for facility test and performance test of the directory tree database. This command is used in the following format. `\fIpath\fR' specifies the path of a database file. `\fIrnum\fR' specifies the number of iterations.
.PP
.RS
.br
\fBkcforesttest order \fR[\fB\-th \fInum\fB\fR]\fB \fR[\fB\-rnd\fR]\fB \fR[\fB\-set\fR|\fB\-get\fR|\fB\-getw\fR|\fB\-rem\fR|\fB\-etc\fR]\fB \fR[\fB\-tran\fR]\fB \fR[\fB\-oat\fR|\fB\-onl\fR|\fB\-onl\fR|\fB\-otl\fR|\fB\-onr\fR]\fB \fR[\fB\-tc\fR]\fB \fR[\fB\-bnum \fInum\fB\fR]\fB \fR[\fB\-psiz \fInum\fB\fR]\fB \fR[\fB\-pccap \fInum\fB\fR]\fB \fR[\fB\-rcd\fR|\fB\-rcld\fR|\fB\-rcdd\fR]\fB \fR[\fB\-lv\fR]\fB \fIpath\fB \fIrnum\fB\fR
.RS
Performs in\-order tests.
.RE
.br
\fBkcforesttest queue \fR[\fB\-th \fInum\fB\fR]\fB \fR[\fB\-it \fInum\fB\fR]\fB \fR[\fB\-rnd\fR]\fB \fR[\fB\-oat\fR|\fB\-onl\fR|\fB\-onl\fR|\fB\-otl\fR|\fB\-onr\fR]\fB \fR[\fB\-tc\fR]\fB \fR[\fB\-bnum \fInum\fB\fR]\fB \fR[\fB\-psiz \fInum\fB\fR]\fB \fR[\fB\-pccap \fInum\fB\fR]\fB \fR[\fB\-rcd\fR|\fB\-rcld\fR|\fB\-rcdd\fR]\fB \fR[\fB\-lv\fR]\fB \fIpath\fB \fIrnum\fB\fR
.RS
Performs queuing operations.
.RE
.br
\fBkcforesttest wicked \fR[\fB\-th \fInum\fB\fR]\fB \fR[\fB\-it \fInum\fB\fR]\fB \fR[\fB\-oat\fR|\fB\-onl\fR|\fB\-onl\fR|\fB\-otl\fR|\fB\-onr\fR]\fB \fR[\fB\-tc\fR]\fB \fR[\fB\-bnum \fInum\fB\fR]\fB \fR[\fB\-psiz \fInum\fB\fR]\fB \fR[\fB\-pccap \fInum\fB\fR]\fB \fR[\fB\-rcd\fR|\fB\-rcld\fR|\fB\-rcdd\fR]\fB \fR[\fB\-lv\fR]\fB \fIpath\fB \fIrnum\fB\fR
.RS
Performs mixed operations selected at random.
.RE
.br
\fBkcforesttest tran \fR[\fB\-th \fInum\fB\fR]\fB \fR[\fB\-it \fInum\fB\fR]\fB \fR[\fB\-hard\fR]\fB \fR[\fB\-oat\fR|\fB\-onl\fR|\fB\-onl\fR|\fB\-otl\fR|\fB\-onr\fR]\fB \fR[\fB\-tc\fR]\fB \fR[\fB\-bnum \fInum\fB\fR]\fB \fR[\fB\-psiz \fInum\fB\fR]\fB \fR[\fB\-pccap \fInum\fB\fR]\fB \fR[\fB\-rcd\fR|\fB\-rcld\fR|\fB\-rcdd\fR]\fB \fR[\fB\-lv\fR]\fB \fIpath\fB \fIrnum\fB\fR
.RS
Performs test of transaction.
.RE
.RE
.PP
Options feature the following.
.PP
.RS
\fB\-th \fInum\fR\fR : specifies the number of worker threads.
.br
\fB\-rnd\fR : performs random test.
.br
\fB\-set\fR : performs setting operation only.
.br
\fB\-get\fR : performs getting operation only.
.br
\fB\-getw\fR : performs getting with a buffer operation only.
.br
\fB\-rem\fR : performs removing operation only.
.br
\fB\-etc\fR : performs miscellaneous operations.
.br
\fB\-tran\fR : performs transaction.
.br
\fB\-oat\fR : opens the database with the auto transaction option.
.br
\fB\-oas\fR : opens the database with the auto synchronization option.
.br
\fB\-onl\fR : opens the database with the no locking option.
.br
\fB\-otl\fR : opens the database with the try locking option.
.br
\fB\-onr\fR : opens the database with the no auto repair option.
.br
\fB\-tc\fR : tunes the database with the compression option.
.br
\fB\-bnum \fInum\fR\fR : specifies the number of buckets of the hash table.
.br
\fB\-psiz \fInum\fR\fR : specifies the size of each page.
.br
\fB\-pccap \fInum\fR\fR : specifies the capacity size of the page cache.
.br
\fB\-rcd\fR : use the decimal comparator instead of the lexical one.
.br
\fB\-rcld\fR : use the lexical descending comparator instead of the ascending one.
.br
\fB\-rcdd\fR : use the decimal descending comparator instead of the lexical one.
.br
\fB\-lv\fR : reports all errors.
.br
\fB\-it \fInum\fR\fR : specifies the number of repetition.
.br
\fB\-hard\fR : performs physical synchronization.
.br
.RE
.PP
This command returns 0 on success, another on failure.
.SH SEE ALSO
.PP
.BR kcforestmgr (1)
kyotocabinet-1.2.80/man/kcstashtest.1 0000644 0001750 0001750 00000003176 11757416060 016512 0 ustar mikio mikio .TH "KCSTASHTEST" 1 "2012-05-24" "Man Page" "Kyoto Cabinet"
.SH NAME
kcstashtest \- command line interface to test the stash database
.SH DESCRIPTION
.PP
The command `\fBkcstashtest\fR' is a utility for facility test and performance test of the stash database. This command is used in the following format. `\fIrnum\fR' specifies the number of iterations.
.PP
.RS
.br
\fBkccachetest order \fR[\fB\-th \fInum\fB\fR]\fB \fR[\fB\-rnd\fR]\fB \fR[\fB\-etc\fR]\fB \fR[\fB\-tran\fR]\fB \fR[\fB\-bnum \fInum\fB\fR]\fB \fR[\fB\-lv\fR]\fB \fIrnum\fB\fR
.RS
Performs in\-order tests.
.RE
.br
\fBkccachetest queue \fR[\fB\-th \fInum\fB\fR]\fB \fR[\fB\-it \fInum\fB\fR]\fB \fR[\fB\-rnd\fR]\fB \fR[\fB\-bnum \fInum\fB\fR]\fB \fR[\fB\-lv\fR]\fB \fIrnum\fB\fR
.RS
Performs queuing operations.
.RE
.br
\fBkccachetest wicked \fR[\fB\-th \fInum\fB\fR]\fB \fR[\fB\-it \fInum\fB\fR]\fB \fR[\fB\-bnum \fInum\fB\fR]\fB \fR[\fB\-lv\fR]\fB \fIrnum\fB\fR
.RS
Performs mixed operations selected at random.
.RE
.br
\fBkccachetest tran \fR[\fB\-th \fInum\fB\fR]\fB \fR[\fB\-it \fInum\fB\fR]\fB \fR[\fB\-bnum \fInum\fB\fR]\fB \fR[\fB\-lv\fR]\fB \fIrnum\fB\fR
.RS
Performs test of transaction.
.RE
.RE
.PP
Options feature the following.
.PP
.RS
\fB\-th \fInum\fR\fR : specifies the number of worker threads.
.br
\fB\-rnd\fR : performs random test.
.br
\fB\-etc\fR : performs miscellaneous operations.
.br
\fB\-tran\fR : performs transaction.
.br
\fB\-bnum \fInum\fR\fR : specifies the number of buckets of the hash table.
.br
\fB\-lv\fR : reports all errors.
.br
\fB\-it \fInum\fR\fR : specifies the number of repetition.
.br
.RE
.PP
This command returns 0 on success, another on failure.
kyotocabinet-1.2.80/kcpolytest.cc 0000664 0001750 0001750 00000313547 14416044124 016026 0 ustar mikio mikio /*************************************************************************************************
* The test cases of the polymorphic database
* Copyright (C) 2009-2012 Mikio Hirabayashi
* This file is part of Kyoto Cabinet.
* This program is free software: you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation, either version
* 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with this program.
* If not, see .
*************************************************************************************************/
#include
#include
#include "cmdcommon.h"
// global variables
const char* g_progname; // program name
uint32_t g_randseed; // random seed
int64_t g_memusage; // memory usage
// function prototypes
int main(int argc, char** argv);
static void usage();
static void dberrprint(kc::BasicDB* db, int32_t line, const char* func);
static void dberrprint(kc::IndexDB* db, int32_t line, const char* func);
static void dbmetaprint(kc::BasicDB* db, bool verbose);
static void dbmetaprint(kc::IndexDB* db, bool verbose);
static int32_t runorder(int argc, char** argv);
static int32_t runqueue(int argc, char** argv);
static int32_t runwicked(int argc, char** argv);
static int32_t runtran(int argc, char** argv);
static int32_t runmapred(int argc, char** argv);
static int32_t runindex(int argc, char** argv);
static int32_t runmisc(int argc, char** argv);
static int32_t procorder(const char* path, int64_t rnum, int32_t thnum, bool rnd, int32_t mode,
bool tran, int32_t oflags, bool lv);
static int32_t procqueue(const char* path, int64_t rnum, int32_t thnum, int32_t itnum, bool rnd,
int32_t oflags, bool lv);
static int32_t procwicked(const char* path, int64_t rnum, int32_t thnum, int32_t itnum,
int32_t oflags, bool lv);
static int32_t proctran(const char* path, int64_t rnum, int32_t thnum, int32_t itnum, bool hard,
int32_t oflags, bool lv);
static int32_t procmapred(const char* path, int64_t rnum, bool rnd, bool ru, int32_t oflags,
bool lv, const char* tmpdir, int64_t dbnum,
int64_t clim, int64_t cbnum, int32_t opts);
static int32_t procindex(const char* path, int64_t rnum, int32_t thnum, bool rnd, int32_t mode,
int32_t oflags, bool lv);
static int32_t procmisc(const char* path);
// main routine
int main(int argc, char** argv) {
g_progname = argv[0];
const char* ebuf = kc::getenv("KCRNDSEED");
g_randseed = ebuf ? (uint32_t)kc::atoi(ebuf) : (uint32_t)(kc::time() * 1000);
mysrand(g_randseed);
g_memusage = memusage();
kc::setstdiobin();
if (argc < 2) usage();
int32_t rv = 0;
if (!std::strcmp(argv[1], "order")) {
rv = runorder(argc, argv);
} else if (!std::strcmp(argv[1], "queue")) {
rv = runqueue(argc, argv);
} else if (!std::strcmp(argv[1], "wicked")) {
rv = runwicked(argc, argv);
} else if (!std::strcmp(argv[1], "tran")) {
rv = runtran(argc, argv);
} else if (!std::strcmp(argv[1], "mapred")) {
rv = runmapred(argc, argv);
} else if (!std::strcmp(argv[1], "index")) {
rv = runindex(argc, argv);
} else if (!std::strcmp(argv[1], "misc")) {
rv = runmisc(argc, argv);
} else {
usage();
}
if (rv != 0) {
oprintf("FAILED: KCRNDSEED=%u PID=%ld", g_randseed, (long)kc::getpid());
for (int32_t i = 0; i < argc; i++) {
oprintf(" %s", argv[i]);
}
oprintf("\n\n");
}
return rv;
}
// print the usage and exit
static void usage() {
eprintf("%s: test cases of the polymorphic database of Kyoto Cabinet\n", g_progname);
eprintf("\n");
eprintf("usage:\n");
eprintf(" %s order [-th num] [-rnd] [-set|-get|-getw|-rem|-etc] [-tran]"
" [-oat|-oas|-onl|-otl|-onr] [-lv] path rnum\n", g_progname);
eprintf(" %s queue [-th num] [-it num] [-rnd] [-oat|-oas|-onl|-otl|-onr] [-lv]"
" path rnum\n", g_progname);
eprintf(" %s wicked [-th num] [-it num] [-oat|-oas|-onl|-otl|-onr] [-lv]"
" path rnum\n", g_progname);
eprintf(" %s tran [-th num] [-it num] [-hard] [-oat|-oas|-onl|-otl|-onr] [-lv]"
" path rnum\n", g_progname);
eprintf(" %s mapred [-rnd] [-ru] [-oat|-oas|-onl|-otl|-onr] [-lv] [-tmp str]"
" [-dbnum num] [-clim num] [-cbnum num] [-xnl] [-xpm] [-xpr] [-xpf] [-xnc]"
" path rnum\n", g_progname);
eprintf(" %s index [-th num] [-rnd] [-set|-get|-rem|-etc]"
" [-oat|-oas|-onl|-otl|-onr] [-lv] path rnum\n", g_progname);
eprintf(" %s misc path\n", g_progname);
eprintf("\n");
std::exit(1);
}
// print the error message of a database
static void dberrprint(kc::BasicDB* db, int32_t line, const char* func) {
const kc::BasicDB::Error& err = db->error();
oprintf("%s: %d: %s: %s: %d: %s: %s\n",
g_progname, line, func, db->path().c_str(), err.code(), err.name(), err.message());
}
// print the error message of a database
static void dberrprint(kc::IndexDB* idb, int32_t line, const char* func) {
dberrprint(idb->reveal_inner_db(), line, func);
}
// print members of a database
static void dbmetaprint(kc::BasicDB* db, bool verbose) {
if (verbose) {
std::map status;
if (db->status(&status)) {
std::map::iterator it = status.begin();
std::map::iterator itend = status.end();
while (it != itend) {
oprintf("%s: %s\n", it->first.c_str(), it->second.c_str());
++it;
}
}
} else {
oprintf("count: %lld\n", (long long)db->count());
oprintf("size: %lld\n", (long long)db->size());
}
int64_t musage = memusage();
if (musage > 0) oprintf("memory: %lld\n", (long long)(musage - g_memusage));
}
// print members of a database
static void dbmetaprint(kc::IndexDB* db, bool verbose) {
if (verbose) {
std::map status;
if (db->status(&status)) {
std::map::iterator it = status.begin();
std::map::iterator itend = status.end();
while (it != itend) {
oprintf("%s: %s\n", it->first.c_str(), it->second.c_str());
++it;
}
}
} else {
oprintf("count: %lld\n", (long long)db->count());
oprintf("size: %lld\n", (long long)db->size());
}
int64_t musage = memusage();
if (musage > 0) oprintf("memory: %lld\n", (long long)(musage - g_memusage));
}
// parse arguments of order command
static int32_t runorder(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
const char* rstr = NULL;
int32_t thnum = 1;
bool rnd = false;
int32_t mode = 0;
bool tran = false;
int32_t oflags = 0;
bool lv = false;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-th")) {
if (++i >= argc) usage();
thnum = kc::atoix(argv[i]);
} else if (!std::strcmp(argv[i], "-rnd")) {
rnd = true;
} else if (!std::strcmp(argv[i], "-set")) {
mode = 's';
} else if (!std::strcmp(argv[i], "-get")) {
mode = 'g';
} else if (!std::strcmp(argv[i], "-getw")) {
mode = 'w';
} else if (!std::strcmp(argv[i], "-rem")) {
mode = 'r';
} else if (!std::strcmp(argv[i], "-etc")) {
mode = 'e';
} else if (!std::strcmp(argv[i], "-tran")) {
tran = true;
} else if (!std::strcmp(argv[i], "-oat")) {
oflags |= kc::PolyDB::OAUTOTRAN;
} else if (!std::strcmp(argv[i], "-oas")) {
oflags |= kc::PolyDB::OAUTOSYNC;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::PolyDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::PolyDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::PolyDB::ONOREPAIR;
} else if (!std::strcmp(argv[i], "-lv")) {
lv = true;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else if (!rstr) {
rstr = argv[i];
} else {
usage();
}
}
if (!path || !rstr) usage();
int64_t rnum = kc::atoix(rstr);
if (rnum < 1 || thnum < 1) usage();
if (thnum > THREADMAX) thnum = THREADMAX;
int32_t rv = procorder(path, rnum, thnum, rnd, mode, tran, oflags, lv);
return rv;
}
// parse arguments of queue command
static int32_t runqueue(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
const char* rstr = NULL;
int32_t thnum = 1;
int32_t itnum = 1;
bool rnd = false;
int32_t oflags = 0;
bool lv = false;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-th")) {
if (++i >= argc) usage();
thnum = kc::atoix(argv[i]);
} else if (!std::strcmp(argv[i], "-it")) {
if (++i >= argc) usage();
itnum = kc::atoix(argv[i]);
} else if (!std::strcmp(argv[i], "-rnd")) {
rnd = true;
} else if (!std::strcmp(argv[i], "-oat")) {
oflags |= kc::PolyDB::OAUTOTRAN;
} else if (!std::strcmp(argv[i], "-oas")) {
oflags |= kc::PolyDB::OAUTOSYNC;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::PolyDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::PolyDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::PolyDB::ONOREPAIR;
} else if (!std::strcmp(argv[i], "-lv")) {
lv = true;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else if (!rstr) {
rstr = argv[i];
} else {
usage();
}
}
if (!path || !rstr) usage();
int64_t rnum = kc::atoix(rstr);
if (rnum < 1 || thnum < 1 || itnum < 1) usage();
if (thnum > THREADMAX) thnum = THREADMAX;
int32_t rv = procqueue(path, rnum, thnum, itnum, rnd, oflags, lv);
return rv;
}
// parse arguments of wicked command
static int32_t runwicked(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
const char* rstr = NULL;
int32_t thnum = 1;
int32_t itnum = 1;
int32_t oflags = 0;
bool lv = false;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-th")) {
if (++i >= argc) usage();
thnum = kc::atoix(argv[i]);
} else if (!std::strcmp(argv[i], "-it")) {
if (++i >= argc) usage();
itnum = kc::atoix(argv[i]);
} else if (!std::strcmp(argv[i], "-oat")) {
oflags |= kc::PolyDB::OAUTOTRAN;
} else if (!std::strcmp(argv[i], "-oas")) {
oflags |= kc::PolyDB::OAUTOSYNC;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::PolyDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::PolyDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::PolyDB::ONOREPAIR;
} else if (!std::strcmp(argv[i], "-lv")) {
lv = true;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else if (!rstr) {
rstr = argv[i];
} else {
usage();
}
}
if (!path || !rstr) usage();
int64_t rnum = kc::atoix(rstr);
if (rnum < 1 || thnum < 1 || itnum < 1) usage();
if (thnum > THREADMAX) thnum = THREADMAX;
int32_t rv = procwicked(path, rnum, thnum, itnum, oflags, lv);
return rv;
}
// parse arguments of tran command
static int32_t runtran(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
const char* rstr = NULL;
int32_t thnum = 1;
int32_t itnum = 1;
bool hard = false;
int32_t oflags = 0;
bool lv = false;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-th")) {
if (++i >= argc) usage();
thnum = kc::atoix(argv[i]);
} else if (!std::strcmp(argv[i], "-it")) {
if (++i >= argc) usage();
itnum = kc::atoix(argv[i]);
} else if (!std::strcmp(argv[i], "-hard")) {
hard = true;
} else if (!std::strcmp(argv[i], "-oat")) {
oflags |= kc::PolyDB::OAUTOTRAN;
} else if (!std::strcmp(argv[i], "-oas")) {
oflags |= kc::PolyDB::OAUTOSYNC;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::PolyDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::PolyDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::PolyDB::ONOREPAIR;
} else if (!std::strcmp(argv[i], "-lv")) {
lv = true;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else if (!rstr) {
rstr = argv[i];
} else {
usage();
}
}
if (!path || !rstr) usage();
int64_t rnum = kc::atoix(rstr);
if (rnum < 1 || thnum < 1 || itnum < 1) usage();
if (thnum > THREADMAX) thnum = THREADMAX;
int32_t rv = proctran(path, rnum, thnum, itnum, hard, oflags, lv);
return rv;
}
// parse arguments of mapred command
static int32_t runmapred(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
const char* rstr = NULL;
bool rnd = false;
bool ru = false;
int32_t oflags = 0;
bool lv = false;
const char* tmpdir = "";
int64_t dbnum = -1;
int64_t clim = -1;
int64_t cbnum = -1;
int32_t opts = 0;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-rnd")) {
rnd = true;
} else if (!std::strcmp(argv[i], "-ru")) {
ru = true;
} else if (!std::strcmp(argv[i], "-oat")) {
oflags |= kc::PolyDB::OAUTOTRAN;
} else if (!std::strcmp(argv[i], "-oas")) {
oflags |= kc::PolyDB::OAUTOSYNC;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::PolyDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::PolyDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::PolyDB::ONOREPAIR;
} else if (!std::strcmp(argv[i], "-lv")) {
lv = true;
} else if (!std::strcmp(argv[i], "-tmp")) {
if (++i >= argc) usage();
tmpdir = argv[i];
} else if (!std::strcmp(argv[i], "-dbnum")) {
if (++i >= argc) usage();
dbnum = kc::atoix(argv[i]);
} else if (!std::strcmp(argv[i], "-clim")) {
if (++i >= argc) usage();
clim = kc::atoix(argv[i]);
} else if (!std::strcmp(argv[i], "-cbnum")) {
if (++i >= argc) usage();
cbnum = kc::atoix(argv[i]);
} else if (!std::strcmp(argv[i], "-xnl")) {
opts |= kc::MapReduce::XNOLOCK;
} else if (!std::strcmp(argv[i], "-xpm")) {
opts |= kc::MapReduce::XPARAMAP;
} else if (!std::strcmp(argv[i], "-xpr")) {
opts |= kc::MapReduce::XPARARED;
} else if (!std::strcmp(argv[i], "-xpf")) {
opts |= kc::MapReduce::XPARAFLS;
} else if (!std::strcmp(argv[i], "-xnc")) {
opts |= kc::MapReduce::XNOCOMP;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else if (!rstr) {
rstr = argv[i];
} else {
usage();
}
}
if (!path || !rstr) usage();
int64_t rnum = kc::atoix(rstr);
if (rnum < 1) usage();
int32_t rv = procmapred(path, rnum, rnd, ru, oflags, lv, tmpdir, dbnum, clim, cbnum, opts);
return rv;
}
// parse arguments of index command
static int32_t runindex(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
const char* rstr = NULL;
int32_t thnum = 1;
bool rnd = false;
int32_t mode = 0;
int32_t oflags = 0;
bool lv = false;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-th")) {
if (++i >= argc) usage();
thnum = kc::atoix(argv[i]);
} else if (!std::strcmp(argv[i], "-rnd")) {
rnd = true;
} else if (!std::strcmp(argv[i], "-set")) {
mode = 's';
} else if (!std::strcmp(argv[i], "-get")) {
mode = 'g';
} else if (!std::strcmp(argv[i], "-rem")) {
mode = 'r';
} else if (!std::strcmp(argv[i], "-etc")) {
mode = 'e';
} else if (!std::strcmp(argv[i], "-oat")) {
oflags |= kc::PolyDB::OAUTOTRAN;
} else if (!std::strcmp(argv[i], "-oas")) {
oflags |= kc::PolyDB::OAUTOSYNC;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::PolyDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::PolyDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::PolyDB::ONOREPAIR;
} else if (!std::strcmp(argv[i], "-lv")) {
lv = true;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else if (!rstr) {
rstr = argv[i];
} else {
usage();
}
}
if (!path || !rstr) usage();
int64_t rnum = kc::atoix(rstr);
if (rnum < 1 || thnum < 1) usage();
int32_t rv = procindex(path, rnum, thnum, rnd, mode, oflags, lv);
return rv;
}
// parse arguments of misc command
static int32_t runmisc(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else usage();
} else if (!path) {
argbrk = true;
path = argv[i];
} else {
usage();
}
}
if (!path) usage();
int32_t rv = procmisc(path);
return rv;
}
// perform order command
static int32_t procorder(const char* path, int64_t rnum, int32_t thnum, bool rnd, int32_t mode,
bool tran, int32_t oflags, bool lv) {
oprintf("\n seed=%u path=%s rnum=%lld thnum=%d rnd=%d mode=%d tran=%d"
" oflags=%d lv=%d\n\n",
g_randseed, path, (long long)rnum, thnum, rnd, mode, tran, oflags, lv);
bool err = false;
kc::PolyDB db;
oprintf("opening the database:\n");
double stime = kc::time();
db.tune_logger(stdlogger(g_progname, &std::cout),
lv ? kc::UINT32MAX : kc::BasicDB::Logger::WARN | kc::BasicDB::Logger::ERROR);
uint32_t omode = kc::PolyDB::OWRITER | kc::PolyDB::OCREATE | kc::PolyDB::OTRUNCATE;
if (mode == 'r') {
omode = kc::PolyDB::OWRITER | kc::PolyDB::OCREATE;
} else if (mode == 'g' || mode == 'w') {
omode = kc::PolyDB::OREADER;
}
if (!db.open(path, omode | oflags)) {
dberrprint(&db, __LINE__, "DB::open");
err = true;
}
double etime = kc::time();
dbmetaprint(&db, false);
oprintf("time: %.3f\n", etime - stime);
if (mode == 0 || mode == 's' || mode == 'e') {
oprintf("setting records:\n");
stime = kc::time();
class ThreadSet : public kc::Thread {
public:
void setparams(int32_t id, kc::BasicDB* db, int64_t rnum, int32_t thnum,
bool rnd, bool tran) {
id_ = id;
db_ = db;
rnum_ = rnum;
thnum_ = thnum;
err_ = false;
rnd_ = rnd;
tran_ = tran;
}
bool error() {
return err_;
}
void run() {
int64_t base = id_ * rnum_;
int64_t range = rnum_ * thnum_;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
if (tran_ && !db_->begin_transaction(false)) {
dberrprint(db_, __LINE__, "DB::begin_transaction");
err_ = true;
}
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld",
(long long)(rnd_ ? myrand(range) + 1 : base + i));
if (!db_->set(kbuf, ksiz, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::set");
err_ = true;
}
if (rnd_ && i % 8 == 0) {
switch (myrand(8)) {
case 0: {
if (!db_->set(kbuf, ksiz, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::set");
err_ = true;
}
break;
}
case 1: {
if (!db_->append(kbuf, ksiz, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::append");
err_ = true;
}
break;
}
case 2: {
if (!db_->remove(kbuf, ksiz) && db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::remove");
err_ = true;
}
break;
}
case 3: {
kc::DB::Cursor* cur = db_->cursor();
if (cur->jump(kbuf, ksiz)) {
switch (myrand(8)) {
default: {
size_t rsiz;
char* rbuf = cur->get_key(&rsiz, myrand(10) == 0);
if (rbuf) {
delete[] rbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get_key");
err_ = true;
}
break;
}
case 1: {
size_t rsiz;
char* rbuf = cur->get_value(&rsiz, myrand(10) == 0);
if (rbuf) {
delete[] rbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get_value");
err_ = true;
}
break;
}
case 2: {
size_t rksiz;
const char* rvbuf;
size_t rvsiz;
char* rkbuf = cur->get(&rksiz, &rvbuf, &rvsiz, myrand(10) == 0);
if (rkbuf) {
delete[] rkbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get");
err_ = true;
}
break;
}
case 3: {
std::string key, value;
if (!cur->get(&key, &value, myrand(10) == 0) &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get");
err_ = true;
}
break;
}
case 4: {
if (myrand(8) == 0 && !cur->remove() &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::remove");
err_ = true;
}
break;
}
}
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::jump");
err_ = true;
}
delete cur;
break;
}
default: {
size_t vsiz;
char* vbuf = db_->get(kbuf, ksiz, &vsiz);
if (vbuf) {
delete[] vbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::get");
err_ = true;
}
break;
}
}
}
if (tran_ && !db_->end_transaction(true)) {
dberrprint(db_, __LINE__, "DB::end_transaction");
err_ = true;
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::BasicDB* db_;
int64_t rnum_;
int32_t thnum_;
bool err_;
bool rnd_;
bool tran_;
};
ThreadSet threadsets[THREADMAX];
if (thnum < 2) {
threadsets[0].setparams(0, &db, rnum, thnum, rnd, tran);
threadsets[0].run();
if (threadsets[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threadsets[i].setparams(i, &db, rnum, thnum, rnd, tran);
threadsets[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadsets[i].join();
if (threadsets[i].error()) err = true;
}
}
etime = kc::time();
dbmetaprint(&db, mode == 's');
oprintf("time: %.3f\n", etime - stime);
}
if (mode == 'e') {
oprintf("adding records:\n");
stime = kc::time();
class ThreadAdd : public kc::Thread {
public:
void setparams(int32_t id, kc::BasicDB* db, int64_t rnum, int32_t thnum,
bool rnd, bool tran) {
id_ = id;
db_ = db;
rnum_ = rnum;
thnum_ = thnum;
err_ = false;
rnd_ = rnd;
tran_ = tran;
}
bool error() {
return err_;
}
void run() {
int64_t base = id_ * rnum_;
int64_t range = rnum_ * thnum_;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
if (tran_ && !db_->begin_transaction(false)) {
dberrprint(db_, __LINE__, "DB::begin_transaction");
err_ = true;
}
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld",
(long long)(rnd_ ? myrand(range) + 1 : base + i));
if (!db_->add(kbuf, ksiz, kbuf, ksiz) &&
db_->error() != kc::BasicDB::Error::DUPREC) {
dberrprint(db_, __LINE__, "DB::add");
err_ = true;
}
if (tran_ && !db_->end_transaction(true)) {
dberrprint(db_, __LINE__, "DB::end_transaction");
err_ = true;
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::BasicDB* db_;
int64_t rnum_;
int32_t thnum_;
bool err_;
bool rnd_;
bool tran_;
};
ThreadAdd threadadds[THREADMAX];
if (thnum < 2) {
threadadds[0].setparams(0, &db, rnum, thnum, rnd, tran);
threadadds[0].run();
if (threadadds[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threadadds[i].setparams(i, &db, rnum, thnum, rnd, tran);
threadadds[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadadds[i].join();
if (threadadds[i].error()) err = true;
}
}
etime = kc::time();
dbmetaprint(&db, false);
oprintf("time: %.3f\n", etime - stime);
}
if (mode == 'e') {
oprintf("appending records:\n");
stime = kc::time();
class ThreadAppend : public kc::Thread {
public:
void setparams(int32_t id, kc::BasicDB* db, int64_t rnum, int32_t thnum,
bool rnd, bool tran) {
id_ = id;
db_ = db;
rnum_ = rnum;
thnum_ = thnum;
err_ = false;
rnd_ = rnd;
tran_ = tran;
}
bool error() {
return err_;
}
void run() {
int64_t base = id_ * rnum_;
int64_t range = rnum_ * thnum_;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
if (tran_ && !db_->begin_transaction(false)) {
dberrprint(db_, __LINE__, "DB::begin_transaction");
err_ = true;
}
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld",
(long long)(rnd_ ? myrand(range) + 1 : base + i));
if (!db_->append(kbuf, ksiz, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::append");
err_ = true;
}
if (tran_ && !db_->end_transaction(true)) {
dberrprint(db_, __LINE__, "DB::end_transaction");
err_ = true;
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::BasicDB* db_;
int64_t rnum_;
int32_t thnum_;
bool err_;
bool rnd_;
bool tran_;
};
ThreadAppend threadappends[THREADMAX];
if (thnum < 2) {
threadappends[0].setparams(0, &db, rnum, thnum, rnd, tran);
threadappends[0].run();
if (threadappends[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threadappends[i].setparams(i, &db, rnum, thnum, rnd, tran);
threadappends[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadappends[i].join();
if (threadappends[i].error()) err = true;
}
}
etime = kc::time();
dbmetaprint(&db, false);
oprintf("time: %.3f\n", etime - stime);
}
if (mode == 0 || mode == 'g' || mode == 'e') {
oprintf("getting records:\n");
stime = kc::time();
class ThreadGet : public kc::Thread {
public:
void setparams(int32_t id, kc::BasicDB* db, int64_t rnum, int32_t thnum,
bool rnd, bool tran) {
id_ = id;
db_ = db;
rnum_ = rnum;
thnum_ = thnum;
err_ = false;
rnd_ = rnd;
tran_ = tran;
}
bool error() {
return err_;
}
void run() {
int64_t base = id_ * rnum_;
int64_t range = rnum_ * thnum_;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
if (tran_ && !db_->begin_transaction(false)) {
dberrprint(db_, __LINE__, "DB::begin_transaction");
err_ = true;
}
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld",
(long long)(rnd_ ? myrand(range) + 1 : base + i));
size_t vsiz;
char* vbuf = db_->get(kbuf, ksiz, &vsiz);
if (vbuf) {
if (vsiz < ksiz || std::memcmp(vbuf, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::get");
err_ = true;
}
delete[] vbuf;
} else if (!rnd_ || db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::get");
err_ = true;
}
if (rnd_ && i % 8 == 0) {
switch (myrand(8)) {
case 0: {
if (!db_->set(kbuf, ksiz, kbuf, ksiz) &&
db_->error() != kc::BasicDB::Error::NOPERM) {
dberrprint(db_, __LINE__, "DB::set");
err_ = true;
}
break;
}
case 1: {
if (!db_->append(kbuf, ksiz, kbuf, ksiz) &&
db_->error() != kc::BasicDB::Error::NOPERM) {
dberrprint(db_, __LINE__, "DB::append");
err_ = true;
}
break;
}
case 2: {
if (!db_->remove(kbuf, ksiz) &&
db_->error() != kc::BasicDB::Error::NOPERM &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::remove");
err_ = true;
}
break;
}
case 3: {
kc::DB::Cursor* cur = db_->cursor();
if (cur->jump(kbuf, ksiz)) {
switch (myrand(8)) {
default: {
size_t rsiz;
char* rbuf = cur->get_key(&rsiz, myrand(10) == 0);
if (rbuf) {
delete[] rbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get_key");
err_ = true;
}
break;
}
case 1: {
size_t rsiz;
char* rbuf = cur->get_value(&rsiz, myrand(10) == 0);
if (rbuf) {
delete[] rbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get_value");
err_ = true;
}
break;
}
case 2: {
size_t rksiz;
const char* rvbuf;
size_t rvsiz;
char* rkbuf = cur->get(&rksiz, &rvbuf, &rvsiz, myrand(10) == 0);
if (rkbuf) {
delete[] rkbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get");
err_ = true;
}
break;
}
case 3: {
std::string key, value;
if (!cur->get(&key, &value, myrand(10) == 0) &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get");
err_ = true;
}
break;
}
case 4: {
if (myrand(8) == 0 && !cur->remove() &&
db_->error() != kc::BasicDB::Error::NOPERM &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::remove");
err_ = true;
}
break;
}
}
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::jump");
err_ = true;
}
delete cur;
break;
}
default: {
size_t vsiz;
char* vbuf = db_->get(kbuf, ksiz, &vsiz);
if (vbuf) {
delete[] vbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::get");
err_ = true;
}
break;
}
}
}
if (tran_ && !db_->end_transaction(true)) {
dberrprint(db_, __LINE__, "DB::end_transaction");
err_ = true;
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::BasicDB* db_;
int64_t rnum_;
int32_t thnum_;
bool err_;
bool rnd_;
bool tran_;
};
ThreadGet threadgets[THREADMAX];
if (thnum < 2) {
threadgets[0].setparams(0, &db, rnum, thnum, rnd, tran);
threadgets[0].run();
if (threadgets[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threadgets[i].setparams(i, &db, rnum, thnum, rnd, tran);
threadgets[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadgets[i].join();
if (threadgets[i].error()) err = true;
}
}
etime = kc::time();
dbmetaprint(&db, mode == 'g');
oprintf("time: %.3f\n", etime - stime);
}
if (mode == 'w' || mode == 'e') {
oprintf("getting records with a buffer:\n");
stime = kc::time();
class ThreadGetBuffer : public kc::Thread {
public:
void setparams(int32_t id, kc::BasicDB* db, int64_t rnum, int32_t thnum,
bool rnd, bool tran) {
id_ = id;
db_ = db;
rnum_ = rnum;
thnum_ = thnum;
err_ = false;
rnd_ = rnd;
tran_ = tran;
}
bool error() {
return err_;
}
void run() {
int64_t base = id_ * rnum_;
int64_t range = rnum_ * thnum_;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
if (tran_ && !db_->begin_transaction(false)) {
dberrprint(db_, __LINE__, "DB::begin_transaction");
err_ = true;
}
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld",
(long long)(rnd_ ? myrand(range) + 1 : base + i));
char vbuf[RECBUFSIZ];
int32_t vsiz = db_->get(kbuf, ksiz, vbuf, sizeof(vbuf));
if (vsiz >= 0) {
if (vsiz < (int32_t)ksiz || std::memcmp(vbuf, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::get");
err_ = true;
}
} else if (!rnd_ || db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::get");
err_ = true;
}
if (tran_ && !db_->end_transaction(true)) {
dberrprint(db_, __LINE__, "DB::end_transaction");
err_ = true;
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::BasicDB* db_;
int64_t rnum_;
int32_t thnum_;
bool err_;
bool rnd_;
bool tran_;
};
ThreadGetBuffer threadgetbuffers[THREADMAX];
if (thnum < 2) {
threadgetbuffers[0].setparams(0, &db, rnum, thnum, rnd, tran);
threadgetbuffers[0].run();
if (threadgetbuffers[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threadgetbuffers[i].setparams(i, &db, rnum, thnum, rnd, tran);
threadgetbuffers[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadgetbuffers[i].join();
if (threadgetbuffers[i].error()) err = true;
}
}
etime = kc::time();
dbmetaprint(&db, mode == 'w');
oprintf("time: %.3f\n", etime - stime);
}
if (mode == 'e') {
oprintf("traversing the database by the inner iterator:\n");
stime = kc::time();
int64_t cnt = db.count();
class VisitorIterator : public kc::DB::Visitor {
public:
explicit VisitorIterator(int64_t rnum, bool rnd) :
rnum_(rnum), rnd_(rnd), cnt_(0), rbuf_() {
std::memset(rbuf_, '+', sizeof(rbuf_));
}
int64_t cnt() {
return cnt_;
}
private:
const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) {
cnt_++;
const char* rv = NOP;
switch (rnd_ ? myrand(7) : cnt_ % 7) {
case 0: {
rv = rbuf_;
*sp = rnd_ ? myrand(sizeof(rbuf_)) : sizeof(rbuf_) / (cnt_ % 5 + 1);
break;
}
case 1: {
rv = REMOVE;
break;
}
}
if (rnum_ > 250 && cnt_ % (rnum_ / 250) == 0) {
oputchar('.');
if (cnt_ == rnum_ || cnt_ % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)cnt_);
}
return rv;
}
int64_t rnum_;
bool rnd_;
int64_t cnt_;
char rbuf_[RECBUFSIZ];
} visitoriterator(rnum, rnd);
if (tran && !db.begin_transaction(false)) {
dberrprint(&db, __LINE__, "DB::begin_transaction");
err = true;
}
if (!db.iterate(&visitoriterator, true)) {
dberrprint(&db, __LINE__, "DB::iterate");
err = true;
}
if (rnd) oprintf(" (end)\n");
if (tran && !db.end_transaction(true)) {
dberrprint(&db, __LINE__, "DB::end_transaction");
err = true;
}
if (visitoriterator.cnt() != cnt) {
dberrprint(&db, __LINE__, "DB::iterate");
err = true;
}
etime = kc::time();
dbmetaprint(&db, false);
oprintf("time: %.3f\n", etime - stime);
}
if (mode == 'e') {
oprintf("traversing the database by the outer cursor:\n");
stime = kc::time();
int64_t cnt = db.count();
class VisitorCursor : public kc::DB::Visitor {
public:
explicit VisitorCursor(int64_t rnum, bool rnd) :
rnum_(rnum), rnd_(rnd), cnt_(0), rbuf_() {
std::memset(rbuf_, '-', sizeof(rbuf_));
}
int64_t cnt() {
return cnt_;
}
private:
const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) {
cnt_++;
const char* rv = NOP;
switch (rnd_ ? myrand(7) : cnt_ % 7) {
case 0: {
rv = rbuf_;
*sp = rnd_ ? myrand(sizeof(rbuf_)) : sizeof(rbuf_) / (cnt_ % 5 + 1);
break;
}
case 1: {
rv = REMOVE;
break;
}
}
if (rnum_ > 250 && cnt_ % (rnum_ / 250) == 0) {
oputchar('.');
if (cnt_ == rnum_ || cnt_ % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)cnt_);
}
return rv;
}
int64_t rnum_;
bool rnd_;
int64_t cnt_;
char rbuf_[RECBUFSIZ];
} visitorcursor(rnum, rnd);
if (tran && !db.begin_transaction(false)) {
dberrprint(&db, __LINE__, "DB::begin_transaction");
err = true;
}
kc::PolyDB::Cursor cur(&db);
if (!cur.jump() && db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, __LINE__, "Cursor::jump");
err = true;
}
kc::DB::Cursor* paracur = db.cursor();
int64_t range = rnum * thnum;
while (!err && cur.accept(&visitorcursor, true, !rnd)) {
if (rnd) {
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld", (long long)myrand(range));
switch (myrand(3)) {
case 0: {
if (!db.remove(kbuf, ksiz) && db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, __LINE__, "DB::remove");
err = true;
}
break;
}
case 1: {
if (!paracur->jump(kbuf, ksiz) && db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, __LINE__, "Cursor::jump");
err = true;
}
break;
}
default: {
if (!cur.step() && db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, __LINE__, "Cursor::step");
err = true;
}
break;
}
}
}
}
if (db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, __LINE__, "Cursor::accept");
err = true;
}
oprintf(" (end)\n");
delete paracur;
if (tran && !db.end_transaction(true)) {
dberrprint(&db, __LINE__, "DB::end_transaction");
err = true;
}
if (!rnd && visitorcursor.cnt() != cnt) {
dberrprint(&db, __LINE__, "Cursor::accept");
err = true;
}
etime = kc::time();
dbmetaprint(&db, false);
oprintf("time: %.3f\n", etime - stime);
}
if (mode == 'e') {
oprintf("synchronizing the database:\n");
stime = kc::time();
if (!db.synchronize(false, NULL)) {
dberrprint(&db, __LINE__, "DB::synchronize");
err = true;
}
class SyncProcessor : public kc::BasicDB::FileProcessor {
public:
explicit SyncProcessor(int64_t size) : size_(size) {}
private:
bool process(const std::string& path, int64_t count, int64_t size) {
if (size != size_) return false;
return true;
}
int64_t rnum_;
bool rnd_;
int64_t size_;
int64_t msiz_;
} syncprocessor(db.size());
if (!db.synchronize(false, &syncprocessor)) {
dberrprint(&db, __LINE__, "DB::synchronize");
err = true;
}
if (!db.occupy(rnd ? myrand(2) == 0 : true, &syncprocessor)) {
dberrprint(&db, __LINE__, "DB::occupy");
err = true;
}
etime = kc::time();
dbmetaprint(&db, false);
oprintf("time: %.3f\n", etime - stime);
}
if (mode == 'e' && db.size() < (256LL << 20)) {
oprintf("dumping records into snapshot:\n");
stime = kc::time();
std::ostringstream ostrm;
if (!db.dump_snapshot(&ostrm)) {
dberrprint(&db, __LINE__, "DB::dump_snapshot");
err = true;
}
etime = kc::time();
dbmetaprint(&db, false);
oprintf("time: %.3f\n", etime - stime);
oprintf("loading records from snapshot:\n");
stime = kc::time();
int64_t cnt = db.count();
if (rnd && myrand(2) == 0 && !db.clear()) {
dberrprint(&db, __LINE__, "DB::clear");
err = true;
}
const std::string& str = ostrm.str();
std::istringstream istrm(str);
if (!db.load_snapshot(&istrm) || db.count() != cnt) {
dberrprint(&db, __LINE__, "DB::load_snapshot");
err = true;
}
etime = kc::time();
dbmetaprint(&db, false);
oprintf("time: %.3f\n", etime - stime);
}
if (mode == 0 || mode == 'r' || mode == 'e') {
oprintf("removing records:\n");
stime = kc::time();
class ThreadRemove : public kc::Thread {
public:
void setparams(int32_t id, kc::BasicDB* db, int64_t rnum, int32_t thnum,
bool rnd, int32_t mode, bool tran) {
id_ = id;
db_ = db;
rnum_ = rnum;
thnum_ = thnum;
err_ = false;
rnd_ = rnd;
mode_ = mode;
tran_ = tran;
}
bool error() {
return err_;
}
void run() {
int64_t base = id_ * rnum_;
int64_t range = rnum_ * thnum_;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
if (tran_ && !db_->begin_transaction(false)) {
dberrprint(db_, __LINE__, "DB::begin_transaction");
err_ = true;
}
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld",
(long long)(rnd_ ? myrand(range) + 1 : base + i));
if (!db_->remove(kbuf, ksiz) &&
((!rnd_ && mode_ != 'e') || db_->error() != kc::BasicDB::Error::NOREC)) {
dberrprint(db_, __LINE__, "DB::remove");
err_ = true;
}
if (rnd_ && i % 8 == 0) {
switch (myrand(8)) {
case 0: {
if (!db_->set(kbuf, ksiz, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::set");
err_ = true;
}
break;
}
case 1: {
if (!db_->append(kbuf, ksiz, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::append");
err_ = true;
}
break;
}
case 2: {
if (!db_->remove(kbuf, ksiz) &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::remove");
err_ = true;
}
break;
}
case 3: {
kc::DB::Cursor* cur = db_->cursor();
if (cur->jump(kbuf, ksiz)) {
switch (myrand(8)) {
default: {
size_t rsiz;
char* rbuf = cur->get_key(&rsiz, myrand(10) == 0);
if (rbuf) {
delete[] rbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get_key");
err_ = true;
}
break;
}
case 1: {
size_t rsiz;
char* rbuf = cur->get_value(&rsiz, myrand(10) == 0);
if (rbuf) {
delete[] rbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get_value");
err_ = true;
}
break;
}
case 2: {
size_t rksiz;
const char* rvbuf;
size_t rvsiz;
char* rkbuf = cur->get(&rksiz, &rvbuf, &rvsiz, myrand(10) == 0);
if (rkbuf) {
delete[] rkbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get");
err_ = true;
}
break;
}
case 3: {
std::string key, value;
if (!cur->get(&key, &value, myrand(10) == 0) &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get");
err_ = true;
}
break;
}
case 4: {
if (myrand(8) == 0 && !cur->remove() &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::remove");
err_ = true;
}
break;
}
}
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::jump");
err_ = true;
}
delete cur;
break;
}
default: {
size_t vsiz;
char* vbuf = db_->get(kbuf, ksiz, &vsiz);
if (vbuf) {
delete[] vbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::get");
err_ = true;
}
break;
}
}
}
if (tran_ && !db_->end_transaction(true)) {
dberrprint(db_, __LINE__, "DB::end_transaction");
err_ = true;
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::BasicDB* db_;
int64_t rnum_;
int32_t thnum_;
bool err_;
bool rnd_;
int32_t mode_;
bool tran_;
};
ThreadRemove threadremoves[THREADMAX];
if (thnum < 2) {
threadremoves[0].setparams(0, &db, rnum, thnum, rnd, mode, tran);
threadremoves[0].run();
if (threadremoves[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threadremoves[i].setparams(i, &db, rnum, thnum, rnd, mode, tran);
threadremoves[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadremoves[i].join();
if (threadremoves[i].error()) err = true;
}
}
etime = kc::time();
dbmetaprint(&db, mode == 'r' || mode == 'e');
oprintf("time: %.3f\n", etime - stime);
}
oprintf("closing the database:\n");
stime = kc::time();
if (!db.close()) {
dberrprint(&db, __LINE__, "DB::close");
err = true;
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("%s\n\n", err ? "error" : "ok");
return err ? 1 : 0;
}
// perform queue command
static int32_t procqueue(const char* path, int64_t rnum, int32_t thnum, int32_t itnum, bool rnd,
int32_t oflags, bool lv) {
oprintf("\n seed=%u path=%s rnum=%lld thnum=%d itnum=%d rnd=%d"
" oflags=%d lv=%d\n\n",
g_randseed, path, (long long)rnum, thnum, itnum, rnd, oflags, lv);
bool err = false;
kc::PolyDB db;
db.tune_logger(stdlogger(g_progname, &std::cout),
lv ? kc::UINT32MAX : kc::BasicDB::Logger::WARN | kc::BasicDB::Logger::ERROR);
for (int32_t itcnt = 1; itcnt <= itnum; itcnt++) {
if (itnum > 1) oprintf("iteration %d:\n", itcnt);
double stime = kc::time();
uint32_t omode = kc::PolyDB::OWRITER | kc::PolyDB::OCREATE;
if (itcnt == 1) omode |= kc::PolyDB::OTRUNCATE;
if (!db.open(path, omode)) {
dberrprint(&db, __LINE__, "DB::open");
err = true;
}
class ThreadQueue : public kc::Thread {
public:
void setparams(int32_t id, kc::PolyDB* db, int64_t rnum, int32_t thnum, bool rnd,
int64_t width) {
id_ = id;
db_ = db;
rnum_ = rnum;
thnum_ = thnum;
rnd_ = rnd;
width_ = width;
err_ = false;
}
bool error() {
return err_;
}
void run() {
kc::DB::Cursor* cur = db_->cursor();
int64_t base = id_ * rnum_;
int64_t range = rnum_ * thnum_;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%010lld", (long long)(base + i));
if (!db_->set(kbuf, ksiz, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::set");
err_ = true;
}
if (rnd_) {
if (myrand(width_ / 2) == 0) {
if (!cur->jump() && db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::jump");
err_ = true;
}
ksiz = std::sprintf(kbuf, "%010lld", (long long)myrand(range) + 1);
switch (myrand(10)) {
case 0: {
if (!db_->set(kbuf, ksiz, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::set");
err_ = true;
}
break;
}
case 1: {
if (!db_->append(kbuf, ksiz, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::append");
err_ = true;
}
break;
}
case 2: {
if (!db_->remove(kbuf, ksiz) &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::remove");
err_ = true;
}
break;
}
}
int64_t dnum = myrand(width_) + 2;
for (int64_t j = 0; j < dnum; j++) {
if (!cur->remove() && db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::remove");
err_ = true;
}
}
}
} else {
if (i > width_) {
if (!cur->jump() && db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::jump");
err_ = true;
}
if (!cur->remove() && db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::remove");
err_ = true;
}
}
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
delete cur;
}
private:
int32_t id_;
kc::PolyDB* db_;
int64_t rnum_;
int32_t thnum_;
bool rnd_;
int64_t width_;
bool err_;
};
int64_t width = rnum / 10;
ThreadQueue threads[THREADMAX];
if (thnum < 2) {
threads[0].setparams(0, &db, rnum, thnum, rnd, width);
threads[0].run();
if (threads[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threads[i].setparams(i, &db, rnum, thnum, rnd, width);
threads[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threads[i].join();
if (threads[i].error()) err = true;
}
}
int64_t count = db.count();
if (!rnd && itcnt == 1 && count != width * thnum) {
dberrprint(&db, __LINE__, "DB::count");
err = true;
}
if ((rnd ? (myrand(2) == 0) : itcnt == itnum) && count > 0) {
kc::DB::Cursor* cur = db.cursor();
if (!cur->jump()) {
dberrprint(&db, __LINE__, "Cursor::jump");
err = true;
}
for (int64_t i = 1; i <= count; i++) {
if (!cur->remove()) {
dberrprint(&db, __LINE__, "Cursor::jump");
err = true;
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
if (rnd) oprintf(" (end)\n");
delete cur;
if (db.count() != 0) {
dberrprint(&db, __LINE__, "DB::count");
err = true;
}
}
dbmetaprint(&db, itcnt == itnum);
if (!db.close()) {
dberrprint(&db, __LINE__, "DB::close");
err = true;
}
oprintf("time: %.3f\n", kc::time() - stime);
}
oprintf("%s\n\n", err ? "error" : "ok");
return err ? 1 : 0;
}
// perform wicked command
static int32_t procwicked(const char* path, int64_t rnum, int32_t thnum, int32_t itnum,
int32_t oflags, bool lv) {
oprintf("\n seed=%u path=%s rnum=%lld thnum=%d itnum=%d"
" oflags=%d lv=%d\n\n",
g_randseed, path, (long long)rnum, thnum, itnum, oflags, lv);
bool err = false;
kc::PolyDB db;
db.tune_logger(stdlogger(g_progname, &std::cout),
lv ? kc::UINT32MAX : kc::BasicDB::Logger::WARN | kc::BasicDB::Logger::ERROR);
for (int32_t itcnt = 1; itcnt <= itnum; itcnt++) {
if (itnum > 1) oprintf("iteration %d:\n", itcnt);
double stime = kc::time();
uint32_t omode = kc::PolyDB::OWRITER | kc::PolyDB::OCREATE;
if (itcnt == 1) omode |= kc::PolyDB::OTRUNCATE;
if (!db.open(path, omode | oflags)) {
dberrprint(&db, __LINE__, "DB::open");
err = true;
}
class ThreadWicked : public kc::Thread {
public:
void setparams(int32_t id, kc::PolyDB* db, int64_t rnum, int32_t thnum,
const char* lbuf) {
id_ = id;
db_ = db;
rnum_ = rnum;
thnum_ = thnum;
lbuf_ = lbuf;
err_ = false;
}
bool error() {
return err_;
}
void run() {
kc::DB::Cursor* cur = db_->cursor();
int64_t range = rnum_ * thnum_ / 2;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
bool tran = myrand(100) == 0;
if (tran) {
if (myrand(2) == 0) {
if (!db_->begin_transaction(myrand(rnum_) == 0)) {
if (db_->error() != kc::BasicDB::Error::NOIMPL) {
dberrprint(db_, __LINE__, "DB::begin_transaction");
tran = false;
err_ = true;
}
tran = false;
}
} else {
if (!db_->begin_transaction_try(myrand(rnum_) == 0)) {
if (db_->error() != kc::BasicDB::Error::LOGIC &&
db_->error() != kc::BasicDB::Error::NOIMPL) {
dberrprint(db_, __LINE__, "DB::begin_transaction_try");
err_ = true;
}
tran = false;
}
}
}
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%lld", (long long)(myrand(range) + 1));
if (myrand(1000) == 0) {
ksiz = myrand(RECBUFSIZ) + 1;
if (myrand(2) == 0) {
for (size_t j = 0; j < ksiz; j++) {
kbuf[j] = j;
}
} else {
for (size_t j = 0; j < ksiz; j++) {
kbuf[j] = myrand(256);
}
}
}
const char* vbuf = kbuf;
size_t vsiz = ksiz;
if (myrand(10) == 0) {
vbuf = lbuf_;
vsiz = myrand(RECBUFSIZL) / (myrand(5) + 1);
}
do {
switch (myrand(10)) {
case 0: {
if (!db_->set(kbuf, ksiz, vbuf, vsiz)) {
dberrprint(db_, __LINE__, "DB::set");
err_ = true;
}
break;
}
case 1: {
if (!db_->add(kbuf, ksiz, vbuf, vsiz) &&
db_->error() != kc::BasicDB::Error::DUPREC) {
dberrprint(db_, __LINE__, "DB::add");
err_ = true;
}
break;
}
case 2: {
if (!db_->replace(kbuf, ksiz, vbuf, vsiz) &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::replace");
err_ = true;
}
break;
}
case 3: {
if (!db_->append(kbuf, ksiz, vbuf, vsiz)) {
dberrprint(db_, __LINE__, "DB::append");
err_ = true;
}
break;
}
case 4: {
if (myrand(2) == 0) {
int64_t num = myrand(rnum_);
int64_t orig = myrand(10) == 0 ? kc::INT64MIN : myrand(rnum_);
if (myrand(10) == 0) orig = orig == kc::INT64MIN ? kc::INT64MAX : -orig;
if (db_->increment(kbuf, ksiz, num, orig) == kc::INT64MIN &&
db_->error() != kc::BasicDB::Error::LOGIC) {
dberrprint(db_, __LINE__, "DB::increment");
err_ = true;
}
} else {
double num = myrand(rnum_ * 10) / (myrand(rnum_) + 1.0);
double orig = myrand(10) == 0 ? -kc::inf() : myrand(rnum_);
if (myrand(10) == 0) orig = -orig;
if (kc::chknan(db_->increment_double(kbuf, ksiz, num, orig)) &&
db_->error() != kc::BasicDB::Error::LOGIC) {
dberrprint(db_, __LINE__, "DB::increment_double");
err_ = true;
}
}
break;
}
case 5: {
if (!db_->cas(kbuf, ksiz, kbuf, ksiz, vbuf, vsiz) &&
db_->error() != kc::BasicDB::Error::LOGIC) {
dberrprint(db_, __LINE__, "DB::cas");
err_ = true;
}
break;
}
case 6: {
if (!db_->remove(kbuf, ksiz) &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::remove");
err_ = true;
}
break;
}
case 7: {
if (myrand(2) == 0) {
if (db_->check(kbuf, ksiz) < 0 && db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::check");
err_ = true;
}
} else {
size_t rsiz;
char* rbuf = db_->seize(kbuf, ksiz, &rsiz);
if (rbuf) {
delete[] rbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::seize");
err_ = true;
}
}
break;
}
case 8: {
if (myrand(10) == 0) {
if (myrand(4) == 0) {
if (!cur->jump_back(kbuf, ksiz) &&
db_->error() != kc::BasicDB::Error::NOIMPL &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::jump_back");
err_ = true;
}
} else {
if (!cur->jump(kbuf, ksiz) &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::jump");
err_ = true;
}
}
} else {
class VisitorImpl : public kc::DB::Visitor {
public:
explicit VisitorImpl(const char* lbuf) : lbuf_(lbuf) {}
private:
const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) {
const char* rv = NOP;
switch (myrand(3)) {
case 0: {
rv = lbuf_;
*sp = myrand(RECBUFSIZL) / (myrand(5) + 1);
break;
}
case 1: {
rv = REMOVE;
break;
}
}
return rv;
}
const char* lbuf_;
} visitor(lbuf_);
if (!cur->accept(&visitor, true, myrand(2) == 0) &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::accept");
err_ = true;
}
if (myrand(5) > 0 && !cur->step() &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::step");
err_ = true;
}
}
if (myrand(rnum_ / 50 + 1) == 0) {
std::vector keys;
std::string prefix(kbuf, ksiz > 0 ? ksiz - 1 : 0);
if (db_->match_prefix(prefix, &keys, myrand(10)) == -1) {
dberrprint(db_, __LINE__, "DB::match_prefix");
err_ = true;
}
}
if (myrand(rnum_ / 50 + 1) == 0) {
std::vector keys;
std::string regex(kbuf, ksiz > 0 ? ksiz - 1 : 0);
if (db_->match_regex(regex, &keys, myrand(10)) == -1 &&
db_->error() != kc::BasicDB::Error::LOGIC) {
dberrprint(db_, __LINE__, "DB::match_regex");
err_ = true;
}
}
if (myrand(rnum_ / 50 + 1) == 0) {
std::vector keys;
std::string origin(kbuf, ksiz > 0 ? ksiz - 1 : 0);
if (db_->match_similar(origin, 3, myrand(2) == 0, &keys, myrand(10)) == -1) {
dberrprint(db_, __LINE__, "DB::match_similar");
err_ = true;
}
}
break;
}
default: {
size_t rsiz;
char* rbuf = db_->get(kbuf, ksiz, &rsiz);
if (rbuf) {
delete[] rbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::get");
err_ = true;
}
break;
}
}
} while (myrand(100) == 0);
if (myrand(100) == 0) {
int32_t jnum = myrand(10);
switch (myrand(4)) {
case 0: {
std::map recs;
for (int32_t j = 0; j < jnum; j++) {
char jbuf[RECBUFSIZ];
size_t jsiz = std::sprintf(jbuf, "%lld", (long long)(myrand(range) + 1));
recs[std::string(jbuf, jsiz)] = std::string(kbuf, ksiz);
}
if (db_->set_bulk(recs, myrand(4)) != (int64_t)recs.size()) {
dberrprint(db_, __LINE__, "DB::set_bulk");
err_ = true;
}
break;
}
case 1: {
std::vector keys;
for (int32_t j = 0; j < jnum; j++) {
char jbuf[RECBUFSIZ];
size_t jsiz = std::sprintf(jbuf, "%lld", (long long)(myrand(range) + 1));
keys.push_back(std::string(jbuf, jsiz));
}
if (db_->remove_bulk(keys, myrand(4)) < 0) {
dberrprint(db_, __LINE__, "DB::remove_bulk");
err_ = true;
}
break;
}
default: {
std::vector keys;
for (int32_t j = 0; j < jnum; j++) {
char jbuf[RECBUFSIZ];
size_t jsiz = std::sprintf(jbuf, "%lld", (long long)(myrand(range) + 1));
keys.push_back(std::string(jbuf, jsiz));
}
std::map recs;
if (db_->get_bulk(keys, &recs, myrand(4)) < 0) {
dberrprint(db_, __LINE__, "DB::get_bulk");
err_ = true;
}
break;
}
}
}
if (i == rnum_ / 2) {
if (myrand(thnum_ * 4) == 0 && !db_->clear()) {
dberrprint(db_, __LINE__, "DB::clear");
err_ = true;
} else {
class SyncProcessor : public kc::BasicDB::FileProcessor {
private:
bool process(const std::string& path, int64_t count, int64_t size) {
yield();
return true;
}
} syncprocessor;
if (!db_->synchronize(false, &syncprocessor)) {
dberrprint(db_, __LINE__, "DB::synchronize");
err_ = true;
}
}
}
if (tran) {
yield();
if (!db_->end_transaction(myrand(10) > 0)) {
dberrprint(db_, __LINE__, "DB::end_transactin");
err_ = true;
}
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
delete cur;
}
private:
int32_t id_;
kc::PolyDB* db_;
int64_t rnum_;
int32_t thnum_;
const char* lbuf_;
bool err_;
};
char lbuf[RECBUFSIZL];
std::memset(lbuf, '*', sizeof(lbuf));
ThreadWicked threads[THREADMAX];
if (thnum < 2) {
threads[0].setparams(0, &db, rnum, thnum, lbuf);
threads[0].run();
if (threads[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threads[i].setparams(i, &db, rnum, thnum, lbuf);
threads[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threads[i].join();
if (threads[i].error()) err = true;
}
}
dbmetaprint(&db, itcnt == itnum);
if (!db.close()) {
dberrprint(&db, __LINE__, "DB::close");
err = true;
}
oprintf("time: %.3f\n", kc::time() - stime);
}
oprintf("%s\n\n", err ? "error" : "ok");
return err ? 1 : 0;
}
// perform tran command
static int32_t proctran(const char* path, int64_t rnum, int32_t thnum, int32_t itnum, bool hard,
int32_t oflags, bool lv) {
oprintf("\n seed=%u path=%s rnum=%lld thnum=%d itnum=%d hard=%d"
" oflags=%d lv=%d\n\n",
g_randseed, path, (long long)rnum, thnum, itnum, hard, oflags, lv);
bool err = false;
kc::PolyDB db;
kc::PolyDB paradb;
db.tune_logger(stdlogger(g_progname, &std::cout),
lv ? kc::UINT32MAX : kc::BasicDB::Logger::WARN | kc::BasicDB::Logger::ERROR);
paradb.tune_logger(stdlogger(g_progname, &std::cout), lv ? kc::UINT32MAX :
kc::BasicDB::Logger::WARN | kc::BasicDB::Logger::ERROR);
for (int32_t itcnt = 1; itcnt <= itnum; itcnt++) {
oprintf("iteration %d updating:\n", itcnt);
double stime = kc::time();
uint32_t omode = kc::PolyDB::OWRITER | kc::PolyDB::OCREATE;
if (itcnt == 1) omode |= kc::PolyDB::OTRUNCATE;
if (!db.open(path, omode | oflags)) {
dberrprint(&db, __LINE__, "DB::open");
err = true;
}
std::string parapath = db.path() + "-para.kch";
if (!paradb.open(parapath, omode)) {
dberrprint(¶db, __LINE__, "DB::open");
err = true;
}
class ThreadTran : public kc::Thread {
public:
void setparams(int32_t id, kc::PolyDB* db, kc::PolyDB* paradb, int64_t rnum,
int32_t thnum, bool hard, const char* lbuf) {
id_ = id;
db_ = db;
paradb_ = paradb;
rnum_ = rnum;
thnum_ = thnum;
hard_ = hard;
lbuf_ = lbuf;
err_ = false;
}
bool error() {
return err_;
}
void run() {
kc::DB::Cursor* cur = db_->cursor();
int64_t range = rnum_ * thnum_;
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%lld", (long long)(myrand(range) + 1));
if (!cur->jump(kbuf, ksiz) && db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::jump");
err_ = true;
}
bool tran = true;
if (!db_->begin_transaction(hard_)) {
dberrprint(db_, __LINE__, "DB::begin_transaction");
tran = false;
err_ = true;
}
bool commit = myrand(10) > 0;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
ksiz = std::sprintf(kbuf, "%lld", (long long)(myrand(range) + 1));
const char* vbuf = kbuf;
size_t vsiz = ksiz;
if (myrand(10) == 0) {
vbuf = lbuf_;
vsiz = myrand(RECBUFSIZL) / (myrand(5) + 1);
}
class VisitorImpl : public kc::DB::Visitor {
public:
explicit VisitorImpl(const char* vbuf, size_t vsiz, kc::BasicDB* paradb) :
vbuf_(vbuf), vsiz_(vsiz), paradb_(paradb) {}
private:
const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) {
return visit_empty(kbuf, ksiz, sp);
}
const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) {
const char* rv = NOP;
switch (myrand(3)) {
case 0: {
rv = vbuf_;
*sp = vsiz_;
if (paradb_) paradb_->set(kbuf, ksiz, vbuf_, vsiz_);
break;
}
case 1: {
rv = REMOVE;
if (paradb_) paradb_->remove(kbuf, ksiz);
break;
}
}
return rv;
}
const char* vbuf_;
size_t vsiz_;
kc::BasicDB* paradb_;
} visitor(vbuf, vsiz, !tran || commit ? paradb_ : NULL);
if (myrand(4) == 0) {
if (!cur->accept(&visitor, true, myrand(2) == 0) &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::accept");
err_ = true;
}
} else {
if (!db_->accept(kbuf, ksiz, &visitor, true)) {
dberrprint(db_, __LINE__, "DB::accept");
err_ = true;
}
}
if (tran && myrand(100) == 0) {
if (db_->end_transaction(commit)) {
yield();
if (!db_->begin_transaction(hard_)) {
dberrprint(db_, __LINE__, "DB::begin_transaction");
tran = false;
err_ = true;
}
} else {
dberrprint(db_, __LINE__, "DB::end_transaction");
err_ = true;
}
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
if (tran && !db_->end_transaction(commit)) {
dberrprint(db_, __LINE__, "DB::end_transaction");
err_ = true;
}
delete cur;
}
private:
int32_t id_;
kc::PolyDB* db_;
kc::PolyDB* paradb_;
int64_t rnum_;
int32_t thnum_;
bool hard_;
const char* lbuf_;
bool err_;
};
char lbuf[RECBUFSIZL];
std::memset(lbuf, '*', sizeof(lbuf));
ThreadTran threads[THREADMAX];
if (thnum < 2) {
threads[0].setparams(0, &db, ¶db, rnum, thnum, hard, lbuf);
threads[0].run();
if (threads[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threads[i].setparams(i, &db, ¶db, rnum, thnum, hard, lbuf);
threads[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threads[i].join();
if (threads[i].error()) err = true;
}
}
oprintf("iteration %d checking:\n", itcnt);
if (db.count() != paradb.count()) {
dberrprint(&db, __LINE__, "DB::count");
err = true;
}
class VisitorImpl : public kc::DB::Visitor {
public:
explicit VisitorImpl(int64_t rnum, kc::BasicDB* paradb) :
rnum_(rnum), paradb_(paradb), err_(false), cnt_(0) {}
bool error() {
return err_;
}
private:
const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) {
cnt_++;
size_t rsiz;
char* rbuf = paradb_->get(kbuf, ksiz, &rsiz);
if (rbuf) {
delete[] rbuf;
} else {
dberrprint(paradb_, __LINE__, "DB::get");
err_ = true;
}
if (rnum_ > 250 && cnt_ % (rnum_ / 250) == 0) {
oputchar('.');
if (cnt_ == rnum_ || cnt_ % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)cnt_);
}
return NOP;
}
int64_t rnum_;
kc::BasicDB* paradb_;
bool err_;
int64_t cnt_;
} visitor(rnum, ¶db), paravisitor(rnum, &db);
if (!db.iterate(&visitor, false)) {
dberrprint(&db, __LINE__, "DB::iterate");
err = true;
}
oprintf(" (end)\n");
if (visitor.error()) err = true;
if (!paradb.iterate(¶visitor, false)) {
dberrprint(&db, __LINE__, "DB::iterate");
err = true;
}
oprintf(" (end)\n");
if (paravisitor.error()) err = true;
if (!paradb.close()) {
dberrprint(¶db, __LINE__, "DB::close");
err = true;
}
dbmetaprint(&db, itcnt == itnum);
if (!db.close()) {
dberrprint(&db, __LINE__, "DB::close");
err = true;
}
oprintf("time: %.3f\n", kc::time() - stime);
}
oprintf("%s\n\n", err ? "error" : "ok");
return err ? 1 : 0;
}
// perform mapred command
static int32_t procmapred(const char* path, int64_t rnum, bool rnd, bool ru, int32_t oflags,
bool lv, const char* tmpdir, int64_t dbnum,
int64_t clim, int64_t cbnum, int32_t opts) {
oprintf("\n seed=%u path=%s rnum=%lld rnd=%d ru=%d oflags=%d lv=%d"
" tmp=%s dbnum=%lld clim=%lld cbnum=%lld opts=%d\n\n",
g_randseed, path, (long long)rnum, rnd, ru, oflags, lv,
tmpdir, (long long)dbnum, (long long)clim, (long long)cbnum, opts);
bool err = false;
kc::PolyDB db;
db.tune_logger(stdlogger(g_progname, &std::cout),
lv ? kc::UINT32MAX : kc::BasicDB::Logger::WARN | kc::BasicDB::Logger::ERROR);
double stime = kc::time();
uint32_t omode = kc::PolyDB::OWRITER | kc::PolyDB::OCREATE | kc::PolyDB::OTRUNCATE;
if (ru) omode = kc::PolyDB::OREADER;
if (!db.open(path, omode | oflags)) {
dberrprint(&db, __LINE__, "DB::open");
err = true;
}
class MapReduceImpl : public kc::MapReduce {
public:
MapReduceImpl() : mapcnt_(0), redcnt_(0), lock_() {}
bool map(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) {
mapcnt_.add(1);
return emit(vbuf, vsiz, kbuf, ksiz);
}
bool reduce(const char* kbuf, size_t ksiz, ValueIterator* iter) {
const char* vbuf;
size_t vsiz;
while ((vbuf = iter->next(&vsiz)) != NULL) {
redcnt_.add(1);
}
return true;
}
bool preprocess() {
oprintf("preprocessing:\n");
if (!emit("pre", 3, "process", 7)) return false;
if (!emit("PROCESS", 7, "PRE", 3)) return false;
return true;
}
bool midprocess() {
oprintf("midprocessing:\n");
if (!emit("mid", 3, "process", 7)) return false;
if (!emit("PROCESS", 7, "MID", 3)) return false;
return true;
}
bool postprocess() {
oprintf("postprocessing:\n");
return true;
}
bool log(const char* name, const char* message) {
kc::ScopedMutex lock(&lock_);
oprintf("%s: %s", name, message);
int64_t musage = memusage();
if (musage > 0) oprintf(": memory=%lld", (long long)(musage - g_memusage));
oprintf("\n");
return true;
}
int64_t mapcnt() {
return mapcnt_;
}
int64_t redcnt() {
return redcnt_;
}
private:
kc::AtomicInt64 mapcnt_;
kc::AtomicInt64 redcnt_;
kc::Mutex lock_;
};
MapReduceImpl mr;
mr.tune_storage(dbnum, clim, cbnum);
int64_t pnum = rnum / 100;
if (pnum < 1) pnum = 1;
if (!ru) {
mr.log("misc", "setting records");
for (int64_t i = 1; !err && i <= rnum; i++) {
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%lld", (long long)(rnd ? myrand(rnum) + 1 : i));
char vbuf[RECBUFSIZ];
size_t vsiz = std::sprintf(vbuf, "%lld", (long long)(rnd ? myrand(pnum) + 1 : i % pnum));
if (!db.append(kbuf, ksiz, vbuf, vsiz)) {
dberrprint(&db, __LINE__, "DB::append");
err = true;
}
}
}
if (!mr.execute(&db, tmpdir, opts)) {
dberrprint(&db, __LINE__, "MapReduce::execute");
err = true;
}
if (!rnd && mr.mapcnt() != rnum) {
dberrprint(&db, __LINE__, "MapReduce::mapcnt");
err = true;
}
if (!rnd && rnum % 100 == 0 && mr.redcnt() != rnum + 4) {
dberrprint(&db, __LINE__, "MapReduce::redcnt");
err = true;
}
if (!db.close()) {
dberrprint(&db, __LINE__, "DB::close");
err = true;
}
oprintf("time: %.3f\n", kc::time() - stime);
oprintf("%s\n\n", err ? "error" : "ok");
return err ? 1 : 0;
}
// perform index command
static int32_t procindex(const char* path, int64_t rnum, int32_t thnum, bool rnd, int32_t mode,
int32_t oflags, bool lv) {
oprintf("\n seed=%u path=%s rnum=%lld thnum=%d rnd=%d mode=%d"
" oflags=%d lv=%d\n\n",
g_randseed, path, (long long)rnum, thnum, rnd, mode, oflags, lv);
bool err = false;
kc::IndexDB db;
oprintf("opening the database:\n");
double stime = kc::time();
db.tune_logger(stdlogger(g_progname, &std::cout),
lv ? kc::UINT32MAX : kc::BasicDB::Logger::WARN | kc::BasicDB::Logger::ERROR);
uint32_t omode = kc::PolyDB::OWRITER | kc::PolyDB::OCREATE | kc::PolyDB::OTRUNCATE;
if (mode == 'r') {
omode = kc::PolyDB::OWRITER | kc::PolyDB::OCREATE;
} else if (mode == 'g' || mode == 'w') {
omode = kc::PolyDB::OREADER;
}
if (!db.open(path, omode | oflags)) {
dberrprint(&db, __LINE__, "DB::open");
err = true;
}
double etime = kc::time();
dbmetaprint(&db, false);
oprintf("time: %.3f\n", etime - stime);
if (mode == 0 || mode == 's' || mode == 'e') {
oprintf("appending records:\n");
stime = kc::time();
class ThreadSet : public kc::Thread {
public:
void setparams(int32_t id, kc::IndexDB* db, int64_t rnum, int32_t thnum,
bool rnd, int32_t mode) {
id_ = id;
db_ = db;
rnum_ = rnum;
thnum_ = thnum;
err_ = false;
rnd_ = rnd;
mode_ = mode;
}
bool error() {
return err_;
}
void run() {
int64_t base = id_ * rnum_;
int64_t range = rnum_ * thnum_;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld",
(long long)(rnd_ ? myrand(range) + 1 : base + i));
if (!db_->append(kbuf, ksiz, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::append");
err_ = true;
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::IndexDB* db_;
int64_t rnum_;
int32_t thnum_;
bool err_;
bool rnd_;
int32_t mode_;
};
ThreadSet threadsets[THREADMAX];
if (thnum < 2) {
threadsets[0].setparams(0, &db, rnum, thnum, rnd, mode);
threadsets[0].run();
if (threadsets[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threadsets[i].setparams(i, &db, rnum, thnum, rnd, mode);
threadsets[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadsets[i].join();
if (threadsets[i].error()) err = true;
}
}
etime = kc::time();
dbmetaprint(&db, mode == 's');
oprintf("time: %.3f\n", etime - stime);
}
if (mode == 'e') {
oprintf("wicked testing:\n");
stime = kc::time();
class ThreadWicked : public kc::Thread {
public:
void setparams(int32_t id, kc::IndexDB* db, int64_t rnum, int32_t thnum,
bool rnd, int32_t mode) {
id_ = id;
db_ = db;
rnum_ = rnum;
thnum_ = thnum;
err_ = false;
rnd_ = rnd;
mode_ = mode;
}
bool error() {
return err_;
}
void run() {
int64_t base = id_ * rnum_;
int64_t range = rnum_ * thnum_;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld",
(long long)(rnd_ ? myrand(range) + 1 : base + i));
switch (i % 5) {
case 0: {
if (!db_->set(kbuf, ksiz, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::set");
err_ = true;
}
break;
}
case 1: {
if (!db_->add(kbuf, ksiz, kbuf, ksiz) &&
db_->error() != kc::BasicDB::Error::DUPREC) {
dberrprint(db_, __LINE__, "DB::add");
err_ = true;
}
break;
}
case 2: {
if (!db_->replace(kbuf, ksiz, kbuf, ksiz) &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::replace");
err_ = true;
}
break;
}
default: {
size_t vsiz;
char* vbuf = db_->get(kbuf, ksiz, &vsiz);
if (vbuf) {
delete[] vbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::get");
err_ = true;
}
break;
}
}
if (rnd_ && myrand(range) == 0 && !db_->synchronize(false, NULL)) {
dberrprint(db_, __LINE__, "DB::synchronize");
err_ = true;
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::IndexDB* db_;
int64_t rnum_;
int32_t thnum_;
bool err_;
bool rnd_;
int32_t mode_;
};
ThreadWicked threadsets[THREADMAX];
if (thnum < 2) {
threadsets[0].setparams(0, &db, rnum, thnum, rnd, mode);
threadsets[0].run();
if (threadsets[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threadsets[i].setparams(i, &db, rnum, thnum, rnd, mode);
threadsets[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadsets[i].join();
if (threadsets[i].error()) err = true;
}
}
etime = kc::time();
dbmetaprint(&db, false);
oprintf("time: %.3f\n", etime - stime);
}
if (mode == 0 || mode == 'g' || mode == 'e') {
oprintf("getting records:\n");
stime = kc::time();
class ThreadGet : public kc::Thread {
public:
void setparams(int32_t id, kc::IndexDB* db, int64_t rnum, int32_t thnum,
bool rnd, int32_t mode) {
id_ = id;
db_ = db;
rnum_ = rnum;
thnum_ = thnum;
err_ = false;
rnd_ = rnd;
mode_ = mode;
}
bool error() {
return err_;
}
void run() {
int64_t base = id_ * rnum_;
int64_t range = rnum_ * thnum_;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld",
(long long)(rnd_ ? myrand(range) + 1 : base + i));
size_t vsiz;
char* vbuf = db_->get(kbuf, ksiz, &vsiz);
if (vbuf) {
if (vsiz < ksiz || std::memcmp(vbuf, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::get");
err_ = true;
}
delete[] vbuf;
} else if (!rnd_ || db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::get");
err_ = true;
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::IndexDB* db_;
int64_t rnum_;
int32_t thnum_;
bool err_;
bool rnd_;
int32_t mode_;
};
ThreadGet threadsets[THREADMAX];
if (thnum < 2) {
threadsets[0].setparams(0, &db, rnum, thnum, rnd, mode);
threadsets[0].run();
if (threadsets[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threadsets[i].setparams(i, &db, rnum, thnum, rnd, mode);
threadsets[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadsets[i].join();
if (threadsets[i].error()) err = true;
}
}
etime = kc::time();
dbmetaprint(&db, mode == 'g');
oprintf("time: %.3f\n", etime - stime);
}
if (mode == 0 || mode == 'r' || mode == 'e') {
oprintf("removing records:\n");
stime = kc::time();
class ThreadRemove : public kc::Thread {
public:
void setparams(int32_t id, kc::IndexDB* db, int64_t rnum, int32_t thnum,
bool rnd, int32_t mode) {
id_ = id;
db_ = db;
rnum_ = rnum;
thnum_ = thnum;
err_ = false;
rnd_ = rnd;
mode_ = mode;
}
bool error() {
return err_;
}
void run() {
int64_t base = id_ * rnum_;
int64_t range = rnum_ * thnum_;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld",
(long long)(rnd_ ? myrand(range) + 1 : base + i));
if (!db_->remove(kbuf, ksiz) &&
((!rnd_ && mode_ != 'e') || db_->error() != kc::BasicDB::Error::NOREC)) {
dberrprint(db_, __LINE__, "DB::remove");
err_ = true;
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::IndexDB* db_;
int64_t rnum_;
int32_t thnum_;
bool err_;
bool rnd_;
int32_t mode_;
};
ThreadRemove threadsets[THREADMAX];
if (thnum < 2) {
threadsets[0].setparams(0, &db, rnum, thnum, rnd, mode);
threadsets[0].run();
if (threadsets[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threadsets[i].setparams(i, &db, rnum, thnum, rnd, mode);
threadsets[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadsets[i].join();
if (threadsets[i].error()) err = true;
}
}
etime = kc::time();
dbmetaprint(&db, mode == 'r' || mode == 'e');
oprintf("time: %.3f\n", etime - stime);
}
stime = kc::time();
if (!db.close()) {
dberrprint(&db, __LINE__, "DB::close");
err = true;
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("%s\n\n", err ? "error" : "ok");
return err ? 1 : 0;
}
// perform misc command
static int32_t procmisc(const char* path) {
oprintf("\n seed=%u path=%s\n\n", g_randseed, path);
bool err = false;
oprintf("opening the database:\n");
kc::BasicDB* db = new kc::PolyDB;
db->open(path, kc::BasicDB::OWRITER | kc::BasicDB::OCREATE | kc::BasicDB::OTRUNCATE);
oprintf("setting records:\n");
int64_t rnum = 10000;
for (int64_t i = 1; !err && i <= rnum; i++) {
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld", (long long)i);
if (!db->set(kbuf, ksiz, kbuf, ksiz)) {
dberrprint(db, __LINE__, "DB::set");
err = true;
}
}
oprintf("deploying cursors:\n");
const int32_t cnum = 100;
kc::BasicDB::Cursor* curs[cnum];
for (int32_t i = 0; i < cnum; i++) {
curs[i] = db->cursor();
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld", (long long)i + 1);
if (!curs[i]->jump(kbuf, ksiz)) {
dberrprint(db, __LINE__, "Cursor::jump");
err = true;
}
}
oprintf("accessing records:\n");
for (int64_t i = 1; !err && i <= rnum; i++) {
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld", (long long)i);
if (i % 3 == 0) {
size_t vsiz;
char* vbuf = db->get(kbuf, ksiz, &vsiz);
if (vbuf) {
delete[] vbuf;
} else if (db->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db, __LINE__, "DB::get");
err = true;
}
} else {
if (!db->remove(kbuf, ksiz)) {
dberrprint(db, __LINE__, "DB::remove");
err = true;
}
}
}
oprintf("updating records with cursors:\n");
for (int32_t i = 0; i < cnum; i++) {
kc::BasicDB::Cursor* cur = curs[i];
switch (i % 9) {
default: {
size_t ksiz;
char* kbuf = cur->get_key(&ksiz, i % 2 == 0);
if (kbuf) {
std::string value;
if (!db->get(std::string(kbuf, ksiz), &value)) {
dberrprint(db, __LINE__, "DB::get");
err = true;
}
delete[] kbuf;
} else if (cur->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db, __LINE__, "Cursor::get_key");
err = true;
}
break;
}
case 1: {
size_t vsiz;
char* vbuf = cur->get_value(&vsiz, i % 2 == 0);
if (vbuf) {
delete[] vbuf;
} else if (cur->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db, __LINE__, "Cursor::get_value");
err = true;
}
break;
}
case 2: {
size_t ksiz;
const char* vbuf;
size_t vsiz;
char* kbuf = cur->get(&ksiz, &vbuf, &vsiz, i % 2 == 0);
if (kbuf) {
if (ksiz != vsiz || std::memcmp(kbuf, vbuf, ksiz)) {
dberrprint(db, __LINE__, "Cursor::get");
err = true;
}
delete[] kbuf;
} else if (cur->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db, __LINE__, "Cursor::get");
err = true;
}
break;
}
case 3: {
std::string key, value;
if (cur->get(&key, &value, i % 2 == 0)) {
if (key != value) {
dberrprint(db, __LINE__, "Cursor::get");
err = true;
}
} else if (cur->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db, __LINE__, "Cursor::get");
err = true;
}
break;
}
case 4: {
char vbuf[RECBUFSIZ];
size_t vsiz = std::sprintf(vbuf, "kyoto:%d", i);
if (!cur->set_value(vbuf, vsiz) && cur->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db, __LINE__, "Cursor::set_value");
err = true;
}
break;
}
case 5: {
if (!cur->remove() && cur->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db, __LINE__, "Cursor::remove");
err = true;
}
break;
}
case 6: {
size_t ksiz;
const char* vbuf;
size_t vsiz;
char* kbuf = cur->seize(&ksiz, &vbuf, &vsiz);
if (kbuf) {
delete[] kbuf;
} else if (cur->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db, __LINE__, "Cursor::seize");
err = true;
}
break;
}
case 7: {
std::string key, value;
if (!cur->seize(&key, &value) && cur->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db, __LINE__, "Cursor::get");
err = true;
}
break;
}
}
}
oprintf("bulk operations:\n");
class VisitorBulk : public kc::DB::Visitor {
public:
VisitorBulk() : before_(0), after_(0) {}
int64_t before() {
return before_;
}
int64_t after() {
return after_;
}
private:
void visit_before() {
before_++;
}
void visit_after() {
after_++;
}
int64_t before_;
int64_t after_;
};
std::vector keys;
for (int64_t i = 1; !err && i <= rnum; i++) {
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld", (long long)i);
keys.push_back(std::string(kbuf, ksiz));
if (i % 10 == 0) {
VisitorBulk visitor;
if (db->accept_bulk(keys, &visitor, i % 3 > 0)) {
if (visitor.before() != 1 || visitor.after() != 1) {
dberrprint(db, __LINE__, "DB::accept_bulk");
err = true;
}
} else {
dberrprint(db, __LINE__, "DB::accept_bulk");
err = true;
}
keys.clear();
}
}
kc::PolyDB* pdb = dynamic_cast(db);
if (pdb) {
kc::BasicDB* idb = pdb->reveal_inner_db();
if (idb) {
const std::type_info& info = typeid(*idb);
const char* ext = NULL;
if (info == typeid(kc::HashDB)) {
ext = "kch";
} else if (info == typeid(kc::TreeDB)) {
ext = "kct";
} else if (info == typeid(kc::DirDB)) {
ext = "kcd";
} else if (info == typeid(kc::ForestDB)) {
ext = "kcf";
}
if (ext) {
const std::string& dpath = idb->path() + kc::File::EXTCHR + "tmp" +
kc::File::EXTCHR + ext;
oprintf("copying the database file:\n");
if (!idb->copy(dpath)) {
dberrprint(db, __LINE__, "DB::copy");
err = true;
}
oprintf("merging the database files:\n");
kc::PolyDB srcdb;
if (!srcdb.open(dpath, kc::PolyDB::OREADER)) {
dberrprint(&srcdb, __LINE__, "DB::open");
err = true;
}
kc::BasicDB* bdb = &srcdb;
if (!pdb->merge(&bdb, 1, kc::PolyDB::MAPPEND)) {
dberrprint(db, __LINE__, "DB::merge");
err = true;
}
if (!srcdb.close()) {
dberrprint(&srcdb, __LINE__, "DB::close");
err = true;
}
kc::File::remove_recursively(dpath.c_str());
}
}
}
oprintf("scanning in parallel:\n");
class VisitorCount : public kc::DB::Visitor {
public:
explicit VisitorCount() : cnt_(0) {}
int64_t cnt() {
return cnt_;
}
private:
const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) {
cnt_.add(1);
return NOP;
}
kc::AtomicInt64 cnt_;
} visitorcount;
class ProgressCheckerCount : public kc::BasicDB::ProgressChecker {
public:
explicit ProgressCheckerCount() : cnt_(0) {}
int64_t cnt() {
return cnt_;
}
private:
bool check(const char* name, const char* message, int64_t curcnt, int64_t allcnt) {
cnt_.add(1);
return true;
}
kc::AtomicInt64 cnt_;
} checkercount;
class ThreadWicked : public kc::Thread {
public:
explicit ThreadWicked(kc::BasicDB* db, int64_t rnum) :
db_(db), rnum_(rnum), err_(false) {}
bool error() {
return err_;
}
private:
void run() {
for (int64_t i = 0; i < rnum_; i++) {
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld", (long long)i);
size_t vsiz;
char* vbuf = db_->get(kbuf, ksiz, &vsiz);
if (vbuf) {
delete[] vbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::set");
err_ = true;
}
}
}
kc::BasicDB* db_;
int64_t rnum_;
bool err_;
} threadwicked(pdb, rnum);
threadwicked.start();
if (!db->scan_parallel(&visitorcount, 4, &checkercount)) {
dberrprint(pdb, __LINE__, "DB::scan_parallel");
err = true;
}
threadwicked.join();
if (threadwicked.error()) err = true;
if (visitorcount.cnt() != db->count()) {
dberrprint(pdb, __LINE__, "DB::scan_parallel");
err = true;
}
if (checkercount.cnt() < db->count() + 2) {
dberrprint(pdb, __LINE__, "DB::scan_parallel ss");
err = true;
}
oprintf("deleting the database object:\n");
delete db;
oprintf("deleting the cursor objects:\n");
for (int32_t i = 0; i < cnum; i++) {
delete curs[i];
}
oprintf("re-opening the database object with a external database:\n");
pdb = new kc::PolyDB;
pdb->set_internal_db(new kc::PolyDB);
if (!pdb->open(path, kc::PolyDB::OREADER)) {
dberrprint(pdb, __LINE__, "DB::open");
err = true;
}
oprintf("deleting the database object:\n");
delete pdb;
oprintf("%s\n\n", err ? "error" : "ok");
return err ? 1 : 0;
}
// END OF FILE
kyotocabinet-1.2.80/kcprototest.cc 0000664 0001750 0001750 00000215103 14416044124 016173 0 ustar mikio mikio /*************************************************************************************************
* The test cases of the prototype database
* Copyright (C) 2009-2012 Mikio Hirabayashi
* This file is part of Kyoto Cabinet.
* This program is free software: you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation, either version
* 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with this program.
* If not, see .
*************************************************************************************************/
#include
#include "cmdcommon.h"
// global variables
const char* g_progname; // program name
uint32_t g_randseed; // random seed
int64_t g_memusage; // memory usage
// function prototypes
int main(int argc, char** argv);
static void usage();
static void dberrprint(kc::BasicDB* db, int32_t line, const char* func);
static void dbmetaprint(kc::BasicDB* db, bool verbose);
static int32_t runorder(int argc, char** argv);
static int32_t runqueue(int argc, char** argv);
static int32_t runwicked(int argc, char** argv);
static int32_t runtran(int argc, char** argv);
template
static int32_t procorder(const char* tname, int64_t rnum, int32_t thnum, bool rnd,
bool etc, bool tran);
template
static int32_t procqueue(const char* tname, int64_t rnum, int32_t thnum, int32_t itnum,
bool rnd);
template
static int32_t procwicked(const char* tname, int64_t rnum, int32_t thnum, int32_t itnum);
template
static int32_t proctran(const char* tname, int64_t rnum, int32_t thnum, int32_t itnum);
// main routine
int main(int argc, char** argv) {
g_progname = argv[0];
const char* ebuf = kc::getenv("KCRNDSEED");
g_randseed = ebuf ? (uint32_t)kc::atoi(ebuf) : (uint32_t)(kc::time() * 1000);
mysrand(g_randseed);
g_memusage = memusage();
kc::setstdiobin();
if (argc < 2) usage();
int32_t rv = 0;
if (!std::strcmp(argv[1], "order")) {
rv = runorder(argc, argv);
} else if (!std::strcmp(argv[1], "queue")) {
rv = runqueue(argc, argv);
} else if (!std::strcmp(argv[1], "wicked")) {
rv = runwicked(argc, argv);
} else if (!std::strcmp(argv[1], "tran")) {
rv = runtran(argc, argv);
} else {
usage();
}
if (rv != 0) {
oprintf("FAILED: KCRNDSEED=%u PID=%ld", g_randseed, (long)kc::getpid());
for (int32_t i = 0; i < argc; i++) {
oprintf(" %s", argv[i]);
}
oprintf("\n\n");
}
return rv;
}
// print the usage and exit
static void usage() {
eprintf("%s: test cases of the prototype database of Kyoto Cabinet\n", g_progname);
eprintf("\n");
eprintf("usage:\n");
eprintf(" %s order [-tree] [-th num] [-rnd] [-etc] [-tran] rnum\n", g_progname);
eprintf(" %s queue [-tree] [-th num] [-it num] [-rnd] rnum\n", g_progname);
eprintf(" %s wicked [-tree] [-th num] [-it num] rnum\n", g_progname);
eprintf(" %s tran [-tree] [-th num] [-it num] rnum\n", g_progname);
eprintf("\n");
std::exit(1);
}
// print the error message of a database
static void dberrprint(kc::BasicDB* db, int32_t line, const char* func) {
const kc::BasicDB::Error& err = db->error();
oprintf("%s: %d: %s: %s: %d: %s: %s\n",
g_progname, line, func, db->path().c_str(), err.code(), err.name(), err.message());
}
// print members of a database
static void dbmetaprint(kc::BasicDB* db, bool verbose) {
if (verbose) {
std::map status;
status["opaque"] = "";
if (db->status(&status)) {
uint32_t type = kc::atoi(status["type"].c_str());
oprintf("type: %s (%s) (type=0x%02X)\n",
kc::BasicDB::typecname(type), kc::BasicDB::typestring(type), type);
uint32_t rtype = kc::atoi(status["realtype"].c_str());
if (rtype > 0 && rtype != type)
oprintf("real type: %s (%s) (realtype=0x%02X)\n",
kc::BasicDB::typecname(rtype), kc::BasicDB::typestring(rtype), rtype);
oprintf("path: %s\n", status["path"].c_str());
if (status["opaque"].size() >= 16) {
const char* opaque = status["opaque"].c_str();
oprintf("opaque:");
if (std::count(opaque, opaque + 16, 0) != 16) {
for (int32_t i = 0; i < 16; i++) {
oprintf(" %02X", ((unsigned char*)opaque)[i]);
}
} else {
oprintf(" 0");
}
oprintf("\n");
}
int64_t count = kc::atoi(status["count"].c_str());
std::string cntstr = unitnumstr(count);
oprintf("count: %lld (%s)\n", count, cntstr.c_str());
int64_t size = kc::atoi(status["size"].c_str());
std::string sizestr = unitnumstrbyte(size);
oprintf("size: %lld (%s)\n", size, sizestr.c_str());
}
} else {
oprintf("count: %lld\n", (long long)db->count());
oprintf("size: %lld\n", (long long)db->size());
}
int64_t musage = memusage();
if (musage > 0) oprintf("memory: %lld\n", (long long)(musage - g_memusage));
}
// parse arguments of order command
static int32_t runorder(int argc, char** argv) {
bool argbrk = false;
const char* rstr = NULL;
bool tree = false;
int32_t thnum = 1;
bool rnd = false;
bool etc = false;
bool tran = false;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-tree")) {
tree = true;
} else if (!std::strcmp(argv[i], "-th")) {
if (++i >= argc) usage();
thnum = kc::atoix(argv[i]);
} else if (!std::strcmp(argv[i], "-rnd")) {
rnd = true;
} else if (!std::strcmp(argv[i], "-etc")) {
etc = true;
} else if (!std::strcmp(argv[i], "-tran")) {
tran = true;
} else {
usage();
}
} else if (!rstr) {
argbrk = true;
rstr = argv[i];
} else {
usage();
}
}
if (!rstr) usage();
int64_t rnum = kc::atoix(rstr);
if (rnum < 1 || thnum < 1) usage();
if (thnum > THREADMAX) thnum = THREADMAX;
int32_t rv = 0;
if (tree) {
rv = procorder("Tree", rnum, thnum, rnd, etc, tran);
} else {
rv = procorder("Hash", rnum, thnum, rnd, etc, tran);
}
return rv;
}
// parse arguments of queue command
static int32_t runqueue(int argc, char** argv) {
bool argbrk = false;
const char* rstr = NULL;
bool tree = false;
int32_t thnum = 1;
int32_t itnum = 1;
bool rnd = false;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-tree")) {
tree = true;
} else if (!std::strcmp(argv[i], "-th")) {
if (++i >= argc) usage();
thnum = kc::atoix(argv[i]);
} else if (!std::strcmp(argv[i], "-it")) {
if (++i >= argc) usage();
itnum = kc::atoix(argv[i]);
} else if (!std::strcmp(argv[i], "-rnd")) {
rnd = true;
} else {
usage();
}
} else if (!rstr) {
argbrk = true;
rstr = argv[i];
} else {
usage();
}
}
if (!rstr) usage();
int64_t rnum = kc::atoix(rstr);
if (rnum < 1 || thnum < 1 || itnum < 1) usage();
if (thnum > THREADMAX) thnum = THREADMAX;
int32_t rv = 0;
if (tree) {
rv = procqueue("Tree", rnum, thnum, itnum, rnd);
} else {
rv = procqueue("Hash", rnum, thnum, itnum, rnd);
}
return rv;
}
// parse arguments of wicked command
static int32_t runwicked(int argc, char** argv) {
bool argbrk = false;
const char* rstr = NULL;
bool tree = false;
int32_t thnum = 1;
int32_t itnum = 1;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-tree")) {
tree = true;
} else if (!std::strcmp(argv[i], "-th")) {
if (++i >= argc) usage();
thnum = kc::atoix(argv[i]);
} else if (!std::strcmp(argv[i], "-it")) {
if (++i >= argc) usage();
itnum = kc::atoix(argv[i]);
} else {
usage();
}
} else if (!rstr) {
argbrk = true;
rstr = argv[i];
} else {
usage();
}
}
if (!rstr) usage();
int64_t rnum = kc::atoix(rstr);
if (rnum < 1 || thnum < 1 || itnum < 1) usage();
if (thnum > THREADMAX) thnum = THREADMAX;
int32_t rv = 0;
if (tree) {
rv = procwicked("Tree", rnum, thnum, itnum);
} else {
rv = procwicked("Hash", rnum, thnum, itnum);
}
return rv;
}
// parse arguments of tran command
static int32_t runtran(int argc, char** argv) {
bool argbrk = false;
const char* rstr = NULL;
bool tree = false;
int32_t thnum = 1;
int32_t itnum = 1;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-tree")) {
tree = true;
} else if (!std::strcmp(argv[i], "-th")) {
if (++i >= argc) usage();
thnum = kc::atoix(argv[i]);
} else if (!std::strcmp(argv[i], "-it")) {
if (++i >= argc) usage();
itnum = kc::atoix(argv[i]);
} else {
usage();
}
} else if (!rstr) {
argbrk = true;
rstr = argv[i];
} else {
usage();
}
}
if (!rstr) usage();
int64_t rnum = kc::atoix(rstr);
if (rnum < 1 || thnum < 1 || itnum < 1) usage();
if (thnum > THREADMAX) thnum = THREADMAX;
int32_t rv = 0;
if (tree) {
rv = proctran("Tree", rnum, thnum, itnum);
} else {
rv = proctran("Hash", rnum, thnum, itnum);
}
return rv;
}
// perform order command
template
static int32_t procorder(const char* tname, int64_t rnum, int32_t thnum, bool rnd,
bool etc, bool tran) {
oprintf("<%s In-order Test>\n seed=%u rnum=%lld thnum=%d rnd=%d etc=%d tran=%d\n\n",
tname, g_randseed, (long long)rnum, thnum, rnd, etc, tran);
bool err = false;
PROTODB db;
oprintf("opening the database:\n");
double stime = kc::time();
if (!db.open("-", kc::BasicDB::OWRITER | kc::BasicDB::OCREATE | kc::BasicDB::OTRUNCATE)) {
dberrprint(&db, __LINE__, "DB::open");
err = true;
}
double etime = kc::time();
dbmetaprint(&db, false);
oprintf("time: %.3f\n", etime - stime);
oprintf("setting records:\n");
stime = kc::time();
class ThreadSet : public kc::Thread {
public:
void setparams(int32_t id, kc::BasicDB* db, int64_t rnum, int32_t thnum,
bool rnd, bool tran) {
id_ = id;
db_ = db;
rnum_ = rnum;
thnum_ = thnum;
err_ = false;
rnd_ = rnd;
tran_ = tran;
}
bool error() {
return err_;
}
void run() {
int64_t base = id_ * rnum_;
int64_t range = rnum_ * thnum_;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
if (tran_ && !db_->begin_transaction(false)) {
dberrprint(db_, __LINE__, "DB::begin_transaction");
err_ = true;
}
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld",
(long long)(rnd_ ? myrand(range) + 1 : base + i));
if (!db_->set(kbuf, ksiz, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::set");
err_ = true;
}
if (rnd_ && i % 8 == 0) {
switch (myrand(8)) {
case 0: {
if (!db_->set(kbuf, ksiz, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::set");
err_ = true;
}
break;
}
case 1: {
if (!db_->append(kbuf, ksiz, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::append");
err_ = true;
}
break;
}
case 2: {
if (!db_->remove(kbuf, ksiz) && db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::remove");
err_ = true;
}
break;
}
case 3: {
kc::DB::Cursor* cur = db_->cursor();
if (cur->jump(kbuf, ksiz)) {
switch (myrand(8)) {
default: {
size_t rsiz;
char* rbuf = cur->get_key(&rsiz, myrand(10) == 0);
if (rbuf) {
delete[] rbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get_key");
err_ = true;
}
break;
}
case 1: {
size_t rsiz;
char* rbuf = cur->get_value(&rsiz, myrand(10) == 0);
if (rbuf) {
delete[] rbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get_value");
err_ = true;
}
break;
}
case 2: {
size_t rksiz;
const char* rvbuf;
size_t rvsiz;
char* rkbuf = cur->get(&rksiz, &rvbuf, &rvsiz, myrand(10) == 0);
if (rkbuf) {
delete[] rkbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get");
err_ = true;
}
break;
}
case 3: {
std::string key, value;
if (!cur->get(&key, &value, myrand(10) == 0) &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get");
err_ = true;
}
break;
}
case 4: {
if (myrand(8) == 0 && !cur->remove() &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::remove");
err_ = true;
}
break;
}
}
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::jump");
err_ = true;
}
delete cur;
break;
}
default: {
size_t vsiz;
char* vbuf = db_->get(kbuf, ksiz, &vsiz);
if (vbuf) {
delete[] vbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::get");
err_ = true;
}
break;
}
}
}
if (tran_ && !db_->end_transaction(true)) {
dberrprint(db_, __LINE__, "DB::end_transaction");
err_ = true;
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::BasicDB* db_;
int64_t rnum_;
int32_t thnum_;
bool err_;
bool rnd_;
bool tran_;
};
ThreadSet threadsets[THREADMAX];
if (thnum < 2) {
threadsets[0].setparams(0, &db, rnum, thnum, rnd, tran);
threadsets[0].run();
if (threadsets[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threadsets[i].setparams(i, &db, rnum, thnum, rnd, tran);
threadsets[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadsets[i].join();
if (threadsets[i].error()) err = true;
}
}
etime = kc::time();
dbmetaprint(&db, false);
oprintf("time: %.3f\n", etime - stime);
if (etc) {
oprintf("adding records:\n");
stime = kc::time();
class ThreadAdd : public kc::Thread {
public:
void setparams(int32_t id, kc::BasicDB* db, int64_t rnum, int32_t thnum,
bool rnd, bool tran) {
id_ = id;
db_ = db;
rnum_ = rnum;
thnum_ = thnum;
err_ = false;
rnd_ = rnd;
tran_ = tran;
}
bool error() {
return err_;
}
void run() {
int64_t base = id_ * rnum_;
int64_t range = rnum_ * thnum_;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
if (tran_ && !db_->begin_transaction(false)) {
dberrprint(db_, __LINE__, "DB::begin_transaction");
err_ = true;
}
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld",
(long long)(rnd_ ? myrand(range) + 1 : base + i));
if (!db_->add(kbuf, ksiz, kbuf, ksiz) &&
db_->error() != kc::BasicDB::Error::DUPREC) {
dberrprint(db_, __LINE__, "DB::add");
err_ = true;
}
if (tran_ && !db_->end_transaction(true)) {
dberrprint(db_, __LINE__, "DB::end_transaction");
err_ = true;
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::BasicDB* db_;
int64_t rnum_;
int32_t thnum_;
bool err_;
bool rnd_;
bool tran_;
};
ThreadAdd threadadds[THREADMAX];
if (thnum < 2) {
threadadds[0].setparams(0, &db, rnum, thnum, rnd, tran);
threadadds[0].run();
if (threadadds[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threadadds[i].setparams(i, &db, rnum, thnum, rnd, tran);
threadadds[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadadds[i].join();
if (threadadds[i].error()) err = true;
}
}
etime = kc::time();
dbmetaprint(&db, false);
oprintf("time: %.3f\n", etime - stime);
}
if (etc) {
oprintf("appending records:\n");
stime = kc::time();
class ThreadAppend : public kc::Thread {
public:
void setparams(int32_t id, kc::BasicDB* db, int64_t rnum, int32_t thnum,
bool rnd, bool tran) {
id_ = id;
db_ = db;
rnum_ = rnum;
thnum_ = thnum;
err_ = false;
rnd_ = rnd;
tran_ = tran;
}
bool error() {
return err_;
}
void run() {
int64_t base = id_ * rnum_;
int64_t range = rnum_ * thnum_;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
if (tran_ && !db_->begin_transaction(false)) {
dberrprint(db_, __LINE__, "DB::begin_transaction");
err_ = true;
}
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld",
(long long)(rnd_ ? myrand(range) + 1 : base + i));
if (!db_->append(kbuf, ksiz, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::append");
err_ = true;
}
if (tran_ && !db_->end_transaction(true)) {
dberrprint(db_, __LINE__, "DB::end_transaction");
err_ = true;
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::BasicDB* db_;
int64_t rnum_;
int32_t thnum_;
bool err_;
bool rnd_;
bool tran_;
};
ThreadAppend threadappends[THREADMAX];
if (thnum < 2) {
threadappends[0].setparams(0, &db, rnum, thnum, rnd, tran);
threadappends[0].run();
if (threadappends[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threadappends[i].setparams(i, &db, rnum, thnum, rnd, tran);
threadappends[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadappends[i].join();
if (threadappends[i].error()) err = true;
}
}
etime = kc::time();
dbmetaprint(&db, false);
oprintf("time: %.3f\n", etime - stime);
char* opaque = db.opaque();
if (opaque) {
std::memcpy(opaque, "1234567890123456", 16);
if (!db.synchronize_opaque()) {
dberrprint(&db, __LINE__, "DB::synchronize_opaque");
err = true;
}
} else {
dberrprint(&db, __LINE__, "DB::opaque");
err = true;
}
}
oprintf("getting records:\n");
stime = kc::time();
class ThreadGet : public kc::Thread {
public:
void setparams(int32_t id, kc::BasicDB* db, int64_t rnum, int32_t thnum,
bool rnd, bool tran) {
id_ = id;
db_ = db;
rnum_ = rnum;
thnum_ = thnum;
err_ = false;
rnd_ = rnd;
tran_ = tran;
}
bool error() {
return err_;
}
void run() {
int64_t base = id_ * rnum_;
int64_t range = rnum_ * thnum_;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
if (tran_ && !db_->begin_transaction(false)) {
dberrprint(db_, __LINE__, "DB::begin_transaction");
err_ = true;
}
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld",
(long long)(rnd_ ? myrand(range) + 1 : base + i));
size_t vsiz;
char* vbuf = db_->get(kbuf, ksiz, &vsiz);
if (vbuf) {
if (vsiz < ksiz || std::memcmp(vbuf, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::get");
err_ = true;
}
delete[] vbuf;
} else if (!rnd_ || db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::get");
err_ = true;
}
if (rnd_ && i % 8 == 0) {
switch (myrand(8)) {
case 0: {
if (!db_->set(kbuf, ksiz, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::set");
err_ = true;
}
break;
}
case 1: {
if (!db_->append(kbuf, ksiz, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::append");
err_ = true;
}
break;
}
case 2: {
if (!db_->remove(kbuf, ksiz) &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::remove");
err_ = true;
}
break;
}
case 3: {
kc::DB::Cursor* cur = db_->cursor();
if (cur->jump(kbuf, ksiz)) {
switch (myrand(8)) {
default: {
size_t rsiz;
char* rbuf = cur->get_key(&rsiz, myrand(10) == 0);
if (rbuf) {
delete[] rbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get_key");
err_ = true;
}
break;
}
case 1: {
size_t rsiz;
char* rbuf = cur->get_value(&rsiz, myrand(10) == 0);
if (rbuf) {
delete[] rbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get_value");
err_ = true;
}
break;
}
case 2: {
size_t rksiz;
const char* rvbuf;
size_t rvsiz;
char* rkbuf = cur->get(&rksiz, &rvbuf, &rvsiz, myrand(10) == 0);
if (rkbuf) {
delete[] rkbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get");
err_ = true;
}
break;
}
case 3: {
std::string key, value;
if (!cur->get(&key, &value, myrand(10) == 0) &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get");
err_ = true;
}
break;
}
case 4: {
if (myrand(8) == 0 && !cur->remove() &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::remove");
err_ = true;
}
break;
}
}
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::jump");
err_ = true;
}
delete cur;
break;
}
default: {
size_t vsiz;
char* vbuf = db_->get(kbuf, ksiz, &vsiz);
if (vbuf) {
delete[] vbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::get");
err_ = true;
}
break;
}
}
}
if (tran_ && !db_->end_transaction(true)) {
dberrprint(db_, __LINE__, "DB::end_transaction");
err_ = true;
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::BasicDB* db_;
int64_t rnum_;
int32_t thnum_;
bool err_;
bool rnd_;
bool tran_;
};
ThreadGet threadgets[THREADMAX];
if (thnum < 2) {
threadgets[0].setparams(0, &db, rnum, thnum, rnd, tran);
threadgets[0].run();
if (threadgets[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threadgets[i].setparams(i, &db, rnum, thnum, rnd, tran);
threadgets[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadgets[i].join();
if (threadgets[i].error()) err = true;
}
}
etime = kc::time();
dbmetaprint(&db, false);
oprintf("time: %.3f\n", etime - stime);
if (etc) {
oprintf("getting records with a buffer:\n");
stime = kc::time();
class ThreadGetBuffer : public kc::Thread {
public:
void setparams(int32_t id, kc::BasicDB* db, int64_t rnum, int32_t thnum,
bool rnd, bool tran) {
id_ = id;
db_ = db;
rnum_ = rnum;
thnum_ = thnum;
err_ = false;
rnd_ = rnd;
tran_ = tran;
}
bool error() {
return err_;
}
void run() {
int64_t base = id_ * rnum_;
int64_t range = rnum_ * thnum_;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
if (tran_ && !db_->begin_transaction(false)) {
dberrprint(db_, __LINE__, "DB::begin_transaction");
err_ = true;
}
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld",
(long long)(rnd_ ? myrand(range) + 1 : base + i));
char vbuf[RECBUFSIZ];
int32_t vsiz = db_->get(kbuf, ksiz, vbuf, sizeof(vbuf));
if (vsiz >= 0) {
if (vsiz < (int32_t)ksiz || std::memcmp(vbuf, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::get");
err_ = true;
}
} else if (!rnd_ || db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::get");
err_ = true;
}
if (tran_ && !db_->end_transaction(true)) {
dberrprint(db_, __LINE__, "DB::end_transaction");
err_ = true;
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::BasicDB* db_;
int64_t rnum_;
int32_t thnum_;
bool err_;
bool rnd_;
bool tran_;
};
ThreadGetBuffer threadgetbuffers[THREADMAX];
if (thnum < 2) {
threadgetbuffers[0].setparams(0, &db, rnum, thnum, rnd, tran);
threadgetbuffers[0].run();
if (threadgetbuffers[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threadgetbuffers[i].setparams(i, &db, rnum, thnum, rnd, tran);
threadgetbuffers[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadgetbuffers[i].join();
if (threadgetbuffers[i].error()) err = true;
}
}
etime = kc::time();
dbmetaprint(&db, false);
oprintf("time: %.3f\n", etime - stime);
}
if (etc) {
oprintf("traversing the database by the inner iterator:\n");
stime = kc::time();
int64_t cnt = db.count();
class VisitorIterator : public kc::DB::Visitor {
public:
explicit VisitorIterator(int64_t rnum, bool rnd) :
rnum_(rnum), rnd_(rnd), cnt_(0), rbuf_() {
std::memset(rbuf_, '+', sizeof(rbuf_));
}
int64_t cnt() {
return cnt_;
}
private:
const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) {
cnt_++;
const char* rv = NOP;
switch (rnd_ ? myrand(7) : cnt_ % 7) {
case 0: {
rv = rbuf_;
*sp = rnd_ ? myrand(sizeof(rbuf_)) : sizeof(rbuf_) / (cnt_ % 5 + 1);
break;
}
case 1: {
rv = REMOVE;
break;
}
}
if (rnum_ > 250 && cnt_ % (rnum_ / 250) == 0) {
oputchar('.');
if (cnt_ == rnum_ || cnt_ % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)cnt_);
}
return rv;
}
int64_t rnum_;
bool rnd_;
int64_t cnt_;
char rbuf_[RECBUFSIZ];
} visitoriterator(rnum, rnd);
if (tran && !db.begin_transaction(false)) {
dberrprint(&db, __LINE__, "DB::begin_transaction");
err = true;
}
if (!db.iterate(&visitoriterator, true)) {
dberrprint(&db, __LINE__, "DB::iterate");
err = true;
}
if (rnd) oprintf(" (end)\n");
if (tran && !db.end_transaction(true)) {
dberrprint(&db, __LINE__, "DB::end_transaction");
err = true;
}
if (visitoriterator.cnt() != cnt) {
dberrprint(&db, __LINE__, "DB::iterate");
err = true;
}
etime = kc::time();
dbmetaprint(&db, false);
oprintf("time: %.3f\n", etime - stime);
}
if (etc) {
oprintf("traversing the database by the outer cursor:\n");
stime = kc::time();
int64_t cnt = db.count();
class VisitorCursor : public kc::DB::Visitor {
public:
explicit VisitorCursor(int64_t rnum, bool rnd) :
rnum_(rnum), rnd_(rnd), cnt_(0), rbuf_() {
std::memset(rbuf_, '-', sizeof(rbuf_));
}
int64_t cnt() {
return cnt_;
}
private:
const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) {
cnt_++;
const char* rv = NOP;
switch (rnd_ ? myrand(7) : cnt_ % 7) {
case 0: {
rv = rbuf_;
*sp = rnd_ ? myrand(sizeof(rbuf_)) : sizeof(rbuf_) / (cnt_ % 5 + 1);
break;
}
case 1: {
rv = REMOVE;
break;
}
}
if (rnum_ > 250 && cnt_ % (rnum_ / 250) == 0) {
oputchar('.');
if (cnt_ == rnum_ || cnt_ % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)cnt_);
}
return rv;
}
int64_t rnum_;
bool rnd_;
int64_t cnt_;
char rbuf_[RECBUFSIZ];
} visitorcursor(rnum, rnd);
if (tran && !db.begin_transaction(false)) {
dberrprint(&db, __LINE__, "DB::begin_transaction");
err = true;
}
typename PROTODB::Cursor cur(&db);
if (!cur.jump() && db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, __LINE__, "Cursor::jump");
err = true;
}
kc::DB::Cursor* paracur = db.cursor();
int64_t range = rnum * thnum;
while (!err && cur.accept(&visitorcursor, true, !rnd)) {
if (rnd) {
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld", (long long)myrand(range));
switch (myrand(3)) {
case 0: {
if (!db.remove(kbuf, ksiz) && db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, __LINE__, "DB::remove");
err = true;
}
break;
}
case 1: {
if (!paracur->jump(kbuf, ksiz) && db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, __LINE__, "Cursor::jump");
err = true;
}
break;
}
default: {
if (!cur.step() && db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, __LINE__, "Cursor::step");
err = true;
}
break;
}
}
}
}
if (db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, __LINE__, "Cursor::accept");
err = true;
}
oprintf(" (end)\n");
delete paracur;
if (tran && !db.end_transaction(true)) {
dberrprint(&db, __LINE__, "DB::end_transaction");
err = true;
}
if (!rnd && visitorcursor.cnt() != cnt) {
dberrprint(&db, __LINE__, "Cursor::accept");
err = true;
}
etime = kc::time();
dbmetaprint(&db, false);
oprintf("time: %.3f\n", etime - stime);
}
if (etc) {
oprintf("synchronizing the database:\n");
stime = kc::time();
if (!db.synchronize(false, NULL)) {
dberrprint(&db, __LINE__, "DB::synchronize");
err = true;
}
class SyncProcessor : public kc::BasicDB::FileProcessor {
public:
explicit SyncProcessor(int64_t rnum, bool rnd, int64_t size) :
rnum_(rnum), rnd_(rnd), size_(size) {}
private:
bool process(const std::string& path, int64_t count, int64_t size) {
if (size != size_) return false;
return true;
}
int64_t rnum_;
bool rnd_;
int64_t size_;
} syncprocessor(rnum, rnd, db.size());
if (!db.synchronize(false, &syncprocessor)) {
dberrprint(&db, __LINE__, "DB::synchronize");
err = true;
}
if (!db.occupy(rnd ? myrand(2) == 0 : true, &syncprocessor)) {
dberrprint(&db, __LINE__, "DB::occupy");
err = true;
}
etime = kc::time();
dbmetaprint(&db, false);
oprintf("time: %.3f\n", etime - stime);
}
if (etc && db.size() < (256LL << 20)) {
oprintf("dumping records into snapshot:\n");
stime = kc::time();
std::ostringstream ostrm;
if (!db.dump_snapshot(&ostrm)) {
dberrprint(&db, __LINE__, "DB::dump_snapshot");
err = true;
}
etime = kc::time();
dbmetaprint(&db, false);
oprintf("time: %.3f\n", etime - stime);
oprintf("loading records from snapshot:\n");
stime = kc::time();
int64_t cnt = db.count();
if (rnd && myrand(2) == 0 && !db.clear()) {
dberrprint(&db, __LINE__, "DB::clear");
err = true;
}
const std::string& str = ostrm.str();
std::istringstream istrm(str);
if (!db.load_snapshot(&istrm) || db.count() != cnt) {
dberrprint(&db, __LINE__, "DB::load_snapshot");
err = true;
}
etime = kc::time();
dbmetaprint(&db, false);
oprintf("time: %.3f\n", etime - stime);
}
oprintf("removing records:\n");
stime = kc::time();
class ThreadRemove : public kc::Thread {
public:
void setparams(int32_t id, kc::BasicDB* db, int64_t rnum, int32_t thnum,
bool rnd, bool etc, bool tran) {
id_ = id;
db_ = db;
rnum_ = rnum;
thnum_ = thnum;
err_ = false;
rnd_ = rnd;
etc_ = etc;
tran_ = tran;
}
bool error() {
return err_;
}
void run() {
int64_t base = id_ * rnum_;
int64_t range = rnum_ * thnum_;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
if (tran_ && !db_->begin_transaction(false)) {
dberrprint(db_, __LINE__, "DB::begin_transaction");
err_ = true;
}
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld",
(long long)(rnd_ ? myrand(range) + 1 : base + i));
if (!db_->remove(kbuf, ksiz) &&
((!rnd_ && !etc_) || db_->error() != kc::BasicDB::Error::NOREC)) {
dberrprint(db_, __LINE__, "DB::remove");
err_ = true;
}
if (rnd_ && i % 8 == 0) {
switch (myrand(8)) {
case 0: {
if (!db_->set(kbuf, ksiz, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::set");
err_ = true;
}
break;
}
case 1: {
if (!db_->append(kbuf, ksiz, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::append");
err_ = true;
}
break;
}
case 2: {
if (!db_->remove(kbuf, ksiz) &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::remove");
err_ = true;
}
break;
}
case 3: {
kc::DB::Cursor* cur = db_->cursor();
if (cur->jump(kbuf, ksiz)) {
switch (myrand(8)) {
default: {
size_t rsiz;
char* rbuf = cur->get_key(&rsiz, myrand(10) == 0);
if (rbuf) {
delete[] rbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get_key");
err_ = true;
}
break;
}
case 1: {
size_t rsiz;
char* rbuf = cur->get_value(&rsiz, myrand(10) == 0);
if (rbuf) {
delete[] rbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get_value");
err_ = true;
}
break;
}
case 2: {
size_t rksiz;
const char* rvbuf;
size_t rvsiz;
char* rkbuf = cur->get(&rksiz, &rvbuf, &rvsiz, myrand(10) == 0);
if (rkbuf) {
delete[] rkbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get");
err_ = true;
}
break;
}
case 3: {
std::string key, value;
if (!cur->get(&key, &value, myrand(10) == 0) &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get");
err_ = true;
}
break;
}
case 4: {
if (myrand(8) == 0 && !cur->remove() &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::remove");
err_ = true;
}
break;
}
}
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::jump");
err_ = true;
}
delete cur;
break;
}
default: {
size_t vsiz;
char* vbuf = db_->get(kbuf, ksiz, &vsiz);
if (vbuf) {
delete[] vbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::get");
err_ = true;
}
break;
}
}
}
if (tran_ && !db_->end_transaction(true)) {
dberrprint(db_, __LINE__, "DB::end_transaction");
err_ = true;
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::BasicDB* db_;
int64_t rnum_;
int32_t thnum_;
bool err_;
bool rnd_;
bool etc_;
bool tran_;
};
ThreadRemove threadremoves[THREADMAX];
if (thnum < 2) {
threadremoves[0].setparams(0, &db, rnum, thnum, rnd, etc, tran);
threadremoves[0].run();
if (threadremoves[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threadremoves[i].setparams(i, &db, rnum, thnum, rnd, etc, tran);
threadremoves[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadremoves[i].join();
if (threadremoves[i].error()) err = true;
}
}
etime = kc::time();
dbmetaprint(&db, true);
oprintf("time: %.3f\n", etime - stime);
oprintf("closing the database:\n");
stime = kc::time();
if (!db.close()) {
dberrprint(&db, __LINE__, "DB::close");
err = true;
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("%s\n\n", err ? "error" : "ok");
return err ? 1 : 0;
}
// perform queue command
template
static int32_t procqueue(const char* tname, int64_t rnum, int32_t thnum, int32_t itnum,
bool rnd) {
oprintf("<%s Queue Test>\n seed=%u rnum=%lld thnum=%d itnum=%d rnd=%d\n\n",
tname, g_randseed, (long long)rnum, thnum, itnum, rnd);
bool err = false;
PROTODB db;
for (int32_t itcnt = 1; itcnt <= itnum; itcnt++) {
if (itnum > 1) oprintf("iteration %d:\n", itcnt);
double stime = kc::time();
uint32_t omode = PROTODB::OWRITER | PROTODB::OCREATE;
if (itcnt == 1) omode |= PROTODB::OTRUNCATE;
if (!db.open("-", omode)) {
dberrprint(&db, __LINE__, "DB::open");
err = true;
}
class ThreadQueue : public kc::Thread {
public:
void setparams(int32_t id, PROTODB* db, int64_t rnum, int32_t thnum, bool rnd,
int64_t width) {
id_ = id;
db_ = db;
rnum_ = rnum;
thnum_ = thnum;
rnd_ = rnd;
width_ = width;
err_ = false;
}
bool error() {
return err_;
}
void run() {
kc::DB::Cursor* cur = db_->cursor();
int64_t base = id_ * rnum_;
int64_t range = rnum_ * thnum_;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%010lld", (long long)(base + i));
if (!db_->set(kbuf, ksiz, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::set");
err_ = true;
}
if (rnd_) {
if (myrand(width_ / 2) == 0) {
if (!cur->jump() && db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::jump");
err_ = true;
}
ksiz = std::sprintf(kbuf, "%010lld", (long long)myrand(range) + 1);
switch (myrand(10)) {
case 0: {
if (!db_->set(kbuf, ksiz, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::set");
err_ = true;
}
break;
}
case 1: {
if (!db_->append(kbuf, ksiz, kbuf, ksiz)) {
dberrprint(db_, __LINE__, "DB::append");
err_ = true;
}
break;
}
case 2: {
if (!db_->remove(kbuf, ksiz) &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::remove");
err_ = true;
}
break;
}
}
int64_t dnum = myrand(width_) + 2;
for (int64_t j = 0; j < dnum; j++) {
if (myrand(2) == 0) {
size_t rsiz;
char* rbuf = cur->get_key(&rsiz);
if (rbuf) {
if (myrand(10) == 0 && !db_->remove(rbuf, rsiz) &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::remove");
err_ = true;
}
if (myrand(2) == 0 && !cur->jump(rbuf, rsiz) &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::jump");
err_ = true;
}
if (myrand(10) == 0 && !db_->remove(rbuf, rsiz) &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::remove");
err_ = true;
}
delete[] rbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get_key");
err_ = true;
}
}
if (!cur->remove() && db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::remove");
err_ = true;
}
}
}
} else {
if (i > width_) {
if (!cur->jump() && db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::jump");
err_ = true;
}
if (!cur->remove() && db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::remove");
err_ = true;
}
}
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
delete cur;
}
private:
int32_t id_;
PROTODB* db_;
int64_t rnum_;
int32_t thnum_;
bool rnd_;
int64_t width_;
bool err_;
};
int64_t width = rnum / 10;
ThreadQueue threads[THREADMAX];
if (thnum < 2) {
threads[0].setparams(0, &db, rnum, thnum, rnd, width);
threads[0].run();
if (threads[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threads[i].setparams(i, &db, rnum, thnum, rnd, width);
threads[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threads[i].join();
if (threads[i].error()) err = true;
}
}
int64_t count = db.count();
if (!rnd && itcnt == 1 && count != width * thnum) {
dberrprint(&db, __LINE__, "DB::count");
err = true;
}
if ((rnd ? (myrand(2) == 0) : itcnt == itnum) && count > 0) {
kc::DB::Cursor* cur = db.cursor();
if (!cur->jump()) {
dberrprint(&db, __LINE__, "Cursor::jump");
err = true;
}
for (int64_t i = 1; i <= count; i++) {
if (!cur->remove()) {
dberrprint(&db, __LINE__, "Cursor::remove");
err = true;
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
if (rnd) oprintf(" (end)\n");
delete cur;
if (db.count() != 0) {
dberrprint(&db, __LINE__, "DB::count");
err = true;
}
}
dbmetaprint(&db, itcnt == itnum);
if (!db.close()) {
dberrprint(&db, __LINE__, "DB::close");
err = true;
}
oprintf("time: %.3f\n", kc::time() - stime);
}
oprintf("%s\n\n", err ? "error" : "ok");
return err ? 1 : 0;
}
// perform wicked command
template
static int32_t procwicked(const char* tname, int64_t rnum, int32_t thnum, int32_t itnum) {
oprintf("<%s Wicked Test>\n seed=%u rnum=%lld thnum=%d itnum=%d\n\n",
tname, g_randseed, (long long)rnum, thnum, itnum);
bool err = false;
PROTODB db;
for (int32_t itcnt = 1; itcnt <= itnum; itcnt++) {
if (itnum > 1) oprintf("iteration %d:\n", itcnt);
double stime = kc::time();
uint32_t omode = kc::BasicDB::OWRITER | kc::BasicDB::OCREATE;
if (itcnt == 1) omode |= kc::BasicDB::OTRUNCATE;
if (!db.open("-", omode)) {
dberrprint(&db, __LINE__, "DB::open");
err = true;
}
class ThreadWicked : public kc::Thread {
public:
void setparams(int32_t id, PROTODB* db, int64_t rnum, int32_t thnum,
const char* lbuf) {
id_ = id;
db_ = db;
rnum_ = rnum;
thnum_ = thnum;
lbuf_ = lbuf;
err_ = false;
}
bool error() {
return err_;
}
void run() {
kc::DB::Cursor* cur = db_->cursor();
int64_t range = rnum_ * thnum_ / 2;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
bool tran = myrand(100) == 0;
if (tran) {
if (myrand(2) == 0) {
if (!db_->begin_transaction(myrand(rnum_) == 0)) {
dberrprint(db_, __LINE__, "DB::begin_transaction");
tran = false;
err_ = true;
}
} else {
if (!db_->begin_transaction_try(myrand(rnum_) == 0)) {
if (db_->error() != kc::BasicDB::Error::LOGIC) {
dberrprint(db_, __LINE__, "DB::begin_transaction_try");
err_ = true;
}
tran = false;
}
}
}
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%lld", (long long)(myrand(range) + 1));
if (myrand(1000) == 0) {
ksiz = myrand(RECBUFSIZ) + 1;
if (myrand(2) == 0) {
for (size_t j = 0; j < ksiz; j++) {
kbuf[j] = j;
}
} else {
for (size_t j = 0; j < ksiz; j++) {
kbuf[j] = myrand(256);
}
}
}
const char* vbuf = kbuf;
size_t vsiz = ksiz;
if (myrand(10) == 0) {
vbuf = lbuf_;
vsiz = myrand(RECBUFSIZL) / (myrand(5) + 1);
}
do {
switch (myrand(10)) {
case 0: {
if (!db_->set(kbuf, ksiz, vbuf, vsiz)) {
dberrprint(db_, __LINE__, "DB::set");
err_ = true;
}
break;
}
case 1: {
if (!db_->add(kbuf, ksiz, vbuf, vsiz) &&
db_->error() != kc::BasicDB::Error::DUPREC) {
dberrprint(db_, __LINE__, "DB::add");
err_ = true;
}
break;
}
case 2: {
if (!db_->replace(kbuf, ksiz, vbuf, vsiz) &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::replace");
err_ = true;
}
break;
}
case 3: {
if (!db_->append(kbuf, ksiz, vbuf, vsiz)) {
dberrprint(db_, __LINE__, "DB::append");
err_ = true;
}
break;
}
case 4: {
if (myrand(2) == 0) {
int64_t num = myrand(rnum_);
int64_t orig = myrand(10) == 0 ? kc::INT64MIN : myrand(rnum_);
if (myrand(10) == 0) orig = orig == kc::INT64MIN ? kc::INT64MAX : -orig;
if (db_->increment(kbuf, ksiz, num, orig) == kc::INT64MIN &&
db_->error() != kc::BasicDB::Error::LOGIC) {
dberrprint(db_, __LINE__, "DB::increment");
err_ = true;
}
} else {
double num = myrand(rnum_ * 10) / (myrand(rnum_) + 1.0);
double orig = myrand(10) == 0 ? -kc::inf() : myrand(rnum_);
if (myrand(10) == 0) orig = -orig;
if (kc::chknan(db_->increment_double(kbuf, ksiz, num, orig)) &&
db_->error() != kc::BasicDB::Error::LOGIC) {
dberrprint(db_, __LINE__, "DB::increment_double");
err_ = true;
}
}
break;
}
case 5: {
if (!db_->cas(kbuf, ksiz, kbuf, ksiz, vbuf, vsiz) &&
db_->error() != kc::BasicDB::Error::LOGIC) {
dberrprint(db_, __LINE__, "DB::cas");
err_ = true;
}
break;
}
case 6: {
if (!db_->remove(kbuf, ksiz) &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::remove");
err_ = true;
}
break;
}
case 7: {
if (myrand(2) == 0) {
if (db_->check(kbuf, ksiz) < 0 && db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::check");
err_ = true;
}
} else {
size_t rsiz;
char* rbuf = db_->seize(kbuf, ksiz, &rsiz);
if (rbuf) {
delete[] rbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::seize");
err_ = true;
}
}
break;
}
case 8: {
if (myrand(10) == 0) {
if (myrand(4) == 0) {
if (!cur->jump_back(kbuf, ksiz) &&
db_->error() != kc::BasicDB::Error::NOIMPL &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::jump_back");
err_ = true;
}
} else {
if (!cur->jump(kbuf, ksiz) &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::jump");
err_ = true;
}
}
} else {
class VisitorImpl : public kc::DB::Visitor {
public:
explicit VisitorImpl(const char* lbuf) : lbuf_(lbuf) {}
private:
const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) {
const char* rv = NOP;
switch (myrand(3)) {
case 0: {
rv = lbuf_;
*sp = myrand(RECBUFSIZL) / (myrand(5) + 1);
break;
}
case 1: {
rv = REMOVE;
break;
}
}
return rv;
}
const char* lbuf_;
} visitor(lbuf_);
if (!cur->accept(&visitor, true, myrand(2) == 0) &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::accept");
err_ = true;
}
if (myrand(5) > 0 && !cur->step() &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::step");
err_ = true;
}
}
break;
}
default: {
size_t rsiz;
char* rbuf = db_->get(kbuf, ksiz, &rsiz);
if (rbuf) {
delete[] rbuf;
} else if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "DB::get");
err_ = true;
}
break;
}
}
} while (myrand(100) == 0);
if (myrand(100) == 0) {
int32_t jnum = myrand(10);
switch (myrand(4)) {
case 0: {
std::map recs;
for (int32_t j = 0; j < jnum; j++) {
char jbuf[RECBUFSIZ];
size_t jsiz = std::sprintf(jbuf, "%lld", (long long)(myrand(range) + 1));
recs[std::string(jbuf, jsiz)] = std::string(kbuf, ksiz);
}
if (db_->set_bulk(recs, myrand(4)) != (int64_t)recs.size()) {
dberrprint(db_, __LINE__, "DB::set_bulk");
err_ = true;
}
break;
}
case 1: {
std::vector keys;
for (int32_t j = 0; j < jnum; j++) {
char jbuf[RECBUFSIZ];
size_t jsiz = std::sprintf(jbuf, "%lld", (long long)(myrand(range) + 1));
keys.push_back(std::string(jbuf, jsiz));
}
if (db_->remove_bulk(keys, myrand(4)) < 0) {
dberrprint(db_, __LINE__, "DB::remove_bulk");
err_ = true;
}
break;
}
default: {
std::vector keys;
for (int32_t j = 0; j < jnum; j++) {
char jbuf[RECBUFSIZ];
size_t jsiz = std::sprintf(jbuf, "%lld", (long long)(myrand(range) + 1));
keys.push_back(std::string(jbuf, jsiz));
}
std::map recs;
if (db_->get_bulk(keys, &recs, myrand(4)) < 0) {
dberrprint(db_, __LINE__, "DB::get_bulk");
err_ = true;
}
break;
}
}
}
if (i == rnum_ / 2) {
if (myrand(thnum_ * 4) == 0) {
if (!db_->clear()) {
dberrprint(db_, __LINE__, "DB::clear");
err_ = true;
}
} else {
class SyncProcessor : public kc::BasicDB::FileProcessor {
private:
bool process(const std::string& path, int64_t count, int64_t size) {
yield();
return true;
}
} syncprocessor;
if (!db_->synchronize(false, &syncprocessor)) {
dberrprint(db_, __LINE__, "DB::synchronize");
err_ = true;
}
}
}
if (tran) {
yield();
if (!db_->end_transaction(myrand(10) > 0)) {
dberrprint(db_, __LINE__, "DB::end_transactin");
err_ = true;
}
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
delete cur;
}
private:
int32_t id_;
PROTODB* db_;
int64_t rnum_;
int32_t thnum_;
const char* lbuf_;
bool err_;
};
char lbuf[RECBUFSIZL];
std::memset(lbuf, '*', sizeof(lbuf));
ThreadWicked threads[THREADMAX];
if (thnum < 2) {
threads[0].setparams(0, &db, rnum, thnum, lbuf);
threads[0].run();
if (threads[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threads[i].setparams(i, &db, rnum, thnum, lbuf);
threads[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threads[i].join();
if (threads[i].error()) err = true;
}
}
dbmetaprint(&db, itcnt == itnum);
if (!db.close()) {
dberrprint(&db, __LINE__, "DB::close");
err = true;
}
oprintf("time: %.3f\n", kc::time() - stime);
}
oprintf("%s\n\n", err ? "error" : "ok");
return err ? 1 : 0;
}
// perform order command
template
static int32_t proctran(const char* tname, int64_t rnum, int32_t thnum, int32_t itnum) {
oprintf("<%s Transaction Test>\n seed=%u rnum=%lld thnum=%d itnum=%d\n\n",
tname, g_randseed, (long long)rnum, thnum, itnum);
bool err = false;
PROTODB db;
PROTODB paradb;
for (int32_t itcnt = 1; itcnt <= itnum; itcnt++) {
oprintf("iteration %d updating:\n", itcnt);
double stime = kc::time();
uint32_t omode = kc::BasicDB::OWRITER | kc::BasicDB::OCREATE;
if (itcnt == 1) omode |= kc::BasicDB::OTRUNCATE;
if (!db.open("-", omode)) {
dberrprint(&db, __LINE__, "DB::open");
err = true;
}
if (!paradb.open("para", omode)) {
dberrprint(¶db, __LINE__, "DB::open");
err = true;
}
class ThreadTran : public kc::Thread {
public:
void setparams(int32_t id, PROTODB* db, PROTODB* paradb, int64_t rnum,
int32_t thnum, const char* lbuf) {
id_ = id;
db_ = db;
paradb_ = paradb;
rnum_ = rnum;
thnum_ = thnum;
lbuf_ = lbuf;
err_ = false;
}
bool error() {
return err_;
}
void run() {
kc::DB::Cursor* cur = db_->cursor();
int64_t range = rnum_ * thnum_;
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%lld", (long long)(myrand(range) + 1));
if (!cur->jump(kbuf, ksiz) && db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::jump");
err_ = true;
}
bool tran = true;
if (!db_->begin_transaction(false)) {
dberrprint(db_, __LINE__, "DB::begin_transaction");
tran = false;
err_ = true;
}
bool commit = myrand(10) > 0;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
ksiz = std::sprintf(kbuf, "%lld", (long long)(myrand(range) + 1));
const char* vbuf = kbuf;
size_t vsiz = ksiz;
if (myrand(10) == 0) {
vbuf = lbuf_;
vsiz = myrand(RECBUFSIZL) / (myrand(5) + 1);
}
class VisitorImpl : public kc::DB::Visitor {
public:
explicit VisitorImpl(const char* vbuf, size_t vsiz, kc::BasicDB* paradb) :
vbuf_(vbuf), vsiz_(vsiz), paradb_(paradb) {}
private:
const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) {
return visit_empty(kbuf, ksiz, sp);
}
const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) {
const char* rv = NOP;
switch (myrand(3)) {
case 0: {
rv = vbuf_;
*sp = vsiz_;
if (paradb_) paradb_->set(kbuf, ksiz, vbuf_, vsiz_);
break;
}
case 1: {
rv = REMOVE;
if (paradb_) paradb_->remove(kbuf, ksiz);
break;
}
}
return rv;
}
const char* vbuf_;
size_t vsiz_;
kc::BasicDB* paradb_;
} visitor(vbuf, vsiz, !tran || commit ? paradb_ : NULL);
if (myrand(4) == 0) {
if (!cur->accept(&visitor, true, myrand(2) == 0) &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::accept");
err_ = true;
}
} else {
if (!db_->accept(kbuf, ksiz, &visitor, true)) {
dberrprint(db_, __LINE__, "DB::accept");
err_ = true;
}
}
if (myrand(1000) == 0) {
ksiz = std::sprintf(kbuf, "%lld", (long long)(myrand(range) + 1));
if (!cur->jump(kbuf, ksiz)) {
if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::jump");
err_ = true;
} else if (!cur->jump() && db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::jump");
err_ = true;
}
}
std::vector keys;
keys.reserve(100);
while (myrand(50) != 0) {
std::string key;
if (cur->get_key(&key)) {
keys.push_back(key);
if (!cur->get_value(&key) && db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get_value");
err_ = true;
}
} else {
if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::get_key");
err_ = true;
}
break;
}
if (!cur->step()) {
if (db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::jump");
err_ = true;
}
break;
}
}
class Remover : public kc::DB::Visitor {
public:
explicit Remover(kc::BasicDB* paradb) : paradb_(paradb) {}
private:
const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) {
if (myrand(200) == 0) return NOP;
if (paradb_) paradb_->remove(kbuf, ksiz);
return REMOVE;
}
kc::BasicDB* paradb_;
} remover(!tran || commit ? paradb_ : NULL);
std::vector::iterator it = keys.begin();
std::vector::iterator end = keys.end();
while (it != end) {
if (myrand(50) == 0) {
if (!cur->accept(&remover, true, false) &&
db_->error() != kc::BasicDB::Error::NOREC) {
dberrprint(db_, __LINE__, "Cursor::accept");
err_ = true;
}
} else {
if (!db_->accept(it->c_str(), it->size(), &remover, true)) {
dberrprint(db_, __LINE__, "DB::accept");
err_ = true;
}
}
++it;
}
}
if (tran && myrand(100) == 0) {
if (db_->end_transaction(commit)) {
yield();
if (!db_->begin_transaction(false)) {
dberrprint(db_, __LINE__, "DB::begin_transaction");
tran = false;
err_ = true;
}
} else {
dberrprint(db_, __LINE__, "DB::end_transaction");
err_ = true;
}
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
if (tran && !db_->end_transaction(commit)) {
dberrprint(db_, __LINE__, "DB::end_transaction");
err_ = true;
}
delete cur;
}
private:
int32_t id_;
PROTODB* db_;
PROTODB* paradb_;
int64_t rnum_;
int32_t thnum_;
const char* lbuf_;
bool err_;
};
char lbuf[RECBUFSIZL];
std::memset(lbuf, '*', sizeof(lbuf));
ThreadTran threads[THREADMAX];
if (thnum < 2) {
threads[0].setparams(0, &db, ¶db, rnum, thnum, lbuf);
threads[0].run();
if (threads[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threads[i].setparams(i, &db, ¶db, rnum, thnum, lbuf);
threads[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threads[i].join();
if (threads[i].error()) err = true;
}
}
oprintf("iteration %d checking:\n", itcnt);
if (db.count() != paradb.count()) {
dberrprint(&db, __LINE__, "DB::count");
err = true;
}
class VisitorImpl : public kc::DB::Visitor {
public:
explicit VisitorImpl(int64_t rnum, kc::BasicDB* paradb) :
rnum_(rnum), paradb_(paradb), err_(false), cnt_(0) {}
bool error() {
return err_;
}
private:
const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) {
cnt_++;
size_t rsiz;
char* rbuf = paradb_->get(kbuf, ksiz, &rsiz);
if (rbuf) {
delete[] rbuf;
} else {
dberrprint(paradb_, __LINE__, "DB::get");
err_ = true;
}
if (rnum_ > 250 && cnt_ % (rnum_ / 250) == 0) {
oputchar('.');
if (cnt_ == rnum_ || cnt_ % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)cnt_);
}
return NOP;
}
int64_t rnum_;
kc::BasicDB* paradb_;
bool err_;
int64_t cnt_;
} visitor(rnum, ¶db), paravisitor(rnum, &db);
if (!db.iterate(&visitor, false)) {
dberrprint(&db, __LINE__, "DB::iterate");
err = true;
}
oprintf(" (end)\n");
if (visitor.error()) err = true;
if (!paradb.iterate(¶visitor, false)) {
dberrprint(&db, __LINE__, "DB::iterate");
err = true;
}
oprintf(" (end)\n");
if (paravisitor.error()) err = true;
if (!paradb.close()) {
dberrprint(¶db, __LINE__, "DB::close");
err = true;
}
dbmetaprint(&db, itcnt == itnum);
if (!db.close()) {
dberrprint(&db, __LINE__, "DB::close");
err = true;
}
oprintf("time: %.3f\n", kc::time() - stime);
}
oprintf("%s\n\n", err ? "error" : "ok");
return err ? 1 : 0;
}
// END OF FILE
kyotocabinet-1.2.80/kcregex.h 0000664 0001750 0001750 00000010342 14416044124 015102 0 ustar mikio mikio /*************************************************************************************************
* Regular expression
* Copyright (C) 2009-2012 Mikio Hirabayashi
* This file is part of Kyoto Cabinet.
* This program is free software: you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation, either version
* 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with this program.
* If not, see .
*************************************************************************************************/
#ifndef _KCREGEX_H // duplication check
#define _KCREGEX_H
#include
#include
namespace kyotocabinet { // common namespace
/**
* Regular expression.
*/
class Regex {
public:
/**
* Options.
*/
enum Option {
IGNCASE = 1 << 0, ///< case-insensitive
MATCHONLY = 1 << 1, ///< matching only
};
/**
* Default constructor.
*/
explicit Regex();
/**
* Destructor.
*/
~Regex();
/**
* Compile a string of regular expression.
* @param regex the string of regular expression.
* @param opts the optional features by bitwise-or: Regex::IGNCASE for case-insensitive
* matching, Regex::MATCHONLY for matching only usage.
*/
bool compile(const std::string& regex, uint32_t opts = 0);
/**
* Check whether a string matches the regular expression.
* @param str the string.
* @return true if the string matches, or false if not.
*/
bool match(const std::string& str);
/**
* Check whether a string matches the regular expression.
* @param str the string.
* @param alt the alternative string with which each substring is replaced. Each "$" in the
* string escapes the following character. Special escapes "$1" through "$9" refer to partial
* substrings corresponding to sub-expressions in the regular expression. "$0" and "$&" refer
* to the whole matching substring.
* @return the result string.
*/
std::string replace(const std::string& str, const std::string& alt);
/**
* Check whether a string matches a regular expression.
* @param str the string.
* @param pattern the matching pattern.
* @param opts the optional features by bitwise-or: Regex::IGNCASE for case-insensitive
* matching, Regex::MATCHONLY for matching only usage.
* @return true if the string matches, or false if not.
*/
static bool match(const std::string& str, const std::string& pattern, uint32_t opts = 0) {
Regex regex;
if (!regex.compile(pattern, opts)) return false;
return regex.match(str);
}
/**
* Check whether a string matches the regular expression.
* @param str the string.
* @param pattern the matching pattern.
* @param alt the alternative string with which each substring is replaced. Each "$" in the
* string escapes the following character. Special escapes "$1" through "$9" refer to partial
* substrings corresponding to sub-expressions in the regular expression. "$0" and "$&" refer
* to the whole matching substring.
* @param opts the optional features by bitwise-or: Regex::IGNCASE for case-insensitive
* matching, Regex::MATCHONLY for matching only usage.
* @return the result string.
*/
static std::string replace(const std::string& str, const std::string& pattern,
const std::string& alt, uint32_t opts = 0) {
Regex regex;
if (!regex.compile(pattern, opts)) return str;
return regex.replace(str, alt);
}
private:
/** Dummy constructor to forbid the use. */
Regex(const Regex&);
/** Dummy Operator to forbid the use. */
Regex& operator =(const Regex&);
/** Opaque pointer. */
void* opq_;
};
} // common namespace
#endif // duplication check
// END OF FILE
kyotocabinet-1.2.80/kcdbext.cc 0000664 0001750 0001750 00000002252 14416044124 015235 0 ustar mikio mikio /*************************************************************************************************
* Database extension
* Copyright (C) 2009-2012 Mikio Hirabayashi
* This file is part of Kyoto Cabinet.
* This program is free software: you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation, either version
* 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with this program.
* If not, see .
*************************************************************************************************/
#include "kcdbext.h"
#include "myconf.h"
namespace kyotocabinet { // common namespace
// There is no implementation now.
} // common namespace
// END OF FILE
kyotocabinet-1.2.80/myconf.h 0000664 0001750 0001750 00000012353 14416044124 014751 0 ustar mikio mikio /*************************************************************************************************
* System-dependent configurations
* Copyright (C) 2009-2012 Mikio Hirabayashi
* This file is part of Kyoto Cabinet.
* This program is free software: you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation, either version
* 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with this program.
* If not, see .
*************************************************************************************************/
#ifndef _MYCONF_H // duplication check
#define _MYCONF_H
/*************************************************************************************************
* system discrimination
*************************************************************************************************/
#if defined(__linux__)
#define _SYS_LINUX_
#define _KC_OSNAME "Linux"
#elif defined(__FreeBSD__)
#define _SYS_FREEBSD_
#define _KC_OSNAME "FreeBSD"
#elif defined(__NetBSD__)
#define _SYS_NETBSD_
#define _KC_OSNAME "NetBSD"
#elif defined(__OpenBSD__)
#define _SYS_OPENBSD_
#define _KC_OSNAME "OpenBSD"
#elif defined(__sun__) || defined(__sun)
#define _SYS_SUNOS_
#define _KC_OSNAME "SunOS"
#elif defined(__hpux)
#define _SYS_HPUX_
#define _KC_OSNAME "HP-UX"
#elif defined(__osf)
#define _SYS_TRU64_
#define _KC_OSNAME "Tru64"
#elif defined(_AIX)
#define _SYS_AIX_
#define _KC_OSNAME "AIX"
#elif defined(__APPLE__) && defined(__MACH__)
#define _SYS_MACOSX_
#define _KC_OSNAME "Mac OS X"
#elif defined(_MSC_VER)
#define _SYS_MSVC_
#define _KC_OSNAME "Windows (VC++)"
#elif defined(_WIN32)
#define _SYS_MINGW_
#define _KC_OSNAME "Windows (MinGW)"
#elif defined(__CYGWIN__)
#define _SYS_CYGWIN_
#define _KC_OSNAME "Windows (Cygwin)"
#else
#define _SYS_GENERIC_
#define _KC_OSNAME "Generic"
#endif
#define _KC_VERSION "1.2.80"
#define _KC_LIBVER 16
#define _KC_LIBREV 14
#define _KC_FMTVER 6
#if defined(_MYBIGEND)
#define _KC_BIGEND 1
#else
#define _KC_BIGEND 0
#endif
#if defined(_MYGCCATOMIC)
#define _KC_GCCATOMIC 1
#else
#define _KC_GCCATOMIC 0
#endif
#if defined(_MYZLIB)
#define _KC_ZLIB 1
#else
#define _KC_ZLIB 0
#endif
#if defined(_MYLZO)
#define _KC_LZO 1
#else
#define _KC_LZO 0
#endif
#if defined(_MYLZMA)
#define _KC_LZMA 1
#else
#define _KC_LZMA 0
#endif
#if defined(_SYS_MSVC_)
#define _KC_PXREGEX 0
#else
#define _KC_PXREGEX 1
#endif
/*************************************************************************************************
* notation of the file system
*************************************************************************************************/
#if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
#define MYPATHCHR '\\'
#define MYPATHSTR "\\"
#define MYEXTCHR '.'
#define MYEXTSTR "."
#define MYCDIRSTR "."
#define MYPDIRSTR ".."
#else
#define MYPATHCHR '/'
#define MYPATHSTR "/"
#define MYEXTCHR '.'
#define MYEXTSTR "."
#define MYCDIRSTR "."
#define MYPDIRSTR ".."
#endif
/*************************************************************************************************
* general headers
*************************************************************************************************/
extern "C" {
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
}
extern "C" {
#include
}
#if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
#include
#include
#include
#include
#include
#include
#include
#else
extern "C" {
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
}
extern "C" {
#include
#include
}
#endif
#if defined(_SYS_FREEBSD_) || defined(_SYS_OPENBSD_) || defined(_SYS_NETBSD_) || \
defined(_SYS_MACOSX_)
#define pthread_spinlock_t pthread_mutex_t
#define pthread_spin_init(KC_a, KC_b) \
pthread_mutex_init(KC_a, NULL)
#define pthread_spin_destroy(KC_a) \
pthread_mutex_destroy(KC_a)
#define pthread_spin_lock(KC_a) \
pthread_mutex_lock(KC_a)
#define pthread_spin_trylock(KC_a) \
pthread_mutex_trylock(KC_a)
#define pthread_spin_unlock(KC_a) \
pthread_mutex_unlock(KC_a)
#endif
#endif // duplication check
// END OF FILE
kyotocabinet-1.2.80/kyotocabinet.idl 0000664 0001750 0001750 00000024010 14416044124 016463 0 ustar mikio mikio /*************************************************************************************************
* IDL for bindings of scripting languages
* Copyright (C) 2009-2012 FAL Labs
* This file is part of Kyoto Cabinet.
* This program is free software: you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation, either version
* 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with this program.
* If not, see .
*************************************************************************************************/
/**
* namespace of Kyoto Cabinet
*/
module kyotocabinet {
//----------------------------------------------------------------
// prediction
//----------------------------------------------------------------
interface List;
interface Map;
interface Error;
interface Visitor;
interface FileProcessor;
interface Logger;
interface Cursor;
interface DB;
//----------------------------------------------------------------
// list of strings (substituted by the native mechanism)
//----------------------------------------------------------------
interface List {
string get(in long index);
};
//----------------------------------------------------------------
// map of strings (substituted by the native mechanism)
//----------------------------------------------------------------
interface Map {
string get(in string key);
};
//----------------------------------------------------------------
// error information
//----------------------------------------------------------------
interface Error {
const long SUCCESS = 0;
const long NOIMPL = 1;
const long INVALID = 2;
const long NOREPOS = 3;
const long NOPERM = 4;
const long BROKEN = 5;
const long DUPREC = 6;
const long NOREC = 7;
const long LOGIC = 8;
const long SYSTEM = 9;
const long MISC = 15;
long code();
string name();
string message();
};
//----------------------------------------------------------------
// record visitor
//----------------------------------------------------------------
interface Visitor {
const string NOP = "";
const string REMOVE = "";
string visit_full(in string key, in string value);
string visit_empty(in string key);
};
//----------------------------------------------------------------
// file processor
//----------------------------------------------------------------
interface FileProcessor {
boolean process(in string path, in long long count, in long long size);
};
//----------------------------------------------------------------
// event logger
//----------------------------------------------------------------
interface Logger {
const long INFO = 0;
const long WARN = 1;
const long ERROR = 2;
void log(in string file, in long line, in string func, in long kind, in string message);
};
//----------------------------------------------------------------
// meta operation trigger
//----------------------------------------------------------------
interface MetaTrigger {
const long OPEN = 0;
const long CLOSE = 1;
const long CLEAR = 2;
const long ITERATE = 3;
const long SYNCHRONIZE = 4;
const long OCCUPY = 5;
const long BEGINTRAN = 6;
const long COMMITTRAN = 7;
const long ABORTTRAN = 8;
const long MISC = 15;
void trigger(in long kind, in string message);
};
//----------------------------------------------------------------
// cursor
//----------------------------------------------------------------
interface Cursor {
boolean accept(inout Visitor visitor, in boolean writable, in boolean step);
boolean set_value(in string value, in boolean step);
boolean remove();
string get_key(in boolean step);
string get_value(in boolean step);
boolean jump();
boolean jump_(in string key);
boolean jump_back();
boolean jump_back_(in string key);
boolean step();
boolean step_back();
DB db();
Error error();
};
//----------------------------------------------------------------
// common database operations
//----------------------------------------------------------------
interface DB {
const long OREADER = 1 << 0;
const long OWRITER = 1 << 1;
const long OCREATE = 1 << 2;
const long OTRUNCATE = 1 << 3;
const long OAUTOTRAN = 1 << 4;
const long OAUTOSYNC = 1 << 5;
const long ONOLOCK = 1 << 6;
const long OTRYLOCK = 1 << 7;
const long ONOREPAIR = 1 << 8;
Error error();
boolean open(in string path, in long mode);
boolean close();
boolean accept(in string key, inout Visitor visitor, in boolean writable);
boolean accept_bulk(in List keys, inout Visitor visitor, in boolean writable);
boolean iterate(inout Visitor visitor, in boolean writable);
boolean scan_parallel(inout Visitor visitor, in long thnum);
boolean set(in string key, in string value);
boolean add(in string key, in string value);
boolean replace(in string key, in string value);
boolean append(in string key, in string value);
long long increment(in string key, in long long num, in long long orig);
double increment_double(in string key, in double num, in double orig);
boolean cas(in string key, in string oval, in string nval);
boolean remove(in string key);
string get(in string key);
long check(in string key);
string seize(in string key);
long long set_bulk(in Map recs);
long long remove_bulk(in List keys);
Map get_bulk(in List keys);
boolean clear();
boolean synchronize(in boolean hard, inout FileProcessor proc);
boolean occupy(in boolean writable, inout FileProcessor proc);
boolean copy(in string dest);
boolean begin_transaction(in boolean hard);
boolean end_transaction(in boolean commit);
boolean dump_snapshot(in string dest);
boolean load_snapshot(in string src);
long long count();
long long size();
string path();
Map status();
Cursor cursor();
boolean tune_logger(inout Logger logger);
boolean tune_meta_trigger(inout MetaTrigger trigger);
};
//----------------------------------------------------------------
// prototype hash database
//----------------------------------------------------------------
interface ProtoHashDB :DB {
};
//----------------------------------------------------------------
// prototype tree database
//----------------------------------------------------------------
interface ProtoTreeDB :DB {
};
//----------------------------------------------------------------
// stash database
//----------------------------------------------------------------
interface StashDB :DB {
boolean tune_buckets(in long long bnum);
};
//----------------------------------------------------------------
// cache hash database
//----------------------------------------------------------------
interface CacheDB :DB {
boolean tune_options(in long opts);
boolean tune_buckets(in long long bnum);
boolean cap_count(in long long count);
boolean cap_size(in long long size);
};
//----------------------------------------------------------------
// cache tree database
//----------------------------------------------------------------
interface GrassDB :DB {
boolean tune_options(in long opts);
boolean tune_buckets(in long long bnum);
boolean tune_page(in long psiz);
boolean tune_page_cache(in long long pccap);
};
//----------------------------------------------------------------
// file hash database
//----------------------------------------------------------------
interface HashDB :DB {
const long TSMALL = 1 << 0;
const long TLINEAR = 1 << 1;
const long TCOMPRESS = 1 << 2;
boolean tune_alignment(in long apow);
boolean tune_fbp(in long fpow);
boolean tune_options(in long opts);
boolean tune_buckets(in long long bnum);
boolean tune_map(in long long msiz);
boolean tune_defrag(in long dfunit);
};
//----------------------------------------------------------------
// file tree database
//----------------------------------------------------------------
interface TreeDB :DB {
const long TSMALL = 1 << 0;
const long TLINEAR = 1 << 1;
const long TCOMPRESS = 1 << 2;
boolean tune_alignment(in long apow);
boolean tune_fbp(in long fpow);
boolean tune_options(in long opts);
boolean tune_buckets(in long long bnum);
boolean tune_page(in long psiz);
boolean tune_map(in long long msiz);
boolean tune_defrag(in long dfunit);
boolean tune_page_cache(in long long pccap);
};
//----------------------------------------------------------------
// directory hash database
//----------------------------------------------------------------
interface DirDB :DB {
const long TCOMPRESS = 1 << 2;
boolean tune_options(in long opts);
};
//----------------------------------------------------------------
// directory tree database
//----------------------------------------------------------------
interface ForestDB :DB {
const long TCOMPRESS = 1 << 2;
boolean tune_options(in long opts);
boolean tune_buckets(in long long bnum);
boolean tune_page(in long psiz);
boolean tune_page_cache(in long long pccap);
};
//----------------------------------------------------------------
// polymorphic database
//----------------------------------------------------------------
interface PolyDB :DB {
List match_prefix(in string prefix, in long long max);
List match_regex(in string regex, in long long max);
List match_similar(in string origin, in long long range, in boolean utf, in long long max);
};
};
/* END OF FILE */
kyotocabinet-1.2.80/kcplantdb.cc 0000664 0001750 0001750 00000002250 14416044124 015551 0 ustar mikio mikio /*************************************************************************************************
* Plant database
* Copyright (C) 2009-2012 Mikio Hirabayashi
* This file is part of Kyoto Cabinet.
* This program is free software: you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation, either version
* 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with this program.
* If not, see .
*************************************************************************************************/
#include "kcplantdb.h"
#include "myconf.h"
namespace kyotocabinet { // common namespace
// There is no implementation now.
} // common namespace
// END OF FILE
kyotocabinet-1.2.80/example/ 0000755 0001750 0001750 00000000000 11757416060 014741 5 ustar mikio mikio kyotocabinet-1.2.80/example/kcmrex.cc 0000644 0001750 0001750 00000002705 11757416060 016545 0 ustar mikio mikio #include
#include
using namespace std;
using namespace kyotocabinet;
// main routine
int main(int argc, char** argv) {
// create the database object
PolyDB db;
// open the database
if (!db.open()) {
cerr << "open error: " << db.error().name() << endl;
}
// store records
db.set("1", "this is a pen");
db.set("2", "what a beautiful pen this is");
db.set("3", "she is beautiful");
// define the mapper and the reducer
class MapReduceImpl : public MapReduce {
// call back function of the mapper
bool map(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) {
vector words;
strsplit(string(vbuf, vsiz), ' ', &words);
for (vector::iterator it = words.begin();
it != words.end(); it++) {
emit(it->data(), it->size(), "", 0);
}
return true;
}
// call back function of the reducer
bool reduce(const char* kbuf, size_t ksiz, ValueIterator* iter) {
size_t count = 0;
const char* vbuf;
size_t vsiz;
while ((vbuf = iter->next(&vsiz)) != NULL) {
count++;
}
cout << string(kbuf, ksiz) << ": " << count << endl;
return true;
}
} mr;
// execute the MapReduce process
if (!mr.execute(&db)) {
cerr << "MapReduce error: " << db.error().name() << endl;
}
// close the database
if (!db.close()) {
cerr << "close error: " << db.error().name() << endl;
}
return 0;
}
kyotocabinet-1.2.80/example/kchashex.cc 0000644 0001750 0001750 00000001734 11757416060 017053 0 ustar mikio mikio #include
using namespace std;
using namespace kyotocabinet;
// main routine
int main(int argc, char** argv) {
// create the database object
HashDB db;
// open the database
if (!db.open("casket.kch", HashDB::OWRITER | HashDB::OCREATE)) {
cerr << "open error: " << db.error().name() << endl;
}
// store records
if (!db.set("foo", "hop") ||
!db.set("bar", "step") ||
!db.set("baz", "jump")) {
cerr << "set error: " << db.error().name() << endl;
}
// retrieve a record
string value;
if (db.get("foo", &value)) {
cout << value << endl;
} else {
cerr << "get error: " << db.error().name() << endl;
}
// traverse records
DB::Cursor* cur = db.cursor();
cur->jump();
string ckey, cvalue;
while (cur->get(&ckey, &cvalue, true)) {
cout << ckey << ":" << cvalue << endl;
}
delete cur;
// close the database
if (!db.close()) {
cerr << "close error: " << db.error().name() << endl;
}
return 0;
}
kyotocabinet-1.2.80/example/kcforestex.cc 0000644 0001750 0001750 00000001741 11757416060 017430 0 ustar mikio mikio #include
using namespace std;
using namespace kyotocabinet;
// main routine
int main(int argc, char** argv) {
// create the database object
ForestDB db;
// open the database
if (!db.open("casket.kcf", ForestDB::OWRITER | ForestDB::OCREATE)) {
cerr << "open error: " << db.error().name() << endl;
}
// store records
if (!db.set("foo", "hop") ||
!db.set("bar", "step") ||
!db.set("baz", "jump")) {
cerr << "set error: " << db.error().name() << endl;
}
// retrieve a record
string value;
if (db.get("foo", &value)) {
cout << value << endl;
} else {
cerr << "get error: " << db.error().name() << endl;
}
// traverse records
DB::Cursor* cur = db.cursor();
cur->jump();
string ckey, cvalue;
while (cur->get(&ckey, &cvalue, true)) {
cout << ckey << ":" << cvalue << endl;
}
delete cur;
// close the database
if (!db.close()) {
cerr << "close error: " << db.error().name() << endl;
}
return 0;
}
kyotocabinet-1.2.80/example/kccacheex.cc 0000644 0001750 0001750 00000001727 11757416060 017175 0 ustar mikio mikio #include
using namespace std;
using namespace kyotocabinet;
// main routine
int main(int argc, char** argv) {
// create the database object
CacheDB db;
// open the database
if (!db.open("%", CacheDB::OWRITER | CacheDB::OCREATE)) {
cerr << "open error: " << db.error().name() << endl;
}
// store records
if (!db.set("foo", "hop") ||
!db.set("bar", "step") ||
!db.set("baz", "jump")) {
cerr << "set error: " << db.error().name() << endl;
}
// retrieve a record
string value;
if (db.get("foo", &value)) {
cout << value << endl;
} else {
cerr << "get error: " << db.error().name() << endl;
}
// traverse records
DB::Cursor* cur = db.cursor();
cur->jump();
string ckey, cvalue;
while (cur->get(&ckey, &cvalue, true)) {
cout << ckey << ":" << cvalue << endl;
}
delete cur;
// close the database
if (!db.close()) {
cerr << "close error: " << db.error().name() << endl;
}
return 0;
}
kyotocabinet-1.2.80/example/kcvisex.cc 0000644 0001750 0001750 00000002455 11757416060 016732 0 ustar mikio mikio #include
using namespace std;
using namespace kyotocabinet;
// main routine
int main(int argc, char** argv) {
// create the database object
PolyDB db;
// open the database
if (!db.open("casket.kch", PolyDB::OREADER)) {
cerr << "open error: " << db.error().name() << endl;
}
// define the visitor
class VisitorImpl : public DB::Visitor {
// call back function for an existing record
const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t *sp) {
cout << string(kbuf, ksiz) << ":" << string(vbuf, vsiz) << endl;
return NOP;
}
// call back function for an empty record space
const char* visit_empty(const char* kbuf, size_t ksiz, size_t *sp) {
cerr << string(kbuf, ksiz) << " is missing" << endl;
return NOP;
}
} visitor;
// retrieve a record with visitor
if (!db.accept("foo", 3, &visitor, false) ||
!db.accept("dummy", 5, &visitor, false)) {
cerr << "accept error: " << db.error().name() << endl;
}
// traverse records with visitor
if (!db.iterate(&visitor, false)) {
cerr << "iterate error: " << db.error().name() << endl;
}
// close the database
if (!db.close()) {
cerr << "close error: " << db.error().name() << endl;
}
return 0;
}
kyotocabinet-1.2.80/example/kcprotoex.cc 0000644 0001750 0001750 00000001743 11757416060 017273 0 ustar mikio mikio #include
using namespace std;
using namespace kyotocabinet;
// main routine
int main(int argc, char** argv) {
// create the database object
ProtoHashDB db;
// open the database
if (!db.open("-", ProtoHashDB::OWRITER | ProtoHashDB::OCREATE)) {
cerr << "open error: " << db.error().name() << endl;
}
// store records
if (!db.set("foo", "hop") ||
!db.set("bar", "step") ||
!db.set("baz", "jump")) {
cerr << "set error: " << db.error().name() << endl;
}
// retrieve a record
string value;
if (db.get("foo", &value)) {
cout << value << endl;
} else {
cerr << "get error: " << db.error().name() << endl;
}
// traverse records
DB::Cursor* cur = db.cursor();
cur->jump();
string ckey, cvalue;
while (cur->get(&ckey, &cvalue, true)) {
cout << ckey << ":" << cvalue << endl;
}
delete cur;
// close the database
if (!db.close()) {
cerr << "close error: " << db.error().name() << endl;
}
return 0;
}
kyotocabinet-1.2.80/example/kcgrassex.cc 0000644 0001750 0001750 00000001727 11757416060 017251 0 ustar mikio mikio #include
using namespace std;
using namespace kyotocabinet;
// main routine
int main(int argc, char** argv) {
// create the database object
GrassDB db;
// open the database
if (!db.open("*", GrassDB::OWRITER | GrassDB::OCREATE)) {
cerr << "open error: " << db.error().name() << endl;
}
// store records
if (!db.set("foo", "hop") ||
!db.set("bar", "step") ||
!db.set("baz", "jump")) {
cerr << "set error: " << db.error().name() << endl;
}
// retrieve a record
string value;
if (db.get("foo", &value)) {
cout << value << endl;
} else {
cerr << "get error: " << db.error().name() << endl;
}
// traverse records
DB::Cursor* cur = db.cursor();
cur->jump();
string ckey, cvalue;
while (cur->get(&ckey, &cvalue, true)) {
cout << ckey << ":" << cvalue << endl;
}
delete cur;
// close the database
if (!db.close()) {
cerr << "close error: " << db.error().name() << endl;
}
return 0;
}
kyotocabinet-1.2.80/example/kclangcex.c 0000644 0001750 0001750 00000004125 11757416060 017046 0 ustar mikio mikio #include
/* call back function for an existing record */
const char* visitfull(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t *sp, void* opq) {
fwrite(kbuf, 1, ksiz, stdout);
printf(":");
fwrite(vbuf, 1, vsiz, stdout);
printf("\n");
return KCVISNOP;
}
/* call back function for an empty record space */
const char* visitempty(const char* kbuf, size_t ksiz, size_t *sp, void* opq) {
fwrite(kbuf, 1, ksiz, stdout);
printf(" is missing\n");
return KCVISNOP;
}
/* main routine */
int main(int argc, char** argv) {
KCDB* db;
KCCUR* cur;
char *kbuf, *vbuf;
size_t ksiz, vsiz;
const char *cvbuf;
/* create the database object */
db = kcdbnew();
/* open the database */
if (!kcdbopen(db, "casket.kch", KCOWRITER | KCOCREATE)) {
fprintf(stderr, "open error: %s\n", kcecodename(kcdbecode(db)));
}
/* store records */
if (!kcdbset(db, "foo", 3, "hop", 3) ||
!kcdbset(db, "bar", 3, "step", 4) ||
!kcdbset(db, "baz", 3, "jump", 4)) {
fprintf(stderr, "set error: %s\n", kcecodename(kcdbecode(db)));
}
/* retrieve a record */
vbuf = kcdbget(db, "foo", 3, &vsiz);
if (vbuf) {
printf("%s\n", vbuf);
kcfree(vbuf);
} else {
fprintf(stderr, "get error: %s\n", kcecodename(kcdbecode(db)));
}
/* traverse records */
cur = kcdbcursor(db);
kccurjump(cur);
while ((kbuf = kccurget(cur, &ksiz, &cvbuf, &vsiz, 1)) != NULL) {
printf("%s:%s\n", kbuf, cvbuf);
kcfree(kbuf);
}
kccurdel(cur);
/* retrieve a record with visitor */
if (!kcdbaccept(db, "foo", 3, visitfull, visitempty, NULL, 0) ||
!kcdbaccept(db, "dummy", 5, visitfull, visitempty, NULL, 0)) {
fprintf(stderr, "accept error: %s\n", kcecodename(kcdbecode(db)));
}
/* traverse records with visitor */
if (!kcdbiterate(db, visitfull, NULL, 0)) {
fprintf(stderr, "iterate error: %s\n", kcecodename(kcdbecode(db)));
}
/* close the database */
if (!kcdbclose(db)) {
fprintf(stderr, "close error: %s\n", kcecodename(kcdbecode(db)));
}
/* delete the database object */
kcdbdel(db);
return 0;
}
kyotocabinet-1.2.80/example/Makefile 0000644 0001750 0001750 00000005103 11523256007 016372 0 ustar mikio mikio # Makefile for sample programs of Kyoto Cabinet
#================================================================
# Setting Variables
#================================================================
# Generic settings
SHELL = /bin/sh
# Targets
MYBINS = kcprotoex kccacheex kcgrassex kchashex kctreeex kcdirex kcforestex \
kcpolyex kcvisex kcmrex kclangcex
# Building binaries
CC = gcc
CXX = g++
CFLAGS = -I. -I.. -Wall -ansi -pedantic -fsigned-char -O2
CXXFLAGS = -I. -I.. -Wall -fsigned-char -O2
LDFLAGS =
LIBS = -L. -L.. -lkyotocabinet -lstdc++ -lz -lrt -lpthread -lm -lc
LDENV = LD_RUN_PATH=/lib:/usr/lib:$(HOME)/lib:/usr/local/lib:.:..
RUNENV = LD_LIBRARY_PATH=/lib:/usr/lib:$(HOME)/lib:/usr/local/lib:.:..
#================================================================
# Suffix rules
#================================================================
.SUFFIXES :
.SUFFIXES : .c .cc .o
.c.o :
$(CC) -c $(CFLAGS) $<
.cc.o :
$(CXX) -c $(CXXFLAGS) $<
#================================================================
# Actions
#================================================================
all : $(MYBINS)
clean :
rm -rf $(MYBINS) *.exe *.o a.out check.out gmon.out leak.log casket* *~
static :
make LDFLAGS="$(LDFLAGS) -static"
check :
rm -rf casket*
$(RUNENV) ./kcprotoex
$(RUNENV) ./kccacheex
$(RUNENV) ./kcgrassex
$(RUNENV) ./kchashex
$(RUNENV) ./kctreeex
$(RUNENV) ./kcdirex
$(RUNENV) ./kcforestex
$(RUNENV) ./kcpolyex
$(RUNENV) ./kcvisex
$(RUNENV) ./kcmrex
$(RUNENV) ./kclangcex
.PHONY : all clean static
#================================================================
# Building binaries
#================================================================
kcprotoex : kcprotoex.o
$(LDENV) $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(LIBS)
kccacheex : kccacheex.o
$(LDENV) $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(LIBS)
kcgrassex : kcgrassex.o
$(LDENV) $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(LIBS)
kchashex : kchashex.o
$(LDENV) $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(LIBS)
kctreeex : kctreeex.o
$(LDENV) $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(LIBS)
kcdirex : kcdirex.o
$(LDENV) $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(LIBS)
kcforestex : kcforestex.o
$(LDENV) $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(LIBS)
kcpolyex : kcpolyex.o
$(LDENV) $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(LIBS)
kcvisex : kcvisex.o
$(LDENV) $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(LIBS)
kcmrex : kcmrex.o
$(LDENV) $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(LIBS)
kclangcex : kclangcex.o
$(LDENV) $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) $(LIBS)
# END OF FILE
kyotocabinet-1.2.80/example/kcdirex.cc 0000644 0001750 0001750 00000001730 11757416060 016702 0 ustar mikio mikio #include
using namespace std;
using namespace kyotocabinet;
// main routine
int main(int argc, char** argv) {
// create the database object
DirDB db;
// open the database
if (!db.open("casket.kcd", DirDB::OWRITER | DirDB::OCREATE)) {
cerr << "open error: " << db.error().name() << endl;
}
// store records
if (!db.set("foo", "hop") ||
!db.set("bar", "step") ||
!db.set("baz", "jump")) {
cerr << "set error: " << db.error().name() << endl;
}
// retrieve a record
string value;
if (db.get("foo", &value)) {
cout << value << endl;
} else {
cerr << "get error: " << db.error().name() << endl;
}
// traverse records
DB::Cursor* cur = db.cursor();
cur->jump();
string ckey, cvalue;
while (cur->get(&ckey, &cvalue, true)) {
cout << ckey << ":" << cvalue << endl;
}
delete cur;
// close the database
if (!db.close()) {
cerr << "close error: " << db.error().name() << endl;
}
return 0;
}
kyotocabinet-1.2.80/example/kctreeex.cc 0000644 0001750 0001750 00000001734 11757416060 017067 0 ustar mikio mikio #include
using namespace std;
using namespace kyotocabinet;
// main routine
int main(int argc, char** argv) {
// create the database object
TreeDB db;
// open the database
if (!db.open("casket.kct", TreeDB::OWRITER | TreeDB::OCREATE)) {
cerr << "open error: " << db.error().name() << endl;
}
// store records
if (!db.set("foo", "hop") ||
!db.set("bar", "step") ||
!db.set("baz", "jump")) {
cerr << "set error: " << db.error().name() << endl;
}
// retrieve a record
string value;
if (db.get("foo", &value)) {
cout << value << endl;
} else {
cerr << "get error: " << db.error().name() << endl;
}
// traverse records
DB::Cursor* cur = db.cursor();
cur->jump();
string ckey, cvalue;
while (cur->get(&ckey, &cvalue, true)) {
cout << ckey << ":" << cvalue << endl;
}
delete cur;
// close the database
if (!db.close()) {
cerr << "close error: " << db.error().name() << endl;
}
return 0;
}
kyotocabinet-1.2.80/example/kcpolyex.cc 0000644 0001750 0001750 00000001734 11757416060 017113 0 ustar mikio mikio #include
using namespace std;
using namespace kyotocabinet;
// main routine
int main(int argc, char** argv) {
// create the database object
PolyDB db;
// open the database
if (!db.open("casket.kch", PolyDB::OWRITER | PolyDB::OCREATE)) {
cerr << "open error: " << db.error().name() << endl;
}
// store records
if (!db.set("foo", "hop") ||
!db.set("bar", "step") ||
!db.set("baz", "jump")) {
cerr << "set error: " << db.error().name() << endl;
}
// retrieve a record
string value;
if (db.get("foo", &value)) {
cout << value << endl;
} else {
cerr << "get error: " << db.error().name() << endl;
}
// traverse records
DB::Cursor* cur = db.cursor();
cur->jump();
string ckey, cvalue;
while (cur->get(&ckey, &cvalue, true)) {
cout << ckey << ":" << cvalue << endl;
}
delete cur;
// close the database
if (!db.close()) {
cerr << "close error: " << db.error().name() << endl;
}
return 0;
}
kyotocabinet-1.2.80/kccompare.cc 0000664 0001750 0001750 00000003507 14416044124 015561 0 ustar mikio mikio /*************************************************************************************************
* Comparator functions
* Copyright (C) 2009-2012 Mikio Hirabayashi
* This file is part of Kyoto Cabinet.
* This program is free software: you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation, either version
* 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with this program.
* If not, see .
*************************************************************************************************/
#include "kccompare.h"
#include "myconf.h"
namespace kyotocabinet { // common namespace
/**
* Prepared pointer of the comparator in the lexical order.
*/
LexicalComparator lexicalfunc;
LexicalComparator* const LEXICALCOMP = &lexicalfunc;
/**
* Prepared pointer of the comparator in the lexical descending order.
*/
LexicalDescendingComparator lexicaldescfunc;
LexicalDescendingComparator* const LEXICALDESCCOMP = &lexicaldescfunc;
/**
* Prepared pointer of the comparator in the decimal order.
*/
DecimalComparator decimalfunc;
DecimalComparator* const DECIMALCOMP = &decimalfunc;
/**
* Prepared pointer of the comparator in the decimal descending order.
*/
DecimalDescendingComparator decimaldescfunc;
DecimalDescendingComparator* const DECIMALDESCCOMP = &decimaldescfunc;
} // common namespace
// END OF FILE
kyotocabinet-1.2.80/kcregex.cc 0000664 0001750 0001750 00000011654 14416044124 015247 0 ustar mikio mikio /*************************************************************************************************
* Regular expression
* Copyright (C) 2009-2012 Mikio Hirabayashi
* This file is part of Kyoto Cabinet.
* This program is free software: you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation, either version
* 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with this program.
* If not, see .
*************************************************************************************************/
#include "kcregex.h"
#include "myconf.h"
#if _KC_PXREGEX
extern "C" {
#include
}
#else
#include
#endif
namespace kyotocabinet { // common namespace
/**
* Regex internal.
*/
struct RegexCore {
#if _KC_PXREGEX
::regex_t rbuf;
bool alive;
bool nosub;
#else
std::regex* rbuf;
#endif
};
/**
* Default constructor.
*/
Regex::Regex() : opq_(NULL) {
#if _KC_PXREGEX
_assert_(true);
RegexCore* core = new RegexCore;
core->alive = false;
core->nosub = false;
opq_ = (void*)core;
#else
_assert_(true);
RegexCore* core = new RegexCore;
core->rbuf = NULL;
opq_ = (void*)core;
#endif
}
/**
* Destructor.
*/
Regex::~Regex() {
#if _KC_PXREGEX
_assert_(true);
RegexCore* core = (RegexCore*)opq_;
if (core->alive) ::regfree(&core->rbuf);
delete core;
#else
_assert_(true);
RegexCore* core = (RegexCore*)opq_;
delete core->rbuf;
delete core;
#endif
}
/**
* Compile a string of regular expression.
*/
bool Regex::compile(const std::string& regex, uint32_t opts) {
#if _KC_PXREGEX
_assert_(true);
RegexCore* core = (RegexCore*)opq_;
if (core->alive) {
::regfree(&core->rbuf);
core->alive = false;
}
int32_t cflags = REG_EXTENDED;
if (opts & IGNCASE) cflags |= REG_ICASE;
if ((opts & MATCHONLY) || regex.empty()) {
cflags |= REG_NOSUB;
core->nosub = true;
}
if (::regcomp(&core->rbuf, regex.c_str(), cflags) != 0) return false;
core->alive = true;
return true;
#else
_assert_(true);
RegexCore* core = (RegexCore*)opq_;
if (core->rbuf) {
delete core->rbuf;
core->rbuf = NULL;
}
int32_t cflags = std::regex::ECMAScript;
if (opts & IGNCASE) cflags |= std::regex::icase;
if ((opts & MATCHONLY) || regex.empty()) cflags |= std::regex::nosubs;
try {
core->rbuf = new std::regex(regex, (std::regex::flag_type)cflags);
} catch (...) {
core->rbuf = NULL;
return false;
}
return true;
#endif
}
/**
* Check whether a string matches the regular expression.
*/
bool Regex::match(const std::string& str) {
#if _KC_PXREGEX
_assert_(true);
RegexCore* core = (RegexCore*)opq_;
if (!core->alive) return false;
if (core->nosub) return ::regexec(&core->rbuf, str.c_str(), 0, NULL, 0) == 0;
::regmatch_t subs[1];
return ::regexec(&core->rbuf, str.c_str(), 1, subs, 0) == 0;
#else
_assert_(true);
RegexCore* core = (RegexCore*)opq_;
if (!core->rbuf) return false;
std::smatch res;
return std::regex_search(str, res, *core->rbuf);
#endif
}
/**
* Check whether a string matches the regular expression.
*/
std::string Regex::replace(const std::string& str, const std::string& alt) {
#if _KC_PXREGEX
_assert_(true);
RegexCore* core = (RegexCore*)opq_;
if (!core->alive || core->nosub) return str;
regmatch_t subs[256];
if (::regexec(&core->rbuf, str.c_str(), sizeof(subs) / sizeof(*subs), subs, 0) != 0)
return str;
const char* sp = str.c_str();
std::string xstr;
bool first = true;
while (sp[0] != '\0' && ::regexec(&core->rbuf, sp, 10, subs, first ? 0 : REG_NOTBOL) == 0) {
first = false;
if (subs[0].rm_so == -1) break;
xstr.append(sp, subs[0].rm_so);
for (const char* rp = alt.c_str(); *rp != '\0'; rp++) {
if (*rp == '$') {
if (rp[1] >= '0' && rp[1] <= '9') {
int32_t num = rp[1] - '0';
if (subs[num].rm_so != -1 && subs[num].rm_eo != -1)
xstr.append(sp + subs[num].rm_so, subs[num].rm_eo - subs[num].rm_so);
++rp;
} else if (rp[1] == '&') {
xstr.append(sp + subs[0].rm_so, subs[0].rm_eo - subs[0].rm_so);
++rp;
} else if (rp[1] != '\0') {
xstr.append(++rp, 1);
}
} else {
xstr.append(rp, 1);
}
}
sp += subs[0].rm_eo;
if (subs[0].rm_eo < 1) break;
}
xstr.append(sp);
return xstr;
#else
_assert_(true);
RegexCore* core = (RegexCore*)opq_;
if (!core->rbuf) return str;
return std::regex_replace(str, *core->rbuf, alt);
#endif
}
} // common namespace
// END OF FILE
kyotocabinet-1.2.80/kctextdb.cc 0000664 0001750 0001750 00000002254 14416044124 015423 0 ustar mikio mikio /*************************************************************************************************
* Plain text database
* Copyright (C) 2009-2012 Mikio Hirabayashi
* This file is part of Kyoto Cabinet.
* This program is free software: you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation, either version
* 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with this program.
* If not, see .
*************************************************************************************************/
#include "kctextdb.h"
#include "myconf.h"
namespace kyotocabinet { // common namespace
// There is no implementation now.
} // common namespace
// END OF FILE
kyotocabinet-1.2.80/Makefile.in 0000644 0001750 0001750 00000152276 11604605501 015357 0 ustar mikio mikio # Makefile for Kyoto Cabinet
#================================================================
# Setting Variables
#================================================================
# Generic settings
SHELL = @SHELL@
# Package information
PACKAGE = @PACKAGE_NAME@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
VERSION = @PACKAGE_VERSION@
PACKAGEDIR = $(PACKAGE)-$(VERSION)
PACKAGETGZ = $(PACKAGE)-$(VERSION).tar.gz
LIBVER = @MYLIBVER@
LIBREV = @MYLIBREV@
FORMATVER = @MYFORMATVER@
# Targets
HEADERFILES = @MYHEADERFILES@
LIBRARYFILES = @MYLIBRARYFILES@
LIBOBJFILES = @MYLIBOBJFILES@
COMMANDFILES = @MYCOMMANDFILES@
MAN1FILES = @MYMAN1FILES@
DOCUMENTFILES = @MYDOCUMENTFILES@
PCFILES = @MYPCFILES@
# Install destinations
prefix = @prefix@
exec_prefix = @exec_prefix@
datarootdir = @datarootdir@
INCLUDEDIR = @includedir@
LIBDIR = @libdir@
BINDIR = @bindir@
LIBEXECDIR = @libexecdir@
DATADIR = @datadir@/$(PACKAGE)
MAN1DIR = @mandir@/man1
DOCDIR = @docdir@
PCDIR = @libdir@/pkgconfig
DESTDIR =
# Building configuration
CC = @CC@
CXX = @CXX@
CPPFLAGS = @MYCPPFLAGS@ \
-D_KC_PREFIX="\"$(prefix)\"" -D_KC_INCLUDEDIR="\"$(INCLUDEDIR)\"" \
-D_KC_LIBDIR="\"$(LIBDIR)\"" -D_KC_BINDIR="\"$(BINDIR)\"" -D_KC_LIBEXECDIR="\"$(LIBEXECDIR)\"" \
-D_KC_APPINC="\"-I$(INCLUDEDIR)\"" -D_KC_APPLIBS="\"-L$(LIBDIR) -lkyotocabinet @LIBS@\""
CFLAGS = @MYCFLAGS@
CXXFLAGS = @MYCXXFLAGS@
LDFLAGS = @MYLDFLAGS@
CMDLDFLAGS = @MYCMDLDFLAGS@
CMDLIBS = @MYCMDLIBS@
LIBS = @LIBS@
RUNENV = @MYLDLIBPATHENV@=@MYLDLIBPATH@
POSTCMD = @MYPOSTCMD@
#================================================================
# Suffix rules
#================================================================
.SUFFIXES :
.SUFFIXES : .c .cc .o
.c.o :
$(CC) -c $(CPPFLAGS) $(CFLAGS) $<
.cc.o :
$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $<
#================================================================
# Actions
#================================================================
all : $(LIBRARYFILES) $(COMMANDFILES)
@$(POSTCMD)
@printf '\n'
@printf '#================================================================\n'
@printf '# Ready to install.\n'
@printf '#================================================================\n'
clean :
rm -rf $(LIBRARYFILES) $(LIBOBJFILES) $(COMMANDFILES) $(CGIFILES) \
*.o *.gch a.out check.in check.out gmon.out *.log *.vlog words.tsv \
casket* *.kch *.kct *.kcd *.kcf *.wal *.tmpkc* *.kcss *~ hoge moge tako ika
version :
sed -e 's/_KC_VERSION.*/_KC_VERSION "$(VERSION)"/' \
-e "s/_KC_LIBVER.*/_KC_LIBVER $(LIBVER)/" \
-e "s/_KC_LIBREV.*/_KC_LIBREV $(LIBREV)/" \
-e 's/_KC_FMTVER.*/_KC_FMTVER $(FORMATVER)/' myconf.h > myconf.h~
[ -f myconf.h~ ] && mv -f myconf.h~ myconf.h
untabify :
ls *.cc *.h *.idl | while read name ; \
do \
sed -e 's/\t/ /g' -e 's/ *$$//' $$name > $$name~; \
[ -f $$name~ ] && mv -f $$name~ $$name ; \
done
install :
mkdir -p $(DESTDIR)$(INCLUDEDIR)
cp -Rf $(HEADERFILES) $(DESTDIR)$(INCLUDEDIR)
mkdir -p $(DESTDIR)$(LIBDIR)
cp -Rf $(LIBRARYFILES) $(DESTDIR)$(LIBDIR)
mkdir -p $(DESTDIR)$(BINDIR)
cp -Rf $(COMMANDFILES) $(DESTDIR)$(BINDIR)
mkdir -p $(DESTDIR)$(MAN1DIR)
cd man && cp -Rf $(MAN1FILES) $(DESTDIR)$(MAN1DIR)
mkdir -p $(DESTDIR)$(DOCDIR)
cp -Rf $(DOCUMENTFILES) $(DESTDIR)$(DOCDIR)
mkdir -p $(DESTDIR)$(PCDIR)
cp -Rf $(PCFILES) $(DESTDIR)$(PCDIR)
@printf '\n'
@printf '#================================================================\n'
@printf '# Thanks for using Kyoto Cabinet.\n'
@printf '#================================================================\n'
install-strip :
$(MAKE) DESTDIR=$(DESTDIR) install
cd $(DESTDIR)$(BINDIR) && strip $(COMMANDFILES)
uninstall :
-cd $(DESTDIR)$(INCLUDEDIR) && rm -f $(HEADERFILES)
-cd $(DESTDIR)$(LIBDIR) && rm -f $(LIBRARYFILES)
-cd $(DESTDIR)$(BINDIR) && rm -f $(COMMANDFILES)
-cd $(DESTDIR)$(MAN1DIR) && rm -f $(MAN1FILES)
-cd $(DESTDIR)$(DOCDIR) && rm -rf $(DOCUMENTFILES) && rmdir $(DOCDIR)
-cd $(DESTDIR)$(PCDIR) && rm -f $(PCFILES)
dist :
$(MAKE) version
$(MAKE) untabify
$(MAKE) distclean
cd .. && tar cvf - $(PACKAGEDIR) | gzip -c > $(PACKAGETGZ)
sync ; sync
distclean : clean
cd example && $(MAKE) clean
rm -rf Makefile kyotocabinet.pc \
config.cache config.log config.status config.tmp autom4te.cache
check :
$(MAKE) check-util
$(MAKE) check-proto
$(MAKE) check-stash
$(MAKE) check-cache
$(MAKE) check-grass
$(MAKE) check-hash
$(MAKE) check-tree
$(MAKE) check-dir
$(MAKE) check-forest
$(MAKE) check-poly
$(MAKE) check-langc
rm -rf casket*
@printf '\n'
@printf '#================================================================\n'
@printf '# Checking completed.\n'
@printf '#================================================================\n'
check-util :
rm -rf casket*
$(RUNENV) $(RUNCMD) ./kcutilmgr version
$(RUNENV) $(RUNCMD) ./kcutilmgr hex Makefile > check.in
$(RUNENV) $(RUNCMD) ./kcutilmgr hex -d check.in > check.out
$(RUNENV) $(RUNCMD) ./kcutilmgr enc Makefile > check.in
$(RUNENV) $(RUNCMD) ./kcutilmgr enc -d check.in > check.out
$(RUNENV) $(RUNCMD) ./kcutilmgr enc -hex Makefile > check.in
$(RUNENV) $(RUNCMD) ./kcutilmgr enc -hex -d check.in > check.out
$(RUNENV) $(RUNCMD) ./kcutilmgr enc -url Makefile > check.in
$(RUNENV) $(RUNCMD) ./kcutilmgr enc -url -d check.in > check.out
$(RUNENV) $(RUNCMD) ./kcutilmgr enc -quote Makefile > check.in
$(RUNENV) $(RUNCMD) ./kcutilmgr enc -quote -d check.in > check.out
$(RUNENV) $(RUNCMD) ./kcutilmgr ciph -key "hoge" Makefile > check.in
$(RUNENV) $(RUNCMD) ./kcutilmgr ciph -key "hoge" check.in > check.out
$(RUNENV) $(RUNCMD) ./kcutilmgr comp -gz Makefile > check.in
$(RUNENV) $(RUNCMD) ./kcutilmgr comp -gz -d check.in > check.out
$(RUNENV) $(RUNCMD) ./kcutilmgr comp -lzo Makefile > check.in
$(RUNENV) $(RUNCMD) ./kcutilmgr comp -lzo -d check.in > check.out
$(RUNENV) $(RUNCMD) ./kcutilmgr comp -lzma Makefile > check.in
$(RUNENV) $(RUNCMD) ./kcutilmgr comp -lzma -d check.in > check.out
$(RUNENV) $(RUNCMD) ./kcutilmgr hash Makefile > check.in
$(RUNENV) $(RUNCMD) ./kcutilmgr hash -fnv Makefile > check.out
$(RUNENV) $(RUNCMD) ./kcutilmgr hash -path Makefile > check.out
$(RUNENV) $(RUNCMD) ./kcutilmgr regex mikio Makefile > check.out
$(RUNENV) $(RUNCMD) ./kcutilmgr regex -alt "hirarin" mikio Makefile > check.out
$(RUNENV) $(RUNCMD) ./kcutilmgr conf
rm -rf casket*
$(RUNENV) $(RUNCMD) ./kcutiltest mutex -th 4 -iv -1 10000
$(RUNENV) $(RUNCMD) ./kcutiltest cond -th 4 -iv -1 10000
$(RUNENV) $(RUNCMD) ./kcutiltest para -th 4 10000
$(RUNENV) $(RUNCMD) ./kcutiltest para -th 4 -iv -1 10000
$(RUNENV) $(RUNCMD) ./kcutiltest file -th 4 casket 10000
$(RUNENV) $(RUNCMD) ./kcutiltest file -th 4 -rnd -msiz 1m casket 10000
$(RUNENV) $(RUNCMD) ./kcutiltest lhmap -bnum 1000 10000
$(RUNENV) $(RUNCMD) ./kcutiltest lhmap -rnd -bnum 1000 10000
$(RUNENV) $(RUNCMD) ./kcutiltest thmap -bnum 1000 10000
$(RUNENV) $(RUNCMD) ./kcutiltest thmap -rnd -bnum 1000 10000
$(RUNENV) $(RUNCMD) ./kcutiltest talist 10000
$(RUNENV) $(RUNCMD) ./kcutiltest talist -rnd 10000
$(RUNENV) $(RUNCMD) ./kcutiltest misc 10000
check-proto :
rm -rf casket*
$(RUNENV) $(RUNCMD) ./kcprototest order -etc 10000
$(RUNENV) $(RUNCMD) ./kcprototest order -th 4 10000
$(RUNENV) $(RUNCMD) ./kcprototest order -th 4 -rnd -etc 10000
$(RUNENV) $(RUNCMD) ./kcprototest order -th 4 -rnd -etc -tran 10000
$(RUNENV) $(RUNCMD) ./kcprototest wicked 10000
$(RUNENV) $(RUNCMD) ./kcprototest wicked -th 4 -it 4 10000
$(RUNENV) $(RUNCMD) ./kcprototest tran 10000
$(RUNENV) $(RUNCMD) ./kcprototest tran -th 2 -it 4 10000
rm -rf casket*
$(RUNENV) $(RUNCMD) ./kcprototest order -tree -etc 10000
$(RUNENV) $(RUNCMD) ./kcprototest order -tree -th 4 10000
$(RUNENV) $(RUNCMD) ./kcprototest order -tree -th 4 -rnd -etc 10000
$(RUNENV) $(RUNCMD) ./kcprototest order -tree -th 4 -rnd -etc -tran 10000
$(RUNENV) $(RUNCMD) ./kcprototest wicked -tree 10000
$(RUNENV) $(RUNCMD) ./kcprototest wicked -tree -th 4 -it 4 10000
$(RUNENV) $(RUNCMD) ./kcprototest tran -tree 10000
$(RUNENV) $(RUNCMD) ./kcprototest tran -tree -th 2 -it 4 10000
check-stash :
rm -rf casket*
$(RUNENV) $(RUNCMD) ./kcstashtest order -etc -bnum 5000 10000
$(RUNENV) $(RUNCMD) ./kcstashtest order -th 4 -bnum 5000 10000
$(RUNENV) $(RUNCMD) ./kcstashtest order -th 4 -rnd -etc -bnum 5000 10000
$(RUNENV) $(RUNCMD) ./kcstashtest order -th 4 -rnd -etc -bnum 5000 10000
$(RUNENV) $(RUNCMD) ./kcstashtest order -th 4 -rnd -etc -tran \
-bnum 5000 10000
$(RUNENV) $(RUNCMD) ./kcstashtest wicked -bnum 5000 10000
$(RUNENV) $(RUNCMD) ./kcstashtest wicked -th 4 -it 4 -bnum 5000 10000
$(RUNENV) $(RUNCMD) ./kcstashtest tran -bnum 5000 10000
$(RUNENV) $(RUNCMD) ./kcstashtest tran -th 2 -it 4 -bnum 5000 10000
check-cache :
rm -rf casket*
$(RUNENV) $(RUNCMD) ./kccachetest order -etc -bnum 5000 10000
$(RUNENV) $(RUNCMD) ./kccachetest order -th 4 -bnum 5000 10000
$(RUNENV) $(RUNCMD) ./kccachetest order -th 4 -rnd -etc -bnum 5000 -capcnt 10000 10000
$(RUNENV) $(RUNCMD) ./kccachetest order -th 4 -rnd -etc -bnum 5000 -capsiz 10000 10000
$(RUNENV) $(RUNCMD) ./kccachetest order -th 4 -rnd -etc -tran \
-tc -bnum 5000 -capcnt 10000 10000
$(RUNENV) $(RUNCMD) ./kccachetest wicked -bnum 5000 10000
$(RUNENV) $(RUNCMD) ./kccachetest wicked -th 4 -it 4 -tc -bnum 5000 -capcnt 10000 10000
$(RUNENV) $(RUNCMD) ./kccachetest tran -bnum 5000 10000
$(RUNENV) $(RUNCMD) ./kccachetest tran -th 2 -it 4 -tc -bnum 5000 10000
check-grass :
rm -rf casket*
$(RUNENV) $(RUNCMD) ./kcgrasstest order -etc -bnum 5000 10000
$(RUNENV) $(RUNCMD) ./kcgrasstest order -th 4 -bnum 5000 10000
$(RUNENV) $(RUNCMD) ./kcgrasstest order -th 4 -rnd -etc -bnum 5000 10000
$(RUNENV) $(RUNCMD) ./kcgrasstest order -th 4 -rnd -etc -bnum 5000 10000
$(RUNENV) $(RUNCMD) ./kcgrasstest order -th 4 -rnd -etc -tran \
-tc -bnum 5000 -pccap 10k -rcd 500
$(RUNENV) $(RUNCMD) ./kcgrasstest wicked -bnum 5000 10000
$(RUNENV) $(RUNCMD) ./kcgrasstest wicked -th 4 -it 4 -tc -bnum 5000 -pccap 10k -rcd 1000
$(RUNENV) $(RUNCMD) ./kcgrasstest tran -bnum 500 10000
$(RUNENV) $(RUNCMD) ./kcgrasstest tran -th 2 -it 4 -tc -bnum 5000 -pccap 10k -rcd 5000
check-hash :
rm -rf casket*
$(RUNENV) $(RUNCMD) ./kchashmgr create -otr -apow 1 -fpow 2 -bnum 3 casket
$(RUNENV) $(RUNCMD) ./kchashmgr inform -st casket
$(RUNENV) $(RUNCMD) ./kchashmgr set -add casket duffy 1231
$(RUNENV) $(RUNCMD) ./kchashmgr set -add casket micky 0101
$(RUNENV) $(RUNCMD) ./kchashmgr set casket fal 1007
$(RUNENV) $(RUNCMD) ./kchashmgr set casket mikio 0211
$(RUNENV) $(RUNCMD) ./kchashmgr set casket natsuki 0810
$(RUNENV) $(RUNCMD) ./kchashmgr set casket micky ""
$(RUNENV) $(RUNCMD) ./kchashmgr set -app casket duffy kukuku
$(RUNENV) $(RUNCMD) ./kchashmgr remove casket micky
$(RUNENV) $(RUNCMD) ./kchashmgr list -pv casket > check.out
$(RUNENV) $(RUNCMD) ./kchashmgr set casket ryu 1
$(RUNENV) $(RUNCMD) ./kchashmgr set casket ken 2
$(RUNENV) $(RUNCMD) ./kchashmgr remove casket duffy
$(RUNENV) $(RUNCMD) ./kchashmgr set casket ryu syo-ryu-ken
$(RUNENV) $(RUNCMD) ./kchashmgr set casket ken tatsumaki-senpu-kyaku
$(RUNENV) $(RUNCMD) ./kchashmgr set -inci casket int 1234
$(RUNENV) $(RUNCMD) ./kchashmgr set -inci casket int 5678
$(RUNENV) $(RUNCMD) ./kchashmgr set -incd casket double 1234.5678
$(RUNENV) $(RUNCMD) ./kchashmgr set -incd casket double 8765.4321
$(RUNENV) $(RUNCMD) ./kchashmgr get casket mikio
$(RUNENV) $(RUNCMD) ./kchashmgr get casket ryu
$(RUNENV) $(RUNCMD) ./kchashmgr import casket lab/numbers.tsv
$(RUNENV) $(RUNCMD) ./kchashmgr list -pv -px casket > check.out
$(RUNENV) $(RUNCMD) ./kchashmgr copy casket casket-para
$(RUNENV) $(RUNCMD) ./kchashmgr dump casket check.out
$(RUNENV) $(RUNCMD) ./kchashmgr load -otr casket check.out
$(RUNENV) $(RUNCMD) ./kchashmgr defrag -onl casket
$(RUNENV) $(RUNCMD) ./kchashmgr setbulk casket aa aaa bb bbb cc ccc dd ddd
$(RUNENV) $(RUNCMD) ./kchashmgr removebulk casket aa bb zz
$(RUNENV) $(RUNCMD) ./kchashmgr getbulk casket aa bb cc dd
$(RUNENV) $(RUNCMD) ./kchashmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kchashmgr inform -st casket
$(RUNENV) $(RUNCMD) ./kchashmgr create -otr -otl -onr -apow 1 -fpow 3 \
-ts -tl -tc -bnum 1 casket
$(RUNENV) $(RUNCMD) ./kchashmgr import casket < lab/numbers.tsv
$(RUNENV) $(RUNCMD) ./kchashmgr set casket mikio kyotocabinet
$(RUNENV) $(RUNCMD) ./kchashmgr set -app casket tako ikaunini
$(RUNENV) $(RUNCMD) ./kchashmgr set -app casket mikio kyototyrant
$(RUNENV) $(RUNCMD) ./kchashmgr set -app casket mikio kyotodystopia
$(RUNENV) $(RUNCMD) ./kchashmgr get -px casket mikio > check.out
$(RUNENV) $(RUNCMD) ./kchashmgr list casket > check.out
$(RUNENV) $(RUNCMD) ./kchashmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kchashmgr clear casket
rm -rf casket*
$(RUNENV) $(RUNCMD) ./kchashtest order -set -bnum 5000 -msiz 50000 casket 10000
$(RUNENV) $(RUNCMD) ./kchashtest order -get -msiz 50000 casket 10000
$(RUNENV) $(RUNCMD) ./kchashtest order -getw -msiz 5000 casket 10000
$(RUNENV) $(RUNCMD) ./kchashtest order -rem -msiz 50000 casket 10000
$(RUNENV) $(RUNCMD) ./kchashtest order -bnum 5000 -msiz 50000 casket 10000
$(RUNENV) $(RUNCMD) ./kchashtest order -etc \
-bnum 5000 -msiz 50000 -dfunit 4 casket 10000
$(RUNENV) $(RUNCMD) ./kchashtest order -th 4 \
-bnum 5000 -msiz 50000 -dfunit 4 casket 10000
$(RUNENV) $(RUNCMD) ./kchashtest order -th 4 -rnd -etc \
-bnum 5000 -msiz 50000 -dfunit 4 casket 10000
$(RUNENV) $(RUNCMD) ./kchashmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kchashtest order -th 4 -rnd -etc -tran \
-bnum 5000 -msiz 50000 -dfunit 4 casket 10000
$(RUNENV) $(RUNCMD) ./kchashmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kchashtest order -th 4 -rnd -etc -oat \
-bnum 5000 -msiz 50000 -dfunit 4 casket 10000
$(RUNENV) $(RUNCMD) ./kchashmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kchashtest order -th 4 -rnd -etc \
-apow 2 -fpow 3 -ts -tl -tc -bnum 5000 -msiz 50000 -dfunit 4 casket 10000
$(RUNENV) $(RUNCMD) ./kchashmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kchashtest queue \
-bnum 5000 -msiz 50000 casket 10000
$(RUNENV) $(RUNCMD) ./kchashmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kchashtest queue -rnd \
-bnum 5000 -msiz 50000 casket 10000
$(RUNENV) $(RUNCMD) ./kchashmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kchashtest queue -th 4 -it 4 \
-bnum 5000 -msiz 50000 casket 10000
$(RUNENV) $(RUNCMD) ./kchashmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kchashtest queue -th 4 -it 4 -rnd \
-bnum 5000 -msiz 50000 casket 10000
$(RUNENV) $(RUNCMD) ./kchashmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kchashtest wicked -bnum 5000 -msiz 50000 casket 10000
$(RUNENV) $(RUNCMD) ./kchashmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kchashtest wicked -th 4 -it 4 \
-bnum 5000 -msiz 50000 -dfunit 4 casket 10000
$(RUNENV) $(RUNCMD) ./kchashmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kchashtest wicked -th 4 -it 4 -oat \
-bnum 5000 -msiz 50000 -dfunit 4 casket 10000
$(RUNENV) $(RUNCMD) ./kchashmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kchashtest wicked -th 4 -it 4 \
-apow 2 -fpow 3 -ts -tl -tc -bnum 10000 -msiz 50000 -dfunit 4 casket 10000
$(RUNENV) $(RUNCMD) ./kchashmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kchashtest tran casket 10000
$(RUNENV) $(RUNCMD) ./kchashtest tran -th 2 -it 4 casket 10000
$(RUNENV) $(RUNCMD) ./kchashtest tran -th 2 -it 4 \
-apow 2 -fpow 3 -ts -tl -tc -bnum 10000 -msiz 50000 -dfunit 4 casket 10000
check-tree :
rm -rf casket*
$(RUNENV) $(RUNCMD) ./kctreemgr create -otr -apow 1 -fpow 2 -bnum 3 casket
$(RUNENV) $(RUNCMD) ./kctreemgr inform -st casket
$(RUNENV) $(RUNCMD) ./kctreemgr set -add casket duffy 1231
$(RUNENV) $(RUNCMD) ./kctreemgr set -add casket micky 0101
$(RUNENV) $(RUNCMD) ./kctreemgr set casket fal 1007
$(RUNENV) $(RUNCMD) ./kctreemgr set casket mikio 0211
$(RUNENV) $(RUNCMD) ./kctreemgr set casket natsuki 0810
$(RUNENV) $(RUNCMD) ./kctreemgr set casket micky ""
$(RUNENV) $(RUNCMD) ./kctreemgr set -app casket duffy kukuku
$(RUNENV) $(RUNCMD) ./kctreemgr remove casket micky
$(RUNENV) $(RUNCMD) ./kctreemgr list -pv casket > check.out
$(RUNENV) $(RUNCMD) ./kctreemgr set casket ryu 1
$(RUNENV) $(RUNCMD) ./kctreemgr set casket ken 2
$(RUNENV) $(RUNCMD) ./kctreemgr remove casket duffy
$(RUNENV) $(RUNCMD) ./kctreemgr set casket ryu syo-ryu-ken
$(RUNENV) $(RUNCMD) ./kctreemgr set casket ken tatsumaki-senpu-kyaku
$(RUNENV) $(RUNCMD) ./kctreemgr set -inci casket int 1234
$(RUNENV) $(RUNCMD) ./kctreemgr set -inci casket int 5678
$(RUNENV) $(RUNCMD) ./kctreemgr set -incd casket double 1234.5678
$(RUNENV) $(RUNCMD) ./kctreemgr set -incd casket double 8765.4321
$(RUNENV) $(RUNCMD) ./kctreemgr get casket mikio
$(RUNENV) $(RUNCMD) ./kctreemgr get casket ryu
$(RUNENV) $(RUNCMD) ./kctreemgr import casket lab/numbers.tsv
$(RUNENV) $(RUNCMD) ./kctreemgr list -des -pv -px casket > check.out
$(RUNENV) $(RUNCMD) ./kctreemgr copy casket casket-para
$(RUNENV) $(RUNCMD) ./kctreemgr dump casket check.out
$(RUNENV) $(RUNCMD) ./kctreemgr load -otr casket check.out
$(RUNENV) $(RUNCMD) ./kctreemgr defrag -onl casket
$(RUNENV) $(RUNCMD) ./kctreemgr setbulk casket aa aaa bb bbb cc ccc dd ddd
$(RUNENV) $(RUNCMD) ./kctreemgr removebulk casket aa bb zz
$(RUNENV) $(RUNCMD) ./kctreemgr getbulk casket aa bb cc dd
$(RUNENV) $(RUNCMD) ./kctreemgr check -onr casket
$(RUNENV) $(RUNCMD) ./kctreemgr inform -st casket
$(RUNENV) $(RUNCMD) ./kctreemgr create -otr -otl -onr -apow 1 -fpow 3 \
-ts -tl -tc -bnum 1 casket
$(RUNENV) $(RUNCMD) ./kctreemgr import casket < lab/numbers.tsv
$(RUNENV) $(RUNCMD) ./kctreemgr set casket mikio kyotocabinet
$(RUNENV) $(RUNCMD) ./kctreemgr set -app casket tako ikaunini
$(RUNENV) $(RUNCMD) ./kctreemgr set -app casket mikio kyototyrant
$(RUNENV) $(RUNCMD) ./kctreemgr set -app casket mikio kyotodystopia
$(RUNENV) $(RUNCMD) ./kctreemgr get -px casket mikio > check.out
$(RUNENV) $(RUNCMD) ./kctreemgr list casket > check.out
$(RUNENV) $(RUNCMD) ./kctreemgr check -onr casket
$(RUNENV) $(RUNCMD) ./kctreemgr clear casket
rm -rf casket*
$(RUNENV) $(RUNCMD) ./kctreetest order -set \
-psiz 100 -bnum 5000 -msiz 50000 -pccap 100k casket 10000
$(RUNENV) $(RUNCMD) ./kctreetest order -get \
-msiz 50000 -pccap 100k casket 10000
$(RUNENV) $(RUNCMD) ./kctreetest order -getw \
-msiz 5000 -pccap 100k casket 10000
$(RUNENV) $(RUNCMD) ./kctreetest order -rem \
-msiz 50000 -pccap 100k casket 10000
$(RUNENV) $(RUNCMD) ./kctreetest order \
-bnum 5000 -psiz 100 -msiz 50000 -pccap 100k casket 10000
$(RUNENV) $(RUNCMD) ./kctreetest order -etc \
-bnum 5000 -psiz 1000 -msiz 50000 -dfunit 4 -pccap 100k casket 10000
$(RUNENV) $(RUNCMD) ./kctreetest order -th 4 \
-bnum 5000 -psiz 1000 -msiz 50000 -dfunit 4 -pccap 100k casket 10000
$(RUNENV) $(RUNCMD) ./kctreetest order -th 4 -pccap 100k -rnd -etc \
-bnum 5000 -psiz 1000 -msiz 50000 -dfunit 4 -pccap 100k -rcd casket 10000
$(RUNENV) $(RUNCMD) ./kctreemgr check -onr casket
$(RUNENV) $(RUNCMD) ./kctreetest order -th 4 -rnd -etc -tran \
-bnum 5000 -psiz 1000 -msiz 50000 -dfunit 4 -pccap 100k casket 1000
$(RUNENV) $(RUNCMD) ./kctreemgr check -onr casket
$(RUNENV) $(RUNCMD) ./kctreetest order -th 4 -rnd -etc -oat \
-bnum 5000 -psiz 1000 -msiz 50000 -dfunit 4 -pccap 100k casket 1000
$(RUNENV) $(RUNCMD) ./kctreemgr check -onr casket
$(RUNENV) $(RUNCMD) ./kctreetest order -th 4 -rnd -etc \
-apow 2 -fpow 3 -ts -tl -tc -bnum 5000 -psiz 1000 -msiz 50000 -dfunit 4 casket 10000
$(RUNENV) $(RUNCMD) ./kctreemgr check -onr casket
$(RUNENV) $(RUNCMD) ./kctreetest queue \
-bnum 5000 -psiz 500 -msiz 50000 casket 10000
$(RUNENV) $(RUNCMD) ./kctreemgr check -onr casket
$(RUNENV) $(RUNCMD) ./kctreetest queue -rnd \
-bnum 5000 -psiz 500 -msiz 50000 casket 10000
$(RUNENV) $(RUNCMD) ./kctreemgr check -onr casket
$(RUNENV) $(RUNCMD) ./kctreetest queue -th 4 -it 4 \
-bnum 5000 -psiz 500 -msiz 50000 casket 10000
$(RUNENV) $(RUNCMD) ./kctreemgr check -onr casket
$(RUNENV) $(RUNCMD) ./kctreetest queue -th 4 -it 4 -rnd \
-bnum 5000 -psiz 500 -msiz 50000 casket 10000
$(RUNENV) $(RUNCMD) ./kctreemgr check -onr casket
$(RUNENV) $(RUNCMD) ./kctreetest wicked \
-bnum 5000 -psiz 1000 -msiz 50000 -pccap 100k casket 10000
$(RUNENV) $(RUNCMD) ./kctreemgr check -onr casket
$(RUNENV) $(RUNCMD) ./kctreetest wicked -th 4 -it 4 \
-bnum 5000 -msiz 50000 -dfunit 4 -pccap 100k -rcd casket 10000
$(RUNENV) $(RUNCMD) ./kctreemgr check -onr casket
$(RUNENV) $(RUNCMD) ./kctreetest wicked -th 4 -it 4 -oat \
-bnum 5000 -msiz 50000 -dfunit 4 -pccap 100k casket 1000
$(RUNENV) $(RUNCMD) ./kctreemgr check -onr casket
$(RUNENV) $(RUNCMD) ./kctreetest wicked -th 4 -it 4 \
-apow 2 -fpow 3 -ts -tl -tc -bnum 10000 -msiz 50000 -dfunit 4 casket 1000
$(RUNENV) $(RUNCMD) ./kctreemgr check -onr casket
$(RUNENV) $(RUNCMD) ./kctreetest tran casket 10000
$(RUNENV) $(RUNCMD) ./kctreetest tran -th 2 -it 4 -pccap 100k casket 10000
$(RUNENV) $(RUNCMD) ./kctreetest tran -th 2 -it 4 \
-apow 2 -fpow 3 -ts -tl -tc -bnum 10000 -msiz 50000 -dfunit 4 -rcd casket 10000
check-dir :
rm -rf casket*
$(RUNENV) $(RUNCMD) ./kcdirmgr create -otr casket
$(RUNENV) $(RUNCMD) ./kcdirmgr inform -st casket
$(RUNENV) $(RUNCMD) ./kcdirmgr set -add casket duffy 1231
$(RUNENV) $(RUNCMD) ./kcdirmgr set -add casket micky 0101
$(RUNENV) $(RUNCMD) ./kcdirmgr set casket fal 1007
$(RUNENV) $(RUNCMD) ./kcdirmgr set casket mikio 0211
$(RUNENV) $(RUNCMD) ./kcdirmgr set casket natsuki 0810
$(RUNENV) $(RUNCMD) ./kcdirmgr set casket micky ""
$(RUNENV) $(RUNCMD) ./kcdirmgr set -app casket duffy kukuku
$(RUNENV) $(RUNCMD) ./kcdirmgr remove casket micky
$(RUNENV) $(RUNCMD) ./kcdirmgr list -pv casket > check.out
$(RUNENV) $(RUNCMD) ./kcdirmgr set casket ryu 1
$(RUNENV) $(RUNCMD) ./kcdirmgr set casket ken 2
$(RUNENV) $(RUNCMD) ./kcdirmgr remove casket duffy
$(RUNENV) $(RUNCMD) ./kcdirmgr set casket ryu syo-ryu-ken
$(RUNENV) $(RUNCMD) ./kcdirmgr set casket ken tatsumaki-senpu-kyaku
$(RUNENV) $(RUNCMD) ./kcdirmgr set -inci casket int 1234
$(RUNENV) $(RUNCMD) ./kcdirmgr set -inci casket int 5678
$(RUNENV) $(RUNCMD) ./kcdirmgr set -incd casket double 1234.5678
$(RUNENV) $(RUNCMD) ./kcdirmgr set -incd casket double 8765.4321
$(RUNENV) $(RUNCMD) ./kcdirmgr get casket mikio
$(RUNENV) $(RUNCMD) ./kcdirmgr get casket ryu
$(RUNENV) $(RUNCMD) ./kcdirmgr import casket lab/numbers.tsv
$(RUNENV) $(RUNCMD) ./kcdirmgr list -pv -px casket > check.out
$(RUNENV) $(RUNCMD) ./kcdirmgr copy casket casket-para
$(RUNENV) $(RUNCMD) ./kcdirmgr dump casket check.out
$(RUNENV) $(RUNCMD) ./kcdirmgr load -otr casket check.out
$(RUNENV) $(RUNCMD) ./kcdirmgr setbulk casket aa aaa bb bbb cc ccc dd ddd
$(RUNENV) $(RUNCMD) ./kcdirmgr removebulk casket aa bb zz
$(RUNENV) $(RUNCMD) ./kcdirmgr getbulk casket aa bb cc dd
$(RUNENV) $(RUNCMD) ./kcdirmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcdirmgr inform -st casket
$(RUNENV) $(RUNCMD) ./kcdirmgr create -otr -otl -onr -tc casket
$(RUNENV) $(RUNCMD) ./kcdirmgr import casket < lab/numbers.tsv
$(RUNENV) $(RUNCMD) ./kcdirmgr set casket mikio kyotocabinet
$(RUNENV) $(RUNCMD) ./kcdirmgr set -app casket tako ikaunini
$(RUNENV) $(RUNCMD) ./kcdirmgr set -app casket mikio kyototyrant
$(RUNENV) $(RUNCMD) ./kcdirmgr set -app casket mikio kyotodystopia
$(RUNENV) $(RUNCMD) ./kcdirmgr get -px casket mikio > check.out
$(RUNENV) $(RUNCMD) ./kcdirmgr list casket > check.out
$(RUNENV) $(RUNCMD) ./kcdirmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcdirmgr clear casket
rm -rf casket*
$(RUNENV) $(RUNCMD) ./kcdirtest order -set casket 500
$(RUNENV) $(RUNCMD) ./kcdirtest order -get casket 500
$(RUNENV) $(RUNCMD) ./kcdirtest order -getw casket 500
$(RUNENV) $(RUNCMD) ./kcdirtest order -rem casket 500
$(RUNENV) $(RUNCMD) ./kcdirtest order casket 500
$(RUNENV) $(RUNCMD) ./kcdirtest order -etc casket 500
$(RUNENV) $(RUNCMD) ./kcdirtest order -th 4 casket 500
$(RUNENV) $(RUNCMD) ./kcdirtest order -th 4 -rnd -etc casket 500
$(RUNENV) $(RUNCMD) ./kcdirmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcdirtest order -th 4 -rnd -etc -tran casket 500
$(RUNENV) $(RUNCMD) ./kcdirmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcdirtest order -th 4 -rnd -etc -oat casket 500
$(RUNENV) $(RUNCMD) ./kcdirmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcdirtest order -th 4 -rnd -etc -tc casket 500
$(RUNENV) $(RUNCMD) ./kcdirmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcdirtest queue casket 500
$(RUNENV) $(RUNCMD) ./kcdirmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcdirtest queue -rnd casket 500
$(RUNENV) $(RUNCMD) ./kcdirmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcdirtest queue -th 4 -it 4 casket 500
$(RUNENV) $(RUNCMD) ./kcdirmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcdirtest queue -th 4 -it 4 -rnd casket 500
$(RUNENV) $(RUNCMD) ./kcdirmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcdirtest wicked casket 500
$(RUNENV) $(RUNCMD) ./kcdirmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcdirtest wicked -th 4 -it 4 casket 500
$(RUNENV) $(RUNCMD) ./kcdirmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcdirtest wicked -th 4 -it 4 -oat casket 500
$(RUNENV) $(RUNCMD) ./kcdirmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcdirtest wicked -th 4 -it 4 -tc casket 500
$(RUNENV) $(RUNCMD) ./kcdirmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcdirtest tran casket 500
$(RUNENV) $(RUNCMD) ./kcdirtest tran -th 2 -it 4 casket 500
$(RUNENV) $(RUNCMD) ./kcdirtest tran -th 2 -it 4 -tc casket 500
check-forest :
rm -rf casket*
$(RUNENV) $(RUNCMD) ./kcforestmgr create -otr -bnum 3 casket
$(RUNENV) $(RUNCMD) ./kcforestmgr inform -st casket
$(RUNENV) $(RUNCMD) ./kcforestmgr set -add casket duffy 1231
$(RUNENV) $(RUNCMD) ./kcforestmgr set -add casket micky 0101
$(RUNENV) $(RUNCMD) ./kcforestmgr set casket fal 1007
$(RUNENV) $(RUNCMD) ./kcforestmgr set casket mikio 0211
$(RUNENV) $(RUNCMD) ./kcforestmgr set casket natsuki 0810
$(RUNENV) $(RUNCMD) ./kcforestmgr set casket micky ""
$(RUNENV) $(RUNCMD) ./kcforestmgr set -app casket duffy kukuku
$(RUNENV) $(RUNCMD) ./kcforestmgr remove casket micky
$(RUNENV) $(RUNCMD) ./kcforestmgr list -pv casket > check.out
$(RUNENV) $(RUNCMD) ./kcforestmgr set casket ryu 1
$(RUNENV) $(RUNCMD) ./kcforestmgr set casket ken 2
$(RUNENV) $(RUNCMD) ./kcforestmgr remove casket duffy
$(RUNENV) $(RUNCMD) ./kcforestmgr set casket ryu syo-ryu-ken
$(RUNENV) $(RUNCMD) ./kcforestmgr set casket ken tatsumaki-senpu-kyaku
$(RUNENV) $(RUNCMD) ./kcforestmgr set -inci casket int 1234
$(RUNENV) $(RUNCMD) ./kcforestmgr set -inci casket int 5678
$(RUNENV) $(RUNCMD) ./kcforestmgr set -incd casket double 1234.5678
$(RUNENV) $(RUNCMD) ./kcforestmgr set -incd casket double 8765.4321
$(RUNENV) $(RUNCMD) ./kcforestmgr get casket mikio
$(RUNENV) $(RUNCMD) ./kcforestmgr get casket ryu
$(RUNENV) $(RUNCMD) ./kcforestmgr import casket lab/numbers.tsv
$(RUNENV) $(RUNCMD) ./kcforestmgr list -des -pv -px casket > check.out
$(RUNENV) $(RUNCMD) ./kcforestmgr copy casket casket-para
$(RUNENV) $(RUNCMD) ./kcforestmgr dump casket check.out
$(RUNENV) $(RUNCMD) ./kcforestmgr load -otr casket check.out
$(RUNENV) $(RUNCMD) ./kcforestmgr setbulk casket aa aaa bb bbb cc ccc dd ddd
$(RUNENV) $(RUNCMD) ./kcforestmgr removebulk casket aa bb zz
$(RUNENV) $(RUNCMD) ./kcforestmgr getbulk casket aa bb cc dd
$(RUNENV) $(RUNCMD) ./kcforestmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcforestmgr inform -st casket
$(RUNENV) $(RUNCMD) ./kcforestmgr create -otr -otl -onr \
-tc -bnum 1 casket
$(RUNENV) $(RUNCMD) ./kcforestmgr import casket < lab/numbers.tsv
$(RUNENV) $(RUNCMD) ./kcforestmgr set casket mikio kyotocabinet
$(RUNENV) $(RUNCMD) ./kcforestmgr set -app casket tako ikaunini
$(RUNENV) $(RUNCMD) ./kcforestmgr set -app casket mikio kyototyrant
$(RUNENV) $(RUNCMD) ./kcforestmgr set -app casket mikio kyotodystopia
$(RUNENV) $(RUNCMD) ./kcforestmgr get -px casket mikio > check.out
$(RUNENV) $(RUNCMD) ./kcforestmgr list casket > check.out
$(RUNENV) $(RUNCMD) ./kcforestmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcforestmgr clear casket
rm -rf casket*
$(RUNENV) $(RUNCMD) ./kcforesttest order -set \
-psiz 100 -bnum 5000 -pccap 100k casket 5000
$(RUNENV) $(RUNCMD) ./kcforesttest order -get \
-pccap 100k casket 5000
$(RUNENV) $(RUNCMD) ./kcforesttest order -getw \
-pccap 100k casket 5000
$(RUNENV) $(RUNCMD) ./kcforesttest order -rem \
-pccap 100k casket 5000
$(RUNENV) $(RUNCMD) ./kcforesttest order \
-bnum 5000 -psiz 100 -pccap 100k casket 5000
$(RUNENV) $(RUNCMD) ./kcforesttest order -etc \
-bnum 5000 -psiz 1000 -pccap 100k casket 5000
$(RUNENV) $(RUNCMD) ./kcforesttest order -th 4 \
-bnum 5000 -psiz 1000 -pccap 100k casket 5000
$(RUNENV) $(RUNCMD) ./kcforesttest order -th 4 -pccap 100k -rnd -etc \
-bnum 5000 -psiz 1000 -pccap 100k -rcd casket 5000
$(RUNENV) $(RUNCMD) ./kcforestmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcforesttest order -th 4 -rnd -etc -tran \
-bnum 500 -psiz 1000 -pccap 100k casket 500
$(RUNENV) $(RUNCMD) ./kcforestmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcforesttest order -th 4 -rnd -etc -oat \
-bnum 500 -psiz 1000 -pccap 100k casket 500
$(RUNENV) $(RUNCMD) ./kcforestmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcforesttest order -th 4 -rnd -etc \
-tc -bnum 5000 -psiz 1000 casket 5000
$(RUNENV) $(RUNCMD) ./kcforestmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcforesttest queue \
-bnum 5000 -psiz 500 casket 5000
$(RUNENV) $(RUNCMD) ./kcforestmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcforesttest queue -rnd \
-bnum 5000 -psiz 500 casket 5000
$(RUNENV) $(RUNCMD) ./kcforestmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcforesttest queue -th 4 -it 4 \
-bnum 5000 -psiz 500 casket 5000
$(RUNENV) $(RUNCMD) ./kcforestmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcforesttest queue -th 4 -it 4 -rnd \
-bnum 5000 -psiz 500 casket 5000
$(RUNENV) $(RUNCMD) ./kcforestmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcforesttest wicked \
-bnum 5000 -psiz 1000 -pccap 100k casket 5000
$(RUNENV) $(RUNCMD) ./kcforestmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcforesttest wicked -th 4 -it 4 \
-bnum 5000 -pccap 100k -rcd casket 5000
$(RUNENV) $(RUNCMD) ./kcforestmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcforesttest wicked -th 4 -it 4 -oat \
-bnum 500 -pccap 100k casket 500
$(RUNENV) $(RUNCMD) ./kcforestmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcforesttest wicked -th 4 -it 4 \
-tc -bnum 500 casket 500
$(RUNENV) $(RUNCMD) ./kcforestmgr check -onr casket
$(RUNENV) $(RUNCMD) ./kcforesttest tran casket 5000
$(RUNENV) $(RUNCMD) ./kcforesttest tran -th 2 -it 4 -pccap 100k casket 5000
$(RUNENV) $(RUNCMD) ./kcforesttest tran -th 2 -it 4 \
-tc -bnum 5000 -rcd casket 5000
check-poly :
rm -rf casket*
$(RUNENV) $(RUNCMD) ./kcpolymgr create -otr "casket.kch#apow=1#fpow=2#bnum=3"
$(RUNENV) $(RUNCMD) ./kcpolymgr inform -st casket.kch
$(RUNENV) $(RUNCMD) ./kcpolymgr set -add casket.kch duffy 1231
$(RUNENV) $(RUNCMD) ./kcpolymgr set -add casket.kch micky 0101
$(RUNENV) $(RUNCMD) ./kcpolymgr set casket.kch fal 1007
$(RUNENV) $(RUNCMD) ./kcpolymgr set casket.kch mikio 0211
$(RUNENV) $(RUNCMD) ./kcpolymgr set casket.kch natsuki 0810
$(RUNENV) $(RUNCMD) ./kcpolymgr set casket.kch micky ""
$(RUNENV) $(RUNCMD) ./kcpolymgr set -app casket.kch duffy kukuku
$(RUNENV) $(RUNCMD) ./kcpolymgr remove casket.kch micky
$(RUNENV) $(RUNCMD) ./kcpolymgr list -pv casket.kch > check.out
$(RUNENV) $(RUNCMD) ./kcpolymgr copy casket.kch casket-para
$(RUNENV) $(RUNCMD) ./kcpolymgr dump casket.kch check.out
$(RUNENV) $(RUNCMD) ./kcpolymgr load -otr casket.kch check.out
$(RUNENV) $(RUNCMD) ./kcpolymgr set casket.kch ryu 1
$(RUNENV) $(RUNCMD) ./kcpolymgr set casket.kch ken 2
$(RUNENV) $(RUNCMD) ./kcpolymgr remove casket.kch duffy
$(RUNENV) $(RUNCMD) ./kcpolymgr set casket.kch ryu syo-ryu-ken
$(RUNENV) $(RUNCMD) ./kcpolymgr set casket.kch ken tatsumaki-senpu-kyaku
$(RUNENV) $(RUNCMD) ./kcpolymgr set -inci casket.kch int 1234
$(RUNENV) $(RUNCMD) ./kcpolymgr set -inci casket.kch int 5678
$(RUNENV) $(RUNCMD) ./kcpolymgr set -incd casket.kch double 1234.5678
$(RUNENV) $(RUNCMD) ./kcpolymgr set -incd casket.kch double 8765.4321
$(RUNENV) $(RUNCMD) ./kcpolymgr get "casket.kch" mikio
$(RUNENV) $(RUNCMD) ./kcpolymgr get "casket.kch" ryu
$(RUNENV) $(RUNCMD) ./kcpolymgr import casket.kch lab/numbers.tsv
$(RUNENV) $(RUNCMD) ./kcpolymgr list -pv -px "casket.kch#mode=r" > check.out
$(RUNENV) $(RUNCMD) ./kcpolymgr setbulk casket.kch aa aaa bb bbb cc ccc dd ddd
$(RUNENV) $(RUNCMD) ./kcpolymgr removebulk casket.kch aa bb zz
$(RUNENV) $(RUNCMD) ./kcpolymgr getbulk casket.kch aa bb cc dd
$(RUNENV) $(RUNCMD) ./kcpolymgr check -onr casket.kch
$(RUNENV) $(RUNCMD) ./kcpolymgr inform -st casket.kch
$(RUNENV) $(RUNCMD) ./kcpolymgr create -otr -otl -onr \
"casket.kct#apow=1#fpow=3#opts=slc#bnum=1"
$(RUNENV) $(RUNCMD) ./kcpolymgr import casket.kct < lab/numbers.tsv
$(RUNENV) $(RUNCMD) ./kcpolymgr set casket.kct mikio kyotocabinet
$(RUNENV) $(RUNCMD) ./kcpolymgr set -app casket.kct tako ikaunini
$(RUNENV) $(RUNCMD) ./kcpolymgr set -app casket.kct mikio kyototyrant
$(RUNENV) $(RUNCMD) ./kcpolymgr set -app casket.kct mikio kyotodystopia
$(RUNENV) $(RUNCMD) ./kcpolymgr get -px casket.kct mikio > check.out
$(RUNENV) $(RUNCMD) ./kcpolymgr list casket.kct > check.out
$(RUNENV) $(RUNCMD) ./kcpolymgr check -onr casket.kct
$(RUNENV) $(RUNCMD) ./kcpolymgr clear casket.kct
rm -rf casket*
$(RUNENV) $(RUNCMD) ./kcpolytest order -set "casket.kct#bnum=5000#msiz=50000" 10000
$(RUNENV) $(RUNCMD) ./kcpolytest order -get "casket.kct#msiz=50000" 10000
$(RUNENV) $(RUNCMD) ./kcpolytest order -getw "casket.kct#msiz=5000" 10000
$(RUNENV) $(RUNCMD) ./kcpolytest order -rem "casket.kct#msiz=50000" 10000
$(RUNENV) $(RUNCMD) ./kcpolytest order "casket.kct#bnum=5000#msiz=50000" 10000
$(RUNENV) $(RUNCMD) ./kcpolytest order -etc \
"casket.kct#bnum=5000#msiz=50000#dfunit=4" 10000
$(RUNENV) $(RUNCMD) ./kcpolytest order -th 4 \
"casket.kct#bnum=5000#msiz=50000#dfunit=4" 10000
$(RUNENV) $(RUNCMD) ./kcpolytest order -th 4 -rnd -etc \
"casket.kct#bnum=5000#msiz=0#dfunit=1" 1000
$(RUNENV) $(RUNCMD) ./kcpolymgr check -onr casket.kct
$(RUNENV) $(RUNCMD) ./kcpolytest order -th 4 -rnd -etc -tran \
"casket.kct#bnum=5000#msiz=0#dfunit=2" 1000
$(RUNENV) $(RUNCMD) ./kcpolymgr check -onr casket.kct
$(RUNENV) $(RUNCMD) ./kcpolytest order -th 4 -rnd -etc -oat \
"casket.kct#bnum=5000#msiz=0#dfunit=3" 1000
$(RUNENV) $(RUNCMD) ./kcpolymgr check -onr casket.kct
$(RUNENV) $(RUNCMD) ./kcpolytest order -th 4 -rnd -etc \
"casket.kct#apow=2#fpow=3#opts=slc#bnum=5000#msiz=0#dfunit=4" 1000
$(RUNENV) $(RUNCMD) ./kcpolymgr check -onr casket.kct
$(RUNENV) $(RUNCMD) ./kcpolytest queue \
"casket.kct#bnum=5000#msiz=0" 10000
$(RUNENV) $(RUNCMD) ./kcpolymgr check -onr casket.kct
$(RUNENV) $(RUNCMD) ./kcpolytest queue -rnd \
"casket.kct#bnum=5000#msiz=0" 10000
$(RUNENV) $(RUNCMD) ./kcpolymgr check -onr casket.kct
$(RUNENV) $(RUNCMD) ./kcpolytest queue -th 4 -it 4 \
"casket.kct#bnum=5000#msiz=0" 10000
$(RUNENV) $(RUNCMD) ./kcpolymgr check -onr casket.kct
$(RUNENV) $(RUNCMD) ./kcpolytest queue -th 4 -it 4 -rnd \
"casket.kct#bnum=5000#msiz=0" 10000
$(RUNENV) $(RUNCMD) ./kcpolymgr check -onr casket.kct
$(RUNENV) $(RUNCMD) ./kcpolytest wicked "casket.kct#bnum=5000#msiz=0" 1000
$(RUNENV) $(RUNCMD) ./kcpolymgr check -onr casket.kct
$(RUNENV) $(RUNCMD) ./kcpolytest wicked -th 4 -it 4 \
"casket.kct#bnum=5000#msiz=0#dfunit=1" 1000
$(RUNENV) $(RUNCMD) ./kcpolymgr check -onr casket.kct
$(RUNENV) $(RUNCMD) ./kcpolytest wicked -th 4 -it 4 -oat \
"casket.kct#bnum=5000#msiz=0#dfunit=1" 1000
$(RUNENV) $(RUNCMD) ./kcpolymgr check -onr casket.kct
$(RUNENV) $(RUNCMD) ./kcpolytest wicked -th 4 -it 4 \
"casket.kct#apow=2#fpow=3#opts=slc#bnum=10000#msiz=0#dfunit=1" 10000
$(RUNENV) $(RUNCMD) ./kcpolymgr check -onr casket.kct
$(RUNENV) $(RUNCMD) ./kcpolytest tran casket.kct 10000
$(RUNENV) $(RUNCMD) ./kcpolytest tran -th 2 -it 4 casket.kct 10000
$(RUNENV) $(RUNCMD) ./kcpolytest tran -th 2 -it 4 \
"casket.kct#apow=2#fpow=3#opts=slc#bnum=10000#msiz=0#dfunit=1" 1000
$(RUNENV) $(RUNCMD) ./kcpolytest mapred -dbnum 2 -clim 10k casket.kct 10000
$(RUNENV) $(RUNCMD) ./kcpolytest mapred -tmp . -dbnum 2 -clim 10k -xnl -xnc \
casket.kct 10000
$(RUNENV) $(RUNCMD) ./kcpolytest mapred -tmp . -dbnum 2 -clim 10k -xpm -xpr -xpf -xnc \
casket.kct 10000
$(RUNENV) $(RUNCMD) ./kcpolytest mapred -rnd -dbnum 2 -clim 10k casket.kct 10000
$(RUNENV) $(RUNCMD) ./kcpolytest index -set "casket.kct#idxclim=32k" 10000
$(RUNENV) $(RUNCMD) ./kcpolytest index -get "casket.kct" 10000
$(RUNENV) $(RUNCMD) ./kcpolytest index -rem "casket.kct" 10000
$(RUNENV) $(RUNCMD) ./kcpolytest index -etc "casket.kct#idxclim=32k" 10000
$(RUNENV) $(RUNCMD) ./kcpolytest index -th 4 -rnd -set \
"casket.kct#idxclim=32k#idxdbnum=4" 10000
$(RUNENV) $(RUNCMD) ./kcpolytest index -th 4 -rnd -get "casket.kct" 10000
$(RUNENV) $(RUNCMD) ./kcpolytest index -th 4 -rnd -rem "casket.kct" 10000
$(RUNENV) $(RUNCMD) ./kcpolytest index -th 4 -rnd -etc \
"casket.kct#idxclim=32k#idxdbnum=4" 10000
rm -rf casket*
$(RUNENV) $(RUNCMD) ./kcpolytest order -rnd "casket.kcx" 10000
$(RUNENV) $(RUNCMD) ./kcpolytest order -th 4 -rnd "casket.kcx" 10000
$(RUNENV) $(RUNCMD) ./kcpolytest wicked "casket.kcx" 10000
$(RUNENV) $(RUNCMD) ./kcpolytest wicked -th 4 "casket.kcx" 10000
$(RUNENV) $(RUNCMD) ./kcpolymgr list -pv "casket.kcx" > check.out
$(RUNENV) $(RUNCMD) ./kcpolymgr list -max 1000 -pv "casket.kcx" > check.out
$(RUNENV) $(RUNCMD) ./kcpolytest mapred "casket.kcx" 10000
$(RUNENV) $(RUNCMD) ./kcpolytest mapred -xpm -xpr -xpf "casket.kcx" 10000
rm -rf casket*
$(RUNENV) $(RUNCMD) ./kcpolytest order -rnd "casket.kch#opts=s#bnum=256" 1000
$(RUNENV) $(RUNCMD) ./kcpolytest order -rnd "casket.kct#opts=l#psiz=256" 1000
$(RUNENV) $(RUNCMD) ./kcpolytest order -rnd "casket.kcd#opts=c#bnum=256" 500
$(RUNENV) $(RUNCMD) ./kcpolytest order -rnd "casket.kcf#opts=c#psiz=256" 500
$(RUNENV) $(RUNCMD) ./kcpolytest order -rnd "casket.kcx" 500
$(RUNENV) $(RUNCMD) ./kcpolymgr merge -add "casket#type=kct" \
casket.kch casket.kct casket.kcd casket.kcf casket.kcx
rm -rf casket*
$(RUNENV) $(RUNCMD) ./kcpolytest misc "casket#type=-"
$(RUNENV) $(RUNCMD) ./kcpolytest misc "casket#type=+"
$(RUNENV) $(RUNCMD) ./kcpolytest misc "casket#type=:"
$(RUNENV) $(RUNCMD) ./kcpolytest misc "casket#type=*#zcomp=def"
$(RUNENV) $(RUNCMD) ./kcpolytest misc "casket#type=%#zcomp=gz"
rm -rf casket*
$(RUNENV) $(RUNCMD) ./kcpolytest misc \
"casket#type=kch#log=-#logkinds=debug#mtrg=-#zcomp=lzocrc"
rm -rf casket*
$(RUNENV) $(RUNCMD) ./kcpolytest misc \
"casket#type=kct#log=-#logkinds=debug#mtrg=-#zcomp=lzmacrc"
rm -rf casket*
$(RUNENV) $(RUNCMD) ./kcpolytest misc \
"casket#type=kcd#zcomp=arc#zkey=mikio"
rm -rf casket*
$(RUNENV) $(RUNCMD) ./kcpolytest misc \
"casket#type=kcf#zcomp=arc#zkey=mikio"
check-langc :
rm -rf casket*
$(RUNENV) $(RUNCMD) ./kclangctest order "casket.kch#bnum=5000#msiz=50000" 10000
$(RUNENV) $(RUNCMD) ./kclangctest order -etc \
"casket.kch#bnum=5000#msiz=50000#dfunit=2" 10000
$(RUNENV) $(RUNCMD) ./kclangctest order -rnd -etc \
"casket.kch#bnum=5000#msiz=50000#dfunit=2" 10000
$(RUNENV) $(RUNCMD) ./kclangctest order -rnd -etc -oat -tran \
"casket.kch#bnum=5000#msiz=50000#dfunit=2#zcomp=arcz" 10000
$(RUNENV) $(RUNCMD) ./kclangctest index "casket.kct#bnum=5000#msiz=50000" 10000
$(RUNENV) $(RUNCMD) ./kclangctest index -etc \
"casket.kct#bnum=5000#msiz=50000#dfunit=2" 10000
$(RUNENV) $(RUNCMD) ./kclangctest index -rnd -etc \
"casket.kct#bnum=5000#msiz=50000#dfunit=2" 10000
$(RUNENV) $(RUNCMD) ./kclangctest index -rnd -etc -oat \
"casket.kct#bnum=5000#msiz=50000#dfunit=2#zcomp=arcz" 10000
$(RUNENV) $(RUNCMD) ./kclangctest map 10000
$(RUNENV) $(RUNCMD) ./kclangctest map -etc -bnum 1000 10000
$(RUNENV) $(RUNCMD) ./kclangctest map -etc -rnd -bnum 1000 10000
$(RUNENV) $(RUNCMD) ./kclangctest list 10000
$(RUNENV) $(RUNCMD) ./kclangctest list -etc 10000
$(RUNENV) $(RUNCMD) ./kclangctest list -etc -rnd 10000
check-valgrind :
$(MAKE) RUNCMD="valgrind --tool=memcheck --log-file=%p.vlog" check
grep ERROR *.vlog | grep -v ' 0 errors' ; true
grep 'at exit' *.vlog | grep -v ' 0 bytes' ; true
check-heavy :
$(MAKE) check-hash-heavy
$(MAKE) check-tree-heavy
check-hash-heavy :
$(RUNENV) ./kchashtest order -th 4 \
-apow 2 -fpow 2 -bnum 500000 -msiz 50m -dfunit 2 casket 250000
$(RUNENV) ./kchashmgr check -onr casket
$(RUNENV) ./kchashtest order -th 4 -rnd \
-apow 2 -fpow 2 -bnum 500000 -msiz 50m -dfunit 2 casket 250000
$(RUNENV) ./kchashmgr check -onr casket
$(RUNENV) ./kchashtest order -th 4 -etc \
-apow 2 -fpow 2 -bnum 500000 -msiz 50m -dfunit 2 casket 250000
$(RUNENV) ./kchashmgr check -onr casket
$(RUNENV) ./kchashtest order -th 4 -etc -rnd \
-apow 2 -fpow 2 -bnum 500000 -msiz 50m -dfunit 2 casket 250000
$(RUNENV) ./kchashmgr check -onr casket
$(RUNENV) ./kchashtest order -th 4 -etc -rnd \
-ts -tl -tc -dfunit 2 casket 25000
$(RUNENV) ./kchashmgr check -onr casket
$(RUNENV) ./kchashtest queue -th 4 -it 10 \
-bnum 1000000 -apow 4 -fpow 12 -msiz 100m -dfunit 2 casket 250000
$(RUNENV) ./kchashmgr check -onr casket
$(RUNENV) ./kchashtest queue -th 4 -it 5 -rnd \
-ts -tl -tc -dfunit 2 casket 25000
$(RUNENV) ./kchashmgr check -onr casket
$(RUNENV) ./kchashtest queue -th 4 -it 2 -oat -rnd \
-bnum 1000 -dfunit 8 casket 25000
$(RUNENV) ./kchashmgr check -onr casket
$(RUNENV) ./kchashtest queue -th 4 -it 2 -oas -rnd \
-bnum 1000 -dfunit 8 casket 2500
$(RUNENV) ./kchashmgr check -onr casket
$(RUNENV) ./kchashtest wicked -th 4 -it 10 \
-bnum 1000000 -apow 4 -fpow 12 -msiz 100m -dfunit 2 casket 250000
$(RUNENV) ./kchashmgr check -onr casket
$(RUNENV) ./kchashtest wicked -th 4 -it 5 \
-ts -tl -tc -dfunit 2 casket 25000
$(RUNENV) ./kchashmgr check -onr casket
$(RUNENV) ./kchashtest wicked -th 4 -it 2 -oat \
-bnum 1000 -dfunit 8 casket 25000
$(RUNENV) ./kchashmgr check -onr casket
$(RUNENV) ./kchashtest wicked -th 4 -it 2 -oas \
-bnum 1000 -dfunit 8 casket 2500
$(RUNENV) ./kchashmgr check -onr casket
$(RUNENV) ./kchashtest tran -th 4 -it 10 \
-apow 2 -fpow 2 -bnum 500000 -msiz 50m -dfunit 2 casket 250000
$(RUNENV) ./kchashmgr check -onr casket
$(RUNENV) ./kchashtest tran -th 4 -it 5 \
-ts -tl -tc -dfunit 2 casket 250000
$(RUNENV) ./kchashmgr check -onr casket
check-tree-heavy :
$(RUNENV) ./kctreetest order -th 4 \
-apow 2 -fpow 2 -bnum 50000 -psiz 1000 -msiz 50m -dfunit 2 -pccap 10m casket 250000
$(RUNENV) ./kctreemgr check -onr casket
$(RUNENV) ./kctreetest order -th 4 -rnd \
-apow 2 -fpow 2 -bnum 50000 -psiz 1000 -msiz 50m -dfunit 2 -pccap 10m casket 250000
$(RUNENV) ./kctreemgr check -onr casket
$(RUNENV) ./kctreetest order -th 4 -etc \
-apow 2 -fpow 2 -bnum 50000 -psiz 1000 -msiz 50m -dfunit 2 -pccap 10m casket 250000
$(RUNENV) ./kctreemgr check -onr casket
$(RUNENV) ./kctreetest order -th 4 -etc -rnd \
-apow 2 -fpow 2 -bnum 50000 -psiz 1000 -msiz 50m -dfunit 2 -pccap 10m casket 250000
$(RUNENV) ./kctreemgr check -onr casket
$(RUNENV) ./kctreetest order -th 4 -etc -rnd \
-ts -tl -tc -dfunit 2 casket 25000
$(RUNENV) ./kctreemgr check -onr casket
$(RUNENV) ./kctreetest queue -th 4 -it 10 \
-bnum 1000000 -apow 4 -fpow 12 -msiz 100m -dfunit 2 -pccap 10m casket 250000
$(RUNENV) ./kctreemgr check -onr casket
$(RUNENV) ./kctreetest queue -th 4 -it 5 -rnd \
-ts -tl -tc -dfunit 2 -pccap 10m casket 25000
$(RUNENV) ./kctreemgr check -onr casket
$(RUNENV) ./kctreetest queue -th 4 -it 2 -oat -rnd \
-bnum 1000 -dfunit 8 -pccap 10m casket 25000
$(RUNENV) ./kctreemgr check -onr casket
$(RUNENV) ./kctreetest queue -th 4 -it 2 -oas -rnd \
-bnum 1000 -dfunit 8 -pccap 10m casket 2500
$(RUNENV) ./kctreemgr check -onr casket
$(RUNENV) ./kctreetest wicked -th 4 -it 5 \
-bnum 100000 -apow 4 -fpow 12 -msiz 100m -dfunit 2 -pccap 10m casket 250000
$(RUNENV) ./kctreemgr check -onr casket
$(RUNENV) ./kctreetest wicked -th 4 -it 2 \
-ts -tl -tc -dfunit 2 -pccap 10m casket 25000
$(RUNENV) ./kctreemgr check -onr casket
$(RUNENV) ./kctreetest wicked -th 4 -it 2 -oat \
-bnum 1000 -dfunit 8 -pccap 10m casket 25000
$(RUNENV) ./kctreemgr check -onr casket
$(RUNENV) ./kctreetest wicked -th 4 -it 2 -oas \
-bnum 1000 -dfunit 8 -pccap 10m casket 2500
$(RUNENV) ./kctreemgr check -onr casket
$(RUNENV) ./kctreetest tran -th 4 -it 5 \
-apow 2 -fpow 2 -bnum 50000 -msiz 50m -dfunit 2 -pccap 10m casket 250000
$(RUNENV) ./kctreemgr check -onr casket
$(RUNENV) ./kctreetest tran -th 4 -it 2 \
-ts -tl -tc -dfunit 2 -pccap 10m casket 250000
$(RUNENV) ./kctreemgr check -onr casket
check-segv :
$(RUNENV) ./lab/segvtest hash "0.5" 100
$(RUNENV) ./lab/segvtest hash "" 10
$(RUNENV) ./lab/segvtest hash "100" 1
$(RUNENV) ./lab/segvtest hash -oat "0.5" 100
$(RUNENV) ./lab/segvtest hash -oat "" 10
$(RUNENV) ./lab/segvtest hash -oat "100" 1
$(RUNENV) ./lab/segvtest hash -tran "" 10
$(RUNENV) ./lab/segvtest hash -wicked "" 10
$(RUNENV) ./lab/segvtest hash -wicked -oat "" 10
$(RUNENV) ./lab/segvtest tree "0.5" 100
$(RUNENV) ./lab/segvtest tree "" 10
$(RUNENV) ./lab/segvtest tree "100" 1
$(RUNENV) ./lab/segvtest tree -oat "0.5" 100
$(RUNENV) ./lab/segvtest tree -oat "" 10
$(RUNENV) ./lab/segvtest tree -oat "100" 1
$(RUNENV) ./lab/segvtest tree -tran "" 10
$(RUNENV) ./lab/segvtest tree -wicked "" 10
$(RUNENV) ./lab/segvtest tree -wicked -oat "" 10
$(RUNENV) ./lab/segvtest dir -oat "" 10
$(RUNENV) ./lab/segvtest dir -oat "0.5" 100
$(RUNENV) ./lab/segvtest dir -oat "" 10
$(RUNENV) ./lab/segvtest dir -oat "100" 1
$(RUNENV) ./lab/segvtest dir -tran "" 10
$(RUNENV) ./lab/segvtest dir -wicked "" 10
$(RUNENV) ./lab/segvtest dir -wicked -oat "" 10
$(RUNENV) ./lab/segvtest forest "" 10
$(RUNENV) ./lab/segvtest forest -oat "0.5" 100
$(RUNENV) ./lab/segvtest forest -oat "" 10
$(RUNENV) ./lab/segvtest forest -oat "100" 1
$(RUNENV) ./lab/segvtest forest -tran "" 10
$(RUNENV) ./lab/segvtest forest -wicked "" 10
$(RUNENV) ./lab/segvtest forest -wicked -oat "" 10
check-forever :
while true ; \
do \
$(MAKE) check || break ; \
$(MAKE) check || break ; \
$(MAKE) check || break ; \
$(MAKE) check || break ; \
$(MAKE) check-heavy || break ; \
$(MAKE) check-segv || break ; \
done
doc :
$(MAKE) docclean
mkdir -p doc/api
doxygen
docclean :
rm -rf doc/api
gch :
$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) *.h
words.tsv :
cat /usr/share/dict/words | \
tr '\t\r' ' ' | grep -v '^ *$$' | cat -n | sort | \
LC_ALL=C sed -e 's/^ *//' -e 's/\(^[0-9]*\)\t\(.*\)/\2\t\1/' > words.tsv
def : libkyotocabinet.a
./lab/makevcdef libkyotocabinet.a > kyotocabinet.def
.PHONY : all clean install check doc
#================================================================
# Building binaries
#================================================================
libkyotocabinet.a : $(LIBOBJFILES)
$(AR) $(ARFLAGS) $@ $(LIBOBJFILES)
libkyotocabinet.so.$(LIBVER).$(LIBREV).0 : $(LIBOBJFILES)
if uname -a | egrep -i 'SunOS' > /dev/null ; \
then \
$(CXX) $(CXXFLAGS) -shared -Wl,-G,-h,libkyotocabinet.so.$(LIBVER) -o $@ \
$(LIBOBJFILES) $(LDFLAGS) $(LIBS) ; \
else \
$(CXX) $(CXXFLAGS) -shared -Wl,-soname,libkyotocabinet.so.$(LIBVER) -o $@ \
$(LIBOBJFILES) $(LDFLAGS) $(LIBS) ; \
fi
libkyotocabinet.so.$(LIBVER) : libkyotocabinet.so.$(LIBVER).$(LIBREV).0
ln -f -s libkyotocabinet.so.$(LIBVER).$(LIBREV).0 $@
libkyotocabinet.so : libkyotocabinet.so.$(LIBVER).$(LIBREV).0
ln -f -s libkyotocabinet.so.$(LIBVER).$(LIBREV).0 $@
libkyotocabinet.$(LIBVER).$(LIBREV).0.dylib : $(LIBOBJFILES)
$(CXX) $(CXXFLAGS) -dynamiclib -o $@ \
-install_name $(LIBDIR)/libkyotocabinet.$(LIBVER).dylib \
-current_version $(LIBVER).$(LIBREV).0 -compatibility_version $(LIBVER) \
$(LIBOBJFILES) $(LDFLAGS) $(LIBS)
libkyotocabinet.$(LIBVER).dylib : libkyotocabinet.$(LIBVER).$(LIBREV).0.dylib
ln -f -s libkyotocabinet.$(LIBVER).$(LIBREV).0.dylib $@
libkyotocabinet.dylib : libkyotocabinet.$(LIBVER).$(LIBREV).0.dylib
ln -f -s libkyotocabinet.$(LIBVER).$(LIBREV).0.dylib $@
kcutiltest : kcutiltest.o $(LIBRARYFILES)
$(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(CMDLDFLAGS) -lkyotocabinet $(CMDLIBS)
kcutilmgr : kcutilmgr.o $(LIBRARYFILES)
$(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(CMDLDFLAGS) -lkyotocabinet $(CMDLIBS)
kcprototest : kcprototest.o $(LIBRARYFILES)
$(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(CMDLDFLAGS) -lkyotocabinet $(CMDLIBS)
kcstashtest : kcstashtest.o $(LIBRARYFILES)
$(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(CMDLDFLAGS) -lkyotocabinet $(CMDLIBS)
kccachetest : kccachetest.o $(LIBRARYFILES)
$(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(CMDLDFLAGS) -lkyotocabinet $(CMDLIBS)
kcgrasstest : kcgrasstest.o $(LIBRARYFILES)
$(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(CMDLDFLAGS) -lkyotocabinet $(CMDLIBS)
kchashtest : kchashtest.o $(LIBRARYFILES)
$(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(CMDLDFLAGS) -lkyotocabinet $(CMDLIBS)
kchashmgr : kchashmgr.o $(LIBRARYFILES)
$(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(CMDLDFLAGS) -lkyotocabinet $(CMDLIBS)
kctreetest : kctreetest.o $(LIBRARYFILES)
$(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(CMDLDFLAGS) -lkyotocabinet $(CMDLIBS)
kctreemgr : kctreemgr.o $(LIBRARYFILES)
$(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(CMDLDFLAGS) -lkyotocabinet $(CMDLIBS)
kcdirtest : kcdirtest.o $(LIBRARYFILES)
$(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(CMDLDFLAGS) -lkyotocabinet $(CMDLIBS)
kcdirmgr : kcdirmgr.o $(LIBRARYFILES)
$(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(CMDLDFLAGS) -lkyotocabinet $(CMDLIBS)
kcforesttest : kcforesttest.o $(LIBRARYFILES)
$(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(CMDLDFLAGS) -lkyotocabinet $(CMDLIBS)
kcforestmgr : kcforestmgr.o $(LIBRARYFILES)
$(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(CMDLDFLAGS) -lkyotocabinet $(CMDLIBS)
kcpolytest : kcpolytest.o $(LIBRARYFILES)
$(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(CMDLDFLAGS) -lkyotocabinet $(CMDLIBS)
kcpolymgr : kcpolymgr.o $(LIBRARYFILES)
$(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(CMDLDFLAGS) -lkyotocabinet $(CMDLIBS)
kclangctest : kclangctest.o $(LIBRARYFILES)
$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) $(CMDLDFLAGS) -lkyotocabinet $(CMDLIBS)
kcutil.o : kccommon.h kcutil.h myconf.h
kcthread.o : kccommon.h kcutil.h kcthread.h myconf.h
kcfile.o : kccommon.h kcutil.h kcthread.h kcfile.h myconf.h
kccompress.o : kccommon.h kcutil.h kccompress.h myconf.h
kccompare.o : kccommon.h kcutil.h kccompare.h myconf.h
kcmap.o : kccommon.h kcutil.h kcmap.h myconf.h
kcregex.o : kccommon.h kcutil.h kcregex.h myconf.h
kcdb.o : kccommon.h kcutil.h kcdb.h kcthread.h kcfile.h kccompress.h kccompare.h \
kcmap.h kcregex.h
kcplantdb.o : kccommon.h kcutil.h kcdb.h kcthread.h kcfile.h kccompress.h kccompare.h \
kcmap.h kcregex.h \
kcplantdb.h
kcprotodb.o : kccommon.h kcutil.h kcdb.h kcthread.h kcfile.h kccompress.h kccompare.h \
kcmap.h kcregex.h \
kcplantdb.h kcprotodb.h
kcstashdb.o : kccommon.h kcutil.h kcdb.h kcthread.h kcfile.h kccompress.h kccompare.h \
kcmap.h kcregex.h \
kcplantdb.h kcstashdb.h
kccachedb.o : kccommon.h kcutil.h kcdb.h kcthread.h kcfile.h kccompress.h kccompare.h \
kcmap.h kcregex.h \
kcplantdb.h kccachedb.h
kchashdb.o : kccommon.h kcutil.h kcdb.h kcthread.h kcfile.h kccompress.h kccompare.h \
kcmap.h kcregex.h \
kcplantdb.h kchashdb.h
kcdirdb.o : kccommon.h kcutil.h kcdb.h kcthread.h kcfile.h kccompress.h kccompare.h \
kcmap.h kcregex.h \
kcplantdb.h kcdirdb.h
kctextdb.o : kccommon.h kcutil.h kcdb.h kcthread.h kcfile.h kccompress.h kccompare.h \
kcmap.h kcregex.h \
kcplantdb.h kctextdb.h
kcpolydb.o : kccommon.h kcutil.h kcdb.h kcthread.h kcfile.h kccompress.h kccompare.h \
kcmap.h kcregex.h \
kcplantdb.h kcprotodb.h kcstashdb.h kccachedb.h kchashdb.h kcdirdb.h kctextdb.h kcpolydb.h
kcdbext.o : kccommon.h kcutil.h kcdb.h kcthread.h kcfile.h kccompress.h kccompare.h \
kcmap.h kcregex.h \
kcplantdb.h kcprotodb.h kcstashdb.h kccachedb.h kchashdb.h kcdirdb.h kctextdb.h \
kcpolydb.h kcdbext.h
kclangc.o : kccommon.h kcutil.h kcdb.h kcthread.h kcfile.h kccompress.h kccompare.h \
kcmap.h kcregex.h \
kcplantdb.h kcprotodb.h kcstashdb.h kccachedb.h kchashdb.h kcdirdb.h kctextdb.h \
kcpolydb.h kcdbext.h kclangc.h
kcutiltest.o kcutilmgr.o : \
kccommon.h kcdb.h kcutil.h kcthread.h kcfile.h kccompress.h kccompare.h \
kcmap.h kcregex.h \
cmdcommon.h
kcprototest.o : \
kccommon.h kcdb.h kcutil.h kcthread.h kcfile.h kccompress.h kccompare.h \
kcmap.h kcregex.h \
kcplantdb.h kcprotodb.h cmdcommon.h
kcstashtest.o : \
kccommon.h kcdb.h kcutil.h kcthread.h kcfile.h kccompress.h kccompare.h \
kcmap.h kcregex.h \
kcplantdb.h kcstashdb.h cmdcommon.h
kccachetest.o : \
kccommon.h kcdb.h kcutil.h kcthread.h kcfile.h kccompress.h kccompare.h \
kcmap.h kcregex.h \
kcplantdb.h kccachedb.h cmdcommon.h
kcgrasstest.o : \
kccommon.h kcdb.h kcutil.h kcthread.h kcfile.h kccompress.h kccompare.h \
kcmap.h kcregex.h \
kcplantdb.h kccachedb.h cmdcommon.h
kchashtest.o kchashmgr.o : \
kccommon.h kcdb.h kcutil.h kcthread.h kcfile.h kccompress.h kccompare.h \
kcmap.h kcregex.h \
kcplantdb.h kchashdb.h cmdcommon.h
kctreetest.o kctreemgr.o : \
kccommon.h kcdb.h kcutil.h kcthread.h kcfile.h kccompress.h kccompare.h \
kcmap.h kcregex.h \
kcplantdb.h kchashdb.h cmdcommon.h
kcdirtest.o kcdirmgr.o : \
kccommon.h kcdb.h kcutil.h kcthread.h kcfile.h kccompress.h kccompare.h \
kcmap.h kcregex.h \
kcplantdb.h kcdirdb.h cmdcommon.h
kcforesttest.o kcforestmgr.o : \
kccommon.h kcdb.h kcutil.h kcthread.h kcfile.h kccompress.h kccompare.h \
kcmap.h kcregex.h \
kcplantdb.h kcdirdb.h cmdcommon.h
kcpolytest.o kcpolymgr.o : \
kccommon.h kcdb.h kcutil.h kcthread.h kcfile.h kccompress.h kccompare.h \
kcmap.h kcregex.h \
kcplantdb.h kcprotodb.h kcstashdb.h kccachedb.h kchashdb.h kcdirdb.h kctextdb.h \
kcpolydb.h kcdbext.h cmdcommon.h
kclangctest.o : \
kccommon.h kcdb.h kcutil.h kcthread.h kcfile.h kccompress.h kccompare.h \
kcmap.h kcregex.h \
kcplantdb.h kcprotodb.h kcstashdb.h kccachedb.h kchashdb.h kcdirdb.h kctextdb.h \
kcpolydb.h kcdbext.h kclangc.h
# END OF FILE
kyotocabinet-1.2.80/kcprotodb.cc 0000664 0001750 0001750 00000002254 14416044124 015602 0 ustar mikio mikio /*************************************************************************************************
* Prototype database
* Copyright (C) 2009-2012 Mikio Hirabayashi
* This file is part of Kyoto Cabinet.
* This program is free software: you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation, either version
* 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with this program.
* If not, see .
*************************************************************************************************/
#include "kcprotodb.h"
#include "myconf.h"
namespace kyotocabinet { // common namespace
// There is no implementation now.
} // common namespace
// END OF FILE
kyotocabinet-1.2.80/kcprotodb.h 0000664 0001750 0001750 00000132441 14416044124 015446 0 ustar mikio mikio /*************************************************************************************************
* Prototype database
* Copyright (C) 2009-2012 Mikio Hirabayashi
* This file is part of Kyoto Cabinet.
* This program is free software: you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation, either version
* 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with this program.
* If not, see .
*************************************************************************************************/
#ifndef _KCPROTODB_H // duplication check
#define _KCPROTODB_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace kyotocabinet { // common namespace
/**
* Prototype implementation of database with STL.
* @param STRMAP a class compatible with the map class of STL.
* @param DBTYPE the database type number of the class.
* @note This class template is a template for concrete classes which wrap data structures
* compatible with std::map. Template instance classes can be inherited but overwriting methods
* is forbidden. The class ProtoHashDB is the instance using std::unordered_map. The class
* ProtoTreeDB is the instance using std::map. Before every database operation, it is necessary
* to call the BasicDB::open method in order to open a database file and connect the database
* object to it. To avoid data missing or 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 objects in a process to open the same database at the same time. It is
* forbidden to share a database object with child processes.
*/
template
class ProtoDB : public BasicDB {
public:
class Cursor;
private:
struct TranLog;
class ScopedVisitor;
/** An alias of list of cursors. */
typedef std::list CursorList;
/** An alias of list of transaction logs. */
typedef std::list TranLogList;
/** The size of the opaque buffer. */
static const size_t OPAQUESIZ = 16;
/** The threshold of busy loop and sleep for locking. */
static const uint32_t LOCKBUSYLOOP = 8192;
public:
/**
* Cursor to indicate a record.
*/
class Cursor : public BasicDB::Cursor {
friend class ProtoDB;
public:
/**
* Constructor.
* @param db the container database object.
*/
explicit Cursor(ProtoDB* db) : db_(db), it_(db->recs_.end()) {
_assert_(db);
ScopedRWLock lock(&db_->mlock_, true);
db_->curs_.push_back(this);
}
/**
* Destructor.
*/
virtual ~Cursor() {
_assert_(true);
if (!db_) return;
ScopedRWLock lock(&db_->mlock_, true);
db_->curs_.remove(this);
}
/**
* Accept a visitor to the current record.
* @param visitor a visitor object.
* @param writable true for writable operation, or false for read-only operation.
* @param step true to move the cursor to the next record, or false for no move.
* @return true on success, or false on failure.
* @note The operation for each record is performed atomically and other threads accessing
* the same record are blocked. To avoid deadlock, any explicit database operation must not
* be performed in this function.
*/
bool accept(Visitor* visitor, bool writable = true, bool step = false) {
_assert_(visitor);
ScopedRWLock lock(&db_->mlock_, true);
if (db_->omode_ == 0) {
db_->set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
if (writable && !(db_->omode_ & OWRITER)) {
db_->set_error(_KCCODELINE_, Error::NOPERM, "permission denied");
return false;
}
if (it_ == db_->recs_.end()) {
db_->set_error(_KCCODELINE_, Error::NOREC, "no record");
return false;
}
const std::string& key = it_->first;
const std::string& value = it_->second;
size_t vsiz;
const char* vbuf = visitor->visit_full(key.data(), key.size(),
value.data(), value.size(), &vsiz);
if (vbuf == Visitor::REMOVE) {
if (db_->tran_) {
TranLog log(key, value);
db_->trlogs_.push_back(log);
}
db_->size_ -= key.size() + value.size();
if (db_->curs_.size() > 1) {
typename CursorList::const_iterator cit = db_->curs_.begin();
typename CursorList::const_iterator citend = db_->curs_.end();
while (cit != citend) {
Cursor* cur = *cit;
if (cur != this && cur->it_ == it_) ++cur->it_;
++cit;
}
}
db_->recs_.erase(it_++);
} else if (vbuf == Visitor::NOP) {
if (step) ++it_;
} else {
if (db_->tran_) {
TranLog log(key, value);
db_->trlogs_.push_back(log);
}
db_->size_ -= value.size();
db_->size_ += vsiz;
it_->second = std::string(vbuf, vsiz);
if (step) ++it_;
}
return true;
}
/**
* Jump the cursor to the first record for forward scan.
* @return true on success, or false on failure.
*/
bool jump() {
_assert_(true);
ScopedRWLock lock(&db_->mlock_, true);
if (db_->omode_ == 0) {
db_->set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
it_ = db_->recs_.begin();
if (it_ == db_->recs_.end()) {
db_->set_error(_KCCODELINE_, Error::NOREC, "no record");
return false;
}
return true;
}
/**
* Jump the cursor to a record for forward scan.
* @param kbuf the pointer to the key region.
* @param ksiz the size of the key region.
* @return true on success, or false on failure.
*/
bool jump(const char* kbuf, size_t ksiz) {
_assert_(kbuf && ksiz <= MEMMAXSIZ);
ScopedRWLock lock(&db_->mlock_, true);
if (db_->omode_ == 0) {
db_->set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
std::string key(kbuf, ksiz);
search(key);
if (it_ == db_->recs_.end()) {
db_->set_error(_KCCODELINE_, Error::NOREC, "no record");
return false;
}
return true;
}
/**
* Jump the cursor to a record for forward scan.
* @note Equal to the original Cursor::jump method except that the parameter is std::string.
*/
bool jump(const std::string& key) {
_assert_(true);
return jump(key.data(), key.size());
}
/**
* Jump the cursor to the last record for backward scan.
* @return true on success, or false on failure.
*/
bool jump_back() {
_assert_(true);
ScopedRWLock lock(&db_->mlock_, true);
if (db_->omode_ == 0) {
db_->set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
it_ = db_->recs_.end();
if (it_ == db_->recs_.begin()) {
db_->set_error(_KCCODELINE_, Error::NOREC, "no record");
return false;
}
if (!iter_back()) {
db_->set_error(_KCCODELINE_, Error::NOIMPL, "not implemented");
return false;
}
return true;
}
/**
* Jump the cursor to a record for backward scan.
* @param kbuf the pointer to the key region.
* @param ksiz the size of the key region.
* @return true on success, or false on failure.
*/
bool jump_back(const char* kbuf, size_t ksiz) {
_assert_(kbuf && ksiz <= MEMMAXSIZ);
ScopedRWLock lock(&db_->mlock_, true);
if (db_->omode_ == 0) {
db_->set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
std::string key(kbuf, ksiz);
search(key);
if (it_ == db_->recs_.end()) {
if (it_ == db_->recs_.begin()) {
db_->set_error(_KCCODELINE_, Error::NOREC, "no record");
return false;
}
if (!iter_back()) {
db_->set_error(_KCCODELINE_, Error::NOIMPL, "not implemented");
return false;
}
} else {
std::string key(kbuf, ksiz);
if (key < it_->first) {
if (it_ == db_->recs_.begin()) {
db_->set_error(_KCCODELINE_, Error::NOREC, "no record");
it_ = db_->recs_.end();
return false;
}
if (!iter_back()) {
db_->set_error(_KCCODELINE_, Error::NOIMPL, "not implemented");
it_ = db_->recs_.end();
return false;
}
}
}
return true;
}
/**
* Jump the cursor to a record for backward scan.
* @note Equal to the original Cursor::jump_back method except that the parameter is
* std::string.
*/
bool jump_back(const std::string& key) {
_assert_(true);
return jump_back(key.data(), key.size());
}
/**
* Step the cursor to the next record.
* @return true on success, or false on failure.
*/
bool step() {
_assert_(true);
ScopedRWLock lock(&db_->mlock_, true);
if (db_->omode_ == 0) {
db_->set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
if (it_ == db_->recs_.end()) {
db_->set_error(_KCCODELINE_, Error::NOREC, "no record");
return false;
}
++it_;
if (it_ == db_->recs_.end()) {
db_->set_error(_KCCODELINE_, Error::NOREC, "no record");
return false;
}
return true;
}
/**
* Step the cursor to the previous record.
* @return true on success, or false on failure.
*/
bool step_back() {
_assert_(true);
ScopedRWLock lock(&db_->mlock_, true);
if (db_->omode_ == 0) {
db_->set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
if (it_ == db_->recs_.begin()) {
db_->set_error(_KCCODELINE_, Error::NOREC, "no record");
it_ = db_->recs_.end();
return false;
}
if (!iter_back()) {
db_->set_error(_KCCODELINE_, Error::NOIMPL, "not implemented");
it_ = db_->recs_.end();
return false;
}
return true;
}
/**
* Get the database object.
* @return the database object.
*/
ProtoDB* db() {
_assert_(true);
return db_;
}
private:
/**
* Search for a record.
*/
void search(const std::string& key);
/**
* Place back the inner iterator.
* @return true on success, or false on failure.
*/
bool iter_back();
/** Dummy constructor to forbid the use. */
Cursor(const Cursor&);
/** Dummy Operator to forbid the use. */
Cursor& operator =(const Cursor&);
/** The inner database. */
ProtoDB* db_;
/** The inner iterator. */
typename STRMAP::iterator it_;
};
/**
* Default constructor.
*/
explicit ProtoDB() :
mlock_(), error_(), logger_(NULL), logkinds_(0), mtrigger_(NULL),
omode_(0), recs_(), curs_(), path_(""), size_(0), opaque_(),
tran_(false), trlogs_(), trsize_(0) {
_assert_(true);
map_tune();
}
/**
* Destructor.
* @note If the database is not closed, it is closed implicitly.
*/
virtual ~ProtoDB() {
_assert_(true);
if (omode_ != 0) close();
if (!curs_.empty()) {
typename CursorList::const_iterator cit = curs_.begin();
typename CursorList::const_iterator citend = curs_.end();
while (cit != citend) {
Cursor* cur = *cit;
cur->db_ = NULL;
++cit;
}
}
}
/**
* Accept a visitor to a record.
* @param kbuf the pointer to the key region.
* @param ksiz the size of the key region.
* @param visitor a visitor object.
* @param writable true for writable operation, or false for read-only operation.
* @return true on success, or false on failure.
* @note The operation for each record is performed atomically and other threads accessing the
* same record are blocked. To avoid deadlock, any explicit database operation must not be
* performed in this function.
*/
bool accept(const char* kbuf, size_t ksiz, Visitor* visitor, bool writable = true) {
_assert_(kbuf && ksiz <= MEMMAXSIZ && visitor);
if (writable) {
ScopedRWLock lock(&mlock_, true);
if (omode_ == 0) {
set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
if (!(omode_ & OWRITER)) {
set_error(_KCCODELINE_, Error::NOPERM, "permission denied");
return false;
}
std::string key(kbuf, ksiz);
typename STRMAP::iterator it = recs_.find(key);
if (it == recs_.end()) {
size_t vsiz;
const char* vbuf = visitor->visit_empty(kbuf, ksiz, &vsiz);
if (vbuf != Visitor::NOP && vbuf != Visitor::REMOVE) {
if (tran_) {
TranLog log(key);
trlogs_.push_back(log);
}
size_ += ksiz + vsiz;
recs_[key] = std::string(vbuf, vsiz);
}
} else {
const std::string& value = it->second;
size_t vsiz;
const char* vbuf = visitor->visit_full(kbuf, ksiz, value.data(), value.size(), &vsiz);
if (vbuf == Visitor::REMOVE) {
if (tran_) {
TranLog log(key, value);
trlogs_.push_back(log);
}
size_ -= ksiz + value.size();
if (!curs_.empty()) {
typename CursorList::const_iterator cit = curs_.begin();
typename CursorList::const_iterator citend = curs_.end();
while (cit != citend) {
Cursor* cur = *cit;
if (cur->it_ == it) ++cur->it_;
++cit;
}
}
recs_.erase(it);
} else if (vbuf != Visitor::NOP) {
if (tran_) {
TranLog log(key, value);
trlogs_.push_back(log);
}
size_ -= value.size();
size_ += vsiz;
it->second = std::string(vbuf, vsiz);
}
}
} else {
ScopedRWLock lock(&mlock_, false);
if (omode_ == 0) {
set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
std::string key(kbuf, ksiz);
const STRMAP& rrecs = recs_;
typename STRMAP::const_iterator it = rrecs.find(key);
if (it == rrecs.end()) {
size_t vsiz;
const char* vbuf = visitor->visit_empty(kbuf, ksiz, &vsiz);
if (vbuf != Visitor::NOP && vbuf != Visitor::REMOVE) {
set_error(_KCCODELINE_, Error::NOPERM, "permission denied");
return false;
}
} else {
const std::string& value = it->second;
size_t vsiz;
const char* vbuf = visitor->visit_full(kbuf, ksiz, value.data(), value.size(), &vsiz);
if (vbuf != Visitor::NOP && vbuf != Visitor::REMOVE) {
set_error(_KCCODELINE_, Error::NOPERM, "permission denied");
return false;
}
}
}
return true;
}
/**
* Accept a visitor to multiple records at once.
* @param keys specifies a string vector of the keys.
* @param visitor a visitor object.
* @param writable true for writable operation, or false for read-only operation.
* @return true on success, or false on failure.
* @note The operations for specified records are performed atomically and other threads
* accessing the same records are blocked. To avoid deadlock, any explicit database operation
* must not be performed in this function.
*/
bool accept_bulk(const std::vector& keys, Visitor* visitor,
bool writable = true) {
_assert_(visitor);
ScopedRWLock lock(&mlock_, true);
if (omode_ == 0) {
set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
if (!(omode_ & OWRITER)) {
set_error(_KCCODELINE_, Error::NOPERM, "permission denied");
return false;
}
ScopedVisitor svis(visitor);
if (keys.empty()) return true;
std::vector::const_iterator kit = keys.begin();
std::vector::const_iterator kitend = keys.end();
while (kit != kitend) {
const std::string& key = *kit;
typename STRMAP::iterator it = recs_.find(key);
if (it == recs_.end()) {
size_t vsiz;
const char* vbuf = visitor->visit_empty(key.data(), key.size(), &vsiz);
if (vbuf != Visitor::NOP && vbuf != Visitor::REMOVE) {
if (tran_) {
TranLog log(key);
trlogs_.push_back(log);
}
size_ += key.size() + vsiz;
recs_[key] = std::string(vbuf, vsiz);
}
} else {
const std::string& value = it->second;
size_t vsiz;
const char* vbuf = visitor->visit_full(key.data(), key.size(),
value.data(), value.size(), &vsiz);
if (vbuf == Visitor::REMOVE) {
if (tran_) {
TranLog log(key, value);
trlogs_.push_back(log);
}
size_ -= key.size() + value.size();
if (!curs_.empty()) {
typename CursorList::const_iterator cit = curs_.begin();
typename CursorList::const_iterator citend = curs_.end();
while (cit != citend) {
Cursor* cur = *cit;
if (cur->it_ == it) ++cur->it_;
++cit;
}
}
recs_.erase(it);
} else if (vbuf != Visitor::NOP) {
if (tran_) {
TranLog log(key, value);
trlogs_.push_back(log);
}
size_ -= value.size();
size_ += vsiz;
it->second = std::string(vbuf, vsiz);
}
}
++kit;
}
return true;
}
/**
* Iterate to accept a visitor for each record.
* @param visitor a visitor object.
* @param writable true for writable operation, or false for read-only operation.
* @param checker a progress checker object. If it is NULL, no checking is performed.
* @return true on success, or false on failure.
* @note The whole iteration is performed atomically and other threads are blocked. To avoid
* deadlock, any explicit database operation must not be performed in this function.
*/
bool iterate(Visitor *visitor, bool writable = true, ProgressChecker* checker = NULL) {
_assert_(visitor);
ScopedRWLock lock(&mlock_, true);
if (omode_ == 0) {
set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
if (writable && !(omode_ & OWRITER)) {
set_error(_KCCODELINE_, Error::NOPERM, "permission denied");
return false;
}
ScopedVisitor svis(visitor);
int64_t allcnt = recs_.size();
if (checker && !checker->check("iterate", "beginning", 0, allcnt)) {
set_error(_KCCODELINE_, Error::LOGIC, "checker failed");
return false;
}
typename STRMAP::iterator it = recs_.begin();
typename STRMAP::iterator itend = recs_.end();
int64_t curcnt = 0;
while (it != itend) {
const std::string& key = it->first;
const std::string& value = it->second;
size_t vsiz;
const char* vbuf = visitor->visit_full(key.data(), key.size(),
value.data(), value.size(), &vsiz);
if (vbuf == Visitor::REMOVE) {
size_ -= key.size() + value.size();
recs_.erase(it++);
} else if (vbuf == Visitor::NOP) {
++it;
} else {
size_ -= value.size();
size_ += vsiz;
it->second = std::string(vbuf, vsiz);
++it;
}
curcnt++;
if (checker && !checker->check("iterate", "processing", curcnt, allcnt)) {
set_error(_KCCODELINE_, Error::LOGIC, "checker failed");
return false;
}
}
if (checker && !checker->check("iterate", "ending", -1, allcnt)) {
set_error(_KCCODELINE_, Error::LOGIC, "checker failed");
return false;
}
trigger_meta(MetaTrigger::ITERATE, "iterate");
return true;
}
/**
* Scan each record in parallel.
* @param visitor a visitor object.
* @param thnum the number of worker threads.
* @param checker a progress checker object. If it is NULL, no checking is performed.
* @return true on success, or false on failure.
* @note This function is for reading records and not for updating ones. The return value of
* the visitor is just ignored. To avoid deadlock, any explicit database operation must not
* be performed in this function.
*/
bool scan_parallel(Visitor *visitor, size_t thnum, ProgressChecker* checker = NULL) {
_assert_(visitor && thnum <= MEMMAXSIZ);
ScopedRWLock lock(&mlock_, false);
if (omode_ == 0) {
set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
if (thnum < 1) thnum = 1;
if (thnum > (size_t)INT8MAX) thnum = INT8MAX;
ScopedVisitor svis(visitor);
int64_t allcnt = recs_.size();
if (checker && !checker->check("scan_parallel", "beginning", -1, allcnt)) {
set_error(_KCCODELINE_, Error::LOGIC, "checker failed");
return false;
}
class ThreadImpl : public Thread {
public:
explicit ThreadImpl() :
db_(NULL), visitor_(NULL), checker_(NULL), allcnt_(0),
itp_(NULL), itend_(), itmtx_(NULL), error_() {}
void init(ProtoDB* db, Visitor* visitor, ProgressChecker* checker, int64_t allcnt,
typename STRMAP::const_iterator* itp, typename STRMAP::const_iterator itend,
Mutex* itmtx) {
db_ = db;
visitor_ = visitor;
checker_ = checker;
allcnt_ = allcnt;
itp_ = itp;
itend_ = itend;
itmtx_ = itmtx;
}
const Error& error() {
return error_;
}
private:
void run() {
ProtoDB* db = db_;
Visitor* visitor = visitor_;
ProgressChecker* checker = checker_;
int64_t allcnt = allcnt_;
typename STRMAP::const_iterator* itp = itp_;
typename STRMAP::const_iterator itend = itend_;
Mutex* itmtx = itmtx_;
while (true) {
itmtx->lock();
if (*itp == itend) {
itmtx->unlock();
break;
}
const std::string& key = (*itp)->first;
const std::string& value = (*itp)->second;
++(*itp);
itmtx->unlock();
size_t vsiz;
visitor->visit_full(key.data(), key.size(), value.data(), value.size(), &vsiz);
if (checker && !checker->check("scan_parallel", "processing", -1, allcnt)) {
db->set_error(_KCCODELINE_, Error::LOGIC, "checker failed");
error_ = db->error();
break;
}
}
}
ProtoDB* db_;
Visitor* visitor_;
ProgressChecker* checker_;
int64_t allcnt_;
typename STRMAP::const_iterator* itp_;
typename STRMAP::const_iterator itend_;
Mutex* itmtx_;
Error error_;
};
bool err = false;
typename STRMAP::const_iterator it = recs_.begin();
typename STRMAP::const_iterator itend = recs_.end();
Mutex itmtx;
ThreadImpl* threads = new ThreadImpl[thnum];
for (size_t i = 0; i < thnum; i++) {
ThreadImpl* thread = threads + i;
thread->init(this, visitor, checker, allcnt, &it, itend, &itmtx);
}
for (size_t i = 0; i < thnum; i++) {
ThreadImpl* thread = threads + i;
thread->start();
}
for (size_t i = 0; i < thnum; i++) {
ThreadImpl* thread = threads + i;
thread->join();
if (thread->error() != Error::SUCCESS) {
*error_ = thread->error();
err = true;
}
}
delete[] threads;
if (err) return false;
if (checker && !checker->check("scan_parallel", "ending", -1, allcnt)) {
set_error(_KCCODELINE_, Error::LOGIC, "checker failed");
return false;
}
trigger_meta(MetaTrigger::ITERATE, "scan_parallel");
return true;
}
/**
* Get the last happened error.
* @return the last happened error.
*/
Error error() const {
_assert_(true);
return error_;
}
/**
* Set the error information.
* @param file the file name 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 code an error code.
* @param message a supplement message.
*/
void set_error(const char* file, int32_t line, const char* func,
Error::Code code, const char* message) {
_assert_(file && line > 0 && func && message);
error_->set(code, message);
if (logger_) {
Logger::Kind kind = code == Error::BROKEN || code == Error::SYSTEM ?
Logger::ERROR : Logger::INFO;
if (kind & logkinds_)
report(file, line, func, kind, "%d: %s: %s", code, Error::codename(code), message);
}
}
/**
* Open a database file.
* @param path the path of a database file.
* @param mode the connection mode. BasicDB::OWRITER as a writer, BasicDB::OREADER as a
* 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, BasicDB::OTRUNCATE, which
* means it creates a new database regardless if the file exists, BasicDB::OAUTOTRAN, which
* means each updating operation is performed in implicit transaction, BasicDB::OAUTOSYNC,
* which means each updating operation is followed by implicit synchronization with the file
* system. The following may be added to both of the reader mode and the writer mode by
* bitwise-or: BasicDB::ONOLOCK, which means it opens the database file without file locking,
* BasicDB::OTRYLOCK, which means locking is performed without blocking, BasicDB::ONOREPAIR,
* which means the database file is not repaired implicitly even if file destruction is
* detected.
* @return true on success, or false on failure.
* @note Every opened database must be closed by the BasicDB::close method when it is no
* longer in use. It is not allowed for two or more database objects in the same process to
* keep their connections to the same database file at the same time.
*/
bool open(const std::string& path, uint32_t mode = OWRITER | OCREATE) {
_assert_(true);
ScopedRWLock lock(&mlock_, true);
if (omode_ != 0) {
set_error(_KCCODELINE_, Error::INVALID, "already opened");
return false;
}
report(_KCCODELINE_, Logger::DEBUG, "opening the database (path=%s)", path.c_str());
omode_ = mode;
path_.append(path);
std::memset(opaque_, 0, sizeof(opaque_));
trigger_meta(MetaTrigger::OPEN, "open");
return true;
}
/**
* Close the database file.
* @return true on success, or false on failure.
*/
bool close() {
_assert_(true);
ScopedRWLock lock(&mlock_, true);
if (omode_ == 0) {
set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
report(_KCCODELINE_, Logger::DEBUG, "closing the database (path=%s)", path_.c_str());
tran_ = false;
trlogs_.clear();
recs_.clear();
if (!curs_.empty()) {
typename CursorList::const_iterator cit = curs_.begin();
typename CursorList::const_iterator citend = curs_.end();
while (cit != citend) {
Cursor* cur = *cit;
cur->it_ = recs_.end();
++cit;
}
}
path_.clear();
omode_ = 0;
trigger_meta(MetaTrigger::CLOSE, "close");
return true;
}
/**
* Synchronize updated contents with the file and the device.
* @param hard true for physical synchronization with the device, or false for logical
* synchronization with the file system.
* @param proc a postprocessor object. If it is NULL, no postprocessing is performed.
* @param checker a progress checker object. If it is NULL, no checking is performed.
* @return true on success, or false on failure.
* @note The operation of the postprocessor is performed atomically and other threads accessing
* the same record are blocked. To avoid deadlock, any explicit database operation must not
* be performed in this function.
*/
bool synchronize(bool hard = false, FileProcessor* proc = NULL,
ProgressChecker* checker = NULL) {
_assert_(true);
ScopedRWLock lock(&mlock_, false);
if (omode_ == 0) {
set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
bool err = false;
if ((omode_ & OWRITER) && checker &&
!checker->check("synchronize", "nothing to be synchronized", -1, -1)) {
set_error(_KCCODELINE_, Error::LOGIC, "checker failed");
return false;
}
if (proc) {
if (checker && !checker->check("synchronize", "running the post processor", -1, -1)) {
set_error(_KCCODELINE_, Error::LOGIC, "checker failed");
return false;
}
if (!proc->process(path_, recs_.size(), size_)) {
set_error(_KCCODELINE_, Error::LOGIC, "postprocessing failed");
err = true;
}
}
trigger_meta(MetaTrigger::SYNCHRONIZE, "synchronize");
return !err;
}
/**
* Occupy database by locking and do something meanwhile.
* @param writable true to use writer lock, or false to use reader lock.
* @param proc a processor object. If it is NULL, no processing is performed.
* @return true on success, or false on failure.
* @note The operation of the processor is performed atomically and other threads accessing
* the same record are blocked. To avoid deadlock, any explicit database operation must not
* be performed in this function.
*/
bool occupy(bool writable = true, FileProcessor* proc = NULL) {
_assert_(true);
ScopedRWLock lock(&mlock_, writable);
bool err = false;
if (proc && !proc->process(path_, recs_.size(), size_)) {
set_error(_KCCODELINE_, Error::LOGIC, "processing failed");
err = true;
}
trigger_meta(MetaTrigger::OCCUPY, "occupy");
return !err;
}
/**
* Begin transaction.
* @param hard true for physical synchronization with the device, or false for logical
* synchronization with the file system.
* @return true on success, or false on failure.
*/
bool begin_transaction(bool hard = false) {
_assert_(true);
uint32_t wcnt = 0;
while (true) {
mlock_.lock_writer();
if (omode_ == 0) {
set_error(_KCCODELINE_, Error::INVALID, "not opened");
mlock_.unlock();
return false;
}
if (!(omode_ & OWRITER)) {
set_error(_KCCODELINE_, Error::NOPERM, "permission denied");
mlock_.unlock();
return false;
}
if (!tran_) break;
mlock_.unlock();
if (wcnt >= LOCKBUSYLOOP) {
Thread::chill();
} else {
Thread::yield();
wcnt++;
}
}
tran_ = true;
trsize_ = size_;
trigger_meta(MetaTrigger::BEGINTRAN, "begin_transaction");
mlock_.unlock();
return true;
}
/**
* Try to begin transaction.
* @param hard true for physical synchronization with the device, or false for logical
* synchronization with the file system.
* @return true on success, or false on failure.
*/
bool begin_transaction_try(bool hard = false) {
_assert_(true);
mlock_.lock_writer();
if (omode_ == 0) {
set_error(_KCCODELINE_, Error::INVALID, "not opened");
mlock_.unlock();
return false;
}
if (!(omode_ & OWRITER)) {
set_error(_KCCODELINE_, Error::NOPERM, "permission denied");
mlock_.unlock();
return false;
}
if (tran_) {
set_error(_KCCODELINE_, Error::LOGIC, "competition avoided");
mlock_.unlock();
return false;
}
tran_ = true;
trsize_ = size_;
trigger_meta(MetaTrigger::BEGINTRAN, "begin_transaction_try");
mlock_.unlock();
return true;
}
/**
* End transaction.
* @param commit true to commit the transaction, or false to abort the transaction.
* @return true on success, or false on failure.
*/
bool end_transaction(bool commit = true) {
_assert_(true);
ScopedRWLock lock(&mlock_, true);
if (omode_ == 0) {
set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
if (!tran_) {
set_error(_KCCODELINE_, Error::INVALID, "not in transaction");
return false;
}
if (!commit) {
if (!curs_.empty()) {
typename CursorList::const_iterator cit = curs_.begin();
typename CursorList::const_iterator citend = curs_.end();
while (cit != citend) {
Cursor* cur = *cit;
cur->it_ = recs_.end();
++cit;
}
}
const TranLogList& logs = trlogs_;
typename TranLogList::const_iterator lit = logs.end();
typename TranLogList::const_iterator litbeg = logs.begin();
while (lit != litbeg) {
--lit;
if (lit->full) {
recs_[lit->key] = lit->value;
} else {
recs_.erase(lit->key);
}
}
size_ = trsize_;
}
trlogs_.clear();
tran_ = false;
trigger_meta(commit ? MetaTrigger::COMMITTRAN : MetaTrigger::ABORTTRAN, "end_transaction");
return true;
}
/**
* Remove all records.
* @return true on success, or false on failure.
*/
bool clear() {
_assert_(true);
ScopedRWLock lock(&mlock_, true);
if (omode_ == 0) {
set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
recs_.clear();
if (!curs_.empty()) {
typename CursorList::const_iterator cit = curs_.begin();
typename CursorList::const_iterator citend = curs_.end();
while (cit != citend) {
Cursor* cur = *cit;
cur->it_ = recs_.end();
++cit;
}
}
std::memset(opaque_, 0, sizeof(opaque_));
trigger_meta(MetaTrigger::CLEAR, "clear");
return true;
}
/**
* Get the number of records.
* @return the number of records, or -1 on failure.
*/
int64_t count() {
_assert_(true);
ScopedRWLock lock(&mlock_, false);
if (omode_ == 0) {
set_error(_KCCODELINE_, Error::INVALID, "not opened");
return -1;
}
return recs_.size();
}
/**
* Get the size of the database file.
* @return the size of the database file in bytes, or -1 on failure.
*/
int64_t size() {
_assert_(true);
ScopedRWLock lock(&mlock_, false);
if (omode_ == 0) {
set_error(_KCCODELINE_, Error::INVALID, "not opened");
return -1;
}
return size_;
}
/**
* Get the path of the database file.
* @return the path of the database file, or an empty string on failure.
*/
std::string path() {
_assert_(true);
ScopedRWLock lock(&mlock_, false);
if (omode_ == 0) {
set_error(_KCCODELINE_, Error::INVALID, "not opened");
return "";
}
return path_;
}
/**
* Get the miscellaneous status information.
* @param strmap a string map to contain the result.
* @return true on success, or false on failure.
*/
bool status(std::map* strmap) {
_assert_(strmap);
ScopedRWLock lock(&mlock_, true);
if (omode_ == 0) {
set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
(*strmap)["type"] = strprintf("%u", (unsigned)DBTYPE);
(*strmap)["realtype"] = strprintf("%u", (unsigned)DBTYPE);
(*strmap)["path"] = path_;
if (strmap->count("opaque") > 0)
(*strmap)["opaque"] = std::string(opaque_, sizeof(opaque_));
(*strmap)["count"] = strprintf("%lld", (long long)recs_.size());
(*strmap)["size"] = strprintf("%lld", (long long)size_);
return true;
}
/**
* Create a cursor object.
* @return the return value is the created cursor object.
* @note Because the object of the return value is allocated by the constructor, it should be
* released with the delete operator when it is no longer in use.
*/
Cursor* cursor() {
_assert_(true);
return new Cursor(this);
}
/**
* Write a log message.
* @param file the file name 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 kind the kind of the event. Logger::DEBUG for debugging, Logger::INFO for normal
* information, Logger::WARN for warning, and Logger::ERROR for fatal error.
* @param message the supplement message.
*/
void log(const char* file, int32_t line, const char* func, Logger::Kind kind,
const char* message) {
_assert_(file && line > 0 && func && message);
ScopedRWLock lock(&mlock_, false);
if (!logger_) return;
logger_->log(file, line, func, kind, message);
}
/**
* Set the internal logger.
* @param logger the logger object.
* @param kinds kinds of logged messages by bitwise-or: Logger::DEBUG for debugging,
* Logger::INFO for normal information, Logger::WARN for warning, and Logger::ERROR for fatal
* error.
* @return true on success, or false on failure.
*/
bool tune_logger(Logger* logger, uint32_t kinds = Logger::WARN | Logger::ERROR) {
_assert_(logger);
ScopedRWLock lock(&mlock_, true);
if (omode_ != 0) {
set_error(_KCCODELINE_, Error::INVALID, "already opened");
return false;
}
logger_ = logger;
logkinds_ = kinds;
return true;
}
/**
* Set the internal meta operation trigger.
* @param trigger the trigger object.
* @return true on success, or false on failure.
*/
bool tune_meta_trigger(MetaTrigger* trigger) {
_assert_(trigger);
ScopedRWLock lock(&mlock_, true);
if (omode_ != 0) {
set_error(_KCCODELINE_, Error::INVALID, "already opened");
return false;
}
mtrigger_ = trigger;
return true;
}
/**
* Get the opaque data.
* @return the pointer to the opaque data region, whose size is 16 bytes.
*/
char* opaque() {
_assert_(true);
ScopedRWLock lock(&mlock_, false);
if (omode_ == 0) {
set_error(_KCCODELINE_, Error::INVALID, "not opened");
return NULL;
}
return opaque_;
}
/**
* Synchronize the opaque data.
* @return true on success, or false on failure.
*/
bool synchronize_opaque() {
_assert_(true);
ScopedRWLock lock(&mlock_, true);
if (omode_ == 0) {
set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
if (!(omode_ & OWRITER)) {
set_error(_KCCODELINE_, Error::NOPERM, "permission denied");
return false;
}
return true;
}
protected:
/**
* Report a message for debugging.
* @param file the file name 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 kind the kind of the event. Logger::DEBUG for debugging, Logger::INFO for normal
* information, Logger::WARN for warning, and Logger::ERROR for fatal error.
* @param format the printf-like format string.
* @param ... used according to the format string.
*/
void report(const char* file, int32_t line, const char* func, Logger::Kind kind,
const char* format, ...) {
_assert_(file && line > 0 && func && format);
if (!logger_ || !(kind & logkinds_)) return;
std::string message;
strprintf(&message, "%s: ", path_.empty() ? "-" : path_.c_str());
va_list ap;
va_start(ap, format);
vstrprintf(&message, format, ap);
va_end(ap);
logger_->log(file, line, func, kind, message.c_str());
}
/**
* Report a message for debugging with variable number of arguments.
* @param file the file name 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 kind the kind of the event. Logger::DEBUG for debugging, Logger::INFO for normal
* information, Logger::WARN for warning, and Logger::ERROR for fatal error.
* @param format the printf-like format string.
* @param ap used according to the format string.
*/
void report_valist(const char* file, int32_t line, const char* func, Logger::Kind kind,
const char* format, va_list ap) {
_assert_(file && line > 0 && func && format);
if (!logger_ || !(kind & logkinds_)) return;
std::string message;
strprintf(&message, "%s: ", path_.empty() ? "-" : path_.c_str());
vstrprintf(&message, format, ap);
logger_->log(file, line, func, kind, message.c_str());
}
/**
* Report the content of a binary buffer for debugging.
* @param file the file name of the epicenter.
* @param line the line number of the epicenter.
* @param func the function name of the program source code.
* @param kind the kind of the event. Logger::DEBUG for debugging, Logger::INFO for normal
* information, Logger::WARN for warning, and Logger::ERROR for fatal error.
* @param name the name of the information.
* @param buf the binary buffer.
* @param size the size of the binary buffer
*/
void report_binary(const char* file, int32_t line, const char* func, Logger::Kind kind,
const char* name, const char* buf, size_t size) {
_assert_(file && line > 0 && func && name && buf && size <= MEMMAXSIZ);
if (!logger_) return;
char* hex = hexencode(buf, size);
report(file, line, func, kind, "%s=%s", name, hex);
delete[] hex;
}
/**
* Trigger a meta database operation.
* @param kind the kind of the event. MetaTrigger::OPEN for opening, MetaTrigger::CLOSE for
* closing, MetaTrigger::CLEAR for clearing, MetaTrigger::ITERATE for iteration,
* MetaTrigger::SYNCHRONIZE for synchronization, MetaTrigger::BEGINTRAN for beginning
* transaction, MetaTrigger::COMMITTRAN for committing transaction, MetaTrigger::ABORTTRAN
* for aborting transaction, and MetaTrigger::MISC for miscellaneous operations.
* @param message the supplement message.
*/
void trigger_meta(MetaTrigger::Kind kind, const char* message) {
_assert_(message);
if (mtrigger_) mtrigger_->trigger(kind, message);
}
private:
/**
* Transaction log.
*/
struct TranLog {
bool full; ///< flag whether full
std::string key; ///< old key
std::string value; ///< old value
/** constructor for a full record */
explicit TranLog(const std::string& pkey, const std::string& pvalue) :
full(true), key(pkey), value(pvalue) {
_assert_(true);
}
/** constructor for an empty record */
explicit TranLog(const std::string& pkey) : full(false), key(pkey) {
_assert_(true);
}
};
/**
* Scoped visitor.
*/
class ScopedVisitor {
public:
/** constructor */
explicit ScopedVisitor(Visitor* visitor) : visitor_(visitor) {
_assert_(visitor);
visitor_->visit_before();
}
/** destructor */
~ScopedVisitor() {
_assert_(true);
visitor_->visit_after();
}
private:
Visitor* visitor_; ///< visitor
};
/**
* Tune the internal map object.
*/
void map_tune();
/** Dummy constructor to forbid the use. */
ProtoDB(const ProtoDB&);
/** Dummy Operator to forbid the use. */
ProtoDB& operator =(const ProtoDB&);
/** The method lock. */
RWLock mlock_;
/** The last happened error. */
TSD error_;
/** The internal logger. */
Logger* logger_;
/** The kinds of logged messages. */
uint32_t logkinds_;
/** The internal meta operation trigger. */
MetaTrigger* mtrigger_;
/** The open mode. */
uint32_t omode_;
/** The map of records. */
STRMAP recs_;
/** The cursor objects. */
CursorList curs_;
/** The path of the database file. */
std::string path_;
/** The total size of records. */
int64_t size_;
/** The opaque data. */
char opaque_[OPAQUESIZ];
/** The flag whether in transaction. */
bool tran_;
/** The transaction logs. */
TranLogList trlogs_;
/** The old size before transaction. */
size_t trsize_;
};
/**
* Search for a record.
*/
template
inline void ProtoDB::Cursor::search(const std::string& key) {
_assert_(true);
it_ = db_->recs_.find(key);
}
/**
* Search for a record.
*/
template <> /** specialization for StringTreeMap */
inline void ProtoDB::Cursor::search(const std::string& key) {
_assert_(true);
it_ = db_->recs_.lower_bound(key);
}
/**
* Place back the inner iterator.
*/
template
inline bool ProtoDB::Cursor::iter_back() {
_assert_(true);
return false;
}
/**
* Place back the inner iterator.
*/
template <> /** specialization for StringTreeMap */
inline bool ProtoDB::Cursor::iter_back() {
_assert_(true);
--it_;
return true;
}
/**
* Tune the internal map object.
*/
template
inline void ProtoDB::map_tune() {
_assert_(true);
}
/**
* Tune the internal map object.
*/
template <> /** specialization for StringTreeMap */
inline void ProtoDB::map_tune() {
_assert_(true);
recs_.rehash(1048583LL);
recs_.max_load_factor(FLTMAX);
}
/** An alias of the prototype hash database. */
typedef ProtoDB ProtoHashDB;
/** An alias of the prototype tree database. */
typedef ProtoDB ProtoTreeDB;
} // common namespace
#endif // duplication check
// END OF FILE
kyotocabinet-1.2.80/kcpolymgr.cc 0000664 0001750 0001750 00000130350 14416044124 015621 0 ustar mikio mikio /*************************************************************************************************
* The command line utility of the polymorphic database
* Copyright (C) 2009-2012 Mikio Hirabayashi
* This file is part of Kyoto Cabinet.
* This program is free software: you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation, either version
* 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with this program.
* If not, see .
*************************************************************************************************/
#include
#include "cmdcommon.h"
// global variables
const char* g_progname; // program name
// function prototypes
int main(int argc, char** argv);
static void usage();
static void dberrprint(kc::BasicDB* db, const char* info);
static int32_t runcreate(int argc, char** argv);
static int32_t runinform(int argc, char** argv);
static int32_t runset(int argc, char** argv);
static int32_t runremove(int argc, char** argv);
static int32_t runget(int argc, char** argv);
static int32_t runlist(int argc, char** argv);
static int32_t runclear(int argc, char** argv);
static int32_t runimport(int argc, char** argv);
static int32_t runcopy(int argc, char** argv);
static int32_t rundump(int argc, char** argv);
static int32_t runload(int argc, char** argv);
static int32_t runmerge(int argc, char** argv);
static int32_t runsetbulk(int argc, char** argv);
static int32_t runremovebulk(int argc, char** argv);
static int32_t rungetbulk(int argc, char** argv);
static int32_t runcheck(int argc, char** argv);
static int32_t proccreate(const char* path, int32_t oflags);
static int32_t procinform(const char* path, int32_t oflags, bool st);
static int32_t procset(const char* path, const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, int32_t oflags, int32_t mode);
static int32_t procremove(const char* path, const char* kbuf, size_t ksiz, int32_t oflags);
static int32_t procget(const char* path, const char* kbuf, size_t ksiz,
int32_t oflags, bool rm, bool px, bool pz);
static int32_t proclist(const char* path, const char*kbuf, size_t ksiz, int32_t oflags,
int32_t mode, bool des, int64_t max, bool rm, bool pv, bool px);
static int32_t procclear(const char* path, int32_t oflags);
static int32_t procimport(const char* path, const char* file, int32_t oflags, bool sx);
static int32_t proccopy(const char* path, const char* file, int32_t oflags);
static int32_t procdump(const char* path, const char* file, int32_t oflags);
static int32_t procload(const char* path, const char* file, int32_t oflags);
static int32_t procmerge(const char* path, int32_t oflags, kc::PolyDB::MergeMode mode,
const std::vector& srcpaths);
static int32_t procsetbulk(const char* path, int32_t oflags,
const std::map& recs);
static int32_t procremovebulk(const char* path, int32_t oflags,
const std::vector& keys);
static int32_t procgetbulk(const char* path, int32_t oflags,
const std::vector& keys, bool px);
static int32_t proccheck(const char* path, int32_t oflags);
// main routine
int main(int argc, char** argv) {
g_progname = argv[0];
kc::setstdiobin();
if (argc < 2) usage();
int32_t rv = 0;
if (!std::strcmp(argv[1], "create")) {
rv = runcreate(argc, argv);
} else if (!std::strcmp(argv[1], "inform")) {
rv = runinform(argc, argv);
} else if (!std::strcmp(argv[1], "set")) {
rv = runset(argc, argv);
} else if (!std::strcmp(argv[1], "remove")) {
rv = runremove(argc, argv);
} else if (!std::strcmp(argv[1], "get")) {
rv = runget(argc, argv);
} else if (!std::strcmp(argv[1], "list")) {
rv = runlist(argc, argv);
} else if (!std::strcmp(argv[1], "clear")) {
rv = runclear(argc, argv);
} else if (!std::strcmp(argv[1], "import")) {
rv = runimport(argc, argv);
} else if (!std::strcmp(argv[1], "copy")) {
rv = runcopy(argc, argv);
} else if (!std::strcmp(argv[1], "dump")) {
rv = rundump(argc, argv);
} else if (!std::strcmp(argv[1], "load")) {
rv = runload(argc, argv);
} else if (!std::strcmp(argv[1], "merge")) {
rv = runmerge(argc, argv);
} else if (!std::strcmp(argv[1], "setbulk")) {
rv = runsetbulk(argc, argv);
} else if (!std::strcmp(argv[1], "removebulk")) {
rv = runremovebulk(argc, argv);
} else if (!std::strcmp(argv[1], "getbulk")) {
rv = rungetbulk(argc, argv);
} else if (!std::strcmp(argv[1], "check")) {
rv = runcheck(argc, argv);
} else if (!std::strcmp(argv[1], "version") || !std::strcmp(argv[1], "--version")) {
printversion();
} else {
usage();
}
return rv;
}
// print the usage and exit
static void usage() {
eprintf("%s: the command line utility of the polymorphic database of Kyoto Cabinet\n",
g_progname);
eprintf("\n");
eprintf("usage:\n");
eprintf(" %s create [-otr] [-onl|-otl|-onr] path\n", g_progname);
eprintf(" %s inform [-onl|-otl|-onr] [-st] path\n", g_progname);
eprintf(" %s set [-onl|-otl|-onr] [-add|-rep|-app|-inci|-incd] [-sx] path key value\n",
g_progname);
eprintf(" %s remove [-onl|-otl|-onr] [-sx] path key\n", g_progname);
eprintf(" %s get [-onl|-otl|-onr] [-rm] [-sx] [-px] [-pz] path key\n", g_progname);
eprintf(" %s list [-onl|-otl|-onr] [-mp|-mr|-ms] [-des] [-max num] [-rm] [-sx] [-pv] [-px]"
" path [key]\n", g_progname);
eprintf(" %s clear [-onl|-otl|-onr] path\n", g_progname);
eprintf(" %s import [-onl|-otl|-onr] [-sx] path [file]\n", g_progname);
eprintf(" %s copy [-onl|-otl|-onr] path file\n", g_progname);
eprintf(" %s dump [-onl|-otl|-onr] path [file]\n", g_progname);
eprintf(" %s load [-otr] [-onl|-otl|-onr] path [file]\n", g_progname);
eprintf(" %s merge [-onl|-otl|-onr] [-add|-rep|-app] path src...\n", g_progname);
eprintf(" %s setbulk [-onl|-otl|-onr] [-sx] path key value ...\n", g_progname);
eprintf(" %s removebulk [-onl|-otl|-onr] [-sx] path key ...\n", g_progname);
eprintf(" %s getbulk [-onl|-otl|-onr] [-sx] [-px] path key ...\n", g_progname);
eprintf(" %s check [-onl|-otl|-onr] path\n", g_progname);
eprintf("\n");
std::exit(1);
}
// print error message of database
static void dberrprint(kc::BasicDB* db, const char* info) {
const kc::BasicDB::Error& err = db->error();
eprintf("%s: %s: %s: %d: %s: %s\n",
g_progname, info, db->path().c_str(), err.code(), err.name(), err.message());
}
// parse arguments of create command
static int32_t runcreate(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
int32_t oflags = 0;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-otr")) {
oflags |= kc::PolyDB::OTRUNCATE;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::PolyDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::PolyDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::PolyDB::ONOREPAIR;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else {
usage();
}
}
if (!path) usage();
int32_t rv = proccreate(path, oflags);
return rv;
}
// parse arguments of inform command
static int32_t runinform(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
int32_t oflags = 0;
bool st = false;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::PolyDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::PolyDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::PolyDB::ONOREPAIR;
} else if (!std::strcmp(argv[i], "-st")) {
st = true;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else {
usage();
}
}
if (!path) usage();
int32_t rv = procinform(path, oflags, st);
return rv;
}
// parse arguments of set command
static int32_t runset(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
const char* kstr = NULL;
const char* vstr = NULL;
int32_t oflags = 0;
int32_t mode = 0;
bool sx = false;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::PolyDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::PolyDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::PolyDB::ONOREPAIR;
} else if (!std::strcmp(argv[i], "-add")) {
mode = 'a';
} else if (!std::strcmp(argv[i], "-rep")) {
mode = 'r';
} else if (!std::strcmp(argv[i], "-app")) {
mode = 'c';
} else if (!std::strcmp(argv[i], "-inci")) {
mode = 'i';
} else if (!std::strcmp(argv[i], "-incd")) {
mode = 'd';
} else if (!std::strcmp(argv[i], "-sx")) {
sx = true;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else if (!kstr) {
kstr = argv[i];
} else if (!vstr) {
vstr = argv[i];
} else {
usage();
}
}
if (!path || !kstr || !vstr) usage();
char* kbuf;
size_t ksiz;
char* vbuf;
size_t vsiz;
if (sx) {
kbuf = kc::hexdecode(kstr, &ksiz);
kstr = kbuf;
vbuf = kc::hexdecode(vstr, &vsiz);
vstr = vbuf;
} else {
ksiz = std::strlen(kstr);
kbuf = NULL;
vsiz = std::strlen(vstr);
vbuf = NULL;
}
int32_t rv = procset(path, kstr, ksiz, vstr, vsiz, oflags, mode);
delete[] kbuf;
delete[] vbuf;
return rv;
}
// parse arguments of remove command
static int32_t runremove(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
const char* kstr = NULL;
int32_t oflags = 0;
bool sx = false;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::PolyDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::PolyDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::PolyDB::ONOREPAIR;
} else if (!std::strcmp(argv[i], "-sx")) {
sx = true;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else if (!kstr) {
kstr = argv[i];
} else {
usage();
}
}
if (!path || !kstr) usage();
char* kbuf;
size_t ksiz;
if (sx) {
kbuf = kc::hexdecode(kstr, &ksiz);
kstr = kbuf;
} else {
ksiz = std::strlen(kstr);
kbuf = NULL;
}
int32_t rv = procremove(path, kstr, ksiz, oflags);
delete[] kbuf;
return rv;
}
// parse arguments of get command
static int32_t runget(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
const char* kstr = NULL;
int32_t oflags = 0;
bool rm = false;
bool sx = false;
bool px = false;
bool pz = false;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::PolyDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::PolyDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::PolyDB::ONOREPAIR;
} else if (!std::strcmp(argv[i], "-rm")) {
rm = true;
} else if (!std::strcmp(argv[i], "-sx")) {
sx = true;
} else if (!std::strcmp(argv[i], "-px")) {
px = true;
} else if (!std::strcmp(argv[i], "-pz")) {
pz = true;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else if (!kstr) {
kstr = argv[i];
} else {
usage();
}
}
if (!path || !kstr) usage();
char* kbuf;
size_t ksiz;
if (sx) {
kbuf = kc::hexdecode(kstr, &ksiz);
kstr = kbuf;
} else {
ksiz = std::strlen(kstr);
kbuf = NULL;
}
int32_t rv = procget(path, kstr, ksiz, oflags, rm, px, pz);
delete[] kbuf;
return rv;
}
// parse arguments of list command
static int32_t runlist(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
const char* kstr = NULL;
int32_t oflags = 0;
int32_t mode = 0;
bool des = false;
int64_t max = -1;
bool rm = false;
bool sx = false;
bool pv = false;
bool px = false;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::PolyDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::PolyDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::PolyDB::ONOREPAIR;
} else if (!std::strcmp(argv[i], "-mp")) {
mode = 'p';
} else if (!std::strcmp(argv[i], "-mr")) {
mode = 'r';
} else if (!std::strcmp(argv[i], "-ms")) {
mode = 's';
} else if (!std::strcmp(argv[i], "-des")) {
des = true;
} else if (!std::strcmp(argv[i], "-max")) {
if (++i >= argc) usage();
max = kc::atoix(argv[i]);
} else if (!std::strcmp(argv[i], "-rm")) {
rm = true;
} else if (!std::strcmp(argv[i], "-sx")) {
sx = true;
} else if (!std::strcmp(argv[i], "-pv")) {
pv = true;
} else if (!std::strcmp(argv[i], "-px")) {
px = true;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else if (!kstr) {
kstr = argv[i];
} else {
usage();
}
}
if (!path) usage();
char* kbuf = NULL;
size_t ksiz = 0;
if (kstr) {
if (sx) {
kbuf = kc::hexdecode(kstr, &ksiz);
kstr = kbuf;
} else {
ksiz = std::strlen(kstr);
kbuf = new char[ksiz+1];
std::memcpy(kbuf, kstr, ksiz);
kbuf[ksiz] = '\0';
}
}
int32_t rv = proclist(path, kbuf, ksiz, oflags, mode, des, max, rm, pv, px);
delete[] kbuf;
return rv;
}
// parse arguments of clear command
static int32_t runclear(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
int32_t oflags = 0;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::PolyDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::PolyDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::PolyDB::ONOREPAIR;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else {
usage();
}
}
if (!path) usage();
int32_t rv = procclear(path, oflags);
return rv;
}
// parse arguments of import command
static int32_t runimport(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
const char* file = NULL;
int32_t oflags = 0;
bool sx = false;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::PolyDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::PolyDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::PolyDB::ONOREPAIR;
} else if (!std::strcmp(argv[i], "-sx")) {
sx = true;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else if (!file) {
file = argv[i];
} else {
usage();
}
}
if (!path) usage();
int32_t rv = procimport(path, file, oflags, sx);
return rv;
}
// parse arguments of copy command
static int32_t runcopy(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
const char* file = NULL;
int32_t oflags = 0;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::PolyDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::PolyDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::PolyDB::ONOREPAIR;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else if (!file) {
file = argv[i];
} else {
usage();
}
}
if (!path || !file) usage();
int32_t rv = proccopy(path, file, oflags);
return rv;
}
// parse arguments of dump command
static int32_t rundump(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
const char* file = NULL;
int32_t oflags = 0;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::PolyDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::PolyDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::PolyDB::ONOREPAIR;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else if (!file) {
file = argv[i];
} else {
usage();
}
}
if (!path) usage();
int32_t rv = procdump(path, file, oflags);
return rv;
}
// parse arguments of load command
static int32_t runload(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
const char* file = NULL;
int32_t oflags = 0;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-otr")) {
oflags |= kc::PolyDB::OTRUNCATE;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::PolyDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::PolyDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::PolyDB::ONOREPAIR;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else if (!file) {
file = argv[i];
} else {
usage();
}
}
if (!path) usage();
int32_t rv = procload(path, file, oflags);
return rv;
}
// parse arguments of merge command
static int32_t runmerge(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
int32_t oflags = 0;
kc::PolyDB::MergeMode mode = kc::PolyDB::MSET;
std::vector srcpaths;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::PolyDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::PolyDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::PolyDB::ONOREPAIR;
} else if (!std::strcmp(argv[i], "-add")) {
mode = kc::PolyDB::MADD;
} else if (!std::strcmp(argv[i], "-rep")) {
mode = kc::PolyDB::MREPLACE;
} else if (!std::strcmp(argv[i], "-app")) {
mode = kc::PolyDB::MAPPEND;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else {
srcpaths.push_back(argv[i]);
}
}
if (!path && srcpaths.size() < 1) usage();
int32_t rv = procmerge(path, oflags, mode, srcpaths);
return rv;
}
// parse arguments of setbulk command
static int32_t runsetbulk(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
std::map recs;
int32_t oflags = 0;
bool sx = false;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::PolyDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::PolyDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::PolyDB::ONOREPAIR;
} else if (!std::strcmp(argv[i], "-sx")) {
sx = true;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else {
const char* kstr = argv[i];
if (++i >= argc) usage();
const char* vstr = argv[i];
char* kbuf;
size_t ksiz;
char* vbuf;
size_t vsiz;
if (sx) {
kbuf = kc::hexdecode(kstr, &ksiz);
kstr = kbuf;
vbuf = kc::hexdecode(vstr, &vsiz);
vstr = vbuf;
} else {
ksiz = std::strlen(kstr);
kbuf = NULL;
vsiz = std::strlen(vstr);
vbuf = NULL;
}
std::string key(kstr, ksiz);
std::string value(vstr, vsiz);
recs[key] = value;
delete[] kbuf;
delete[] vbuf;
}
}
if (!path) usage();
int32_t rv = procsetbulk(path, oflags, recs);
return rv;
}
// parse arguments of removebulk command
static int32_t runremovebulk(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
std::vector keys;
int32_t oflags = 0;
bool sx = false;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::PolyDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::PolyDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::PolyDB::ONOREPAIR;
} else if (!std::strcmp(argv[i], "-sx")) {
sx = true;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else {
const char* kstr = argv[i];
char* kbuf;
size_t ksiz;
if (sx) {
kbuf = kc::hexdecode(kstr, &ksiz);
kstr = kbuf;
} else {
ksiz = std::strlen(kstr);
kbuf = NULL;
}
std::string key(kstr, ksiz);
keys.push_back(key);
delete[] kbuf;
}
}
if (!path) usage();
int32_t rv = procremovebulk(path, oflags, keys);
return rv;
}
// parse arguments of getbulk command
static int32_t rungetbulk(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
std::vector keys;
int32_t oflags = 0;
bool sx = false;
bool px = false;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::PolyDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::PolyDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::PolyDB::ONOREPAIR;
} else if (!std::strcmp(argv[i], "-sx")) {
sx = true;
} else if (!std::strcmp(argv[i], "-px")) {
px = true;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else {
const char* kstr = argv[i];
char* kbuf;
size_t ksiz;
if (sx) {
kbuf = kc::hexdecode(kstr, &ksiz);
kstr = kbuf;
} else {
ksiz = std::strlen(kstr);
kbuf = NULL;
}
std::string key(kstr, ksiz);
keys.push_back(key);
delete[] kbuf;
}
}
if (!path) usage();
int32_t rv = procgetbulk(path, oflags, keys, px);
return rv;
}
// parse arguments of check command
static int32_t runcheck(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
int32_t oflags = 0;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::PolyDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::PolyDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::PolyDB::ONOREPAIR;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else {
usage();
}
}
if (!path) usage();
int32_t rv = proccheck(path, oflags);
return rv;
}
// perform create command
static int32_t proccreate(const char* path, int32_t oflags) {
kc::PolyDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::PolyDB::OWRITER | kc::PolyDB::OCREATE | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform inform command
static int32_t procinform(const char* path, int32_t oflags, bool st) {
kc::PolyDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::PolyDB::OREADER | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
if (st) {
std::map status;
if (db.status(&status)) {
std::map::iterator it = status.begin();
std::map::iterator itend = status.end();
while (it != itend) {
oprintf("%s: %s\n", it->first.c_str(), it->second.c_str());
++it;
}
} else {
dberrprint(&db, "DB::status failed");
err = true;
}
} else {
oprintf("count: %lld\n", (long long)db.count());
oprintf("size: %lld\n", (long long)db.size());
}
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform set command
static int32_t procset(const char* path, const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, int32_t oflags, int32_t mode) {
kc::PolyDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::PolyDB::OWRITER | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
switch (mode) {
default: {
if (!db.set(kbuf, ksiz, vbuf, vsiz)) {
dberrprint(&db, "DB::set failed");
err = true;
}
break;
}
case 'a': {
if (!db.add(kbuf, ksiz, vbuf, vsiz)) {
dberrprint(&db, "DB::add failed");
err = true;
}
break;
}
case 'r': {
if (!db.replace(kbuf, ksiz, vbuf, vsiz)) {
dberrprint(&db, "DB::replace failed");
err = true;
}
break;
}
case 'c': {
if (!db.append(kbuf, ksiz, vbuf, vsiz)) {
dberrprint(&db, "DB::append failed");
err = true;
}
break;
}
case 'i': {
int64_t onum = db.increment(kbuf, ksiz, kc::atoi(vbuf));
if (onum == kc::INT64MIN) {
dberrprint(&db, "DB::increment failed");
err = true;
} else {
oprintf("%lld\n", (long long)onum);
}
break;
}
case 'd': {
double onum = db.increment_double(kbuf, ksiz, kc::atof(vbuf));
if (kc::chknan(onum)) {
dberrprint(&db, "DB::increment_double failed");
err = true;
} else {
oprintf("%f\n", onum);
}
break;
}
}
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform remove command
static int32_t procremove(const char* path, const char* kbuf, size_t ksiz, int32_t oflags) {
kc::PolyDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::PolyDB::OWRITER | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
if (!db.remove(kbuf, ksiz)) {
dberrprint(&db, "DB::remove failed");
err = true;
}
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform get command
static int32_t procget(const char* path, const char* kbuf, size_t ksiz,
int32_t oflags, bool rm, bool px, bool pz) {
kc::PolyDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
uint32_t omode = rm ? kc::PolyDB::OWRITER : kc::PolyDB::OREADER;
if (!db.open(path, omode | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
char* vbuf;
size_t vsiz;
if (rm) {
vbuf = db.seize(kbuf, ksiz, &vsiz);
} else {
vbuf = db.get(kbuf, ksiz, &vsiz);
}
if (vbuf) {
printdata(vbuf, vsiz, px);
if (!pz) oprintf("\n");
delete[] vbuf;
} else {
dberrprint(&db, "DB::get failed");
err = true;
}
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform list command
static int32_t proclist(const char* path, const char*kbuf, size_t ksiz, int32_t oflags,
int32_t mode, bool des, int64_t max, bool rm, bool pv, bool px) {
kc::PolyDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
uint32_t omode = rm ? kc::PolyDB::OWRITER : kc::PolyDB::OREADER;
if (!db.open(path, omode | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
class VisitorImpl : public kc::DB::Visitor {
public:
explicit VisitorImpl(bool rm, bool pv, bool px) : rm_(rm), pv_(pv), px_(px) {}
private:
const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) {
printdata(kbuf, ksiz, px_);
if (pv_) {
oprintf("\t");
printdata(vbuf, vsiz, px_);
}
oprintf("\n");
return rm_ ? REMOVE : NOP;
}
bool rm_;
bool pv_;
bool px_;
} visitor(rm, pv, px);
class Printer {
public:
static bool print(kc::BasicDB* db, const std::vector& keys,
bool des, bool rm, bool pv, bool px) {
bool err = false;
if (des) {
for (int64_t i = (int64_t)keys.size() - 1; i >= 0; i--) {
if (!proc_one(db, keys[i], rm, pv, px)) err = true;
}
} else {
std::vector::const_iterator it = keys.begin();
std::vector::const_iterator itend = keys.end();
while (it != itend) {
if (!proc_one(db, *it, rm, pv, px)) err = true;
++it;
}
}
return !err;
}
private:
static bool proc_one(kc::BasicDB* db, const std::string& key, bool rm, bool pv, bool px) {
bool err = false;
printdata(key.data(), key.size(), px);
if (pv) {
size_t vsiz;
char* vbuf = db->get(key.data(), key.size(), &vsiz);
if (vbuf) {
oprintf("\t");
printdata(vbuf, vsiz, px);
delete[] vbuf;
} else {
dberrprint(db, "DB::get failed");
err = true;
}
}
oprintf("\n");
if (rm && !db->remove(key.data(), key.size())) {
dberrprint(db, "DB::remove failed");
err = true;
}
return !err;
}
};
if (mode == 'p') {
std::vector keys;
if (db.match_prefix(std::string(kbuf, ksiz), &keys, max) >= 0) {
if (!Printer::print(&db, keys, des, rm, pv, px)) err = true;
} else {
dberrprint(&db, "DB::match_prefix failed");
err = true;
}
} else if (mode == 'r') {
std::vector keys;
if (db.match_regex(std::string(kbuf, ksiz), &keys, max) >= 0) {
if (!Printer::print(&db, keys, des, rm, pv, px)) err = true;
} else {
dberrprint(&db, "DB::match_regex failed");
err = true;
}
} else if (mode == 's') {
size_t range = ksiz / 3 + 1;
std::vector keys;
if (db.match_similar(std::string(kbuf, ksiz), range, false, &keys, max) >= 0) {
if (!Printer::print(&db, keys, des, rm, pv, px)) err = true;
} else {
dberrprint(&db, "DB::match_similar failed");
err = true;
}
} else if (kbuf || des || max >= 0) {
if (max < 0) max = kc::INT64MAX;
kc::PolyDB::Cursor cur(&db);
if (des) {
if (kbuf) {
if (!cur.jump_back(kbuf, ksiz) && db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, "Cursor::jump failed");
err = true;
}
} else {
if (!cur.jump_back() && db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, "Cursor::jump failed");
err = true;
}
}
while (!err && max > 0) {
if (!cur.accept(&visitor, rm, true)) {
if (db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, "Cursor::accept failed");
err = true;
}
break;
}
max--;
}
} else {
if (kbuf) {
if (!cur.jump(kbuf, ksiz) && db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, "Cursor::jump failed");
err = true;
}
} else {
if (!cur.jump() && db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, "Cursor::jump failed");
err = true;
}
}
while (!err && max > 0) {
if (!cur.accept(&visitor, rm, true)) {
if (db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, "Cursor::accept failed");
err = true;
}
break;
}
max--;
}
}
} else {
if (!db.iterate(&visitor, rm)) {
dberrprint(&db, "DB::iterate failed");
err = true;
}
}
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform clear command
static int32_t procclear(const char* path, int32_t oflags) {
kc::PolyDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::PolyDB::OWRITER | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
if (!db.clear()) {
dberrprint(&db, "DB::clear failed");
err = true;
}
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform import command
static int32_t procimport(const char* path, const char* file, int32_t oflags, bool sx) {
std::istream *is = &std::cin;
std::ifstream ifs;
if (file) {
ifs.open(file, std::ios_base::in | std::ios_base::binary);
if (!ifs) {
eprintf("%s: %s: open error\n", g_progname, file);
return 1;
}
is = &ifs;
}
kc::PolyDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::PolyDB::OWRITER | kc::PolyDB::OCREATE | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
int64_t cnt = 0;
std::string line;
std::vector fields;
while (!err && mygetline(is, &line)) {
cnt++;
kc::strsplit(line, '\t', &fields);
if (sx) {
std::vector::iterator it = fields.begin();
std::vector::iterator itend = fields.end();
while (it != itend) {
size_t esiz;
char* ebuf = kc::hexdecode(it->c_str(), &esiz);
it->clear();
it->append(ebuf, esiz);
delete[] ebuf;
++it;
}
}
switch (fields.size()) {
case 2: {
if (!db.set(fields[0], fields[1])) {
dberrprint(&db, "DB::set failed");
err = true;
}
break;
}
case 1: {
if (!db.remove(fields[0]) && db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, "DB::remove failed");
err = true;
}
break;
}
}
oputchar('.');
if (cnt % 50 == 0) oprintf(" (%lld)\n", (long long)cnt);
}
if (cnt % 50 > 0) oprintf(" (%lld)\n", (long long)cnt);
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform copy command
static int32_t proccopy(const char* path, const char* file, int32_t oflags) {
kc::PolyDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::PolyDB::OREADER | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
DotChecker checker(&std::cout, -100);
if (!db.copy(file, &checker)) {
dberrprint(&db, "DB::copy failed");
err = true;
}
oprintf(" (end)\n");
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
if (!err) oprintf("%lld blocks were copied successfully\n", (long long)checker.count());
return err ? 1 : 0;
}
// perform dump command
static int32_t procdump(const char* path, const char* file, int32_t oflags) {
kc::PolyDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::PolyDB::OREADER | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
if (file) {
DotChecker checker(&std::cout, 1000);
if (!db.dump_snapshot(file, &checker)) {
dberrprint(&db, "DB::dump_snapshot");
err = true;
}
oprintf(" (end)\n");
if (!err) oprintf("%lld records were dumped successfully\n", (long long)checker.count());
} else {
if (!db.dump_snapshot(&std::cout)) {
dberrprint(&db, "DB::dump_snapshot");
err = true;
}
}
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform load command
static int32_t procload(const char* path, const char* file, int32_t oflags) {
kc::PolyDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::PolyDB::OWRITER | kc::PolyDB::OCREATE | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
if (file) {
DotChecker checker(&std::cout, -1000);
if (!db.load_snapshot(file, &checker)) {
dberrprint(&db, "DB::load_snapshot");
err = true;
}
oprintf(" (end)\n");
if (!err) oprintf("%lld records were loaded successfully\n", (long long)checker.count());
} else {
DotChecker checker(&std::cout, -1000);
if (!db.load_snapshot(&std::cin)) {
dberrprint(&db, "DB::load_snapshot");
err = true;
}
oprintf(" (end)\n");
if (!err) oprintf("%lld records were loaded successfully\n", (long long)checker.count());
}
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform merge command
static int32_t procmerge(const char* path, int32_t oflags, kc::PolyDB::MergeMode mode,
const std::vector& srcpaths) {
kc::PolyDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::PolyDB::OWRITER | kc::PolyDB::OCREATE | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
kc::BasicDB** srcary = new kc::BasicDB*[srcpaths.size()];
size_t srcnum = 0;
std::vector::const_iterator it = srcpaths.begin();
std::vector::const_iterator itend = srcpaths.end();
while (it != itend) {
const std::string srcpath = *it;
kc::PolyDB* srcdb = new kc::PolyDB;
if (srcdb->open(srcpath, kc::PolyDB::OREADER | oflags)) {
srcary[srcnum++] = srcdb;
} else {
dberrprint(srcdb, "DB::open failed");
err = true;
delete srcdb;
}
++it;
}
DotChecker checker(&std::cout, 1000);
if (!db.merge(srcary, srcnum, mode, &checker)) {
dberrprint(&db, "DB::merge failed");
err = true;
}
oprintf(" (end)\n");
for (size_t i = 0; i < srcnum; i++) {
kc::BasicDB* srcdb = srcary[i];
if (!srcdb->close()) {
dberrprint(srcdb, "DB::close failed");
err = true;
}
delete srcdb;
}
delete[] srcary;
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
if (!err) oprintf("%lld records were merged successfully\n", (long long)checker.count());
return err ? 1 : 0;
}
// perform setbulk command
static int32_t procsetbulk(const char* path, int32_t oflags,
const std::map& recs) {
kc::PolyDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::PolyDB::OWRITER | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
if (db.set_bulk(recs) != (int64_t)recs.size()) {
dberrprint(&db, "DB::set_bulk failed");
err = true;
}
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform removebulk command
static int32_t procremovebulk(const char* path, int32_t oflags,
const std::vector& keys) {
kc::PolyDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::PolyDB::OWRITER | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
if (db.remove_bulk(keys) < 0) {
dberrprint(&db, "DB::remove_bulk failed");
err = true;
}
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform getbulk command
static int32_t procgetbulk(const char* path, int32_t oflags,
const std::vector& keys, bool px) {
kc::PolyDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::PolyDB::OREADER | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
std::map recs;
if (db.get_bulk(keys, &recs) >= 0) {
std::map::iterator it = recs.begin();
std::map::iterator itend = recs.end();
while (it != itend) {
printdata(it->first.data(), it->first.size(), px);
oprintf("\t");
printdata(it->second.data(), it->second.size(), px);
oprintf("\n");
++it;
}
} else {
dberrprint(&db, "DB::get_bulk failed");
err = true;
}
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform check command
static int32_t proccheck(const char* path, int32_t oflags) {
kc::PolyDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::PolyDB::OREADER | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
kc::PolyDB::Cursor cur(&db);
if (!cur.jump() && db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, "DB::jump failed");
err = true;
}
int64_t cnt = 0;
while (!err) {
size_t ksiz;
const char* vbuf;
size_t vsiz;
char* kbuf = cur.get(&ksiz, &vbuf, &vsiz);
if (kbuf) {
cnt++;
size_t rsiz;
char* rbuf = db.get(kbuf, ksiz, &rsiz);
if (rbuf) {
if (rsiz != vsiz || std::memcmp(rbuf, vbuf, rsiz)) {
dberrprint(&db, "DB::get failed");
err = true;
}
delete[] rbuf;
} else {
dberrprint(&db, "DB::get failed");
err = true;
}
delete[] kbuf;
if (cnt % 1000 == 0) {
oputchar('.');
if (cnt % 50000 == 0) oprintf(" (%lld)\n", (long long)cnt);
}
} else {
if (db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, "Cursor::get failed");
err = true;
}
break;
}
if (!cur.step() && db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, "Cursor::step failed");
err = true;
}
}
oprintf(" (end)\n");
if (db.count() != cnt) {
dberrprint(&db, "DB::count failed");
err = true;
}
const std::string& rpath = db.path();
kc::File::Status sbuf;
if (kc::File::status(rpath, &sbuf)) {
if (!sbuf.isdir && db.size() != sbuf.size) {
dberrprint(&db, "DB::size failed");
err = true;
}
} else {
dberrprint(&db, "File::status failed");
err = true;
}
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
if (!err) oprintf("%lld records were checked successfully\n", (long long)cnt);
return err ? 1 : 0;
}
// END OF FILE
kyotocabinet-1.2.80/kcstashdb.cc 0000664 0001750 0001750 00000002250 14416044124 015555 0 ustar mikio mikio /*************************************************************************************************
* Stash database
* Copyright (C) 2009-2012 Mikio Hirabayashi
* This file is part of Kyoto Cabinet.
* This program is free software: you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation, either version
* 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with this program.
* If not, see .
*************************************************************************************************/
#include "kcstashdb.h"
#include "myconf.h"
namespace kyotocabinet { // common namespace
// There is no implementation now.
} // common namespace
// END OF FILE
kyotocabinet-1.2.80/kcutil.cc 0000664 0001750 0001750 00000027357 14416044124 015121 0 ustar mikio mikio /*************************************************************************************************
* Utility functions
* Copyright (C) 2009-2012 Mikio Hirabayashi
* This file is part of Kyoto Cabinet.
* This program is free software: you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation, either version
* 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with this program.
* If not, see .
*************************************************************************************************/
#include "kcutil.h"
#include "myconf.h"
namespace kyotocabinet { // common namespace
/** The package version. */
const char* const VERSION = _KC_VERSION;
/** The library version. */
const int32_t LIBVER = _KC_LIBVER;
/** The library revision. */
const int32_t LIBREV = _KC_LIBREV;
/** The database format version. */
const int32_t FMTVER = _KC_FMTVER;
/** The system name. */
const char* const OSNAME = _KC_OSNAME;
/** The flag for big endian environments. */
const bool BIGEND = _KC_BIGEND ? true : false;
/** The clock tick of interruption. */
#if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
const int32_t CLOCKTICK = 100;
#else
const int32_t CLOCKTICK = sysconf(_SC_CLK_TCK);
#endif
/** The size of a page. */
#if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
static int32_t win_getpagesize() {
::SYSTEM_INFO ibuf;
::GetSystemInfo(&ibuf);
return ibuf.dwPageSize;
}
const int32_t PAGESIZ = win_getpagesize();
#else
const int32_t PAGESIZ = sysconf(_SC_PAGESIZE);
#endif
/** The extra feature list. */
const char* const FEATURES = ""
#if _KC_GCCATOMIC
"(atomic)"
#endif
#if _KC_ZLIB
"(zlib)"
#endif
#if _KC_LZO
"(lzo)"
#endif
#if _KC_LZMA
"(lzma)"
#endif
;
// get the levenshtein distance of two arrays
template
static size_t levdist(const CHARTYPE* abuf, size_t asiz, const CHARTYPE* bbuf, size_t bsiz) {
size_t dsiz = bsiz + 1;
size_t tsiz = (asiz + 1) * dsiz;
CNTTYPE tblstack[2048/sizeof(CNTTYPE)];
CNTTYPE* tbl = tsiz > sizeof(tblstack) / sizeof(*tblstack) ? new CNTTYPE[tsiz] : tblstack;
tbl[0] = 0;
for (size_t i = 1; i <= asiz; i++) {
tbl[i*dsiz] = i;
}
for (size_t i = 1; i <= bsiz; i++) {
tbl[i] = i;
}
abuf--;
bbuf--;
for (size_t i = 1; i <= asiz; i++) {
for (size_t j = 1; j <= bsiz; j++) {
uint32_t ac = tbl[(i-1)*dsiz+j] + 1;
uint32_t bc = tbl[i*dsiz+j-1] + 1;
uint32_t cc = tbl[(i-1)*dsiz+j-1] + (abuf[i] != bbuf[j]);
ac = ac < bc ? ac : bc;
tbl[i*dsiz+j] = ac < cc ? ac : cc;
}
}
size_t ed = tbl[asiz*dsiz+bsiz];
if (tbl != tblstack) delete[] tbl;
return ed;
}
/**
* Calculate the levenshtein distance of two regions in bytes.
*/
size_t memdist(const void* abuf, size_t asiz, const void* bbuf, size_t bsiz) {
_assert_(abuf && asiz <= MEMMAXSIZ && bbuf && bsiz <= MEMMAXSIZ);
return asiz > UINT8MAX || bsiz > UINT8MAX ?
levdist((const char*)abuf, asiz, (const char*)bbuf, bsiz) :
levdist((const char*)abuf, asiz, (const char*)bbuf, bsiz);
}
/**
* Calculate the levenshtein distance of two UTF-8 strings.
*/
size_t strutfdist(const char* astr, const char* bstr) {
_assert_(astr && bstr);
size_t anum = strutflen(astr);
uint32_t astack[128];
uint32_t* aary = anum > sizeof(astack) / sizeof(*astack) ? new uint32_t[anum] : astack;
strutftoucs(astr, aary, &anum);
size_t bnum = strutflen(bstr);
uint32_t bstack[128];
uint32_t* bary = bnum > sizeof(bstack) / sizeof(*bstack) ? new uint32_t[bnum] : bstack;
strutftoucs(bstr, bary, &bnum);
size_t dist = strucsdist(aary, anum, bary, bnum);
if (bary != bstack) delete[] bary;
if (aary != astack) delete[] aary;
return dist;
}
/**
* Calculate the levenshtein distance of two UCS-4 arrays.
*/
size_t strucsdist(const uint32_t* aary, size_t anum, const uint32_t* bary, size_t bnum) {
_assert_(aary && anum <= MEMMAXSIZ && bary && bnum <= MEMMAXSIZ);
return anum > UINT8MAX || bnum > UINT8MAX ?
levdist(aary, anum, bary, bnum) :
levdist(aary, anum, bary, bnum);
}
/**
* Allocate a nullified region on memory.
*/
void* mapalloc(size_t size) {
#if defined(_SYS_LINUX_)
_assert_(size > 0 && size <= MEMMAXSIZ);
void* ptr = ::mmap(0, sizeof(size) + size,
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (ptr == MAP_FAILED) throw std::bad_alloc();
*(size_t*)ptr = size;
return (char*)ptr + sizeof(size);
#else
_assert_(size > 0 && size <= MEMMAXSIZ);
void* ptr = std::calloc(size, 1);
if (!ptr) throw std::bad_alloc();
return ptr;
#endif
}
/**
* Free a region on memory.
*/
void mapfree(void* ptr) {
#if defined(_SYS_LINUX_)
_assert_(ptr);
size_t size = *((size_t*)ptr - 1);
::munmap((char*)ptr - sizeof(size), sizeof(size) + size);
#else
_assert_(ptr);
std::free(ptr);
#endif
}
/**
* Get the time of day in seconds.
* @return the time of day in seconds. The accuracy is in microseconds.
*/
double time() {
#if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
_assert_(true);
::FILETIME ft;
::GetSystemTimeAsFileTime(&ft);
::LARGE_INTEGER li;
li.LowPart = ft.dwLowDateTime;
li.HighPart = ft.dwHighDateTime;
return li.QuadPart / 10000000.0;
#else
_assert_(true);
struct ::timeval tv;
if (::gettimeofday(&tv, NULL) != 0) return 0.0;
return tv.tv_sec + tv.tv_usec / 1000000.0;
#endif
}
/**
* Get the process ID.
*/
int64_t getpid() {
#if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
_assert_(true);
return ::GetCurrentProcessId();
#else
_assert_(true);
return ::getpid();
#endif
}
/**
* Get the value of an environment variable.
*/
const char* getenv(const char* name) {
_assert_(name);
return ::getenv(name);
}
/**
* Get system information of the environment.
*/
void getsysinfo(std::map* strmap) {
#if defined(_SYS_LINUX_)
_assert_(strmap);
struct ::rusage rbuf;
std::memset(&rbuf, 0, sizeof(rbuf));
if (::getrusage(RUSAGE_SELF, &rbuf) == 0) {
(*strmap)["ru_utime"] = strprintf("%0.6f",
rbuf.ru_utime.tv_sec + rbuf.ru_utime.tv_usec / 1000000.0);
(*strmap)["ru_stime"] = strprintf("%0.6f",
rbuf.ru_stime.tv_sec + rbuf.ru_stime.tv_usec / 1000000.0);
if (rbuf.ru_maxrss > 0) {
int64_t size = rbuf.ru_maxrss * 1024LL;
(*strmap)["mem_peak"] = strprintf("%lld", (long long)size);
(*strmap)["mem_size"] = strprintf("%lld", (long long)size);
(*strmap)["mem_rss"] = strprintf("%lld", (long long)size);
}
}
std::ifstream ifs;
ifs.open("/proc/self/status", std::ios_base::in | std::ios_base::binary);
if (ifs) {
std::string line;
while (getline(ifs, line)) {
size_t idx = line.find(':');
if (idx != std::string::npos) {
const std::string& name = line.substr(0, idx);
idx++;
while (idx < line.size() && line[idx] >= '\0' && line[idx] <= ' ') {
idx++;
}
const std::string& value = line.substr(idx);
if (name == "VmPeak") {
int64_t size = atoix(value.c_str());
if (size > 0) (*strmap)["mem_peak"] = strprintf("%lld", (long long)size);
} else if (name == "VmSize") {
int64_t size = atoix(value.c_str());
if (size > 0) (*strmap)["mem_size"] = strprintf("%lld", (long long)size);
} else if (name == "VmRSS") {
int64_t size = atoix(value.c_str());
if (size > 0) (*strmap)["mem_rss"] = strprintf("%lld", (long long)size);
}
}
}
ifs.close();
}
ifs.open("/proc/meminfo", std::ios_base::in | std::ios_base::binary);
if (ifs) {
std::string line;
while (getline(ifs, line)) {
size_t idx = line.find(':');
if (idx != std::string::npos) {
const std::string& name = line.substr(0, idx);
idx++;
while (idx < line.size() && line[idx] >= '\0' && line[idx] <= ' ') {
idx++;
}
const std::string& value = line.substr(idx);
if (name == "MemTotal") {
int64_t size = atoix(value.c_str());
if (size > 0) (*strmap)["mem_total"] = strprintf("%lld", (long long)size);
} else if (name == "MemFree") {
int64_t size = atoix(value.c_str());
if (size > 0) (*strmap)["mem_free"] = strprintf("%lld", (long long)size);
} else if (name == "Cached") {
int64_t size = atoix(value.c_str());
if (size > 0) (*strmap)["mem_cached"] = strprintf("%lld", (long long)size);
}
}
}
ifs.close();
}
#elif defined(_SYS_MACOSX_)
_assert_(strmap);
struct ::rusage rbuf;
std::memset(&rbuf, 0, sizeof(rbuf));
if (::getrusage(RUSAGE_SELF, &rbuf) == 0) {
(*strmap)["ru_utime"] = strprintf("%0.6f",
rbuf.ru_utime.tv_sec + rbuf.ru_utime.tv_usec / 1000000.0);
(*strmap)["ru_stime"] = strprintf("%0.6f",
rbuf.ru_stime.tv_sec + rbuf.ru_stime.tv_usec / 1000000.0);
if (rbuf.ru_maxrss > 0) {
int64_t size = rbuf.ru_maxrss;
(*strmap)["mem_peak"] = strprintf("%lld", (long long)size);
(*strmap)["mem_size"] = strprintf("%lld", (long long)size);
(*strmap)["mem_rss"] = strprintf("%lld", (long long)size);
}
}
#elif defined(_SYS_FREEBSD_) || defined(_SYS_SUNOS_)
_assert_(strmap);
struct ::rusage rbuf;
std::memset(&rbuf, 0, sizeof(rbuf));
if (::getrusage(RUSAGE_SELF, &rbuf) == 0) {
(*strmap)["ru_utime"] = strprintf("%0.6f",
rbuf.ru_utime.tv_sec + rbuf.ru_utime.tv_usec / 1000000.0);
(*strmap)["ru_stime"] = strprintf("%0.6f",
rbuf.ru_stime.tv_sec + rbuf.ru_stime.tv_usec / 1000000.0);
if (rbuf.ru_maxrss > 0) {
int64_t size = rbuf.ru_maxrss * 1024LL;
(*strmap)["mem_peak"] = strprintf("%lld", (long long)size);
(*strmap)["mem_size"] = strprintf("%lld", (long long)size);
(*strmap)["mem_rss"] = strprintf("%lld", (long long)size);
}
}
#elif defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
_assert_(strmap);
::DWORD pid = ::GetCurrentProcessId();
::HANDLE ph = ::OpenProcess(PROCESS_QUERY_INFORMATION, false, pid);
if (ph) {
::FILETIME ct, et, kt, ut;
if (::GetProcessTimes(ph, &ct, &et, &kt, &ut)) {
::LARGE_INTEGER li;
li.LowPart = ut.dwLowDateTime;
li.HighPart = ut.dwHighDateTime;
(*strmap)["ru_utime"] = strprintf("%0.6f", li.QuadPart / 10000000.0);
li.LowPart = kt.dwLowDateTime;
li.HighPart = kt.dwHighDateTime;
(*strmap)["ru_stime"] = strprintf("%0.6f", li.QuadPart / 10000000.0);
}
::CloseHandle(ph);
}
::MEMORYSTATUSEX msbuf;
msbuf.dwLength = sizeof(msbuf);
::GlobalMemoryStatusEx(&msbuf);
(*strmap)["mem_total"] = strprintf("%lld", (long long)msbuf.ullTotalPhys);
(*strmap)["mem_free"] = strprintf("%lld", (long long)msbuf.ullAvailPhys);
int64_t cached = msbuf.ullTotalPhys - msbuf.ullAvailPhys;
(*strmap)["mem_cached"] = strprintf("%lld", (long long)cached);
#else
_assert_(strmap);
#endif
}
/**
* Set the standard streams into the binary mode.
*/
void setstdiobin() {
#if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
_assert_(true);
_setmode(_fileno(stdin), O_BINARY);
_setmode(_fileno(stdout), O_BINARY);
_setmode(_fileno(stderr), O_BINARY);
#else
_assert_(true);
#endif
}
} // common namespace
// END OF FILE
kyotocabinet-1.2.80/kchashmgr.cc 0000664 0001750 0001750 00000127705 14416044124 015573 0 ustar mikio mikio /*************************************************************************************************
* The command line utility of the file hash database
* Copyright (C) 2009-2012 Mikio Hirabayashi
* This file is part of Kyoto Cabinet.
* This program is free software: you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation, either version
* 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with this program.
* If not, see .
*************************************************************************************************/
#include
#include "cmdcommon.h"
// global variables
const char* g_progname; // program name
// function prototypes
int main(int argc, char** argv);
static void usage();
static void dberrprint(kc::BasicDB* db, const char* info);
static int32_t runcreate(int argc, char** argv);
static int32_t runinform(int argc, char** argv);
static int32_t runset(int argc, char** argv);
static int32_t runremove(int argc, char** argv);
static int32_t runget(int argc, char** argv);
static int32_t runlist(int argc, char** argv);
static int32_t runclear(int argc, char** argv);
static int32_t runimport(int argc, char** argv);
static int32_t runcopy(int argc, char** argv);
static int32_t rundump(int argc, char** argv);
static int32_t runload(int argc, char** argv);
static int32_t rundefrag(int argc, char** argv);
static int32_t runcheck(int argc, char** argv);
static int32_t runsetbulk(int argc, char** argv);
static int32_t runremovebulk(int argc, char** argv);
static int32_t rungetbulk(int argc, char** argv);
static int32_t proccreate(const char* path, int32_t oflags,
int32_t apow, int32_t fpow, int32_t opts, int64_t bnum);
static int32_t procinform(const char* path, int32_t oflags, bool st);
static int32_t procset(const char* path, const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, int32_t oflags, int32_t mode);
static int32_t procremove(const char* path, const char* kbuf, size_t ksiz, int32_t oflags);
static int32_t procget(const char* path, const char* kbuf, size_t ksiz,
int32_t oflags, bool rm, bool px, bool pz);
static int32_t proclist(const char* path, const char*kbuf, size_t ksiz, int32_t oflags,
int64_t max, bool rm, bool pv, bool px);
static int32_t procclear(const char* path, int32_t oflags);
static int32_t procimport(const char* path, const char* file, int32_t oflags, bool sx);
static int32_t proccopy(const char* path, const char* file, int32_t oflags);
static int32_t procdump(const char* path, const char* file, int32_t oflags);
static int32_t procload(const char* path, const char* file, int32_t oflags);
static int32_t procdefrag(const char* path, int32_t oflags);
static int32_t procsetbulk(const char* path, int32_t oflags,
const std::map& recs);
static int32_t procremovebulk(const char* path, int32_t oflags,
const std::vector& keys);
static int32_t procgetbulk(const char* path, int32_t oflags,
const std::vector& keys, bool px);
static int32_t proccheck(const char* path, int32_t oflags);
// main routine
int main(int argc, char** argv) {
g_progname = argv[0];
kc::setstdiobin();
if (argc < 2) usage();
int32_t rv = 0;
if (!std::strcmp(argv[1], "create")) {
rv = runcreate(argc, argv);
} else if (!std::strcmp(argv[1], "inform")) {
rv = runinform(argc, argv);
} else if (!std::strcmp(argv[1], "set")) {
rv = runset(argc, argv);
} else if (!std::strcmp(argv[1], "remove")) {
rv = runremove(argc, argv);
} else if (!std::strcmp(argv[1], "get")) {
rv = runget(argc, argv);
} else if (!std::strcmp(argv[1], "list")) {
rv = runlist(argc, argv);
} else if (!std::strcmp(argv[1], "clear")) {
rv = runclear(argc, argv);
} else if (!std::strcmp(argv[1], "import")) {
rv = runimport(argc, argv);
} else if (!std::strcmp(argv[1], "copy")) {
rv = runcopy(argc, argv);
} else if (!std::strcmp(argv[1], "dump")) {
rv = rundump(argc, argv);
} else if (!std::strcmp(argv[1], "load")) {
rv = runload(argc, argv);
} else if (!std::strcmp(argv[1], "defrag")) {
rv = rundefrag(argc, argv);
} else if (!std::strcmp(argv[1], "setbulk")) {
rv = runsetbulk(argc, argv);
} else if (!std::strcmp(argv[1], "removebulk")) {
rv = runremovebulk(argc, argv);
} else if (!std::strcmp(argv[1], "getbulk")) {
rv = rungetbulk(argc, argv);
} else if (!std::strcmp(argv[1], "check")) {
rv = runcheck(argc, argv);
} else if (!std::strcmp(argv[1], "version") || !std::strcmp(argv[1], "--version")) {
printversion();
} else {
usage();
}
return rv;
}
// print the usage and exit
static void usage() {
eprintf("%s: the command line utility of the file hash database of Kyoto Cabinet\n",
g_progname);
eprintf("\n");
eprintf("usage:\n");
eprintf(" %s create [-otr] [-onl|-otl|-onr] [-apow num] [-fpow num] [-ts] [-tl] [-tc]"
" [-bnum num] path\n", g_progname);
eprintf(" %s inform [-onl|-otl|-onr] [-st] path\n", g_progname);
eprintf(" %s set [-onl|-otl|-onr] [-add|-rep|-app|-inci|-incd] [-sx] path key value\n",
g_progname);
eprintf(" %s remove [-onl|-otl|-onr] [-sx] path key\n", g_progname);
eprintf(" %s get [-onl|-otl|-onr] [-rm] [-sx] [-px] [-pz] path key\n", g_progname);
eprintf(" %s list [-onl|-otl|-onr] [-max num] [-rm] [-sx] [-pv] [-px] path [key]\n",
g_progname);
eprintf(" %s clear [-onl|-otl|-onr] path\n", g_progname);
eprintf(" %s import [-onl|-otl|-onr] [-sx] path [file]\n", g_progname);
eprintf(" %s copy [-onl|-otl|-onr] path file\n", g_progname);
eprintf(" %s dump [-onl|-otl|-onr] path [file]\n", g_progname);
eprintf(" %s load [-otr] [-onl|-otl|-onr] path [file]\n", g_progname);
eprintf(" %s defrag [-onl|-otl|-onr] path\n", g_progname);
eprintf(" %s setbulk [-onl|-otl|-onr] [-sx] path key value ...\n", g_progname);
eprintf(" %s removebulk [-onl|-otl|-onr] [-sx] path key ...\n", g_progname);
eprintf(" %s getbulk [-onl|-otl|-onr] [-sx] [-px] path key ...\n", g_progname);
eprintf(" %s check [-onl|-otl|-onr] path\n", g_progname);
eprintf("\n");
std::exit(1);
}
// print error message of database
static void dberrprint(kc::BasicDB* db, const char* info) {
const kc::BasicDB::Error& err = db->error();
eprintf("%s: %s: %s: %d: %s: %s\n",
g_progname, info, db->path().c_str(), err.code(), err.name(), err.message());
}
// parse arguments of create command
static int32_t runcreate(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
int32_t oflags = 0;
int32_t apow = -1;
int32_t fpow = -1;
int32_t opts = 0;
int64_t bnum = -1;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-otr")) {
oflags |= kc::HashDB::OTRUNCATE;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::HashDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::HashDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::HashDB::ONOREPAIR;
} else if (!std::strcmp(argv[i], "-apow")) {
if (++i >= argc) usage();
apow = kc::atoix(argv[i]);
} else if (!std::strcmp(argv[i], "-fpow")) {
if (++i >= argc) usage();
fpow = kc::atoix(argv[i]);
} else if (!std::strcmp(argv[i], "-ts")) {
opts |= kc::HashDB::TSMALL;
} else if (!std::strcmp(argv[i], "-tl")) {
opts |= kc::HashDB::TLINEAR;
} else if (!std::strcmp(argv[i], "-tc")) {
opts |= kc::HashDB::TCOMPRESS;
} else if (!std::strcmp(argv[i], "-bnum")) {
if (++i >= argc) usage();
bnum = kc::atoix(argv[i]);
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else {
usage();
}
}
if (!path) usage();
int32_t rv = proccreate(path, oflags, apow, fpow, opts, bnum);
return rv;
}
// parse arguments of inform command
static int32_t runinform(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
int32_t oflags = 0;
bool st = false;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::HashDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::HashDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::HashDB::ONOREPAIR;
} else if (!std::strcmp(argv[i], "-st")) {
st = true;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else {
usage();
}
}
if (!path) usage();
int32_t rv = procinform(path, oflags, st);
return rv;
}
// parse arguments of set command
static int32_t runset(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
const char* kstr = NULL;
const char* vstr = NULL;
int32_t oflags = 0;
int32_t mode = 0;
bool sx = false;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::HashDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::HashDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::HashDB::ONOREPAIR;
} else if (!std::strcmp(argv[i], "-add")) {
mode = 'a';
} else if (!std::strcmp(argv[i], "-rep")) {
mode = 'r';
} else if (!std::strcmp(argv[i], "-app")) {
mode = 'c';
} else if (!std::strcmp(argv[i], "-inci")) {
mode = 'i';
} else if (!std::strcmp(argv[i], "-incd")) {
mode = 'd';
} else if (!std::strcmp(argv[i], "-sx")) {
sx = true;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else if (!kstr) {
kstr = argv[i];
} else if (!vstr) {
vstr = argv[i];
} else {
usage();
}
}
if (!path || !kstr || !vstr) usage();
char* kbuf;
size_t ksiz;
char* vbuf;
size_t vsiz;
if (sx) {
kbuf = kc::hexdecode(kstr, &ksiz);
kstr = kbuf;
vbuf = kc::hexdecode(vstr, &vsiz);
vstr = vbuf;
} else {
ksiz = std::strlen(kstr);
kbuf = NULL;
vsiz = std::strlen(vstr);
vbuf = NULL;
}
int32_t rv = procset(path, kstr, ksiz, vstr, vsiz, oflags, mode);
delete[] kbuf;
delete[] vbuf;
return rv;
}
// parse arguments of remove command
static int32_t runremove(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
const char* kstr = NULL;
int32_t oflags = 0;
bool sx = false;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::HashDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::HashDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::HashDB::ONOREPAIR;
} else if (!std::strcmp(argv[i], "-sx")) {
sx = true;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else if (!kstr) {
kstr = argv[i];
} else {
usage();
}
}
if (!path || !kstr) usage();
char* kbuf;
size_t ksiz;
if (sx) {
kbuf = kc::hexdecode(kstr, &ksiz);
kstr = kbuf;
} else {
ksiz = std::strlen(kstr);
kbuf = NULL;
}
int32_t rv = procremove(path, kstr, ksiz, oflags);
delete[] kbuf;
return rv;
}
// parse arguments of get command
static int32_t runget(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
const char* kstr = NULL;
int32_t oflags = 0;
bool rm = false;
bool sx = false;
bool px = false;
bool pz = false;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::HashDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::HashDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::HashDB::ONOREPAIR;
} else if (!std::strcmp(argv[i], "-rm")) {
rm = true;
} else if (!std::strcmp(argv[i], "-sx")) {
sx = true;
} else if (!std::strcmp(argv[i], "-px")) {
px = true;
} else if (!std::strcmp(argv[i], "-pz")) {
pz = true;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else if (!kstr) {
kstr = argv[i];
} else {
usage();
}
}
if (!path || !kstr) usage();
char* kbuf;
size_t ksiz;
if (sx) {
kbuf = kc::hexdecode(kstr, &ksiz);
kstr = kbuf;
} else {
ksiz = std::strlen(kstr);
kbuf = NULL;
}
int32_t rv = procget(path, kstr, ksiz, oflags, rm, px, pz);
delete[] kbuf;
return rv;
}
// parse arguments of list command
static int32_t runlist(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
const char* kstr = NULL;
int32_t oflags = 0;
int64_t max = -1;
bool rm = false;
bool sx = false;
bool pv = false;
bool px = false;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::HashDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::HashDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::HashDB::ONOREPAIR;
} else if (!std::strcmp(argv[i], "-max")) {
if (++i >= argc) usage();
max = kc::atoix(argv[i]);
} else if (!std::strcmp(argv[i], "-rm")) {
rm = true;
} else if (!std::strcmp(argv[i], "-sx")) {
sx = true;
} else if (!std::strcmp(argv[i], "-pv")) {
pv = true;
} else if (!std::strcmp(argv[i], "-px")) {
px = true;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else if (!kstr) {
kstr = argv[i];
} else {
usage();
}
}
if (!path) usage();
char* kbuf = NULL;
size_t ksiz = 0;
if (kstr) {
if (sx) {
kbuf = kc::hexdecode(kstr, &ksiz);
kstr = kbuf;
} else {
ksiz = std::strlen(kstr);
kbuf = new char[ksiz+1];
std::memcpy(kbuf, kstr, ksiz);
kbuf[ksiz] = '\0';
}
}
int32_t rv = proclist(path, kbuf, ksiz, oflags, max, rm, pv, px);
delete[] kbuf;
return rv;
}
// parse arguments of clear command
static int32_t runclear(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
int32_t oflags = 0;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::HashDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::HashDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::HashDB::ONOREPAIR;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else {
usage();
}
}
if (!path) usage();
int32_t rv = procclear(path, oflags);
return rv;
}
// parse arguments of import command
static int32_t runimport(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
const char* file = NULL;
int32_t oflags = 0;
bool sx = false;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::HashDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::HashDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::HashDB::ONOREPAIR;
} else if (!std::strcmp(argv[i], "-sx")) {
sx = true;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else if (!file) {
file = argv[i];
} else {
usage();
}
}
if (!path) usage();
int32_t rv = procimport(path, file, oflags, sx);
return rv;
}
// parse arguments of copy command
static int32_t runcopy(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
const char* file = NULL;
int32_t oflags = 0;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::HashDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::HashDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::HashDB::ONOREPAIR;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else if (!file) {
file = argv[i];
} else {
usage();
}
}
if (!path || !file) usage();
int32_t rv = proccopy(path, file, oflags);
return rv;
}
// parse arguments of dump command
static int32_t rundump(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
const char* file = NULL;
int32_t oflags = 0;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::HashDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::HashDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::HashDB::ONOREPAIR;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else if (!file) {
file = argv[i];
} else {
usage();
}
}
if (!path) usage();
int32_t rv = procdump(path, file, oflags);
return rv;
}
// parse arguments of load command
static int32_t runload(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
const char* file = NULL;
int32_t oflags = 0;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-otr")) {
oflags |= kc::HashDB::OTRUNCATE;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::HashDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::HashDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::HashDB::ONOREPAIR;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else if (!file) {
file = argv[i];
} else {
usage();
}
}
if (!path) usage();
int32_t rv = procload(path, file, oflags);
return rv;
}
// parse arguments of defrag command
static int32_t rundefrag(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
int32_t oflags = 0;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::HashDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::HashDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::HashDB::ONOREPAIR;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else {
usage();
}
}
if (!path) usage();
int32_t rv = procdefrag(path, oflags);
return rv;
}
// parse arguments of setbulk command
static int32_t runsetbulk(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
std::map recs;
int32_t oflags = 0;
bool sx = false;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::HashDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::HashDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::HashDB::ONOREPAIR;
} else if (!std::strcmp(argv[i], "-sx")) {
sx = true;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else {
const char* kstr = argv[i];
if (++i >= argc) usage();
const char* vstr = argv[i];
char* kbuf;
size_t ksiz;
char* vbuf;
size_t vsiz;
if (sx) {
kbuf = kc::hexdecode(kstr, &ksiz);
kstr = kbuf;
vbuf = kc::hexdecode(vstr, &vsiz);
vstr = vbuf;
} else {
ksiz = std::strlen(kstr);
kbuf = NULL;
vsiz = std::strlen(vstr);
vbuf = NULL;
}
std::string key(kstr, ksiz);
std::string value(vstr, vsiz);
recs[key] = value;
delete[] kbuf;
delete[] vbuf;
}
}
if (!path) usage();
int32_t rv = procsetbulk(path, oflags, recs);
return rv;
}
// parse arguments of removebulk command
static int32_t runremovebulk(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
std::vector keys;
int32_t oflags = 0;
bool sx = false;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::HashDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::HashDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::HashDB::ONOREPAIR;
} else if (!std::strcmp(argv[i], "-sx")) {
sx = true;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else {
const char* kstr = argv[i];
char* kbuf;
size_t ksiz;
if (sx) {
kbuf = kc::hexdecode(kstr, &ksiz);
kstr = kbuf;
} else {
ksiz = std::strlen(kstr);
kbuf = NULL;
}
std::string key(kstr, ksiz);
keys.push_back(key);
delete[] kbuf;
}
}
if (!path) usage();
int32_t rv = procremovebulk(path, oflags, keys);
return rv;
}
// parse arguments of getbulk command
static int32_t rungetbulk(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
std::vector keys;
int32_t oflags = 0;
bool sx = false;
bool px = false;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::HashDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::HashDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::HashDB::ONOREPAIR;
} else if (!std::strcmp(argv[i], "-sx")) {
sx = true;
} else if (!std::strcmp(argv[i], "-px")) {
px = true;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else {
const char* kstr = argv[i];
char* kbuf;
size_t ksiz;
if (sx) {
kbuf = kc::hexdecode(kstr, &ksiz);
kstr = kbuf;
} else {
ksiz = std::strlen(kstr);
kbuf = NULL;
}
std::string key(kstr, ksiz);
keys.push_back(key);
delete[] kbuf;
}
}
if (!path) usage();
int32_t rv = procgetbulk(path, oflags, keys, px);
return rv;
}
// parse arguments of check command
static int32_t runcheck(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
int32_t oflags = 0;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-onl")) {
oflags |= kc::HashDB::ONOLOCK;
} else if (!std::strcmp(argv[i], "-otl")) {
oflags |= kc::HashDB::OTRYLOCK;
} else if (!std::strcmp(argv[i], "-onr")) {
oflags |= kc::HashDB::ONOREPAIR;
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else {
usage();
}
}
if (!path) usage();
int32_t rv = proccheck(path, oflags);
return rv;
}
// perform create command
static int32_t proccreate(const char* path, int32_t oflags,
int32_t apow, int32_t fpow, int32_t opts, int64_t bnum) {
kc::HashDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (apow >= 0) db.tune_alignment(apow);
if (fpow >= 0) db.tune_fbp(fpow);
if (opts > 0) db.tune_options(opts);
if (bnum > 0) db.tune_buckets(bnum);
if (!db.open(path, kc::HashDB::OWRITER | kc::HashDB::OCREATE | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform inform command
static int32_t procinform(const char* path, int32_t oflags, bool st) {
kc::HashDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::HashDB::OREADER | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
if (st) {
std::map status;
status["opaque"] = "";
status["fbpnum_used"] = "";
status["bnum_used"] = "";
if (db.status(&status)) {
uint32_t type = kc::atoi(status["type"].c_str());
oprintf("type: %s (%s) (type=0x%02X)\n",
kc::BasicDB::typecname(type), kc::BasicDB::typestring(type), type);
uint32_t rtype = kc::atoi(status["realtype"].c_str());
if (rtype > 0 && rtype != type)
oprintf("real type: %s (%s) (realtype=0x%02X)\n",
kc::BasicDB::typecname(rtype), kc::BasicDB::typestring(rtype), rtype);
uint32_t chksum = kc::atoi(status["chksum"].c_str());
oprintf("format version: %s (libver=%s.%s) (chksum=0x%02X)\n", status["fmtver"].c_str(),
status["libver"].c_str(), status["librev"].c_str(), chksum);
oprintf("path: %s\n", status["path"].c_str());
int32_t flags = kc::atoi(status["flags"].c_str());
oprintf("status flags:");
if (flags & kc::HashDB::FOPEN) oprintf(" open");
if (flags & kc::HashDB::FFATAL) oprintf(" fatal");
oprintf(" (flags=%d)", flags);
if (kc::atoi(status["recovered"].c_str()) > 0) oprintf(" (recovered)");
if (kc::atoi(status["reorganized"].c_str()) > 0) oprintf(" (reorganized)");
if (kc::atoi(status["trimmed"].c_str()) > 0) oprintf(" (trimmed)");
oprintf("\n", flags);
int32_t apow = kc::atoi(status["apow"].c_str());
oprintf("alignment: %d (apow=%d)\n", 1 << apow, apow);
int32_t fpow = kc::atoi(status["fpow"].c_str());
int32_t fbpnum = fpow > 0 ? 1 << fpow : 0;
int32_t fbpused = kc::atoi(status["fbpnum_used"].c_str());
int64_t frgcnt = kc::atoi(status["frgcnt"].c_str());
oprintf("free block pool: %d (fpow=%d) (used=%d) (frg=%lld)\n",
fbpnum, fpow, fbpused, (long long)frgcnt);
int32_t opts = kc::atoi(status["opts"].c_str());
oprintf("options:");
if (opts & kc::HashDB::TSMALL) oprintf(" small");
if (opts & kc::HashDB::TLINEAR) oprintf(" linear");
if (opts & kc::HashDB::TCOMPRESS) oprintf(" compress");
oprintf(" (opts=%d)\n", opts);
if (status["opaque"].size() >= 16) {
const char* opaque = status["opaque"].c_str();
oprintf("opaque:");
if (std::count(opaque, opaque + 16, 0) != 16) {
for (int32_t i = 0; i < 16; i++) {
oprintf(" %02X", ((unsigned char*)opaque)[i]);
}
} else {
oprintf(" 0");
}
oprintf("\n");
}
int64_t bnum = kc::atoi(status["bnum"].c_str());
int64_t bnumused = kc::atoi(status["bnum_used"].c_str());
int64_t count = kc::atoi(status["count"].c_str());
double load = 0;
if (count > 0 && bnumused > 0) {
load = (double)count / bnumused;
if (!(opts & kc::HashDB::TLINEAR)) load = std::log(load + 1) / std::log(2.0);
}
oprintf("buckets: %lld (used=%lld) (load=%.2f)\n",
(long long)bnum, (long long)bnumused, load);
std::string cntstr = unitnumstr(count);
oprintf("count: %lld (%s)\n", count, cntstr.c_str());
int64_t size = kc::atoi(status["size"].c_str());
int64_t msiz = kc::atoi(status["msiz"].c_str());
int64_t realsize = kc::atoi(status["realsize"].c_str());
std::string sizestr = unitnumstrbyte(size);
oprintf("size: %lld (%s) (map=%lld)", size, sizestr.c_str(), (long long)msiz);
if (size != realsize) oprintf(" (gap=%lld)", (long long)(realsize - size));
oprintf("\n");
} else {
dberrprint(&db, "DB::status failed");
err = true;
}
} else {
uint8_t flags = db.flags();
if (flags != 0) {
oprintf("status:");
if (flags & kc::HashDB::FOPEN) oprintf(" open");
if (flags & kc::HashDB::FFATAL) oprintf(" fatal");
oprintf("\n");
}
oprintf("count: %lld\n", (long long)db.count());
oprintf("size: %lld\n", (long long)db.size());
}
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform set command
static int32_t procset(const char* path, const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, int32_t oflags, int32_t mode) {
kc::HashDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::HashDB::OWRITER | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
switch (mode) {
default: {
if (!db.set(kbuf, ksiz, vbuf, vsiz)) {
dberrprint(&db, "DB::set failed");
err = true;
}
break;
}
case 'a': {
if (!db.add(kbuf, ksiz, vbuf, vsiz)) {
dberrprint(&db, "DB::add failed");
err = true;
}
break;
}
case 'r': {
if (!db.replace(kbuf, ksiz, vbuf, vsiz)) {
dberrprint(&db, "DB::replace failed");
err = true;
}
break;
}
case 'c': {
if (!db.append(kbuf, ksiz, vbuf, vsiz)) {
dberrprint(&db, "DB::append failed");
err = true;
}
break;
}
case 'i': {
int64_t onum = db.increment(kbuf, ksiz, kc::atoi(vbuf));
if (onum == kc::INT64MIN) {
dberrprint(&db, "DB::increment failed");
err = true;
} else {
oprintf("%lld\n", (long long)onum);
}
break;
}
case 'd': {
double onum = db.increment_double(kbuf, ksiz, kc::atof(vbuf));
if (kc::chknan(onum)) {
dberrprint(&db, "DB::increment_double failed");
err = true;
} else {
oprintf("%f\n", onum);
}
break;
}
}
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform remove command
static int32_t procremove(const char* path, const char* kbuf, size_t ksiz, int32_t oflags) {
kc::HashDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::HashDB::OWRITER | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
if (!db.remove(kbuf, ksiz)) {
dberrprint(&db, "DB::remove failed");
err = true;
}
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform get command
static int32_t procget(const char* path, const char* kbuf, size_t ksiz,
int32_t oflags, bool rm, bool px, bool pz) {
kc::HashDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
uint32_t omode = rm ? kc::HashDB::OWRITER : kc::HashDB::OREADER;
if (!db.open(path, omode | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
char* vbuf;
size_t vsiz;
if (rm) {
vbuf = db.seize(kbuf, ksiz, &vsiz);
} else {
vbuf = db.get(kbuf, ksiz, &vsiz);
}
if (vbuf) {
printdata(vbuf, vsiz, px);
if (!pz) oprintf("\n");
delete[] vbuf;
} else {
dberrprint(&db, "DB::get failed");
err = true;
}
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform list command
static int32_t proclist(const char* path, const char*kbuf, size_t ksiz, int32_t oflags,
int64_t max, bool rm, bool pv, bool px) {
kc::HashDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
uint32_t omode = rm ? kc::HashDB::OWRITER : kc::HashDB::OREADER;
if (!db.open(path, omode | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
class VisitorImpl : public kc::DB::Visitor {
public:
explicit VisitorImpl(bool rm, bool pv, bool px) : rm_(rm), pv_(pv), px_(px) {}
private:
const char* visit_full(const char* kbuf, size_t ksiz,
const char* vbuf, size_t vsiz, size_t* sp) {
printdata(kbuf, ksiz, px_);
if (pv_) {
oprintf("\t");
printdata(vbuf, vsiz, px_);
}
oprintf("\n");
return rm_ ? REMOVE : NOP;
}
bool rm_;
bool pv_;
bool px_;
} visitor(rm, pv, px);
if (kbuf || max >= 0) {
if (max < 0) max = kc::INT64MAX;
kc::HashDB::Cursor cur(&db);
if (kbuf) {
if (!cur.jump(kbuf, ksiz) && db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, "Cursor::jump failed");
err = true;
}
} else {
if (!cur.jump() && db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, "Cursor::jump failed");
err = true;
}
}
while (!err && max > 0) {
if (!cur.accept(&visitor, rm, true)) {
if (db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, "Cursor::accept failed");
err = true;
}
break;
}
max--;
}
} else {
if (!db.iterate(&visitor, rm)) {
dberrprint(&db, "DB::iterate failed");
err = true;
}
}
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform clear command
static int32_t procclear(const char* path, int32_t oflags) {
kc::HashDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::HashDB::OWRITER | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
if (!db.clear()) {
dberrprint(&db, "DB::clear failed");
err = true;
}
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform import command
static int32_t procimport(const char* path, const char* file, int32_t oflags, bool sx) {
std::istream *is = &std::cin;
std::ifstream ifs;
if (file) {
ifs.open(file, std::ios_base::in | std::ios_base::binary);
if (!ifs) {
eprintf("%s: %s: open error\n", g_progname, file);
return 1;
}
is = &ifs;
}
kc::HashDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::HashDB::OWRITER | kc::HashDB::OCREATE | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
int64_t cnt = 0;
std::string line;
std::vector fields;
while (!err && mygetline(is, &line)) {
cnt++;
kc::strsplit(line, '\t', &fields);
if (sx) {
std::vector::iterator it = fields.begin();
std::vector::iterator itend = fields.end();
while (it != itend) {
size_t esiz;
char* ebuf = kc::hexdecode(it->c_str(), &esiz);
it->clear();
it->append(ebuf, esiz);
delete[] ebuf;
++it;
}
}
switch (fields.size()) {
case 2: {
if (!db.set(fields[0], fields[1])) {
dberrprint(&db, "DB::set failed");
err = true;
}
break;
}
case 1: {
if (!db.remove(fields[0]) && db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, "DB::remove failed");
err = true;
}
break;
}
}
oputchar('.');
if (cnt % 50 == 0) oprintf(" (%lld)\n", (long long)cnt);
}
if (cnt % 50 > 0) oprintf(" (%lld)\n", (long long)cnt);
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform copy command
static int32_t proccopy(const char* path, const char* file, int32_t oflags) {
kc::HashDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::HashDB::OREADER | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
DotChecker checker(&std::cout, -100);
if (!db.copy(file, &checker)) {
dberrprint(&db, "DB::copy failed");
err = true;
}
oprintf(" (end)\n");
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
if (!err) oprintf("%lld blocks were copied successfully\n", (long long)checker.count());
return err ? 1 : 0;
}
// perform dump command
static int32_t procdump(const char* path, const char* file, int32_t oflags) {
kc::HashDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::HashDB::OREADER | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
if (file) {
DotChecker checker(&std::cout, 1000);
if (!db.dump_snapshot(file)) {
dberrprint(&db, "DB::dump_snapshot");
err = true;
}
oprintf(" (end)\n");
if (!err) oprintf("%lld records were dumped successfully\n", (long long)checker.count());
} else {
if (!db.dump_snapshot(&std::cout)) {
dberrprint(&db, "DB::dump_snapshot");
err = true;
}
}
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform load command
static int32_t procload(const char* path, const char* file, int32_t oflags) {
kc::HashDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::HashDB::OWRITER | kc::HashDB::OCREATE | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
if (file) {
DotChecker checker(&std::cout, -1000);
if (!db.load_snapshot(file)) {
dberrprint(&db, "DB::load_snapshot");
err = true;
}
oprintf(" (end)\n");
if (!err) oprintf("%lld records were loaded successfully\n", (long long)checker.count());
} else {
DotChecker checker(&std::cout, -1000);
if (!db.load_snapshot(&std::cin)) {
dberrprint(&db, "DB::load_snapshot");
err = true;
}
oprintf(" (end)\n");
if (!err) oprintf("%lld records were loaded successfully\n", (long long)checker.count());
}
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform defrag command
static int32_t procdefrag(const char* path, int32_t oflags) {
kc::HashDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::HashDB::OWRITER | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
if (!db.defrag(0)) {
dberrprint(&db, "DB::defrag failed");
err = true;
}
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform setbulk command
static int32_t procsetbulk(const char* path, int32_t oflags,
const std::map& recs) {
kc::HashDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::HashDB::OWRITER | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
if (db.set_bulk(recs) != (int64_t)recs.size()) {
dberrprint(&db, "DB::set_bulk failed");
err = true;
}
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform removebulk command
static int32_t procremovebulk(const char* path, int32_t oflags,
const std::vector& keys) {
kc::HashDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::HashDB::OWRITER | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
if (db.remove_bulk(keys) < 0) {
dberrprint(&db, "DB::remove_bulk failed");
err = true;
}
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform getbulk command
static int32_t procgetbulk(const char* path, int32_t oflags,
const std::vector& keys, bool px) {
kc::HashDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::HashDB::OREADER | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
std::map recs;
if (db.get_bulk(keys, &recs) >= 0) {
std::map::iterator it = recs.begin();
std::map::iterator itend = recs.end();
while (it != itend) {
printdata(it->first.data(), it->first.size(), px);
oprintf("\t");
printdata(it->second.data(), it->second.size(), px);
oprintf("\n");
++it;
}
} else {
dberrprint(&db, "DB::get_bulk failed");
err = true;
}
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
return err ? 1 : 0;
}
// perform check command
static int32_t proccheck(const char* path, int32_t oflags) {
kc::HashDB db;
db.tune_logger(stdlogger(g_progname, &std::cerr));
if (!db.open(path, kc::HashDB::OREADER | oflags)) {
dberrprint(&db, "DB::open failed");
return 1;
}
bool err = false;
kc::HashDB::Cursor cur(&db);
if (!cur.jump() && db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, "DB::jump failed");
err = true;
}
int64_t cnt = 0;
while (!err) {
size_t ksiz;
const char* vbuf;
size_t vsiz;
char* kbuf = cur.get(&ksiz, &vbuf, &vsiz);
if (kbuf) {
cnt++;
size_t rsiz;
char* rbuf = db.get(kbuf, ksiz, &rsiz);
if (rbuf) {
if (rsiz != vsiz || std::memcmp(rbuf, vbuf, rsiz)) {
dberrprint(&db, "DB::get failed");
err = true;
}
delete[] rbuf;
} else {
dberrprint(&db, "DB::get failed");
err = true;
}
delete[] kbuf;
if (cnt % 1000 == 0) {
oputchar('.');
if (cnt % 50000 == 0) oprintf(" (%lld)\n", (long long)cnt);
}
} else {
if (db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, "Cursor::get failed");
err = true;
}
break;
}
if (!cur.step() && db.error() != kc::BasicDB::Error::NOREC) {
dberrprint(&db, "Cursor::step failed");
err = true;
}
}
oprintf(" (end)\n");
if (db.count() != cnt) {
dberrprint(&db, "DB::count failed");
err = true;
}
kc::File::Status sbuf;
if (kc::File::status(path, &sbuf)) {
if (db.size() != sbuf.size && sbuf.size % (1 << 20) != 0) {
dberrprint(&db, "DB::size failed");
err = true;
}
} else {
dberrprint(&db, "File::status failed");
err = true;
}
if (db.flags() & kc::HashDB::FFATAL) {
dberrprint(&db, "DB::flags indicated fatal error");
err = true;
}
if (!db.close()) {
dberrprint(&db, "DB::close failed");
err = true;
}
if (!err) oprintf("%lld records were checked successfully\n", (long long)cnt);
return err ? 1 : 0;
}
// END OF FILE
kyotocabinet-1.2.80/kcutiltest.cc 0000664 0001750 0001750 00000242345 14416044124 016015 0 ustar mikio mikio /*************************************************************************************************
* The test cases of the utility functions
* Copyright (C) 2009-2012 Mikio Hirabayashi
* This file is part of Kyoto Cabinet.
* This program is free software: you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation, either version
* 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with this program.
* If not, see .
*************************************************************************************************/
#include "cmdcommon.h"
// constants
const size_t LOCKSLOTNUM = 128; // number of lock slots
const size_t FILEIOUNIT = 50; // file I/O unit size
// global variables
const char* g_progname; // program name
uint32_t g_randseed; // random seed
int64_t g_memusage; // memory usage
// function prototypes
int main(int argc, char** argv);
static void usage();
static void errprint(int32_t line, const char* format, ...);
static void fileerrprint(kc::File* file, int32_t line, const char* func);
static void filemetaprint(kc::File* file);
static int32_t runmutex(int argc, char** argv);
static int32_t runcond(int argc, char** argv);
static int32_t runpara(int argc, char** argv);
static int32_t runfile(int argc, char** argv);
static int32_t runlhmap(int argc, char** argv);
static int32_t runthmap(int argc, char** argv);
static int32_t runtalist(int argc, char** argv);
static int32_t runmisc(int argc, char** argv);
static int32_t procmutex(int64_t rnum, int32_t thnum, double iv);
static int32_t proccond(int64_t rnum, int32_t thnum, double iv);
static int32_t procpara(int64_t rnum, int32_t thnum, double iv);
static int32_t procfile(const char* path, int64_t rnum, int32_t thnum, bool rnd, int64_t msiz);
static int32_t proclhmap(int64_t rnum, bool rnd, int64_t bnum);
static int32_t procthmap(int64_t rnum, bool rnd, int64_t bnum);
static int32_t proctalist(int64_t rnum, bool rnd);
static int32_t procmisc(int64_t rnum);
// main routine
int main(int argc, char** argv) {
g_progname = argv[0];
const char* ebuf = kc::getenv("KCRNDSEED");
g_randseed = ebuf ? (uint32_t)kc::atoi(ebuf) : (uint32_t)(kc::time() * 1000);
mysrand(g_randseed);
g_memusage = memusage();
kc::setstdiobin();
if (argc < 2) usage();
int32_t rv = 0;
if (!std::strcmp(argv[1], "mutex")) {
rv = runmutex(argc, argv);
} else if (!std::strcmp(argv[1], "cond")) {
rv = runcond(argc, argv);
} else if (!std::strcmp(argv[1], "para")) {
rv = runpara(argc, argv);
} else if (!std::strcmp(argv[1], "file")) {
rv = runfile(argc, argv);
} else if (!std::strcmp(argv[1], "lhmap")) {
rv = runlhmap(argc, argv);
} else if (!std::strcmp(argv[1], "thmap")) {
rv = runthmap(argc, argv);
} else if (!std::strcmp(argv[1], "talist")) {
rv = runtalist(argc, argv);
} else if (!std::strcmp(argv[1], "misc")) {
rv = runmisc(argc, argv);
} else {
usage();
}
if (rv != 0) {
oprintf("FAILED: KCRNDSEED=%u PID=%ld", g_randseed, (long)kc::getpid());
for (int32_t i = 0; i < argc; i++) {
oprintf(" %s", argv[i]);
}
oprintf("\n\n");
}
return rv;
}
// print the usage and exit
static void usage() {
eprintf("%s: test cases of the utility functions of Kyoto Cabinet\n", g_progname);
eprintf("\n");
eprintf("usage:\n");
eprintf(" %s mutex [-th num] [-iv num] rnum\n", g_progname);
eprintf(" %s para [-th num] [-iv num] rnum\n", g_progname);
eprintf(" %s cond [-th num] [-iv num] rnum\n", g_progname);
eprintf(" %s file [-th num] [-rnd] [-msiz num] path rnum\n", g_progname);
eprintf(" %s lhmap [-rnd] [-bnum num] rnum\n", g_progname);
eprintf(" %s thmap [-rnd] [-bnum num] rnum\n", g_progname);
eprintf(" %s talist [-rnd] rnum\n", g_progname);
eprintf(" %s misc rnum\n", g_progname);
eprintf("\n");
std::exit(1);
}
// print formatted error information string and flush the buffer
static void errprint(int32_t line, const char* format, ...) {
std::string msg;
kc::strprintf(&msg, "%s: %d: ", g_progname, line);
va_list ap;
va_start(ap, format);
kc::vstrprintf(&msg, format, ap);
va_end(ap);
kc::strprintf(&msg, "\n");
std::cout << msg;
std::cout.flush();
}
// print error message of file
static void fileerrprint(kc::File* file, int32_t line, const char* func) {
oprintf("%s: %d: %s: %s: %s\n", g_progname, line, func, file->path().c_str(), file->error());
}
// print members of file
static void filemetaprint(kc::File* file) {
oprintf("size: %lld\n", (long long)file->size());
}
// parse arguments of mutex command
static int32_t runmutex(int argc, char** argv) {
bool argbrk = false;
const char* rstr = NULL;
int32_t thnum = 1;
double iv = 0.0;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-th")) {
if (++i >= argc) usage();
thnum = kc::atoix(argv[i]);
} else if (!std::strcmp(argv[i], "-iv")) {
if (++i >= argc) usage();
iv = kc::atof(argv[i]);
} else {
usage();
}
} else if (!rstr) {
argbrk = true;
rstr = argv[i];
} else {
usage();
}
}
if (!rstr) usage();
int64_t rnum = kc::atoix(rstr);
if (rnum < 1 || thnum < 1) usage();
if (thnum > THREADMAX) thnum = THREADMAX;
int32_t rv = procmutex(rnum, thnum, iv);
return rv;
}
// parse arguments of cond command
static int32_t runcond(int argc, char** argv) {
bool argbrk = false;
const char* rstr = NULL;
int32_t thnum = 1;
double iv = 0.0;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-th")) {
if (++i >= argc) usage();
thnum = kc::atoix(argv[i]);
} else if (!std::strcmp(argv[i], "-iv")) {
if (++i >= argc) usage();
iv = kc::atof(argv[i]);
} else {
usage();
}
} else if (!rstr) {
argbrk = true;
rstr = argv[i];
} else {
usage();
}
}
if (!rstr) usage();
int64_t rnum = kc::atoix(rstr);
if (rnum < 1 || thnum < 1) usage();
if (thnum > THREADMAX) thnum = THREADMAX;
int32_t rv = proccond(rnum, thnum, iv);
return rv;
}
// parse arguments of para command
static int32_t runpara(int argc, char** argv) {
bool argbrk = false;
const char* rstr = NULL;
int32_t thnum = 1;
double iv = 0.0;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-th")) {
if (++i >= argc) usage();
thnum = kc::atoix(argv[i]);
} else if (!std::strcmp(argv[i], "-iv")) {
if (++i >= argc) usage();
iv = kc::atof(argv[i]);
} else {
usage();
}
} else if (!rstr) {
argbrk = true;
rstr = argv[i];
} else {
usage();
}
}
if (!rstr) usage();
int64_t rnum = kc::atoix(rstr);
if (rnum < 1 || thnum < 1) usage();
if (thnum > THREADMAX) thnum = THREADMAX;
int32_t rv = procpara(rnum, thnum, iv);
return rv;
}
// parse arguments of file command
static int32_t runfile(int argc, char** argv) {
bool argbrk = false;
const char* path = NULL;
const char* rstr = NULL;
int32_t thnum = 1;
bool rnd = false;
int64_t msiz = 0;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-th")) {
if (++i >= argc) usage();
thnum = kc::atoix(argv[i]);
} else if (!std::strcmp(argv[i], "-rnd")) {
rnd = true;
} else if (!std::strcmp(argv[i], "-msiz")) {
if (++i >= argc) usage();
msiz = kc::atoix(argv[i]);
} else {
usage();
}
} else if (!path) {
argbrk = true;
path = argv[i];
} else if (!rstr) {
rstr = argv[i];
} else {
usage();
}
}
if (!path || !rstr) usage();
int64_t rnum = kc::atoix(rstr);
if (rnum < 1 || thnum < 1 || msiz < 0) usage();
if (thnum > THREADMAX) thnum = THREADMAX;
int32_t rv = procfile(path, rnum, thnum, rnd, msiz);
return rv;
}
// parse arguments of lhmap command
static int32_t runlhmap(int argc, char** argv) {
bool argbrk = false;
const char* rstr = NULL;
bool rnd = false;
int64_t bnum = -1;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-rnd")) {
rnd = true;
} else if (!std::strcmp(argv[i], "-bnum")) {
if (++i >= argc) usage();
bnum = kc::atoix(argv[i]);
} else {
usage();
}
} else if (!rstr) {
argbrk = true;
rstr = argv[i];
} else {
usage();
}
}
if (!rstr) usage();
int64_t rnum = kc::atoix(rstr);
if (rnum < 1) usage();
int32_t rv = proclhmap(rnum, rnd, bnum);
return rv;
}
// parse arguments of thmap command
static int32_t runthmap(int argc, char** argv) {
bool argbrk = false;
const char* rstr = NULL;
bool rnd = false;
int64_t bnum = -1;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-rnd")) {
rnd = true;
} else if (!std::strcmp(argv[i], "-bnum")) {
if (++i >= argc) usage();
bnum = kc::atoix(argv[i]);
} else {
usage();
}
} else if (!rstr) {
argbrk = true;
rstr = argv[i];
} else {
usage();
}
}
if (!rstr) usage();
int64_t rnum = kc::atoix(rstr);
if (rnum < 1) usage();
int32_t rv = procthmap(rnum, rnd, bnum);
return rv;
}
// parse arguments of talist command
static int32_t runtalist(int argc, char** argv) {
bool argbrk = false;
const char* rstr = NULL;
bool rnd = false;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else if (!std::strcmp(argv[i], "-rnd")) {
rnd = true;
} else {
usage();
}
} else if (!rstr) {
argbrk = true;
rstr = argv[i];
} else {
usage();
}
}
if (!rstr) usage();
int64_t rnum = kc::atoix(rstr);
if (rnum < 1) usage();
int32_t rv = proctalist(rnum, rnd);
return rv;
}
// parse arguments of misc command
static int32_t runmisc(int argc, char** argv) {
bool argbrk = false;
const char* rstr = NULL;
for (int32_t i = 2; i < argc; i++) {
if (!argbrk && argv[i][0] == '-') {
if (!std::strcmp(argv[i], "--")) {
argbrk = true;
} else usage();
} else if (!rstr) {
argbrk = true;
rstr = argv[i];
} else {
usage();
}
}
if (!rstr) usage();
int64_t rnum = kc::atoix(rstr);
if (rnum < 1) usage();
int32_t rv = procmisc(rnum);
return rv;
}
// perform mutex command
static int32_t procmutex(int64_t rnum, int32_t thnum, double iv) {
oprintf("\n seed=%u rnum=%lld thnum=%d iv=%.3f\n\n",
g_randseed, (long long)rnum, thnum, iv);
bool err = false;
kc::Mutex mutex;
oprintf("mutex:\n");
double stime = kc::time();
class ThreadMutex : public kc::Thread {
public:
void setparams(int32_t id, kc::Mutex* mutex, int64_t rnum, int32_t thnum, double iv) {
id_ = id;
mutex_ = mutex;
rnum_ = rnum;
thnum_ = thnum;
iv_ = iv;
}
void run() {
for (int64_t i = 1; i <= rnum_; i++) {
mutex_->lock();
if (iv_ > 0) {
sleep(iv_);
} else if (iv_ < 0) {
yield();
}
mutex_->unlock();
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::Mutex* mutex_;
int64_t rnum_;
int32_t thnum_;
double iv_;
};
ThreadMutex threadmutexs[THREADMAX];
if (thnum < 2) {
threadmutexs[0].setparams(0, &mutex, rnum, thnum, iv);
threadmutexs[0].run();
} else {
for (int32_t i = 0; i < thnum; i++) {
threadmutexs[i].setparams(i, &mutex, rnum, thnum, iv);
threadmutexs[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadmutexs[i].join();
}
}
double etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
kc::SlottedMutex smutex(LOCKSLOTNUM);
oprintf("slotted mutex:\n");
stime = kc::time();
class ThreadSlottedMutex : public kc::Thread {
public:
void setparams(int32_t id, kc::SlottedMutex* smutex,
int64_t rnum, int32_t thnum, double iv) {
id_ = id;
smutex_ = smutex;
rnum_ = rnum;
thnum_ = thnum;
iv_ = iv;
}
void run() {
for (int64_t i = 1; i <= rnum_; i++) {
size_t idx = i % LOCKSLOTNUM;
smutex_->lock(idx);
if (iv_ > 0) {
sleep(iv_);
} else if (iv_ < 0) {
yield();
}
smutex_->unlock(idx);
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::SlottedMutex* smutex_;
int64_t rnum_;
int32_t thnum_;
double iv_;
};
ThreadSlottedMutex threadsmutexs[THREADMAX];
if (thnum < 2) {
threadsmutexs[0].setparams(0, &smutex, rnum, thnum, iv);
threadsmutexs[0].run();
} else {
for (int32_t i = 0; i < thnum; i++) {
threadsmutexs[i].setparams(i, &smutex, rnum, thnum, iv);
threadsmutexs[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadsmutexs[i].join();
}
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
kc::SpinLock spinlock;
oprintf("spin lock:\n");
stime = kc::time();
class ThreadSpinLock : public kc::Thread {
public:
void setparams(int32_t id, kc::SpinLock* spinlock, int64_t rnum, int32_t thnum, double iv) {
id_ = id;
spinlock_ = spinlock;
rnum_ = rnum;
thnum_ = thnum;
iv_ = iv;
}
void run() {
for (int64_t i = 1; i <= rnum_; i++) {
spinlock_->lock();
if (iv_ > 0) {
sleep(iv_);
} else if (iv_ < 0) {
yield();
}
spinlock_->unlock();
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::SpinLock* spinlock_;
int64_t rnum_;
int32_t thnum_;
double iv_;
};
ThreadSpinLock threadspins[THREADMAX];
if (thnum < 2) {
threadspins[0].setparams(0, &spinlock, rnum, thnum, iv);
threadspins[0].run();
} else {
for (int32_t i = 0; i < thnum; i++) {
threadspins[i].setparams(i, &spinlock, rnum, thnum, iv);
threadspins[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadspins[i].join();
}
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
kc::SlottedSpinLock sspinlock(LOCKSLOTNUM);
oprintf("slotted spin lock:\n");
stime = kc::time();
class ThreadSlottedSpinLock : public kc::Thread {
public:
void setparams(int32_t id, kc::SlottedSpinLock* sspinlock,
int64_t rnum, int32_t thnum, double iv) {
id_ = id;
sspinlock_ = sspinlock;
rnum_ = rnum;
thnum_ = thnum;
iv_ = iv;
}
void run() {
for (int64_t i = 1; i <= rnum_; i++) {
size_t idx = i % LOCKSLOTNUM;
sspinlock_->lock(idx);
if (iv_ > 0) {
sleep(iv_);
} else if (iv_ < 0) {
yield();
}
sspinlock_->unlock(idx);
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::SlottedSpinLock* sspinlock_;
int64_t rnum_;
int32_t thnum_;
double iv_;
};
ThreadSlottedSpinLock threadsspinlocks[THREADMAX];
if (thnum < 2) {
threadsspinlocks[0].setparams(0, &sspinlock, rnum, thnum, iv);
threadsspinlocks[0].run();
} else {
for (int32_t i = 0; i < thnum; i++) {
threadsspinlocks[i].setparams(i, &sspinlock, rnum, thnum, iv);
threadsspinlocks[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadsspinlocks[i].join();
}
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
kc::RWLock rwlock;
oprintf("reader-writer lock writer:\n");
stime = kc::time();
class ThreadRWLockWriter : public kc::Thread {
public:
void setparams(int32_t id, kc::RWLock* rwlock, int64_t rnum, int32_t thnum, double iv) {
id_ = id;
rwlock_ = rwlock;
rnum_ = rnum;
thnum_ = thnum;
iv_ = iv;
}
void run() {
for (int64_t i = 1; i <= rnum_; i++) {
rwlock_->lock_writer();
if (iv_ > 0) {
sleep(iv_);
} else if (iv_ < 0) {
yield();
}
rwlock_->unlock();
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::RWLock* rwlock_;
int64_t rnum_;
int32_t thnum_;
double iv_;
};
ThreadRWLockWriter threadrwlockwriters[THREADMAX];
if (thnum < 2) {
threadrwlockwriters[0].setparams(0, &rwlock, rnum, thnum, iv);
threadrwlockwriters[0].run();
} else {
for (int32_t i = 0; i < thnum; i++) {
threadrwlockwriters[i].setparams(i, &rwlock, rnum, thnum, iv);
threadrwlockwriters[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadrwlockwriters[i].join();
}
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("reader-writer lock reader:\n");
stime = kc::time();
class ThreadRWLockReader : public kc::Thread {
public:
void setparams(int32_t id, kc::RWLock* rwlock, int64_t rnum, int32_t thnum, double iv) {
id_ = id;
rwlock_ = rwlock;
rnum_ = rnum;
thnum_ = thnum;
iv_ = iv;
}
void run() {
for (int64_t i = 1; i <= rnum_; i++) {
rwlock_->lock_reader();
if (iv_ > 0) {
sleep(iv_);
} else if (iv_ < 0) {
yield();
}
rwlock_->unlock();
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::RWLock* rwlock_;
int64_t rnum_;
int32_t thnum_;
double iv_;
};
ThreadRWLockReader threadrwlockreaders[THREADMAX];
if (thnum < 2) {
threadrwlockreaders[0].setparams(0, &rwlock, rnum, thnum, iv);
threadrwlockreaders[0].run();
} else {
for (int32_t i = 0; i < thnum; i++) {
threadrwlockreaders[i].setparams(i, &rwlock, rnum, thnum, iv);
threadrwlockreaders[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadrwlockreaders[i].join();
}
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
kc::SlottedRWLock srwlock(LOCKSLOTNUM);
oprintf("slotted reader-writer lock writer:\n");
stime = kc::time();
class ThreadSlottedRWLockWriter : public kc::Thread {
public:
void setparams(int32_t id, kc::SlottedRWLock* srwlock,
int64_t rnum, int32_t thnum, double iv) {
id_ = id;
srwlock_ = srwlock;
rnum_ = rnum;
thnum_ = thnum;
iv_ = iv;
}
void run() {
for (int64_t i = 1; i <= rnum_; i++) {
size_t idx = i % LOCKSLOTNUM;
srwlock_->lock_writer(idx);
if (iv_ > 0) {
sleep(iv_);
} else if (iv_ < 0) {
yield();
}
srwlock_->unlock(idx);
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::SlottedRWLock* srwlock_;
int64_t rnum_;
int32_t thnum_;
double iv_;
};
ThreadSlottedRWLockWriter threadsrwlockwriters[THREADMAX];
if (thnum < 2) {
threadsrwlockwriters[0].setparams(0, &srwlock, rnum, thnum, iv);
threadsrwlockwriters[0].run();
} else {
for (int32_t i = 0; i < thnum; i++) {
threadsrwlockwriters[i].setparams(i, &srwlock, rnum, thnum, iv);
threadsrwlockwriters[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadsrwlockwriters[i].join();
}
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("slotted reader-writer lock reader:\n");
stime = kc::time();
class ThreadSlottedRWLockReader : public kc::Thread {
public:
void setparams(int32_t id, kc::SlottedRWLock* srwlock,
int64_t rnum, int32_t thnum, double iv) {
id_ = id;
srwlock_ = srwlock;
rnum_ = rnum;
thnum_ = thnum;
iv_ = iv;
}
void run() {
for (int64_t i = 1; i <= rnum_; i++) {
size_t idx = i % LOCKSLOTNUM;
srwlock_->lock_reader(idx);
if (iv_ > 0) {
sleep(iv_);
} else if (iv_ < 0) {
yield();
}
srwlock_->unlock(idx);
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::SlottedRWLock* srwlock_;
int64_t rnum_;
int32_t thnum_;
double iv_;
};
ThreadSlottedRWLockReader threadsrwlockreaders[THREADMAX];
if (thnum < 2) {
threadsrwlockreaders[0].setparams(0, &srwlock, rnum, thnum, iv);
threadsrwlockreaders[0].run();
} else {
for (int32_t i = 0; i < thnum; i++) {
threadsrwlockreaders[i].setparams(i, &srwlock, rnum, thnum, iv);
threadsrwlockreaders[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadsrwlockreaders[i].join();
}
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
kc::SpinRWLock spinrwlock;
oprintf("spin reader-writer lock writer:\n");
stime = kc::time();
class ThreadSpinRWLockWriter : public kc::Thread {
public:
void setparams(int32_t id, kc::SpinRWLock* spinrwlock,
int64_t rnum, int32_t thnum, double iv) {
id_ = id;
spinrwlock_ = spinrwlock;
rnum_ = rnum;
thnum_ = thnum;
iv_ = iv;
}
void run() {
for (int64_t i = 1; i <= rnum_; i++) {
spinrwlock_->lock_writer();
if (iv_ > 0) {
sleep(iv_);
} else if (iv_ < 0) {
yield();
}
spinrwlock_->unlock();
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::SpinRWLock* spinrwlock_;
int64_t rnum_;
int32_t thnum_;
double iv_;
};
ThreadSpinRWLockWriter threadspinrwlockwriters[THREADMAX];
if (thnum < 2) {
threadspinrwlockwriters[0].setparams(0, &spinrwlock, rnum, thnum, iv);
threadspinrwlockwriters[0].run();
} else {
for (int32_t i = 0; i < thnum; i++) {
threadspinrwlockwriters[i].setparams(i, &spinrwlock, rnum, thnum, iv);
threadspinrwlockwriters[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadspinrwlockwriters[i].join();
}
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("spin reader-writer lock reader:\n");
stime = kc::time();
class ThreadSpinRWLockReader : public kc::Thread {
public:
void setparams(int32_t id, kc::SpinRWLock* spinrwlock,
int64_t rnum, int32_t thnum, double iv) {
id_ = id;
spinrwlock_ = spinrwlock;
rnum_ = rnum;
thnum_ = thnum;
iv_ = iv;
}
void run() {
for (int64_t i = 1; i <= rnum_; i++) {
spinrwlock_->lock_reader();
if (iv_ > 0) {
sleep(iv_);
} else if (iv_ < 0) {
yield();
}
spinrwlock_->unlock();
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::SpinRWLock* spinrwlock_;
int64_t rnum_;
int32_t thnum_;
double iv_;
};
ThreadSpinRWLockReader threadspinrwlockreaders[THREADMAX];
if (thnum < 2) {
threadspinrwlockreaders[0].setparams(0, &spinrwlock, rnum, thnum, iv);
threadspinrwlockreaders[0].run();
} else {
for (int32_t i = 0; i < thnum; i++) {
threadspinrwlockreaders[i].setparams(i, &spinrwlock, rnum, thnum, iv);
threadspinrwlockreaders[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadspinrwlockreaders[i].join();
}
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("spin reader-writer lock wicked:\n");
stime = kc::time();
class ThreadSpinRWLockWicked : public kc::Thread {
public:
void setparams(int32_t id, kc::SpinRWLock* spinrwlock,
int64_t rnum, int32_t thnum, double iv) {
id_ = id;
spinrwlock_ = spinrwlock;
rnum_ = rnum;
thnum_ = thnum;
iv_ = iv;
}
void run() {
for (int64_t i = 1; i <= rnum_; i++) {
if (i % 4 == 0) {
spinrwlock_->lock_writer();
if (i % 16 == 0) {
if (iv_ > 0) {
sleep(iv_);
} else if (iv_ < 0) {
yield();
}
spinrwlock_->demote();
}
} else {
spinrwlock_->lock_reader();
if (i % 7 == 0) {
if (iv_ > 0) {
sleep(iv_);
} else if (iv_ < 0) {
yield();
}
spinrwlock_->promote();
}
}
if (iv_ > 0) {
sleep(iv_);
} else if (iv_ < 0) {
yield();
}
spinrwlock_->unlock();
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::SpinRWLock* spinrwlock_;
int64_t rnum_;
int32_t thnum_;
double iv_;
};
ThreadSpinRWLockWicked threadspinrwlockwickeds[THREADMAX];
if (thnum < 2) {
threadspinrwlockwickeds[0].setparams(0, &spinrwlock, rnum, thnum, iv);
threadspinrwlockwickeds[0].run();
} else {
for (int32_t i = 0; i < thnum; i++) {
threadspinrwlockwickeds[i].setparams(i, &spinrwlock, rnum, thnum, iv);
threadspinrwlockwickeds[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadspinrwlockwickeds[i].join();
}
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
kc::SlottedSpinRWLock ssrwlock(LOCKSLOTNUM);
oprintf("slotted spin reader-writer lock writer:\n");
stime = kc::time();
class ThreadSlottedSpinRWLockWriter : public kc::Thread {
public:
void setparams(int32_t id, kc::SlottedSpinRWLock* ssrwlock,
int64_t rnum, int32_t thnum, double iv) {
id_ = id;
ssrwlock_ = ssrwlock;
rnum_ = rnum;
thnum_ = thnum;
iv_ = iv;
}
void run() {
for (int64_t i = 1; i <= rnum_; i++) {
size_t idx = i % LOCKSLOTNUM;
ssrwlock_->lock_writer(idx);
if (iv_ > 0) {
sleep(iv_);
} else if (iv_ < 0) {
yield();
}
ssrwlock_->unlock(idx);
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::SlottedSpinRWLock* ssrwlock_;
int64_t rnum_;
int32_t thnum_;
double iv_;
};
ThreadSlottedSpinRWLockWriter threadssrwlockwriters[THREADMAX];
if (thnum < 2) {
threadssrwlockwriters[0].setparams(0, &ssrwlock, rnum, thnum, iv);
threadssrwlockwriters[0].run();
} else {
for (int32_t i = 0; i < thnum; i++) {
threadssrwlockwriters[i].setparams(i, &ssrwlock, rnum, thnum, iv);
threadssrwlockwriters[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadssrwlockwriters[i].join();
}
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("slotted spin reader-writer lock reader:\n");
stime = kc::time();
class ThreadSlottedSpinRWLockReader : public kc::Thread {
public:
void setparams(int32_t id, kc::SlottedSpinRWLock* ssrwlock,
int64_t rnum, int32_t thnum, double iv) {
id_ = id;
ssrwlock_ = ssrwlock;
rnum_ = rnum;
thnum_ = thnum;
iv_ = iv;
}
void run() {
for (int64_t i = 1; i <= rnum_; i++) {
size_t idx = i % LOCKSLOTNUM;
ssrwlock_->lock_reader(idx);
if (iv_ > 0) {
sleep(iv_);
} else if (iv_ < 0) {
yield();
}
ssrwlock_->unlock(idx);
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::SlottedSpinRWLock* ssrwlock_;
int64_t rnum_;
int32_t thnum_;
double iv_;
};
ThreadSlottedSpinRWLockReader threadssrwlockreaders[THREADMAX];
if (thnum < 2) {
threadssrwlockreaders[0].setparams(0, &ssrwlock, rnum, thnum, iv);
threadssrwlockreaders[0].run();
} else {
for (int32_t i = 0; i < thnum; i++) {
threadssrwlockreaders[i].setparams(i, &ssrwlock, rnum, thnum, iv);
threadssrwlockreaders[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadssrwlockreaders[i].join();
}
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("atomic increment:\n");
stime = kc::time();
kc::AtomicInt64 anum;
anum = rnum * thnum;
class ThreadAtomic : public kc::Thread {
public:
void setparams(int32_t id, kc::AtomicInt64* anum, int64_t rnum, int32_t thnum, double iv) {
id_ = id;
anum_ = anum;
rnum_ = rnum;
thnum_ = thnum;
iv_ = iv;
}
void run() {
for (int64_t i = 1; i <= rnum_; i++) {
anum_->add(1);
*anum_ += 1;
*anum_ -= 1;
while (true) {
int64_t num = anum_->get();
if (iv_ > 0) {
sleep(iv_);
} else if (iv_ < 0) {
yield();
}
if (anum_->cas(num, num + 1)) break;
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::AtomicInt64* anum_;
int64_t rnum_;
int32_t thnum_;
double iv_;
};
ThreadAtomic threadatomic[THREADMAX];
if (thnum < 2) {
threadatomic[0].setparams(0, &anum, rnum, thnum, iv);
threadatomic[0].run();
} else {
for (int32_t i = 0; i < thnum; i++) {
threadatomic[i].setparams(i, &anum, rnum, thnum, iv);
threadatomic[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadatomic[i].join();
}
}
if (anum.get() != rnum * thnum * 3) {
errprint(__LINE__, "AtomicInt64::get: %lld", (long long)anum.get());
err = true;
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("%s\n\n", err ? "error" : "ok");
return err ? 1 : 0;
}
// perform cond command
static int32_t proccond(int64_t rnum, int32_t thnum, double iv) {
oprintf("\n seed=%u rnum=%lld thnum=%d iv=%.3f\n\n",
g_randseed, (long long)rnum, thnum, iv);
bool err = false;
kc::Mutex mutex;
kc::CondVar cond;
oprintf("conditon variable:\n");
double stime = kc::time();
class ThreadCondVar : public kc::Thread {
public:
void setparams(int32_t id, kc::Mutex* mutex, kc::CondVar* cond,
int64_t rnum, int32_t thnum, double iv) {
id_ = id;
mutex_ = mutex;
cond_ = cond;
rnum_ = rnum;
thnum_ = thnum;
iv_ = iv;
active_ = 1;
}
bool active() {
return active_ > 0;
}
void run() {
for (int64_t i = 1; i <= rnum_; i++) {
mutex_->lock();
if (i % 2 < 1) {
if (iv_ > 0) {
sleep(iv_);
} else if (iv_ < 0) {
yield();
}
}
if (i % 7 == 0) {
cond_->wait(mutex_, 0.001);
} else {
cond_->wait(mutex_);
}
mutex_->unlock();
if (i % 2 > 0) {
if (iv_ > 0) {
sleep(iv_);
} else if (iv_ < 0) {
yield();
}
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
active_ = 0;
}
private:
int32_t id_;
kc::Mutex* mutex_;
kc::CondVar* cond_;
int64_t rnum_;
int32_t thnum_;
double iv_;
kc::AtomicInt64 active_;
};
ThreadCondVar threadcondvars[THREADMAX];
for (int32_t i = 0; i < thnum; i++) {
threadcondvars[i].setparams(i, &mutex, &cond, rnum, thnum, iv);
threadcondvars[i].start();
}
int64_t cnt = 0;
while (true) {
if (iv > 0) {
kc::Thread::sleep(iv);
} else if (iv < 0) {
kc::Thread::yield();
}
int32_t actnum = 0;
for (int32_t i = 0; i < thnum; i++) {
if (threadcondvars[i].active()) actnum++;
bool lock = (cnt + i) % 5 == 0;
if (lock) mutex.lock();
if (cnt % (thnum + 1) < 1) {
cond.broadcast();
} else {
cond.signal();
}
if (lock) mutex.unlock();
}
if (actnum < 1) break;
cnt++;
}
for (int32_t i = 0; i < thnum; i++) {
threadcondvars[i].join();
}
double etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
kc::CondMap cmap;
oprintf("conditon map:\n");
stime = kc::time();
class ThreadCondMap : public kc::Thread {
public:
void setparams(int32_t id, kc::CondMap* cmap, int64_t rnum, int32_t thnum, double iv) {
id_ = id;
cmap_ = cmap;
rnum_ = rnum;
thnum_ = thnum;
iv_ = iv;
active_ = 1;
}
bool active() {
return active_ > 0;
}
void run() {
for (int64_t i = 1; i <= rnum_; i++) {
if (iv_ > 0) {
sleep(iv_);
} else if (iv_ < 0) {
yield();
}
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08d", (int)(i % thnum_));
cmap_->wait(kbuf, ksiz, 0.001);
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
active_ = 0;
}
private:
int32_t id_;
kc::CondMap* cmap_;
int64_t rnum_;
int32_t thnum_;
double iv_;
kc::AtomicInt64 active_;
};
ThreadCondMap threadcondmaps[THREADMAX];
for (int32_t i = 0; i < thnum; i++) {
threadcondmaps[i].setparams(i, &cmap, rnum, thnum, iv);
threadcondmaps[i].start();
}
cnt = 0;
while (true) {
if (iv > 0) {
kc::Thread::sleep(iv);
} else if (iv < 0) {
kc::Thread::yield();
}
int32_t actnum = 0;
for (int32_t i = 0; i < thnum; i++) {
if (threadcondmaps[i].active()) actnum++;
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08d", (int)i);
bool lock = (cnt + i) % 5 == 0;
if (lock) mutex.lock();
if (cnt % (thnum + 1) < 1) {
cmap.broadcast(kbuf, ksiz);
} else {
cmap.signal(kbuf, ksiz);
}
if (lock) mutex.unlock();
}
if (cnt % 1024 < 1) cmap.broadcast_all();
if (actnum < 1) break;
cnt++;
}
for (int32_t i = 0; i < thnum; i++) {
threadcondmaps[i].join();
}
if (cmap.count() != 0) {
errprint(__LINE__, "CondMap::count");
err = true;
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("%s\n\n", err ? "error" : "ok");
return err ? 1 : 0;
}
// perform para command
static int32_t procpara(int64_t rnum, int32_t thnum, double iv) {
oprintf("\n seed=%u rnum=%lld thnum=%d iv=%.3f\n\n",
g_randseed, (long long)rnum, thnum, iv);
bool err = false;
double stime = kc::time();
class TaskQueueImpl : public kc::TaskQueue {
public:
void setparams(int32_t thnum, double iv) {
thnum_ = thnum;
iv_ = iv;
cnt_ = 0;
}
void do_task(kc::TaskQueue::Task* task) {
cnt_ += 1;
if (iv_ > 0) {
kc::Thread::sleep(iv_ * thnum_);
} else if (iv_ < 0) {
kc::Thread::yield();
}
delete task;
}
int64_t done_count() {
return cnt_;
}
private:
int32_t thnum_;
double iv_;
kc::AtomicInt64 cnt_;
};
TaskQueueImpl queue;
queue.setparams(thnum, iv);
queue.start(thnum);
for (int64_t i = 1; i <= rnum; i++) {
kc::TaskQueue::Task* task = new kc::TaskQueue::Task;
queue.add_task(task);
if (iv > 0) {
kc::Thread::sleep(iv);
} else if (iv < 0) {
kc::Thread::yield();
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
oprintf("count: %lld\n", queue.count());
oprintf("done: %lld\n", queue.done_count());
queue.finish();
if (queue.count() != 0) {
errprint(__LINE__, "TaskQueue::count");
err = true;
}
if (queue.done_count() != rnum) {
errprint(__LINE__, "TaskQueueImpl::done_count");
err = true;
}
double etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
int64_t musage = memusage();
if (musage > 0) oprintf("memory: %lld\n", (long long)(musage - g_memusage));
oprintf("%s\n\n", err ? "error" : "ok");
return err ? 1 : 0;
}
// perform file command
static int32_t procfile(const char* path, int64_t rnum, int32_t thnum, bool rnd, int64_t msiz) {
oprintf("\n seed=%u path=%s rnum=%lld thnum=%d rnd=%d msiz=%lld\n\n",
g_randseed, path, (long long)rnum, thnum, rnd, (long long)msiz);
bool err = false;
kc::File file;
oprintf("opening the file:\n");
double stime = kc::time();
if (!file.open(path, kc::File::OWRITER | kc::File::OCREATE | kc::File::OTRUNCATE, msiz)) {
fileerrprint(&file, __LINE__, "File::open");
err = true;
}
double etime = kc::time();
filemetaprint(&file);
oprintf("time: %.3f\n", etime - stime);
oprintf("writing:\n");
class ThreadWrite : public kc::Thread {
public:
void setparams(int32_t id, kc::File* file, int64_t rnum, int32_t thnum, bool rnd) {
id_ = id;
file_ = file;
rnum_ = rnum;
thnum_ = thnum;
rnd_ = rnd;
err_ = false;
}
bool error() {
return err_;
}
void run() {
int64_t base = id_ * rnum_;
int64_t range = rnum_ * thnum_;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
if (rnd_ && myrand(2) == 0) {
char rbuf[RECBUFSIZ];
size_t rsiz = myrand(FILEIOUNIT);
if (rsiz > 0) std::memset(rbuf, '*', rsiz);
if (!file_->append(rbuf, rsiz)) {
fileerrprint(file_, __LINE__, "File::append");
err_ = true;
}
} else {
int64_t num = rnd_ ? myrand(range) : base + i - 1;
int64_t off = num * FILEIOUNIT;
char rbuf[RECBUFSIZ];
size_t rsiz = std::sprintf(rbuf, "[%048lld]", (long long)num);
if (!file_->write(off, rbuf, rsiz)) {
fileerrprint(file_, __LINE__, "File::write");
err_ = true;
}
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::File* file_;
int64_t rnum_;
int32_t thnum_;
bool rnd_;
bool err_;
};
ThreadWrite threadwrites[THREADMAX];
if (thnum < 2) {
threadwrites[0].setparams(0, &file, rnum, thnum, rnd);
threadwrites[0].run();
if (threadwrites[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threadwrites[i].setparams(i, &file, rnum, thnum, rnd);
threadwrites[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadwrites[i].join();
if (threadwrites[i].error()) err = true;
}
}
etime = kc::time();
filemetaprint(&file);
oprintf("time: %.3f\n", etime - stime);
oprintf("reading:\n");
stime = kc::time();
class ThreadRead : public kc::Thread {
public:
void setparams(int32_t id, kc::File* file, int64_t rnum, int32_t thnum, bool rnd) {
id_ = id;
file_ = file;
rnum_ = rnum;
thnum_ = thnum;
rnd_ = rnd;
err_ = false;
}
bool error() {
return err_;
}
void run() {
int64_t size = file_->size();
int64_t base = id_ * rnum_;
int64_t range = rnum_ * thnum_;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
int64_t num = rnd_ ? myrand(range) : base + i - 1;
int64_t off = num * FILEIOUNIT;
char rbuf[RECBUFSIZ];
if (!file_->read(off, rbuf, FILEIOUNIT) && off + (int64_t)FILEIOUNIT < size) {
fileerrprint(file_, __LINE__, "File::read");
err_ = true;
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::File* file_;
int64_t rnum_;
int32_t thnum_;
bool rnd_;
bool err_;
};
ThreadRead threadreads[THREADMAX];
if (thnum < 2) {
threadreads[0].setparams(0, &file, rnum, thnum, rnd);
threadreads[0].run();
if (threadreads[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threadreads[i].setparams(i, &file, rnum, thnum, rnd);
threadreads[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadreads[i].join();
if (threadreads[i].error()) err = true;
}
}
etime = kc::time();
filemetaprint(&file);
oprintf("time: %.3f\n", etime - stime);
if (rnd) {
int64_t off = rnum * thnum * FILEIOUNIT;
char rbuf[RECBUFSIZ];
std::memset(rbuf, '@', FILEIOUNIT);
if (!file.write(off, rbuf, FILEIOUNIT)) {
fileerrprint(&file, __LINE__, "File::write");
err = true;
}
}
oprintf("fast writing:\n");
stime = kc::time();
class ThreadWriteFast : public kc::Thread {
public:
void setparams(int32_t id, kc::File* file, int64_t rnum, int32_t thnum, bool rnd) {
id_ = id;
file_ = file;
rnum_ = rnum;
thnum_ = thnum;
rnd_ = rnd;
err_ = false;
}
bool error() {
return err_;
}
void run() {
int64_t base = id_ * rnum_;
int64_t range = rnum_ * thnum_;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
int64_t num = rnd_ ? myrand(range) : base + i - 1;
int64_t off = num * FILEIOUNIT;
char rbuf[RECBUFSIZ];
size_t rsiz = std::sprintf(rbuf, "[%048lld]", (long long)num);
if (!file_->write_fast(off, rbuf, rsiz)) {
fileerrprint(file_, __LINE__, "File::write_fast");
err_ = true;
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::File* file_;
int64_t rnum_;
int32_t thnum_;
bool rnd_;
bool err_;
};
ThreadWriteFast threadwritefasts[THREADMAX];
if (thnum < 2) {
threadwritefasts[0].setparams(0, &file, rnum, thnum, rnd);
threadwritefasts[0].run();
if (threadwritefasts[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threadwritefasts[i].setparams(i, &file, rnum, thnum, rnd);
threadwritefasts[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadwritefasts[i].join();
if (threadwritefasts[i].error()) err = true;
}
}
etime = kc::time();
filemetaprint(&file);
oprintf("time: %.3f\n", etime - stime);
oprintf("fast reading:\n");
stime = kc::time();
class ThreadReadFast : public kc::Thread {
public:
void setparams(int32_t id, kc::File* file, int64_t rnum, int32_t thnum, bool rnd) {
id_ = id;
file_ = file;
rnum_ = rnum;
thnum_ = thnum;
rnd_ = rnd;
err_ = false;
}
bool error() {
return err_;
}
void run() {
int64_t base = id_ * rnum_;
int64_t range = rnum_ * thnum_;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
int64_t num = rnd_ ? myrand(range) : base + i - 1;
int64_t off = num * FILEIOUNIT;
char rbuf[RECBUFSIZ];
if (!file_->read_fast(off, rbuf, FILEIOUNIT)) {
fileerrprint(file_, __LINE__, "File::read_fast");
err_ = true;
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::File* file_;
int64_t rnum_;
int32_t thnum_;
bool rnd_;
bool err_;
};
ThreadReadFast threadreadfasts[THREADMAX];
if (thnum < 2) {
threadreadfasts[0].setparams(0, &file, rnum, thnum, rnd);
threadreadfasts[0].run();
if (threadreadfasts[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threadreadfasts[i].setparams(i, &file, rnum, thnum, rnd);
threadreadfasts[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadreadfasts[i].join();
if (threadreadfasts[i].error()) err = true;
}
}
etime = kc::time();
filemetaprint(&file);
oprintf("time: %.3f\n", etime - stime);
oprintf("committing transaction:\n");
stime = kc::time();
int64_t qsiz = file.size() / 4;
if (!file.begin_transaction(rnd ? myrand(100) == 0 : false, qsiz)) {
fileerrprint(&file, __LINE__, "File::begin_transaction");
err = true;
}
if (!file.write_transaction(0, qsiz)) {
fileerrprint(&file, __LINE__, "File::write_transaction");
err = true;
}
int64_t fsiz = rnd ? myrand(rnum * thnum * FILEIOUNIT) : rnum * thnum / 2 * FILEIOUNIT + 5;
if (!file.truncate(fsiz)) {
fileerrprint(&file, __LINE__, "File::truncate");
err = true;
}
if (file.size() != fsiz) {
fileerrprint(&file, __LINE__, "File::truncate");
err = true;
}
class ThreadCommit : public kc::Thread {
public:
void setparams(int32_t id, kc::File* file, int64_t rnum, int32_t thnum,
bool rnd, int64_t fsiz) {
id_ = id;
file_ = file;
rnum_ = rnum;
thnum_ = thnum;
rnd_ = rnd;
fsiz_ = fsiz;
err_ = false;
}
bool error() {
return err_;
}
void run() {
int64_t base = id_ * rnum_;
int64_t range = rnum_ * thnum_;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
int64_t num = rnd_ ? myrand(range) : base + i - 1;
int64_t off = num * FILEIOUNIT;
char rbuf[RECBUFSIZ];
size_t rsiz = std::sprintf(rbuf, "[%048lld]", (long long)num);
if (i % 2 == 0 || off > fsiz_ - (int64_t)FILEIOUNIT) {
if (!file_->write(off, rbuf, rsiz)) {
fileerrprint(file_, __LINE__, "File::write");
err_ = true;
}
} else {
if (!file_->write_fast(off, rbuf, rsiz)) {
fileerrprint(file_, __LINE__, "File::write_fast");
err_ = true;
}
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::File* file_;
int64_t rnum_;
int32_t thnum_;
bool rnd_;
int64_t fsiz_;
bool err_;
};
ThreadCommit threadcommits[THREADMAX];
if (thnum < 2) {
threadcommits[0].setparams(0, &file, rnum, thnum, rnd, fsiz);
threadcommits[0].run();
if (threadcommits[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threadcommits[i].setparams(i, &file, rnum, thnum, rnd, fsiz);
threadcommits[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadcommits[i].join();
if (threadcommits[i].error()) err = true;
}
}
if (!file.end_transaction(true)) {
fileerrprint(&file, __LINE__, "File::end_transaction");
err = true;
}
etime = kc::time();
filemetaprint(&file);
oprintf("time: %.3f\n", etime - stime);
oprintf("aborting transaction:\n");
stime = kc::time();
qsiz = file.size() / 4;
if (!file.begin_transaction(rnd ? myrand(100) == 0 : false, qsiz)) {
fileerrprint(&file, __LINE__, "File::begin_transaction");
err = true;
}
if (!file.write_transaction(0, qsiz)) {
fileerrprint(&file, __LINE__, "File::write_transaction");
err = true;
}
int64_t osiz = file.size();
kc::StringTreeMap chkmap;
int64_t chknum = rnum / 100 + 1;
for (int64_t i = 0; i < chknum; i++) {
char rbuf[RECBUFSIZ];
int64_t roff = myrand(osiz);
int32_t rsiz = myrand(RECBUFSIZ);
if (file.read(roff, rbuf, rsiz)) {
std::string key = kc::strprintf("%lld:%d", (long long)roff, rsiz);
chkmap[key] = std::string(rbuf, rsiz);
}
}
fsiz = rnd ? myrand(rnum * thnum * FILEIOUNIT) : rnum * thnum / 2 * FILEIOUNIT + 5;
if (!file.truncate(fsiz)) {
fileerrprint(&file, __LINE__, "File::truncate");
err = true;
}
if (file.size() != fsiz) {
fileerrprint(&file, __LINE__, "File::truncate");
err = true;
}
class ThreadAbort : public kc::Thread {
public:
void setparams(int32_t id, kc::File* file, int64_t rnum, int32_t thnum,
bool rnd, int64_t fsiz) {
id_ = id;
file_ = file;
rnum_ = rnum;
thnum_ = thnum;
rnd_ = rnd;
fsiz_ = fsiz;
err_ = false;
}
bool error() {
return err_;
}
void run() {
int64_t base = id_ * rnum_;
int64_t range = rnum_ * thnum_;
for (int64_t i = 1; !err_ && i <= rnum_; i++) {
int64_t num = rnd_ ? myrand(range) : base + i - 1;
int64_t off = num * FILEIOUNIT;
char rbuf[RECBUFSIZ];
std::memset(rbuf, num, FILEIOUNIT);
if (i % 2 == 0 || off > fsiz_ - (int64_t)FILEIOUNIT) {
if (!file_->write(off, rbuf, FILEIOUNIT)) {
fileerrprint(file_, __LINE__, "File::write");
err_ = true;
}
} else {
if (!file_->write_fast(off, rbuf, FILEIOUNIT)) {
fileerrprint(file_, __LINE__, "File::write_fast");
err_ = true;
}
}
if (id_ < 1 && rnum_ > 250 && i % (rnum_ / 250) == 0) {
oputchar('.');
if (i == rnum_ || i % (rnum_ / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
}
private:
int32_t id_;
kc::File* file_;
int64_t rnum_;
int32_t thnum_;
bool rnd_;
int64_t fsiz_;
bool err_;
};
ThreadAbort threadaborts[THREADMAX];
if (thnum < 2) {
threadaborts[0].setparams(0, &file, rnum, thnum, rnd, fsiz);
threadaborts[0].run();
if (threadaborts[0].error()) err = true;
} else {
for (int32_t i = 0; i < thnum; i++) {
threadaborts[i].setparams(i, &file, rnum, thnum, rnd, fsiz);
threadaborts[i].start();
}
for (int32_t i = 0; i < thnum; i++) {
threadaborts[i].join();
if (threadaborts[i].error()) err = true;
}
}
if (!file.end_transaction(false)) {
fileerrprint(&file, __LINE__, "File::end_transaction");
err = true;
}
if (file.size() != osiz) {
fileerrprint(&file, __LINE__, "File::end_transaction");
err = true;
}
for (kc::StringTreeMap::iterator it = chkmap.begin(); it != chkmap.end(); ++it) {
const char* key = it->first.c_str();
int64_t roff = kc::atoi(key);
int32_t rsiz = kc::atoi(std::strchr(key, ':') + 1);
char rbuf[RECBUFSIZ];
if (file.read(roff, rbuf, rsiz)) {
if (it->second != std::string(rbuf, rsiz)) {
fileerrprint(&file, __LINE__, "File::end_transaction");
err = true;
}
} else {
fileerrprint(&file, __LINE__, "File::end_transaction");
err = true;
}
}
etime = kc::time();
filemetaprint(&file);
oprintf("time: %.3f\n", etime - stime);
oprintf("closing the file:\n");
stime = kc::time();
if (!file.close()) {
fileerrprint(&file, __LINE__, "File::close");
err = true;
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("testing file utility functions:\n");
stime = kc::time();
std::string ostr = "_";
for (int32_t i = 0; i < 100; i++) {
ostr.append(path);
}
ostr.append("_");
if (!kc::File::write_file(path, ostr.c_str(), ostr.size())) {
errprint(__LINE__, "File::write_file");
err = true;
}
int64_t isiz;
char* ibuf = kc::File::read_file(path, &isiz);
if (ibuf) {
if (ostr != ibuf) {
errprint(__LINE__, "File::read_file");
err = true;
}
delete[] ibuf;
} else {
errprint(__LINE__, "File::read_file");
err = true;
}
kc::File::Status sbuf;
if (!kc::File::status(path, &sbuf) || sbuf.isdir || sbuf.size < 1) {
errprint(__LINE__, "File::status");
err = true;
}
if (!kc::File::status(kc::File::CDIRSTR, &sbuf) || !sbuf.isdir) {
errprint(__LINE__, "File::status");
err = true;
}
const std::string& abspath = kc::File::absolute_path(path);
if (abspath.empty()) {
errprint(__LINE__, "File::absolute_path");
err = true;
}
const std::string& tmppath = kc::strprintf("%s%ctmp", path, kc::File::EXTCHR);
if (!kc::File::rename(path, tmppath) || !kc::File::rename(tmppath, path)) {
errprint(__LINE__, "File::rename");
err = true;
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("testing directory utility functions:\n");
stime = kc::time();
std::vector files;
if (!kc::File::read_directory(kc::File::CDIRSTR, &files)) {
errprint(__LINE__, "File::read_directory");
err = true;
}
if (!kc::File::make_directory(tmppath)) {
errprint(__LINE__, "File::make_directory");
err = true;
}
if (!kc::File::remove_directory(tmppath)) {
errprint(__LINE__, "File::remove_directory");
err = true;
}
if (!kc::File::make_directory(tmppath)) {
errprint(__LINE__, "File::make_directory");
err = true;
}
const std::string chldpath = tmppath + kc::File::PATHCHR + "tmp";
if (!kc::File::write_file(chldpath, tmppath.c_str(), tmppath.size())) {
errprint(__LINE__, "File::write_file");
err = true;
}
if (!kc::File::remove_recursively(tmppath)) {
errprint(__LINE__, "File::make_recursively");
err = true;
}
const std::string& cwdpath = kc::File::get_current_directory();
if (cwdpath.empty()) {
errprint(__LINE__, "File::get_current_directory");
err = true;
}
if (!kc::File::set_current_directory(cwdpath)) {
errprint(__LINE__, "File::set_current_directory");
err = true;
}
kc::DirStream dir;
if (!dir.open(cwdpath)) {
errprint(__LINE__, "DirStream::open");
err = true;
}
std::string cpath;
while (dir.read(&cpath)) {
if (!kc::File::status(cpath, &sbuf)) {
errprint(__LINE__, "File::status");
err = true;
}
}
if (!dir.close()) {
errprint(__LINE__, "DirStream::close");
err = true;
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("%s\n\n", err ? "error" : "ok");
return err ? 1 : 0;
}
// perform lhmap command
static int32_t proclhmap(int64_t rnum, bool rnd, int64_t bnum) {
oprintf("\n seed=%u rnum=%lld rnd=%d bnum=%lld\n\n",
g_randseed, (long long)rnum, rnd, (long long)bnum);
bool err = false;
if (bnum < 0) bnum = 0;
typedef kc::LinkedHashMap Map;
Map map(bnum);
oprintf("setting records:\n");
double stime = kc::time();
for (int64_t i = 1; i <= rnum; i++) {
char kbuf[RECBUFSIZ];
std::sprintf(kbuf, "%08lld", (long long)(rnd ? myrand(rnum) + 1 : i));
map.set(kbuf, kbuf, Map::MCURRENT);
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
double etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("count: %lld\n", (long long)map.count());
int64_t musage = memusage();
if (musage > 0) oprintf("memory: %lld\n", (long long)(musage - g_memusage));
oprintf("getting records:\n");
stime = kc::time();
for (int64_t i = 1; !err && i <= rnum; i++) {
char kbuf[RECBUFSIZ];
std::sprintf(kbuf, "%08lld", (long long)(rnd ? myrand(rnum) + 1 : i));
Map::MoveMode mode = Map::MCURRENT;
if (rnd) {
switch (myrand(4)) {
case 0: mode = Map::MFIRST; break;
case 1: mode = Map::MLAST; break;
}
}
if (!map.get(kbuf, mode) && !rnd) {
errprint(__LINE__, "LinkedHashMap::get: %s", kbuf);
err = true;
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("count: %lld\n", (long long)map.count());
musage = memusage();
if (musage > 0) oprintf("memory: %lld\n", (long long)(musage - g_memusage));
oprintf("traversing records:\n");
stime = kc::time();
int64_t cnt = 0;
for (Map::Iterator it = map.begin(); !err && it != map.end(); ++it) {
cnt++;
if (it.key() != it.value()) {
errprint(__LINE__, "LinkedHashMap::Iterator::key");
err = true;
}
if (rnum > 250 && cnt % (rnum / 250) == 0) {
oputchar('.');
if (cnt == rnum || cnt % (rnum / 10) == 0) oprintf(" (%08lld)\n", (long long)cnt);
}
}
if (rnd) oprintf(" (end)\n");
if (cnt != (int64_t)map.count()) {
errprint(__LINE__, "LinkedHashMap::count");
err = true;
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("count: %lld\n", (long long)map.count());
musage = memusage();
if (musage > 0) oprintf("memory: %lld\n", (long long)(musage - g_memusage));
Map paramap(bnum + 31);
oprintf("migrating records:\n");
stime = kc::time();
for (int64_t i = 1; !err && i <= rnum; i++) {
char kbuf[RECBUFSIZ];
std::sprintf(kbuf, "%08lld", (long long)(rnd ? myrand(rnum) + 1 : i));
Map::MoveMode mode = Map::MCURRENT;
if (rnd) {
switch (myrand(4)) {
case 0: mode = Map::MFIRST; break;
case 1: mode = Map::MLAST; break;
}
}
if (!map.migrate(kbuf, ¶map, mode) && !rnd) {
errprint(__LINE__, "LinkedHashMap::migrate: %s", kbuf);
err = true;
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("count: %lld,%lld\n", (long long)map.count(), (long long)paramap.count());
musage = memusage();
if (musage > 0) oprintf("memory: %lld\n", (long long)(musage - g_memusage));
oprintf("removing records:\n");
stime = kc::time();
for (int64_t i = 1; !err && i <= rnum; i++) {
char kbuf[RECBUFSIZ];
std::sprintf(kbuf, "%08lld", (long long)(rnd ? myrand(rnum) + 1 : i));
if (!paramap.remove(kbuf) && !rnd) {
errprint(__LINE__, "LinkedHashMap::remove: %s", kbuf);
err = true;
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("count: %lld,%lld\n", (long long)map.count(), (long long)paramap.count());
musage = memusage();
if (musage > 0) oprintf("memory: %lld\n", (long long)(musage - g_memusage));
if (rnd) {
oprintf("wicked testing:\n");
stime = kc::time();
for (int64_t i = 1; !err && i <= rnum; i++) {
char kbuf[RECBUFSIZ];
std::sprintf(kbuf, "%08lld", (long long)(rnd ? myrand(rnum) + 1 : i));
Map::MoveMode mode = Map::MCURRENT;
if (rnd) {
switch (myrand(4)) {
case 0: mode = Map::MFIRST; break;
case 1: mode = Map::MLAST; break;
}
}
Map *ptr = ↦
Map *paraptr = ¶map;
if (myrand(2) == 0) {
ptr = ¶map;
paraptr = ↦
}
switch (myrand(4)) {
case 0: {
ptr->set(kbuf, kbuf, mode);
break;
}
case 1: {
ptr->get(kbuf, mode);
break;
}
case 2: {
ptr->remove(kbuf);
break;
}
case 3: {
ptr->migrate(kbuf, paraptr, mode);
break;
}
}
if (myrand(rnum * 2 + 1) == 0) ptr->clear();
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
cnt = 0;
for (Map::Iterator it = map.begin(); !err && it != map.end(); ++it) {
cnt++;
if (it.key() != it.value()) {
errprint(__LINE__, "LinkedHashMap::Iterator::key");
err = true;
}
if (rnum > 250 && cnt % (rnum / 250) == 0) {
oputchar('.');
if (cnt == rnum || cnt % (rnum / 10) == 0) oprintf(" (%08lld)\n", (long long)cnt);
}
}
if (rnd) oprintf(" (end)\n");
if (cnt != (int64_t)map.count()) {
errprint(__LINE__, "LinkedHashMap::count");
err = true;
}
cnt = 0;
Map::Iterator it = map.end();
while (!err && it != map.begin()) {
--it;
cnt++;
if (it.key() != it.value()) {
errprint(__LINE__, "LinkedHashMap::Iterator::key");
err = true;
}
if (rnum > 250 && cnt % (rnum / 250) == 0) {
oputchar('.');
if (cnt == rnum || cnt % (rnum / 10) == 0) oprintf(" (%08lld)\n", (long long)cnt);
}
}
if (rnd) oprintf(" (end)\n");
if (cnt != (int64_t)map.count()) {
errprint(__LINE__, "LinkedHashMap::count");
err = true;
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("count: %lld\n", (long long)map.count());
musage = memusage();
if (musage > 0) oprintf("memory: %lld\n", (long long)(musage - g_memusage));
}
oprintf("%s\n\n", err ? "error" : "ok");
return err ? 1 : 0;
}
// perform thmap command
static int32_t procthmap(int64_t rnum, bool rnd, int64_t bnum) {
oprintf("\n seed=%u rnum=%lld rnd=%d bnum=%lld\n\n",
g_randseed, (long long)rnum, rnd, (long long)bnum);
bool err = false;
if (bnum < 0) bnum = 0;
kc::TinyHashMap map(bnum);
oprintf("setting records:\n");
double stime = kc::time();
for (int64_t i = 1; i <= rnum; i++) {
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld", (long long)(rnd ? myrand(rnum) + 1 : i));
map.set(kbuf, ksiz, kbuf, ksiz);
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
double etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("count: %lld\n", (long long)map.count());
int64_t musage = memusage();
if (musage > 0) oprintf("memory: %lld\n", (long long)(musage - g_memusage));
oprintf("getting records:\n");
stime = kc::time();
for (int64_t i = 1; !err && i <= rnum; i++) {
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld", (long long)(rnd ? myrand(rnum) + 1 : i));
size_t vsiz;
const char* vbuf = map.get(kbuf, ksiz, &vsiz);
if (!vbuf && !rnd) {
errprint(__LINE__, "TinyHashMap::get: %s", kbuf);
err = true;
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("count: %lld\n", (long long)map.count());
musage = memusage();
if (musage > 0) oprintf("memory: %lld\n", (long long)(musage - g_memusage));
oprintf("appending records:\n");
stime = kc::time();
for (int64_t i = 1; !err && i <= rnum; i++) {
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld", (long long)(rnd ? myrand(rnum) + 1 : i));
map.append(kbuf, ksiz, kbuf, ksiz);
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("count: %lld\n", (long long)map.count());
musage = memusage();
if (musage > 0) oprintf("memory: %lld\n", (long long)(musage - g_memusage));
oprintf("traversing records:\n");
stime = kc::time();
int64_t cnt = 0;
kc::TinyHashMap::Iterator it(&map);
const char* kbuf, *vbuf;
size_t ksiz, vsiz;
while ((kbuf = it.get(&ksiz, &vbuf, &vsiz)) != NULL) {
cnt++;
it.step();
if (rnum > 250 && cnt % (rnum / 250) == 0) {
oputchar('.');
if (cnt == rnum || cnt % (rnum / 10) == 0) oprintf(" (%08lld)\n", (long long)cnt);
}
}
if (rnd) oprintf(" (end)\n");
if (cnt != (int64_t)map.count()) {
errprint(__LINE__, "TinyHashMap::count");
err = true;
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("count: %lld\n", (long long)map.count());
musage = memusage();
if (musage > 0) oprintf("memory: %lld\n", (long long)(musage - g_memusage));
oprintf("sorting records:\n");
stime = kc::time();
cnt = 0;
kc::TinyHashMap::Sorter sorter(&map);
while ((kbuf = sorter.get(&ksiz, &vbuf, &vsiz)) != NULL) {
cnt++;
sorter.step();
if (rnum > 250 && cnt % (rnum / 250) == 0) {
oputchar('.');
if (cnt == rnum || cnt % (rnum / 10) == 0) oprintf(" (%08lld)\n", (long long)cnt);
}
}
if (rnd) oprintf(" (end)\n");
if (cnt != (int64_t)map.count()) {
errprint(__LINE__, "TinyHashMap::count");
err = true;
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("count: %lld\n", (long long)map.count());
musage = memusage();
if (musage > 0) oprintf("memory: %lld\n", (long long)(musage - g_memusage));
oprintf("removing records:\n");
stime = kc::time();
for (int64_t i = 1; !err && i <= rnum; i++) {
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%08lld", (long long)(rnd ? myrand(rnum) + 1 : i));
if (!map.remove(kbuf, ksiz) && !rnd) {
errprint(__LINE__, "TinyHashMap::remove: %s", kbuf);
err = true;
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("count: %lld\n", (long long)map.count());
musage = memusage();
if (musage > 0) oprintf("memory: %lld\n", (long long)(musage - g_memusage));
if (rnd) {
oprintf("wicked testing:\n");
stime = kc::time();
char lbuf[RECBUFSIZL];
std::memset(lbuf, '*', sizeof(lbuf));
for (int64_t i = 1; !err && i <= rnum; i++) {
char kbuf[RECBUFSIZ];
size_t ksiz = std::sprintf(kbuf, "%lld", (long long)(myrand(rnum) + 1));
size_t vsiz = myrand(sizeof(lbuf));
switch (myrand(6)) {
case 0: {
map.set(kbuf, ksiz, lbuf, vsiz);
break;
}
case 1: {
map.add(kbuf, ksiz, lbuf, vsiz);
break;
}
case 2: {
map.replace(kbuf, ksiz, lbuf, vsiz);
break;
}
case 3: {
map.append(kbuf, ksiz, lbuf, vsiz);
break;
}
case 6: {
map.remove(kbuf, ksiz);
break;
}
default: {
map.get(kbuf, ksiz, &vsiz);
break;
}
}
if (myrand(rnum * 2 + 1) == 0) map.clear();
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("count: %lld\n", (long long)map.count());
musage = memusage();
if (musage > 0) oprintf("memory: %lld\n", (long long)(musage - g_memusage));
}
oprintf("%s\n\n", err ? "error" : "ok");
return err ? 1 : 0;
}
// perform talist command
static int32_t proctalist(int64_t rnum, bool rnd) {
oprintf("\n seed=%u rnum=%lld rnd=%d\n\n",
g_randseed, (long long)rnum, rnd);
bool err = false;
kc::TinyArrayList list;
oprintf("setting records:\n");
double stime = kc::time();
for (int64_t i = 1; i <= rnum; i++) {
char buf[RECBUFSIZ];
size_t size = std::sprintf(buf, "%08lld", (long long)i);
if (rnd && myrand(2) == 0) {
list.unshift(buf, size);
} else {
list.push(buf, size);
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
double etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("count: %lld\n", (long long)list.count());
int64_t musage = memusage();
if (musage > 0) oprintf("memory: %lld\n", (long long)(musage - g_memusage));
oprintf("getting records:\n");
stime = kc::time();
size_t cnt = list.count();
for (int64_t i = 1; i <= rnum; i++) {
size_t size;
list.get(rnd ? myrand(cnt) : i - 1, &size);
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("count: %lld\n", (long long)list.count());
musage = memusage();
if (musage > 0) oprintf("memory: %lld\n", (long long)(musage - g_memusage));
oprintf("removing records:\n");
stime = kc::time();
for (int64_t i = 1; i <= rnum; i++) {
if (rnd && myrand(2) == 0) {
list.shift();
} else {
list.pop();
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("count: %lld\n", (long long)list.count());
musage = memusage();
if (musage > 0) oprintf("memory: %lld\n", (long long)(musage - g_memusage));
if (rnd) {
oprintf("wicked testing:\n");
stime = kc::time();
char lbuf[RECBUFSIZL];
std::memset(lbuf, '*', sizeof(lbuf));
for (int64_t i = 1; !err && i <= rnum; i++) {
size_t size = myrand(sizeof(lbuf));
cnt = list.count();
switch (myrand(10)) {
case 0: {
list.pop();
break;
}
case 1: {
list.unshift(lbuf, size);
break;
}
case 2: {
list.shift();
break;
}
case 3: {
list.insert(lbuf, size, cnt > 0 ? myrand(cnt) : 0);
break;
}
case 4: {
if (cnt > 0) list.remove(myrand(cnt));
break;
}
case 5: {
if (cnt > 0) list.get(myrand(cnt), &size);
break;
}
case 6: {
if (myrand(100) == 0) list.clear();
break;
}
default: {
list.push(lbuf, size);
break;
}
}
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
etime = kc::time();
oprintf("time: %.3f\n", etime - stime);
oprintf("count: %lld\n", (long long)list.count());
musage = memusage();
if (musage > 0) oprintf("memory: %lld\n", (long long)(musage - g_memusage));
}
oprintf("%s\n\n", err ? "error" : "ok");
return err ? 1 : 0;
}
// perform misc command
static int32_t procmisc(int64_t rnum) {
oprintf("\n seed=%u rnum=%lld\n\n", g_randseed, (long long)rnum);
bool err = false;
if (!kc::_dummytest()) {
errprint(__LINE__, "_dummytest");
err = true;
}
double stime = kc::time();
for (int64_t i = 1; !err && i <= rnum; i++) {
uint16_t num16 = (1ULL << myrand(sizeof(num16) * 8)) - 5 + myrand(10);
uint32_t num32 = (1ULL << myrand(sizeof(num32) * 8)) - 5 + myrand(10);
uint64_t num64 = (1ULL << myrand(sizeof(num64) * 8)) - 5 + myrand(10);
if (kc::ntoh16(kc::hton16(num16)) != num16) {
errprint(__LINE__, "ntoh16: %llu", (unsigned long long)num16);
err = true;
}
if (kc::ntoh32(kc::hton32(num32)) != num32) {
errprint(__LINE__, "ntoh32: %llu", (unsigned long long)num32);
err = true;
}
if (kc::ntoh64(kc::hton64(num64)) != num64) {
errprint(__LINE__, "ntoh64: %llu", (unsigned long long)num64);
err = true;
}
char fbuf[sizeof(num64)];
num64 = (uint64_t)myrand(kc::INT32MAX) * myrand(kc::INT16MAX);
kc::writefixnum(fbuf, num64, 6);
uint64_t onum = kc::readfixnum(fbuf, 6);
if (onum != num64) {
errprint(__LINE__, "readfixnum: %llu:%llu",
(unsigned long long)num64, (unsigned long long)onum);
err = true;
}
unsigned char ubuf[RECBUFSIZ];
unsigned char* uwp = ubuf;
if (kc::writevarnum(uwp, num32) != kc::sizevarnum(num32)) {
errprint(__LINE__, "sizevarnum: %llu", (unsigned long long)num32);
err = true;
}
uwp += kc::writevarnum(uwp, num16);
uwp += kc::writevarnum(uwp, num32);
uwp += kc::writevarnum(uwp, num64);
const unsigned char* urp = ubuf;
urp += kc::readvarnum(urp, uwp - urp, &onum);
if (onum != num16) {
errprint(__LINE__, "readvarnum: %llu:%llu",
(unsigned long long)num16, (unsigned long long)onum);
err = true;
}
urp += kc::readvarnum(urp, uwp - urp, &onum);
if (onum != num32) {
errprint(__LINE__, "readvarnum: %llu:%llu",
(unsigned long long)num32, (unsigned long long)onum);
err = true;
}
urp += kc::readvarnum(urp, uwp - urp, &onum);
if (onum != num64) {
errprint(__LINE__, "readvarnum: %llu:%llu",
(unsigned long long)num64, (unsigned long long)onum);
err = true;
}
if (urp != uwp) {
errprint(__LINE__, "readvarnum: %d", (int)(uwp - urp));
err = true;
}
size_t usiz = urp - ubuf;
uint64_t hash = kc::hashmurmur(&num16, sizeof(num16)) + kc::hashmurmur(ubuf, usiz);
hash += kc::hashfnv(&num16, sizeof(num16)) + kc::hashfnv(ubuf, usiz);
char name[kc::NUMBUFSIZ];
hash += kc::hashpath(ubuf, usiz, name);
hash = kc::nearbyprime(myrand(kc::INT32MAX));
if (myrand(256) == 0) {
int32_t unum = myrand(64);
std::vector oucs;
for (int32_t j = 0; j < unum; j++) {
uint32_t c = std::pow(2, myrand(31000000) / 1000000.0);
oucs.push_back(c);
}
std::string utf;
kc::strucstoutf(oucs, &utf);
std::vector nucs;
kc::strutftoucs(utf, &nucs);
if (nucs.size() == oucs.size()) {
for (int32_t j = 0; j < (int32_t)nucs.size(); j++) {
if (nucs[j] != oucs[j]) {
errprint(__LINE__, "strutftoucs: %d:%d", (int)nucs[j], (int)oucs[j]);
err = true;
break;
}
}
} else {
errprint(__LINE__, "strutftoucs: %d:%d", (int)nucs.size(), (int)oucs.size());
err = true;
}
uint32_t* cucs = new uint32_t[utf.size()+1];
size_t cucsnum;
if (myrand(2) == 0) {
kc::strutftoucs(utf.c_str(), cucs, &cucsnum);
} else {
kc::strutftoucs(utf.data(), utf.size(), cucs, &cucsnum);
}
if (cucsnum == oucs.size()) {
char* cutf = new char[cucsnum*6+1];
kc::strucstoutf(cucs, cucsnum, cutf);
if (std::strcmp(cutf, utf.c_str())) {
errprint(__LINE__, "strucstoutf");
err = true;
}
delete[] cutf;
} else {
errprint(__LINE__, "strutftoucs");
err = true;
}
delete[] cucs;
int32_t tnum = myrand(64);
std::vector ovec;
std::map omap;
for (int32_t j = 0; j < tnum; j++) {
char kbuf[RECBUFSIZ];
std::sprintf(kbuf, "%lld", (long long)myrand(rnum));
char vbuf[RECBUFSIZ];
std::sprintf(vbuf, "%lld", (long long)myrand(rnum));
ovec.push_back(vbuf);
omap[kbuf] = vbuf;
}
std::string vstr;
kc::strvecdump(ovec, &vstr);
std::vector nvec;
kc::strvecload(vstr, &nvec);
if (nvec.size() != ovec.size()) {
errprint(__LINE__, "strvecload: %d:%d", (int)nvec.size(), (int)ovec.size());
err = true;
}
std::string mstr;
kc::strmapdump(omap, &mstr);
std::map nmap;
kc::strmapload(mstr, &nmap);
if (nmap.size() != omap.size()) {
errprint(__LINE__, "strmapload: %d:%d", (int)nvec.size(), (int)ovec.size());
err = true;
}
}
char* ebuf = kc::hexencode(ubuf, usiz);
size_t osiz;
char* obuf = kc::hexdecode(ebuf, &osiz);
if (osiz != usiz || std::memcmp(obuf, ubuf, osiz)) {
errprint(__LINE__, "hexencode: %d:%d", (int)osiz, (int)usiz);
err = true;
}
delete[] obuf;
delete[] ebuf;
ebuf = kc::urlencode(ubuf, usiz);
obuf = kc::urldecode(ebuf, &osiz);
if (osiz != usiz || std::memcmp(obuf, ubuf, osiz)) {
errprint(__LINE__, "urlencode: %d:%d", (int)osiz, (int)usiz);
err = true;
}
delete[] obuf;
delete[] ebuf;
ebuf = kc::quoteencode(ubuf, usiz);
obuf = kc::quotedecode(ebuf, &osiz);
if (osiz != usiz || std::memcmp(obuf, ubuf, osiz)) {
errprint(__LINE__, "quoteencode: %d:%d", (int)osiz, (int)usiz);
err = true;
}
delete[] obuf;
delete[] ebuf;
ebuf = kc::baseencode(ubuf, usiz);
obuf = kc::basedecode(ebuf, &osiz);
if (osiz != usiz || std::memcmp(obuf, ubuf, osiz)) {
errprint(__LINE__, "baseencode: %d:%d", (int)osiz, (int)usiz);
err = true;
}
delete[] obuf;
delete[] ebuf;
size_t nsiz = std::strlen(name);
nsiz -= i % nsiz;
ebuf = new char[usiz];
kc::arccipher(ubuf, usiz, name, nsiz, ebuf);
obuf = new char[usiz];
kc::arccipher(ebuf, usiz, name, nsiz, obuf);
if (std::memcmp(obuf, ubuf, usiz)) {
errprint(__LINE__, "arccipher: %s", name);
err = true;
}
if (kc::memicmp(obuf, ubuf, usiz)) {
errprint(__LINE__, "memicmp");
err = true;
}
if (!kc::memmem(obuf, osiz, ubuf, usiz)) {
errprint(__LINE__, "memmem");
err = true;
}
if (!kc::memimem(obuf, osiz, ubuf, usiz)) {
errprint(__LINE__, "memimem");
err = true;
}
if (kc::memdist(obuf, osiz, ubuf, usiz)) {
errprint(__LINE__, "memdist");
err = true;
}
delete[] obuf;
delete[] ebuf;
ebuf = kc::memdup((char*)ubuf, usiz);
ebuf[usiz] = '\0';
obuf = kc::strdup(ebuf);
switch (myrand(18)) {
case 0: kc::atoi(obuf); break;
case 1: kc::atoix(obuf); break;
case 2: kc::atoih(obuf); break;
case 3: kc::atoin((char*)ubuf, usiz); break;
case 4: kc::atof(obuf); break;
case 5: kc::atofn((char*)ubuf, usiz); break;
case 6: kc::strtoupper(obuf); break;
case 7: kc::strtolower(obuf); break;
case 8: kc::strtrim(obuf); break;
case 9: kc::strsqzspc(obuf); break;
case 10: kc::strnrmspc(obuf); break;
case 11: kc::stricmp(obuf, ebuf); break;
case 12: kc::stristr(obuf, ebuf); break;
case 13: kc::strfwm(obuf, ebuf); break;
case 14: kc::strifwm(obuf, ebuf); break;
case 15: kc::strbwm(obuf, ebuf); break;
case 16: kc::stribwm(obuf, ebuf); break;
case 17: kc::strutflen(obuf); break;
}
delete[] obuf;
delete[] ebuf;
kc::ZLIB::Mode zmode;
switch (myrand(3)) {
default: zmode = kc::ZLIB::RAW; break;
case 0: zmode = kc::ZLIB::DEFLATE; break;
case 1: zmode = kc::ZLIB::GZIP; break;
}
size_t zsiz;
char* zbuf = kc::ZLIB::compress(ubuf, usiz, &zsiz, zmode);
if (zbuf) {
obuf = kc::ZLIB::decompress(zbuf, zsiz, &osiz, zmode);
if (obuf) {
if (osiz != usiz || std::memcmp(obuf, ubuf, osiz)) {
errprint(__LINE__, "ZLIB::decompress");
err = true;
}
delete[] obuf;
} else {
errprint(__LINE__, "ZLIB::decompress");
err = true;
}
delete[] zbuf;
} else {
errprint(__LINE__, "ZLIB::compress");
err = true;
}
zbuf = kc::LZO::compress(ubuf, usiz, &zsiz);
if (zbuf) {
obuf = kc::LZO::decompress(zbuf, zsiz, &osiz);
if (obuf) {
if (osiz != usiz || std::memcmp(obuf, ubuf, osiz)) {
errprint(__LINE__, "LZO::decompress");
err = true;
}
delete[] obuf;
} else {
errprint(__LINE__, "LZO::decompress");
err = true;
}
delete[] zbuf;
} else {
errprint(__LINE__, "LZO::compress");
err = true;
}
std::string ustr((char*)ubuf, usiz);
kc::Regex::match(ustr, ".(\x80).");
kc::Regex::replace(ustr, ".(\x80).", "[$0$1$2$&]");
if (rnum > 250 && i % (rnum / 250) == 0) {
oputchar('.');
if (i == rnum || i % (rnum / 10) == 0) oprintf(" (%08lld)\n", (long long)i);
}
}
oprintf("time: %.3f\n", kc::time() - stime);
oprintf("%s\n\n", err ? "error" : "ok");
return err ? 1 : 0;
}
// END OF FILE
kyotocabinet-1.2.80/kcpolydb.h 0000664 0001750 0001750 00000170465 14416044124 015276 0 ustar mikio mikio /*************************************************************************************************
* Polymorphic database
* Copyright (C) 2009-2012 Mikio Hirabayashi
* This file is part of Kyoto Cabinet.
* This program is free software: you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation, either version
* 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with this program.
* If not, see .
*************************************************************************************************/
#ifndef _KCPOLYDB_H // duplication check
#define _KCPOLYDB_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace kyotocabinet { // common namespace
/**
* Polymorphic database.
* @note This class is a concrete class to operate an arbitrary database whose type is determined
* in runtime. This class can be inherited but overwriting methods is forbidden. Before every
* database operation, it is necessary to call the PolyDB::open method in order to open a
* database file and connect the database object to it. To avoid data missing or corruption, it
* is important to close every database file by the PolyDB::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 forbidden to share a database object with child processes.
*/
class PolyDB : public BasicDB {
public:
class Cursor;
private:
class StreamLogger;
class StreamMetaTrigger;
struct SimilarKey;
struct MergeLine;
public:
/**
* Cursor to indicate a record.
*/
class Cursor : public BasicDB::Cursor {
friend class PolyDB;
public:
/**
* Constructor.
* @param db the container database object.
*/
explicit Cursor(PolyDB* db) : db_(db), cur_(NULL) {
_assert_(db);
if (db_->type_ == TYPEVOID) {
ProtoHashDB tmpdb;
cur_ = tmpdb.cursor();
} else {
cur_ = db->db_->cursor();
}
}
/**
* Destructor.
*/
virtual ~Cursor() {
_assert_(true);
delete cur_;
}
/**
* Accept a visitor to the current record.
* @param visitor a visitor object.
* @param writable true for writable operation, or false for read-only operation.
* @param step true to move the cursor to the next record, or false for no move.
* @return true on success, or false on failure.
* @note The operation for each record is performed atomically and other threads accessing
* the same record are blocked. To avoid deadlock, any explicit database operation must not
* be performed in this function.
*/
bool accept(Visitor* visitor, bool writable = true, bool step = false) {
_assert_(visitor);
if (db_->type_ == TYPEVOID) {
db_->set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
return cur_->accept(visitor, writable, step);
}
/**
* Jump the cursor to the first record for forward scan.
* @return true on success, or false on failure.
*/
bool jump() {
_assert_(true);
if (db_->type_ == TYPEVOID) {
db_->set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
return cur_->jump();
}
/**
* Jump the cursor to a record for forward scan.
* @param kbuf the pointer to the key region.
* @param ksiz the size of the key region.
* @return true on success, or false on failure.
*/
bool jump(const char* kbuf, size_t ksiz) {
_assert_(kbuf && ksiz <= MEMMAXSIZ);
if (db_->type_ == TYPEVOID) {
db_->set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
return cur_->jump(kbuf, ksiz);
}
/**
* Jump the cursor to a record for forward scan.
* @note Equal to the original Cursor::jump method except that the parameter is std::string.
*/
bool jump(const std::string& key) {
_assert_(true);
if (db_->type_ == TYPEVOID) {
db_->set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
return jump(key.c_str(), key.size());
}
/**
* Jump the cursor to the last record for backward scan.
* @return true on success, or false on failure.
* @note This method is dedicated to tree databases. Some database types, especially hash
* databases, may provide a dummy implementation.
*/
bool jump_back() {
_assert_(true);
if (db_->type_ == TYPEVOID) {
db_->set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
return cur_->jump_back();
}
/**
* Jump the cursor to a record for backward scan.
* @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 This method is dedicated to tree databases. Some database types, especially hash
* databases, will provide a dummy implementation.
*/
bool jump_back(const char* kbuf, size_t ksiz) {
_assert_(kbuf && ksiz <= MEMMAXSIZ);
if (db_->type_ == TYPEVOID) {
db_->set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
return cur_->jump_back(kbuf, ksiz);
}
/**
* Jump the cursor to a record for backward scan.
* @note Equal to the original Cursor::jump_back method except that the parameter is
* std::string.
*/
bool jump_back(const std::string& key) {
_assert_(true);
return jump_back(key.c_str(), key.size());
}
/**
* Step the cursor to the next record.
* @return true on success, or false on failure.
*/
bool step() {
_assert_(true);
if (db_->type_ == TYPEVOID) {
db_->set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
return cur_->step();
}
/**
* Step the cursor to the previous record.
* @return true on success, or false on failure.
* @note This method is dedicated to tree databases. Some database types, especially hash
* databases, may provide a dummy implementation.
*/
bool step_back() {
_assert_(true);
if (db_->type_ == TYPEVOID) {
db_->set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
return cur_->step_back();
}
/**
* Get the database object.
* @return the database object.
*/
PolyDB* db() {
_assert_(true);
return db_;
}
private:
/** Dummy constructor to forbid the use. */
Cursor(const Cursor&);
/** Dummy Operator to forbid the use. */
Cursor& operator =(const Cursor&);
/** The inner database. */
PolyDB* db_;
/** The inner cursor. */
BasicDB::Cursor* cur_;
};
/**
* Merge modes.
*/
enum MergeMode {
MSET, ///< overwrite the existing value
MADD, ///< keep the existing value
MREPLACE, ///< modify the existing record only
MAPPEND ///< append the new value
};
/**
* Default constructor.
*/
explicit PolyDB() :
type_(TYPEVOID), db_(NULL), error_(),
stdlogstrm_(NULL), stdlogger_(NULL), logger_(NULL), logkinds_(0),
stdmtrgstrm_(NULL), stdmtrigger_(NULL), mtrigger_(NULL), zcomp_(NULL) {
_assert_(true);
}
/**
* Destructor.
* @note If the database is not closed, it is closed implicitly.
*/
virtual ~PolyDB() {
_assert_(true);
if (type_ != TYPEVOID) close();
delete zcomp_;
delete stdmtrigger_;
delete stdmtrgstrm_;
delete stdlogger_;
delete stdlogstrm_;
}
/**
* Set the internal database object.
* @param db the internal database object. Its possession is transferred inside and the
* object is deleted automatically.
* @return true on success, or false on failure.
*/
bool set_internal_db(BasicDB* db) {
_assert_(db);
if (type_ != TYPEVOID) {
set_error(_KCCODELINE_, Error::INVALID, "already opened");
return false;
}
type_ = TYPEMISC;
db_ = db;
return true;
}
/**
* Accept a visitor to a record.
* @param kbuf the pointer to the key region.
* @param ksiz the size of the key region.
* @param visitor a visitor object.
* @param writable true for writable operation, or false for read-only operation.
* @return true on success, or false on failure.
* @note The operation for each record is performed atomically and other threads accessing the
* same record are blocked. To avoid deadlock, any explicit database operation must not be
* performed in this function.
*/
bool accept(const char* kbuf, size_t ksiz, Visitor* visitor, bool writable = true) {
_assert_(kbuf && ksiz <= MEMMAXSIZ && visitor);
if (type_ == TYPEVOID) {
set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
return db_->accept(kbuf, ksiz, visitor, writable);
}
/**
* Accept a visitor to multiple records at once.
* @param keys specifies a string vector of the keys.
* @param visitor a visitor object.
* @param writable true for writable operation, or false for read-only operation.
* @return true on success, or false on failure.
* @note The operations for specified records are performed atomically and other threads
* accessing the same records are blocked. To avoid deadlock, any explicit database operation
* must not be performed in this function.
*/
bool accept_bulk(const std::vector& keys, Visitor* visitor,
bool writable = true) {
_assert_(visitor);
if (type_ == TYPEVOID) {
set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
return db_->accept_bulk(keys, visitor, writable);
}
/**
* Iterate to accept a visitor for each record.
* @param visitor a visitor object.
* @param writable true for writable operation, or false for read-only operation.
* @param checker a progress checker object. If it is NULL, no checking is performed.
* @return true on success, or false on failure.
* @note The whole iteration is performed atomically and other threads are blocked. To avoid
* deadlock, any explicit database operation must not be performed in this function.
*/
bool iterate(Visitor *visitor, bool writable = true, ProgressChecker* checker = NULL) {
_assert_(visitor);
if (type_ == TYPEVOID) {
set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
return db_->iterate(visitor, writable, checker);
}
/**
* Scan each record in parallel.
* @param visitor a visitor object.
* @param thnum the number of worker threads.
* @param checker a progress checker object. If it is NULL, no checking is performed.
* @return true on success, or false on failure.
* @note This function is for reading records and not for updating ones. The return value of
* the visitor is just ignored. To avoid deadlock, any explicit database operation must not
* be performed in this function.
*/
bool scan_parallel(Visitor *visitor, size_t thnum, ProgressChecker* checker = NULL) {
_assert_(visitor && thnum <= MEMMAXSIZ);
if (type_ == TYPEVOID) {
set_error(_KCCODELINE_, Error::INVALID, "not opened");
return false;
}
return db_->scan_parallel(visitor, thnum, checker);
}
/**
* Get the last happened error.
* @return the last happened error.
*/
Error error() const {
_assert_(true);
if (type_ == TYPEVOID) return error_;
return db_->error();
}
/**
* Set the error information.
* @param file the file name 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 code an error code.
* @param message a supplement message.
*/
void set_error(const char* file, int32_t line, const char* func,
Error::Code code, const char* message) {
_assert_(file && line > 0 && func && message);
if (type_ == TYPEVOID) {
error_.set(code, message);
return;
}
db_->set_error(file, line, func, code, message);
}
/**
* Set the error information without source code information.
* @param code an error code.
* @param message a supplement message.
*/
void set_error(Error::Code code, const char* message) {
_assert_(message);
if (type_ == TYPEVOID) {
error_.set(code, message);
return;
}
db_->set_error(_KCCODELINE_, code, message);
}
/**
* Open a database file.
* @param path the path of a database file. If it is "-", the database will be a prototype
* hash database. If it is "+", the database will be a prototype tree database. If it is ":",
* the database will be a stash database. If it is "*", the database will be a cache hash
* database. If it is "%", the database will be a cache tree database. If its suffix is
* ".kch", the database will be a file hash database. If its suffix is ".kct", the database
* will be a file tree database. If its suffix is ".kcd", the database will be a directory
* hash database. If its suffix is ".kcf", the database will be a directory tree database.
* If its suffix is ".kcx", the database will be a plain text database. Otherwise, this
* function fails. Tuning parameters can trail the name, separated by "#". Each parameter is
* composed of the name and the value, separated by "=". If the "type" parameter is specified,
* the database type is determined by the value in "-", "+", ":", "*", "%", "kch", "kct",
* "kcd", kcf", and "kcx". All database types support the logging parameters of "log",
* "logkinds", and "logpx". The prototype hash database and the prototype tree database do
* not support any other tuning parameter. The stash database supports "bnum". The cache
* hash database supports "opts", "bnum", "zcomp", "capcnt", "capsiz", and "zkey". The cache
* tree database supports all parameters of the cache hash database except for capacity
* limitation, and supports "psiz", "rcomp", "pccap" in addition. The file hash database
* supports "apow", "fpow", "opts", "bnum", "msiz", "dfunit", "zcomp", and "zkey". The file
* tree database supports all parameters of the file hash database and "psiz", "rcomp",
* "pccap" in addition. The directory hash database supports "opts", "zcomp", and "zkey".
* The directory tree database supports all parameters of the directory hash database and
* "psiz", "rcomp", "pccap" in addition. The plain text database does not support any other
* tuning parameter.
* @param mode the connection mode. PolyDB::OWRITER as a writer, PolyDB::OREADER as a
* reader. The following may be added to the writer mode by bitwise-or: PolyDB::OCREATE,
* which means it creates a new database if the file does not exist, PolyDB::OTRUNCATE, which
* means it creates a new database regardless if the file exists, PolyDB::OAUTOTRAN, which
* means each updating operation is performed in implicit transaction, PolyDB::OAUTOSYNC,
* which means each updating operation is followed by implicit synchronization with the file
* system. The following may be added to both of the reader mode and the writer mode by
* bitwise-or: PolyDB::ONOLOCK, which means it opens the database file without file locking,
* PolyDB::OTRYLOCK, which means locking is performed without blocking, PolyDB::ONOREPAIR,
* which means the database file is not repaired implicitly even if file destruction is
* detected.
* @return true on success, or false on failure.
* @note The tuning parameter "log" is for the original "tune_logger" and the value specifies
* the path of the log file, or "-" for the standard output, or "+" for the standard error.
* "logkinds" specifies kinds of logged messages and the value can be "debug", "info", "warn",
* or "error". "logpx" specifies the prefix of each log message. "opts" is for "tune_options"
* and the value can contain "s" for the small option, "l" for the linear option, and "c" for
* the compress option. "bnum" corresponds to "tune_bucket". "zcomp" is for "tune_compressor"
* and the value can be "zlib" for the ZLIB raw compressor, "def" for the ZLIB deflate
* compressor, "gz" for the ZLIB gzip compressor, "lzo" for the LZO compressor, "lzma" for the
* LZMA compressor, or "arc" for the Arcfour cipher. "zkey" specifies the cipher key of the
* compressor. "capcnt" is for "cap_count". "capsiz" is for "cap_size". "psiz" is for
* "tune_page". "rcomp" is for "tune_comparator" and the value can be "lex" for the lexical
* comparator, "dec" for the decimal comparator, "lexdesc" for the lexical descending
* comparator, or "decdesc" for the decimal descending comparator. "pccap" is for
* "tune_page_cache". "apow" is for "tune_alignment". "fpow" is for "tune_fbp". "msiz" is
* for "tune_map". "dfunit" is for "tune_defrag". Every opened database must be closed by
* the PolyDB::close method when it is no longer in use. It is not allowed for two or more
* database objects in the same process to keep their connections to the same database file at
* the same time.
*/
bool open(const std::string& path = ":", uint32_t mode = OWRITER | OCREATE) {
_assert_(true);
if (type_ == TYPEMISC) {
if (logger_) db_->tune_logger(logger_, logkinds_);
if (mtrigger_) db_->tune_meta_trigger(mtrigger_);
return db_->open(path, mode);
}
if (type_ != TYPEVOID) {
set_error(_KCCODELINE_, Error::INVALID, "already opened");
return false;
}
std::vector elems;
strsplit(path, '#', &elems);
std::string fpath;
Type type = TYPEVOID;
std::string logname = "";
std::string logpx = "";
uint32_t logkinds = Logger::WARN | Logger::ERROR;
std::string mtrgname = "";
std::string mtrgpx = "";
int64_t bnum = -1;
int64_t capcnt = -1;
int64_t capsiz = -1;
int32_t apow = -1;
int32_t fpow = -1;
bool tsmall = false;
bool tlinear = false;
bool tcompress = false;
int64_t msiz = -1;
int64_t dfunit = -1;
std::string zcompname = "";
int64_t psiz = -1;
Comparator* rcomp = NULL;
int64_t pccap = 0;
std::string zkey = "";
std::vector::iterator it = elems.begin();
std::vector::iterator itend = elems.end();
if (it != itend) {
fpath = *it;
++it;
}
const char* fstr = fpath.c_str();
const char* pv = std::strrchr(fstr, File::PATHCHR);
if (pv) fstr = pv + 1;
if (!std::strcmp(fstr, "-")) {
type = TYPEPHASH;
} else if (!std::strcmp(fstr, "+")) {
type = TYPEPTREE;
} else if (!std::strcmp(fstr, ":")) {
type = TYPESTASH;
} else if (!std::strcmp(fstr, "*")) {
type = TYPECACHE;
} else if (!std::strcmp(fstr, "%")) {
type = TYPEGRASS;
} else {
pv = std::strrchr(fstr, File::EXTCHR);
if (pv) {
pv++;
if (!std::strcmp(pv, "kcph") || !std::strcmp(pv, "phdb")) {
type = TYPEPHASH;
} else if (!std::strcmp(pv, "kcpt") || !std::strcmp(pv, "ptdb")) {
type = TYPEPTREE;
} else if (!std::strcmp(pv, "kcs") || !std::strcmp(pv, "sdb")) {
type = TYPESTASH;
} else if (!std::strcmp(pv, "kcc") || !std::strcmp(pv, "cdb")) {
type = TYPECACHE;
} else if (!std::strcmp(pv, "kcg") || !std::strcmp(pv, "gdb")) {
type = TYPEGRASS;
} else if (!std::strcmp(pv, "kch") || !std::strcmp(pv, "hdb")) {
type = TYPEHASH;
} else if (!std::strcmp(pv, "kct") || !std::strcmp(pv, "tdb")) {
type = TYPETREE;
} else if (!std::strcmp(pv, "kcd") || !std::strcmp(pv, "ddb")) {
type = TYPEDIR;
} else if (!std::strcmp(pv, "kcf") || !std::strcmp(pv, "fdb")) {
type = TYPEFOREST;
} else if (!std::strcmp(pv, "kcx") || !std::strcmp(pv, "xdb") ||
!std::strcmp(pv, "txt") || !std::strcmp(pv, "text") ||
!std::strcmp(pv, "tsv") || !std::strcmp(pv, "csv")) {
type = TYPETEXT;
}
}
}
while (it != itend) {
std::vector fields;
if (strsplit(*it, '=', &fields) > 1) {
const char* key = fields[0].c_str();
const char* value = fields[1].c_str();
if (!std::strcmp(key, "type")) {
if (!std::strcmp(value, "-") || !std::strcmp(value, "kcph") ||
!std::strcmp(value, "phdb") || !std::strcmp(value, "phash")) {
type = TYPEPHASH;
} else if (!std::strcmp(value, "+") || !std::strcmp(value, "kcpt") ||
!std::strcmp(value, "ptdb") || !std::strcmp(value, "ptree")) {
type = TYPEPTREE;
} else if (!std::strcmp(value, ":") || !std::strcmp(value, "kcs") ||
!std::strcmp(value, "sdb") || !std::strcmp(value, "stash")) {
type = TYPESTASH;
} else if (!std::strcmp(value, "*") || !std::strcmp(value, "kcc") ||
!std::strcmp(value, "cdb") || !std::strcmp(value, "cache")) {
type = TYPECACHE;
} else if (!std::strcmp(value, "%") || !std::strcmp(value, "kcg") ||
!std::strcmp(value, "gdb") || !std::strcmp(value, "grass")) {
type = TYPEGRASS;
} else if (!std::strcmp(value, "kch") || !std::strcmp(value, "hdb") ||
!std::strcmp(value, "hash")) {
type = TYPEHASH;
} else if (!std::strcmp(value, "kct") || !std::strcmp(value, "tdb") ||
!std::strcmp(value, "tree")) {
type = TYPETREE;
} else if (!std::strcmp(value, "kcd") || !std::strcmp(value, "ddb") ||
!std::strcmp(value, "dir") || !std::strcmp(value, "directory")) {
type = TYPEDIR;
} else if (!std::strcmp(value, "kcf") || !std::strcmp(value, "fdb") ||
!std::strcmp(value, "for") || !std::strcmp(value, "forest")) {
type = TYPEFOREST;
} else if (!std::strcmp(value, "kcx") || !std::strcmp(value, "xdb") ||
!std::strcmp(value, "txt") || !std::strcmp(value, "text")) {
type = TYPETEXT;
}
} else if (!std::strcmp(key, "log") || !std::strcmp(key, "logger")) {
logname = value;
} else if (!std::strcmp(key, "logkinds") || !std::strcmp(key, "logkind")) {
if (!std::strcmp(value, "debug") || !std::strcmp(value, "debugging")) {
logkinds = Logger::DEBUG | Logger::INFO | Logger::WARN | Logger::ERROR;
} else if (!std::strcmp(value, "info") || !std::strcmp(value, "information")) {
logkinds = Logger::INFO | Logger::WARN | Logger::ERROR;
} else if (!std::strcmp(value, "warn") || !std::strcmp(value, "warning")) {
logkinds = Logger::WARN | Logger::ERROR;
} else if (!std::strcmp(value, "error") || !std::strcmp(value, "fatal")) {
logkinds = Logger::ERROR;
} else {
logkinds = atoix(value);
}
} else if (!std::strcmp(key, "logpx") || !std::strcmp(key, "lpx")) {
logpx = value;
} else if (!std::strcmp(key, "mtrg") || !std::strcmp(key, "metatrigger") ||
!std::strcmp(key, "meta_trigger")) {
mtrgname = value;
} else if (!std::strcmp(key, "mtrgpx") || !std::strcmp(key, "mtpx")) {
mtrgpx = value;
} else if (!std::strcmp(key, "bnum") || !std::strcmp(key, "buckets")) {
bnum = atoix(value);
} else if (!std::strcmp(key, "capcnt") || !std::strcmp(key, "capcount") ||
!std::strcmp(key, "cap_count")) {
capcnt = atoix(value);
} else if (!std::strcmp(key, "capsiz") || !std::strcmp(key, "capsize") ||
!std::strcmp(key, "cap_size")) {
capsiz = atoix(value);
} else if (!std::strcmp(key, "apow") || !std::strcmp(key, "alignment")) {
apow = atoix(value);
} else if (!std::strcmp(key, "fpow") || !std::strcmp(key, "fbp")) {
fpow = atoix(value);
} else if (!std::strcmp(key, "opts") || !std::strcmp(key, "options")) {
if (std::strchr(value, 's')) tsmall = true;
if (std::strchr(value, 'l')) tlinear = true;
if (std::strchr(value, 'c')) tcompress = true;
} else if (!std::strcmp(key, "msiz") || !std::strcmp(key, "map")) {
msiz = atoix(value);
} else if (!std::strcmp(key, "dfunit") || !std::strcmp(key, "defrag")) {
dfunit = atoix(value);
} else if (!std::strcmp(key, "zcomp") || !std::strcmp(key, "compressor")) {
zcompname = value;
} else if (!std::strcmp(key, "psiz") || !std::strcmp(key, "page")) {
psiz = atoix(value);
} else if (!std::strcmp(key, "pccap") || !std::strcmp(key, "cache")) {
pccap = atoix(value);
} else if (!std::strcmp(key, "rcomp") || !std::strcmp(key, "comparator")) {
if (!std::strcmp(value, "lex") || !std::strcmp(value, "lexical")) {
rcomp = LEXICALCOMP;
} else if (!std::strcmp(value, "dec") || !std::strcmp(value, "decimal")) {
rcomp = DECIMALCOMP;
} else if (!std::strcmp(value, "lexdesc") || !std::strcmp(value, "lexicaldesc")) {
rcomp = LEXICALDESCCOMP;
} else if (!std::strcmp(value, "decdesc") || !std::strcmp(value, "decimaldesc")) {
rcomp = DECIMALDESCCOMP;
}
} else if (!std::strcmp(key, "zkey") || !std::strcmp(key, "pass") ||
!std::strcmp(key, "password")) {
zkey = value;
}
}
++it;
}
delete stdlogger_;
delete stdlogstrm_;
stdlogstrm_ = NULL;
stdlogger_ = NULL;
if (!logname.empty()) {
std::ostream* stdlogstrm = NULL;
if (logname == "-" || logname == "[stdout]" || logname == "[cout]") {
stdlogstrm = &std::cout;
} else if (logname == "+" || logname == "[stderr]" || logname == "[cerr]") {
stdlogstrm = &std::cerr;
} else {
std::ofstream *ofs = new std::ofstream;
ofs->open(logname.c_str(),
std::ios_base::out | std::ios_base::binary | std::ios_base::app);
if (!*ofs) ofs->open(logname.c_str(), std::ios_base::out | std::ios_base::binary);
if (ofs) {
stdlogstrm = ofs;
stdlogstrm_ = ofs;
} else {
delete ofs;
}
}
if (stdlogstrm) stdlogger_ = new StreamLogger(stdlogstrm, logpx.c_str());
}
delete stdmtrigger_;
delete stdmtrgstrm_;
stdmtrgstrm_ = NULL;
stdmtrigger_ = NULL;
if (!mtrgname.empty()) {
std::ostream* stdmtrgstrm = NULL;
if (mtrgname == "-" || mtrgname == "[stdout]" || mtrgname == "[cout]") {
stdmtrgstrm = &std::cout;
} else if (mtrgname == "+" || mtrgname == "[stderr]" || mtrgname == "[cerr]") {
stdmtrgstrm = &std::cerr;
} else {
std::ofstream *ofs = new std::ofstream;
ofs->open(mtrgname.c_str(),
std::ios_base::out | std::ios_base::binary | std::ios_base::app);
if (!*ofs) ofs->open(mtrgname.c_str(), std::ios_base::out | std::ios_base::binary);
if (ofs) {
stdmtrgstrm = ofs;
stdmtrgstrm_ = ofs;
} else {
delete ofs;
}
}
if (stdmtrgstrm) stdmtrigger_ = new StreamMetaTrigger(stdmtrgstrm, mtrgpx.c_str());
}
delete zcomp_;
zcomp_ = NULL;
ArcfourCompressor* arccomp = NULL;
if (!zcompname.empty()) {
if (zcompname == "zlib" || zcompname == "raw") {
zcomp_ = new ZLIBCompressor;
} else if (zcompname == "def" || zcompname == "deflate") {
zcomp_ = new ZLIBCompressor;
} else if (zcompname == "gz" || zcompname == "gzip") {
zcomp_ = new ZLIBCompressor;
} else if (zcompname == "lzo" || zcompname == "oz") {
zcomp_ = new LZOCompressor;
} else if (zcompname == "lzocrc" || zcompname == "ozcrc") {
zcomp_ = new LZOCompressor;
} else if (zcompname == "lzma" || zcompname == "xz") {
zcomp_ = new LZMACompressor;
} else if (zcompname == "lzmacrc" || zcompname == "xzcrc") {
zcomp_ = new LZMACompressor