#include #include "acl_cpp/lib_acl.hpp" #include static acl::atomic_long __count = 0; static int __inter = 10000; class wdb { public: wdb(const char* home) : home_(home) , conn_(NULL) {} ~wdb(void) { if (conn_) { conn_->close(conn_, NULL); } } bool open(void) { if (conn_) { return true; } int ret = wiredtiger_open(home_.c_str(), NULL, "create", &conn_); if (ret != 0) { printf("open %s failed, ret=%d\r\n", home_.c_str(), ret); return false; } return true; } WT_CONNECTION* get_conn(void) const { return conn_; } private: acl::string home_; WT_CONNECTION *conn_; }; class wdb_sess { public: wdb_sess(wdb& db) : db_(db) , session_(NULL) , cursor_(NULL) {} ~wdb_sess(void) {} bool open(void) { bool ret = db_.get_conn()->open_session(db_.get_conn(), NULL, NULL, &session_); if (ret != 0) { printf("open session failed, ret=%d\r\n", ret); return false; } ret = session_->create(session_, "table:access", "key_format=S, value_format=S"); if (ret != 0) { printf("create session failed, ret=%d\r\n", ret); return false; } ret = session_->open_cursor(session_, "table:access", NULL, NULL, &cursor_); if (ret != 0) { printf("create table failed, ret=%d\r\n", ret); return false; } return true; } bool add(const char* key, const char* value) { assert(cursor_); cursor_->set_key(cursor_, key); cursor_->set_value(cursor_, value); int ret = cursor_->insert(cursor_); if (ret != 0) { printf("insert %s %s failed, ret=%d\r\n", key, value, ret); return false; } cursor_->reset(cursor_); return true; } bool get(const char* key, acl::string& value) { assert(cursor_); cursor_->set_key(cursor_, key); int ret = cursor_->search(cursor_); if (ret != 0) { printf("search %s failed, ret=%d\r\n", key, ret); return false; } const char* v; ret = cursor_->get_value(cursor_, &v); if (ret != 0) { printf("get_value %s failed, ret=%d\r\n", key, ret); return false; } value = v; cursor_->reset(cursor_); return true; } bool del(const char* key) { assert(cursor_); cursor_->set_key(cursor_, key); int ret = cursor_->remove(cursor_); if (ret != 0) { printf("remove %s failed, ret=%d\r\n", key, ret); return false; } cursor_->reset(cursor_); return true; } private: wdb& db_; WT_SESSION *session_; WT_CURSOR *cursor_; }; class db_thread : public acl::thread { public: db_thread(int id, wdb& db, const char* action, int max) : id_(id), db_(db), action_(action), max_(max) {} ~db_thread(void) {} private: // @override void* run(void) { wdb_sess sess(db_); if (sess.open() == false) { printf("open db session failed\r\n"); return NULL; } if (action_ == "add") { add(sess, max_); } else if (action_ == "get") { get(sess, max_); } else if (action_ == "del") { del(sess, max_); } else { printf("invalid action=%s\r\n", action_.c_str()); } return NULL; } void add(wdb_sess& sess, long long max) { acl::string key, value; long long i, n; struct timeval begin; gettimeofday(&begin, NULL); for (i = 0; i < max; i++) { key.format("key-%d-%lld", id_, i); value.format("value-%lld", i); bool ret = sess.add(key.c_str(), value.c_str()); if (!ret) { printf("add failed, key=%s, value=%s\r\n", key.c_str(), value.c_str()); break; } n = ++__count; if (i % __inter == 0) { char buf[128]; snprintf(buf, sizeof(buf), "i=%lld, count=%lld, value=%s", i, n, value.c_str()); acl::meter_time(__FILE__, __LINE__, buf); } } struct timeval end; gettimeofday(&end, NULL); double spent = acl::stamp_sub(end, begin); double speed = (i * 1000) / ( spent > 1 ? spent : 1); printf("add over, n=%lld, spent=%.2f seconds, speed=%.2f\r\n", i, spent / 1000, speed); } void get(wdb_sess& sess, long long max) { acl::string key, value; long long i; long long n, j = 0, k = max - 1; struct timeval begin; gettimeofday(&begin, NULL); for (i = 0; i < max; i++) { if (i % 2 == 0) { key.format("key-%d-%lld", id_, j++); } else { key.format("key-%d-%lld", id_, k--); } bool ret = sess.get(key.c_str(), value); if (!ret) { printf("Get failed, key=%s\r\n", key.c_str()); break; } else if (i < 10) { printf("key=%s, value=%s\r\n", key.c_str(), value.c_str()); } n = ++__count; if (i % __inter == 0) { char buf[128]; snprintf(buf, sizeof(buf), "i=%lld, count=%lld, value=%s", i, n, value.c_str()); acl::meter_time(__FILE__, __LINE__, buf); } } struct timeval end; gettimeofday(&end, NULL); double spent = acl::stamp_sub(end, begin); double speed = (i * 1000) / ( spent > 1 ? spent : 1); printf("get over, n=%lld, spend=%.2f seconds, speed=%.2f\r\n", i, spent / 1000, speed); } void del(wdb_sess& sess, long long max) { acl::string key; long long i; for (i = 0; i < max; i++) { key.format("key-%d-%lld", id_, i); bool ret = sess.del(key.c_str()); if (!ret) { printf("Del failed, key=%s\r\n", key.c_str()); break; } } printf("del over, n=%lld\r\n", i); } private: int id_; wdb& db_; acl::string action_; int max_; }; static void usage(const char* procname) { printf("usage: %s -h [help]\r\n" " -c threads_count\r\n" " -a action[default: get, add|get|del]\r\n" " -n max_loop\r\n" " -i inter\r\n" , procname); } int main(int argc, char* argv[]) { const char* dbpath = "./db"; int ch, max = 1000, nthread = 1; acl::string action("get"); while ((ch = getopt(argc, argv, "hn:a:c:i:")) > 0) { switch (ch) { case 'h': usage(argv[0]); return 0; case 'n': max = atoi(optarg); break; case 'a': action = optarg; break; case 'c': nthread = atoi(optarg); break; case 'i': __inter = atoi(optarg); break; default: break; } } acl::string path; path << dbpath; wdb db(path); if (!db.open()) { printf("open db(%s) error\r\n", dbpath); return 1; } std::vector threads; for (int i = 0; i < nthread; i++) { acl::thread* thr = new db_thread(i, db, action, max); threads.push_back(thr); thr->start(); } for (std::vector::iterator it = threads.begin(); it != threads.end(); ++it) { (*it)->wait(); delete *it; } return 0; }