123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513 |
- // Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
- //
- // Permission to use, copy, modify, and/or distribute this software for any
- // purpose with or without fee is hereby granted, provided that the above
- // copyright notice and this permission notice appear in all copies.
- //
- // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- // PERFORMANCE OF THIS SOFTWARE.
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdint.h>
- #include <string.h>
- #include <sstream>
- #include <iostream>
- #include <sqlite3.h>
- #include "sqlite_ubench.h"
- using namespace std;
- SQLite_uBenchmark::SQLite_uBenchmark(const string& filename,
- uint32_t num_iterations,
- bool sync, bool verbose)
- :uBenchmark(num_iterations, filename, sync, verbose),
- db_(NULL) {
- }
- void SQLite_uBenchmark::connect() {
- int result = sqlite3_open(dbname_.c_str(), &db_);
- if (result != SQLITE_OK) {
- failure("Failed to open DB file");
- }
- result = sqlite3_exec(db_, "DELETE FROM lease4", NULL, NULL, NULL);
- if (result != SQLITE_OK) {
- failure("Failed to delete old entries");
- }
- if (sync_) {
- sqlite3_exec(db_, "PRAGMA synchronous = ON", NULL, NULL, NULL);
- } else {
- sqlite3_exec(db_, "PRAGMA synchronous = OFF", NULL, NULL, NULL);
- }
- // see http://www.sqlite.org/pragma.html#pragma_journal_mode
- // for detailed explanation. Available modes: DELETE, TRUNCATE,
- // PERSIST, MEMORY, WAL, OFF
- sqlite3_exec(db_, "PRAGMA journal_mode = OFF", NULL, NULL, NULL);
- }
- void SQLite_uBenchmark::disconnect() {
- if (db_) {
- sqlite3_close(db_);
- db_ = NULL;
- } else {
- throw "Can't close SQLite connection: it was never open.";
- }
- }
- void SQLite_uBenchmark::createLease4Test() {
- if (!db_) {
- throw "SQLite connection is closed.";
- }
- uint32_t addr = BASE_ADDR4; // Let's start with 1.0.0.0 address
- const uint8_t hwaddr_len = 20; // Not a real field
- char hwaddr[hwaddr_len];
- const uint8_t client_id_len = 128;
- char client_id[client_id_len];
- uint32_t valid_lft = 1000; // We can use the same value for all leases
- uint32_t recycle_time = 0; // Not supported in any foresable future,
- // so keep this as 0
- char cltt[48]; // Timestamp
- uint32_t pool_id = 0; // Let's use pools 0-99
- bool fixed = false;
- string hostname("foo"); // Will generate it dynamically
- bool fqdn_fwd = true; // Let's pretend to do AAAA update
- bool fqdn_rev = true; // Let's pretend to do PTR update
- cout << "CREATE: ";
- for (uint8_t i = 0; i < hwaddr_len; i++) {
- hwaddr[i] = 65 + i;
- }
- hwaddr[19] = 0; // workaround
- for (uint8_t i = 0; i < client_id_len; i++) {
- client_id[i] = 33 + i;
- }
- client_id[6] = 'X'; // there's apostrophe here. It would confuse
- // query formatting, let's get rid of it
- client_id[127] = 0; // workaround
- sqlite3_stmt *stmt = NULL;
- if (compiled_stmt_) {
- char query[] = "INSERT INTO lease4(addr,hwaddr,client_id,"
- "valid_lft,recycle_time,cltt,pool_id,fixed,hostname,"
- "fqdn_fwd,fqdn_rev) VALUES(?001,?002,?003,?004,?005,?006,?007,?008,?009,?010,?011);";
- int result = sqlite3_prepare_v2(db_, query, strlen(query), &stmt, NULL);
- if (result != SQLITE_OK) {
- failure("Failed to compile statement");
- }
- }
- for (uint32_t i = 0; i < num_; i++) {
- sprintf(cltt, "2012-07-11 15:43:%02d", i % 60);
- addr++;
- char* errorMsg = NULL;
- if (!compiled_stmt_) {
- // the first address is 1.0.0.0.
- char query[2000];
- /// @todo: Encode HWADDR and CLIENT-ID properly
- sprintf(query, "INSERT INTO lease4(addr,hwaddr,client_id,"
- "valid_lft,recycle_time,cltt,pool_id,fixed,hostname,"
- "fqdn_fwd,fqdn_rev) VALUES(%u,'%s','%s',%d,%d,'%s',%d,'%s','%s','%s','%s');",
- addr, hwaddr, client_id, valid_lft, recycle_time,
- cltt, pool_id, (fixed?"true":"false"),
- hostname.c_str(), (fqdn_fwd?"true":"false"), (fqdn_rev?"true":"false"));
- int result = sqlite3_exec(db_, query, NULL, 0, &errorMsg);
- if (result != SQLITE_OK) {
- stringstream tmp;
- tmp << "INSERT error:" << errorMsg;
- failure(tmp.str().c_str());
- }
- } else {
- // compiled statement
- int result = sqlite3_bind_int(stmt, 1, addr);
- if (result != SQLITE_OK) {
- failure("sqlite3_bind_int() for column 1");
- }
- result = sqlite3_bind_blob(stmt, 2, hwaddr, hwaddr_len, NULL);
- if (result != SQLITE_OK) {
- failure("sqlite3_bind_blob() for column 2");
- }
- result = sqlite3_bind_blob(stmt, 3, client_id, client_id_len, NULL);
- if (result != SQLITE_OK) {
- failure("sqlite3_bind_blob() for column 3");
- }
- if (sqlite3_bind_int(stmt, 4, valid_lft) != SQLITE_OK) {
- failure("sqlite3_bind_int() for column 4");
- }
- if (sqlite3_bind_int(stmt, 5, recycle_time) != SQLITE_OK) {
- failure("sqlite3_bind_int() for column 5");
- }
- if (sqlite3_bind_text(stmt, 6, cltt, strlen(cltt), NULL) != SQLITE_OK) {
- failure("sqlite3_bind_int() for column 6");
- }
- if (sqlite3_bind_int(stmt, 7, pool_id) != SQLITE_OK) {
- failure("sqlite3_bind_int() for column 7");
- }
- if (sqlite3_bind_int(stmt, 7, pool_id) != SQLITE_OK) {
- failure("sqlite3_bind_int() for column 7");
- }
- if (sqlite3_bind_int(stmt, 8, fixed) != SQLITE_OK) {
- failure("sqlite3_bind_int() for column 8");
- }
- if (sqlite3_bind_text(stmt, 9, hostname.c_str(), hostname.length(), NULL) != SQLITE_OK) {
- failure("sqlite3_bind_int() for column 9");
- }
- if (sqlite3_bind_int(stmt, 10, fqdn_fwd) != SQLITE_OK) {
- failure("sqlite3_bind_int() for column 10");
- }
- if (sqlite3_bind_int(stmt, 11, fqdn_rev) != SQLITE_OK) {
- failure("sqlite3_bind_int() for column 11");
- }
- result = sqlite3_step(stmt);
- if (result != SQLITE_DONE) {
- failure("Failed to execute INSERT clause");
- }
- // let's reset the compiled statement, so it can be used in the
- // next iteration
- result = sqlite3_reset(stmt);
- if (result != SQLITE_OK) {
- failure("Failed to execute sqlite3_reset()");
- }
- }
- if (verbose_) {
- cout << ".";
- }
- }
- if (compiled_stmt_) {
- int result = sqlite3_finalize(stmt);
- if (result != SQLITE_OK) {
- failure("sqlite3_finalize() failed");
- }
- }
- cout << endl;
- }
- static int search_callback(void *counter, int argc, char** argv,
- char** azColName){
- int* cnt = static_cast<int*>(counter);
- (*cnt)++;
- char buf[512];
- // retrieved lease can be accessed here
- for(int i = 0; i < argc; i++){
- // pretend we do something with returned lease
- if (argv[i]) {
- strncpy(buf, azColName[i], 512);
- strncpy(buf, argv[i], 512);
- }
- // Uncomment this to print out all contents
- // cout << azColName[i] << "=" << (argv[i] ? argv[i] : "NULL") << endl;
- }
- return (0);
- }
- void SQLite_uBenchmark::searchLease4Test() {
- if (!db_) {
- throw "SQLite connection is closed.";
- }
- cout << "RETRIEVE: ";
- sqlite3_stmt *stmt = NULL;
- if (compiled_stmt_) {
- const char query[] = "SELECT lease_id,addr,hwaddr,client_id,valid_lft,"
- "cltt,pool_id,fixed,hostname,fqdn_fwd,fqdn_rev "
- "FROM lease4 where addr=?1";
- int result = sqlite3_prepare_v2(db_, query, strlen(query), &stmt, NULL);
- if (result != SQLITE_OK) {
- failure("Failed to compile statement");
- }
- }
- for (uint32_t i = 0; i < num_; i++) {
- uint32_t addr = BASE_ADDR4 + random() % int(num_ / hitratio_);
- int cnt = 0;
- if (!compiled_stmt_) {
- char* errorMsg = NULL;
- char query[512];
- sprintf(query, "SELECT lease_id,addr,hwaddr,client_id,valid_lft,"
- "cltt,pool_id,fixed,hostname,fqdn_fwd,fqdn_rev "
- "FROM lease4 where addr=%d", addr);
- int result = sqlite3_exec(db_, query, search_callback, &cnt, &errorMsg);
- if (result != SQLITE_OK) {
- stringstream tmp;
- tmp << "SELECT failed: " << errorMsg;
- failure(tmp.str().c_str());
- }
- } else {
- // compiled statement
- int result = sqlite3_bind_int(stmt, 1, addr);
- if (result != SQLITE_OK) {
- failure("sqlite3_bind_int() for column 1");
- }
- result = sqlite3_step(stmt);
- switch (result) {
- case SQLITE_ROW:
- {
- uint32_t lease_addr = sqlite3_column_int(stmt, 1);
- const void * lease_hwaddr = sqlite3_column_blob(stmt, 2);
- uint32_t lease_hwaddr_len = sqlite3_column_bytes(stmt, 2);
- const void * lease_clientid = sqlite3_column_blob(stmt, 3);
- uint32_t lease_clientid_len = sqlite3_column_bytes(stmt, 3);
- uint32_t lease_valid_lft = sqlite3_column_int(stmt, 4);
- // cltt
- const unsigned char *lease_cltt = sqlite3_column_text(stmt, 5);
- uint32_t lease_pool_id = sqlite3_column_int(stmt, 6);
- uint32_t lease_fixed = sqlite3_column_int(stmt, 7);
- const unsigned char *lease_hostname = sqlite3_column_text(stmt, 8);
- uint32_t lease_fqdn_fwd = sqlite3_column_int(stmt, 9);
- uint32_t lease_fqdn_rev = sqlite3_column_int(stmt, 10);
- if (lease_addr || lease_hwaddr || lease_hwaddr_len || lease_clientid ||
- lease_clientid_len || lease_valid_lft || lease_cltt || lease_pool_id ||
- lease_fixed || lease_hostname || lease_fqdn_fwd || lease_fqdn_rev) {
- // we don't need this information, we just want to obtain it to measure
- // the overhead. That strange if is only to quell compiler/cppcheck
- // warning about unused variables.
- cnt = 1;
- }
- cnt = 1; // there is at least one row
- break;
- }
- case SQLITE_DONE:
- cnt = 0; // there are no rows at all (i.e. no such lease)
- break;
- default:
- failure("Failed to execute SELECT clause");
- }
- // let's reset the compiled statement, so it can be used in the
- // next iteration
- result = sqlite3_reset(stmt);
- if (result != SQLITE_OK) {
- failure("Failed to execute sqlite3_reset()");
- }
- }
- if (verbose_) {
- cout << (cnt?".":"X");
- }
- }
- if (compiled_stmt_) {
- int result = sqlite3_finalize(stmt);
- if (result != SQLITE_OK) {
- failure("sqlite3_finalize() failed");
- }
- }
- cout << endl;
- }
- void SQLite_uBenchmark::updateLease4Test() {
- if (!db_) {
- throw "SQLite connection is closed.";
- }
- cout << "UPDATE: ";
- sqlite3_stmt *stmt = NULL;
- if (compiled_stmt_) {
- const char query[] = "UPDATE lease4 SET valid_lft=1002, cltt='now' WHERE addr=?1";
- int result = sqlite3_prepare_v2(db_, query, strlen(query), &stmt, NULL);
- if (result != SQLITE_OK) {
- failure("Failed to compile statement");
- }
- }
- for (uint32_t i = 0; i < num_; i++) {
- uint32_t addr = BASE_ADDR4 + random() % num_;
- if (!compiled_stmt_) {
- char* errorMsg = NULL;
- char query[512];
- sprintf(query, "UPDATE lease4 SET valid_lft=1002, cltt='now' WHERE addr=%d",
- addr);
- int result = sqlite3_exec(db_, query, NULL /* no callback here*/, 0, &errorMsg);
- if (result != SQLITE_OK) {
- stringstream tmp;
- tmp << "UPDATE error:" << errorMsg;
- failure(tmp.str().c_str());
- }
- } else {
- int result = sqlite3_bind_int(stmt, 1, addr);
- if (result != SQLITE_OK) {
- failure("sqlite3_bind_int() for column 1");
- }
- result = sqlite3_step(stmt);
- if (result != SQLITE_OK && result != SQLITE_DONE) {
- failure("Failed to execute sqlite3_step() for UPDATE");
- }
- // let's reset the compiled statement, so it can be used in the
- // next iteration
- result = sqlite3_reset(stmt);
- if (result != SQLITE_OK) {
- failure("Failed to execute sqlite3_reset()");
- }
- }
- if (verbose_) {
- cout << ".";
- }
- }
- if (compiled_stmt_) {
- int result = sqlite3_finalize(stmt);
- if (result != SQLITE_OK) {
- failure("sqlite3_finalize() failed");
- }
- }
- cout << endl;
- }
- void SQLite_uBenchmark::deleteLease4Test() {
- if (!db_) {
- throw "SQLite connection is closed.";
- }
- cout << "DELETE: ";
- sqlite3_stmt *stmt = NULL;
- if (compiled_stmt_) {
- const char query[] = "DELETE FROM lease4 WHERE addr=?1";
- int result = sqlite3_prepare_v2(db_, query, strlen(query), &stmt, NULL);
- if (result != SQLITE_OK) {
- failure("Failed to compile statement");
- }
- }
- for (uint32_t i = 0; i < num_; i++) {
- uint32_t addr = BASE_ADDR4 + i;
- if (!compiled_stmt_) {
- char* errorMsg = NULL;
- char query[2000];
- sprintf(query, "DELETE FROM lease4 WHERE addr=%d", addr);
- int result = sqlite3_exec(db_, query, NULL /* no callback here*/, 0, &errorMsg);
- if (result != SQLITE_OK) {
- stringstream tmp;
- tmp << "DELETE error:" << errorMsg;
- failure(tmp.str().c_str());
- }
- } else {
- // compiled statement
- int result = sqlite3_bind_int(stmt, 1, addr);
- if (result != SQLITE_OK) {
- failure("sqlite3_bind_int() for column 1");
- }
- result = sqlite3_step(stmt);
- if (result != SQLITE_OK && result != SQLITE_DONE) {
- failure("Failed to execute sqlite3_step() for UPDATE");
- }
- // let's reset the compiled statement, so it can be used in the
- // next iteration
- result = sqlite3_reset(stmt);
- if (result != SQLITE_OK) {
- failure("Failed to execute sqlite3_reset()");
- }
- }
- if (verbose_) {
- cout << ".";
- }
- }
- if (compiled_stmt_) {
- int result = sqlite3_finalize(stmt);
- if (result != SQLITE_OK) {
- failure("sqlite3_finalize() failed");
- }
- }
- cout << endl;
- }
- void SQLite_uBenchmark::printInfo() {
- cout << "SQLite version is " << sqlite3_libversion()
- << "sourceid version is " << sqlite3_sourceid() << endl;
- }
- int main(int argc, char* const argv[]) {
- const char* filename = "sqlite.db";
- uint32_t num = 100;
- bool sync = true;
- bool verbose = true;
- SQLite_uBenchmark bench(filename, num, sync, verbose);
- bench.parseCmdline(argc, argv);
- int result = bench.run();
- return (result);
- }
|