/*************************************************************************************************
* Common symbols for command line utilities
* 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 .
*************************************************************************************************/
#ifndef _CMDCOMMON_H // duplication check
#define _CMDCOMMON_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#if !defined(_KC_PREFIX)
#define _KC_PREFIX "*"
#endif
#if !defined(_KC_INCLUDEDIR)
#define _KC_INCLUDEDIR "*"
#endif
#if !defined(_KC_LIBDIR)
#define _KC_LIBDIR "*"
#endif
#if !defined(_KC_BINDIR)
#define _KC_BINDIR "*"
#endif
#if !defined(_KC_LIBEXECDIR)
#define _KC_LIBEXECDIR "*"
#endif
#if !defined(_KC_APPINC)
#define _KC_APPINC "*"
#endif
#if !defined(_KC_APPLIBS)
#define _KC_APPLIBS "*"
#endif
namespace kc = kyotocabinet;
// constants
const int32_t THREADMAX = 64; // maximum number of threads
const size_t RECBUFSIZ = 64; // buffer size for a record
const size_t RECBUFSIZL = 1024; // buffer size for a long record
// global variables
uint64_t g_rnd_x = 123456789;
uint64_t g_rnd_y = 362436069;
uint64_t g_rnd_z = 521288629;
uint64_t g_rnd_w = 88675123;
// function prototypes
void mysrand(int64_t seed);
int64_t myrand(int64_t range);
int64_t memusage();
void oprintf(const char* format, ...);
void oputchar(char c);
void eprintf(const char* format, ...);
void printversion();
void printdata(const char* buf, int32_t size, bool px);
bool mygetline(std::istream* is, std::string* str);
std::string unitnumstr(int64_t num);
std::string unitnumstrbyte(int64_t num);
kc::BasicDB::ProgressChecker* stdchecker(const char* prefix, std::ostream* strm);
kc::BasicDB::Logger* stdlogger(const char* progname, std::ostream* strm);
void printdb(kc::BasicDB* db, bool px = false);
// checker to show progress by printing dots
class DotChecker : public kc::BasicDB::ProgressChecker {
public:
explicit DotChecker(std::ostream* strm, int64_t freq) : strm_(strm), freq_(freq), cnt_(0) {}
int64_t count() {
return cnt_;
}
private:
bool check(const char* name, const char* message, int64_t curcnt, int64_t allcnt) {
if (std::strcmp(message, "processing") || freq_ == 0) return true;
if (freq_ < 0) {
cnt_++;
if (cnt_ % -freq_ == 0) {
oputchar('.');
if (cnt_ % (-freq_ * 50) == 0) oprintf(" (%lld)\n", (long long)cnt_);
}
} else {
if (curcnt > cnt_) {
cnt_ = curcnt;
if (cnt_ % freq_ == 0) {
oputchar('.');
if (cnt_ % (freq_ * 50) == 0) oprintf(" (%lld)\n", (long long)cnt_);
}
}
}
return true;
}
std::ostream* strm_;
int64_t freq_;
int64_t cnt_;
};
// get the random seed
inline void mysrand(int64_t seed) {
g_rnd_x = seed;
for (int32_t i = 0; i < 16; i++) {
myrand(1);
}
}
// get a random number
inline int64_t myrand(int64_t range) {
uint64_t t = g_rnd_x ^ (g_rnd_x << 11);
g_rnd_x = g_rnd_y;
g_rnd_y = g_rnd_z;
g_rnd_z = g_rnd_w;
g_rnd_w = (g_rnd_w ^ (g_rnd_w >> 19)) ^ (t ^ (t >> 8));
return (g_rnd_w & kc::INT64MAX) % range;
}
// get the current memory usage
inline int64_t memusage() {
std::map info;
kc::getsysinfo(&info);
return kc::atoi(info["mem_rss"].c_str());
}
// print formatted information string and flush the buffer
inline void oprintf(const char* format, ...) {
std::string msg;
va_list ap;
va_start(ap, format);
kc::vstrprintf(&msg, format, ap);
va_end(ap);
std::cout << msg;
std::cout.flush();
}
// print a character and flush the buffer
inline void oputchar(char c) {
std::cout << c;
std::cout.flush();
}
// print formatted error string and flush the buffer
inline void eprintf(const char* format, ...) {
std::string msg;
va_list ap;
va_start(ap, format);
kc::vstrprintf(&msg, format, ap);
va_end(ap);
std::cerr << msg;
std::cerr.flush();
}
// print the versin information
inline void printversion() {
oprintf("Kyoto Cabinet %s (%d.%d:%d) on %s\n",
kc::VERSION, kc::LIBVER, kc::LIBREV, kc::FMTVER, kc::OSNAME);
}
// print record data
inline void printdata(const char* buf, int32_t size, bool px) {
size_t cnt = 0;
char numbuf[kc::NUMBUFSIZ];
while (size-- > 0) {
if (px) {
if (cnt++ > 0) putchar(' ');
std::sprintf(numbuf, "%02X", *(unsigned char*)buf);
std::cout << numbuf;
} else {
std::cout << *buf;
}
buf++;
}
}
// read a line from a file descriptor
inline bool mygetline(std::istream* is, std::string* str) {
str->clear();
bool hit = false;
char c;
while (is->get(c)) {
hit = true;
if (c == '\0' || c == '\r') continue;
if (c == '\n') break;
str->append(1, c);
}
return hit;
}
// convert a number into the string with the decimal unit
inline std::string unitnumstr(int64_t num) {
if (num >= std::pow(1000.0, 6)) {
return kc::strprintf("%.3Lf quintillion", (long double)num / std::pow(1000.0, 6));
} else if (num >= std::pow(1000.0, 5)) {
return kc::strprintf("%.3Lf quadrillion", (long double)num / std::pow(1000.0, 5));
} else if (num >= std::pow(1000.0, 4)) {
return kc::strprintf("%.3Lf trillion", (long double)num / std::pow(1000.0, 4));
} else if (num >= std::pow(1000.0, 3)) {
return kc::strprintf("%.3Lf billion", (long double)num / std::pow(1000.0, 3));
} else if (num >= std::pow(1000.0, 2)) {
return kc::strprintf("%.3Lf million", (long double)num / std::pow(1000.0, 2));
} else if (num >= std::pow(1000.0, 1)) {
return kc::strprintf("%.3Lf thousand", (long double)num / std::pow(1000.0, 1));
}
return kc::strprintf("%lld", (long long)num);
}
// convert a number into the string with the byte unit
inline std::string unitnumstrbyte(int64_t num) {
if ((unsigned long long)num >= 1ULL << 60) {
return kc::strprintf("%.3Lf EiB", (long double)num / (1ULL << 60));
} else if ((unsigned long long)num >= 1ULL << 50) {
return kc::strprintf("%.3Lf PiB", (long double)num / (1ULL << 50));
} else if ((unsigned long long)num >= 1ULL << 40) {
return kc::strprintf("%.3Lf TiB", (long double)num / (1ULL << 40));
} else if ((unsigned long long)num >= 1ULL << 30) {
return kc::strprintf("%.3Lf GiB", (long double)num / (1ULL << 30));
} else if ((unsigned long long)num >= 1ULL << 20) {
return kc::strprintf("%.3Lf MiB", (long double)num / (1ULL << 20));
} else if ((unsigned long long)num >= 1ULL << 10) {
return kc::strprintf("%.3Lf KiB", (long double)num / (1ULL << 10));
}
return kc::strprintf("%lld B", (long long)num);
}
// get the progress checker to print the parameters
inline kc::BasicDB::ProgressChecker* stdchecker(const char* prefix, std::ostream* strm) {
class CheckerImpl : public kc::BasicDB::ProgressChecker {
public:
explicit CheckerImpl(std::ostream* strm, const char* prefix) :
strm_(strm), prefix_(prefix) {}
bool check(const char* name, const char* message, int64_t curcnt, int64_t allcnt) {
*strm_ << prefix_ << ": " << name << ": " << message << ": " <<
curcnt << "/" << allcnt << std::endl;
return true;
}
private:
std::ostream* strm_;
const char* prefix_;
};
static CheckerImpl checker(strm, prefix);
return &checker;
}
// get the logger into the standard stream
inline kc::BasicDB::Logger* stdlogger(const char* prefix, std::ostream* strm) {
class LoggerImpl : public kc::BasicDB::Logger {
public:
explicit LoggerImpl(std::ostream* strm, const char* prefix) :
strm_(strm), prefix_(prefix) {}
void log(const char* file, int32_t line, const char* func, Kind kind,
const char* message) {
const char* kstr = "MISC";
switch (kind) {
case kc::BasicDB::Logger::DEBUG: kstr = "DEBUG"; break;
case kc::BasicDB::Logger::INFO: kstr = "INFO"; break;
case kc::BasicDB::Logger::WARN: kstr = "WARN"; break;
case kc::BasicDB::Logger::ERROR: kstr = "ERROR"; break;
}
*strm_ << prefix_ << ": [" << kstr << "]: " <<
file << ": " << line << ": " << func << ": " << message << std::endl;
}
private:
std::ostream* strm_;
const char* prefix_;
};
static LoggerImpl logger(strm, prefix);
return &logger;
}
// print all record of a database
inline void printdb(kc::BasicDB* db, bool px) {
class Printer : public kc::DB::Visitor {
public:
explicit Printer(bool px) : 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_);
oputchar('\t');
printdata(vbuf, vsiz, px_);
oputchar('\n');
return NOP;
}
bool px_;
} printer(px);
db->iterate(&printer, false);
}
#endif // duplication check
// END OF FILE