2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-30 05:27:55 +00:00

[3736] Removed dhcp-ubench and folders.

This commit is contained in:
Marcin Siodelski 2015-03-06 20:11:22 +01:00
parent bfce8a989b
commit a25ec56db7
20 changed files with 1 additions and 3935 deletions

View File

@ -2,7 +2,7 @@ ACLOCAL_AMFLAGS = -I m4macros ${ACLOCAL_FLAGS}
# ^^^^^^^^ This has to be the first line and cannot come later in this
# Makefile.am due to some bork in some versions of autotools.
SUBDIRS = compatcheck doc . ext src tests m4macros
SUBDIRS = compatcheck doc . ext src m4macros
USE_LCOV=@USE_LCOV@
LCOV=@LCOV@
GENHTML=@GENHTML@
@ -81,7 +81,6 @@ endif
if HAVE_OPENSSL
openssl/\* \
endif
tests/\* \
unittests/\* \
\*_unittests.cc \
\*_unittest.cc \

View File

@ -1504,8 +1504,6 @@ AC_CONFIG_FILES([compatcheck/Makefile
src/lib/util/threads/tests/Makefile
src/lib/util/unittests/Makefile
tools/path_replacer.sh
tests/Makefile
tests/tools/Makefile
])
AC_CONFIG_COMMANDS([permissions], [

View File

@ -1 +0,0 @@
SUBDIRS = tools

View File

@ -1 +0,0 @@
SUBDIRS = .

View File

@ -1,65 +0,0 @@
# Linux switches
CFLAGS= -Ofast -Wall -pedantic -Wextra
# Mac OS: We don't use pedantic as Mac OS version of MySQL (5.5.24) does use long long (not part of ISO C++)
#CFLAGS=-g -O0 -Wall -Wextra -I/opt/local/include
# Mac OS does not require -lrt
# Linux requires -lrt
LDFLAGS=-lrt
MEMFILE_CFLAGS=
MEMFILE_LDFLAGS=
# It is mysql_config on most Linux systems and mysql_config5 on Mac OS
MYSQL_CONFIG=mysql_config
MYSQL_CFLAGS=`$(MYSQL_CONFIG) --cflags`
MYSQL_LDFLAGS=`$(MYSQL_CONFIG) --libs`
SQLITE_CFLAGS=`pkg-config sqlite3 --cflags`
SQLITE_LDFLAGS=`pkg-config sqlite3 --libs`
all: mysql_ubench sqlite_ubench memfile_ubench
doc: dhcp-perf-guide.html dhcp-perf-guide.pdf
mysql_ubench.o: mysql_ubench.cc mysql_ubench.h benchmark.h
$(CXX) $< -c $(CFLAGS) $(MYSQL_CFLAGS)
benchmark.o: benchmark.cc benchmark.h
$(CXX) $< -c $(CFLAGS) $(MYSQL_CFLAGS)
mysql_ubench: mysql_ubench.o benchmark.o
$(CXX) $< benchmark.o -o mysql_ubench $(CFLAGS) $(MYSQL_CFLAGS) $(LDFLAGS) $(MYSQL_LDFLAGS)
sqlite_ubench.o: sqlite_ubench.cc sqlite_ubench.h benchmark.h
$(CXX) $< -c $(CFLAGS) $(SQLLITE_CFLAGS)
sqlite_ubench: sqlite_ubench.o benchmark.o
$(CXX) $< benchmark.o -o sqlite_ubench $(CFLAGS) $(SQLITE_CFLAGS) $(LDFLAGS) $(SQLITE_LDFLAGS)
memfile_ubench.o: memfile_ubench.cc memfile_ubench.h benchmark.h
$(CXX) $< -c $(CFLAGS) $(MEMFILE_CFLAGS)
memfile_ubench: memfile_ubench.o benchmark.o
$(CXX) $< benchmark.o -o memfile_ubench $(LDFLAGS) $(MEMFILE_LDFLAGS)
clean:
rm -f mysql_ubench sqlite_ubench memfile_ubench *.o
version.ent:
ln -s ../../../doc/version.ent
dhcp-perf-guide.html: dhcp-perf-guide.xml version.ent
xsltproc --novalid --xinclude --nonet \
-o $@ \
--path ../../../doc \
--stringparam section.autolabel 1 \
--stringparam section.label.includes.component.label 1 \
--stringparam html.stylesheet bind10-guide.css \
http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl \
dhcp-perf-guide.xml
dhcp-perf-guide.pdf: dhcp-perf-guide.xml
dblatex -P doc.collab.show=0 -P latex.output.revhistory=0 $<

View File

@ -1,10 +0,0 @@
This directory contains benchmarks for various planned and considered database
backends for BIND10 DHCP, codename Kea.
Before using the code, please read DHCP Performance Guide, available in
HTML and PDF formats.
To compile the code, type: make
To regenerate documentation, type: make doc

View File

@ -1,198 +0,0 @@
// 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 <iostream>
#include <stdlib.h>
#include <string.h>
#include <boost/lexical_cast.hpp>
#include "benchmark.h"
// The following headers are for getting precise time (clock_gettime on Linux or that mac os thingie)
#include <time.h>
#include <sys/time.h>
#ifdef __MACH__
#include <mach/clock.h>
#include <mach/mach.h>
#endif
using namespace std;
uBenchmark::uBenchmark(uint32_t iterations, const std::string& dbname,
bool sync /*= false*/, bool verbose /*= true*/,
const std::string& host /* = "" */,
const std::string& user /* = "" */,
const std::string& pass /* = "" */)
:num_(iterations), sync_(sync), verbose_(verbose),
hostname_(host), user_(user), passwd_(pass), dbname_(dbname),
hitratio_(0.9f), compiled_stmt_(true)
{
/// @todo: make compiled statements a configurable parameter
/// @todo: convert hitratio_ to user-configurable parameter
memset(ts_, 0, sizeof(ts_));
}
void uBenchmark::usage() {
cout << "This is a benchmark designed to measure expected performance" << endl;
cout << "of several backends. This backend identifies itself as:" << endl;
printInfo();
cout << endl << "Possible command-line parameters:" << endl;
cout << " -h - help (you are reading this)" << endl;
cout << " -m hostname - specifies MySQL server to connect (MySQL backend only)" << endl;
cout << " -u username - specifies MySQL user name (MySQL backend only)" << endl;
cout << " -p password - specifies MySQL passwod (MySQL backend only)" << endl;
cout << " -f name - database or filename (MySQL, SQLite and memfile)" << endl;
cout << " -n integer - number of test iterations (MySQL, SQLite and memfile)" << endl;
cout << " -s yes|no - synchronous/asynchronous operation (MySQL, SQLite and memfile)" << endl;
cout << " -v yes|no - verbose mode (MySQL, SQLite and memfile)" << endl;
cout << " -c yes|no - compiled statements (MySQL and SQLite)" << endl;
exit(EXIT_FAILURE);
}
void uBenchmark::parseCmdline(int argc, char* const argv[]) {
int ch;
while ((ch = getopt(argc, argv, "hm:u:p:f:n:s:v:c:")) != -1) {
switch (ch) {
case 'h':
usage();
case 'm':
hostname_ = string(optarg);
break;
case 'u':
user_ = string(optarg);
break;
case 'p':
passwd_ = string(optarg);
break;
case 'f':
dbname_ = string(optarg);
break;
case 'n':
try {
num_ = boost::lexical_cast<unsigned int>(optarg);
} catch (const boost::bad_lexical_cast &) {
cerr << "Failed to parse number of iterations (-n option):"
<< optarg << endl;
usage();
}
break;
case 'c':
compiled_stmt_ = !strcasecmp(optarg, "yes") || !strcmp(optarg, "1");
break;
case 's':
sync_ = !strcasecmp(optarg, "yes") || !strcmp(optarg, "1");
break;
case 'v':
verbose_ = !strcasecmp(optarg, "yes") || !strcmp(optarg, "1");
break;
default:
usage();
}
}
}
void uBenchmark::failure(const char* operation) {
cout << "Error during " << operation << endl;
throw string(operation);
}
void uBenchmark::printClock(const std::string& operation, uint32_t num,
const struct timespec& before,
const struct timespec& after) {
long int tv_sec = after.tv_sec - before.tv_sec;
long int tv_nsec = after.tv_nsec - before.tv_nsec;
if (tv_nsec < 0) {
tv_sec--;
tv_nsec += 1000000000; // 10^9
}
double oneoper = (tv_nsec/1000 + tv_sec*1000000)/num;
cout << operation << " repeated " << num << " times took "
<< tv_sec << " s, " << tv_nsec/1000 << " us, 1 operation took "
<< oneoper << "us (or " << (1000000/oneoper) << " oper/sec)" << endl;
}
int uBenchmark::run() {
cout << "Starting test. Parameters:" << endl
<< "Number of iterations : " << num_ << endl
<< "Sync/async : " << (sync_ ? "sync" : "async") << endl
<< "Verbose : " << (verbose_ ? "verbose" : "quiet") << endl
<< "Compiled statements : " << (compiled_stmt_ ? "yes": "no") << endl
<< "Database name : " << dbname_ << endl
<< "MySQL hostname : " << hostname_ << endl
<< "MySQL username : " << user_ << endl
<< "MySQL password : " << passwd_ << endl << endl;
srandom(time(NULL));
try {
connect();
ts_[0] = getTime();
createLease4Test();
ts_[1] = getTime();
searchLease4Test();
ts_[2] = getTime();
updateLease4Test();
ts_[3] = getTime();
deleteLease4Test();
ts_[4] = getTime();
disconnect();
} catch (const std::string& e) {
cout << "Failed: " << e << endl;
return (-1);
}
printClock("Create leases4", num_, ts_[0], ts_[1]);
printClock("Search leases4", num_, ts_[1], ts_[2]);
printClock("Update leases4", num_, ts_[2], ts_[3]);
printClock("Delete leases4", num_, ts_[3], ts_[4]);
return (0);
}
struct timespec uBenchmark::getTime() {
struct timespec ts;
#ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time
clock_serv_t cclock;
mach_timespec_t mts;
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
clock_get_time(cclock, &mts);
mach_port_deallocate(mach_task_self(), cclock);
ts.tv_sec = mts.tv_sec;
ts.tv_nsec = mts.tv_nsec;
#else
clock_gettime(CLOCK_REALTIME, &ts);
#endif
return ts;
}

View File

@ -1,209 +0,0 @@
// 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 <string>
#include <stdint.h>
#ifndef BENCHMARK_H
#define BENCHMARK_H
/// @brief Micro-benchmark base class.
///
/// This class represents an abstract DHCP database backend benchmark.
/// It is not intended to be used directly, but serves as a common
/// denominator for specific backend benchmarks that are derived from
/// it. Currently there are at least 3 benchmarks implemented that
/// take advantage of it:
/// - MySQL (MySQL_uBenchmark)
/// - SQLite (SQLite_uBenchmark)
/// - memfile (memfile_uBenchmark)
class uBenchmark {
public:
/// @brief the sole constructor, used by all derivated benchmarks
///
/// @param iterations number of iterations of each step (insert, search,
/// update, delete)
/// @param dbname name of the database (that is backend-specific, either
/// filename or DB name)
/// @param sync sync or async test mode
/// @param verbose should extra logging be enabled?
/// @param host some backends (currently only MySQL) need this (optional)
/// @param username some backends (currently only MySQL) need this (optional)
/// @param pass some backends (currently only MySQL) need this (optional)
uBenchmark(uint32_t iterations, const std::string& dbname,
bool sync, bool verbose,
const std::string& host = "",
const std::string& username = "",
const std::string& pass = "");
/// @brief Prints version information about specific backend.
///
/// The implementation is provided by the DB-specific class.
virtual void printInfo() = 0;
/// @brief Opens a connection to the database.
///
/// The implementation is provided by the DB-specific class.
virtual void connect() = 0;
/// @brief Closes connection to the database.
///
/// The implementation is provided by the DB-specific class.
virtual void disconnect() = 0;
/// @brief Benchmarks IPv4 address lease creation.
///
/// That benchmark method will be called first.
/// It is expected to create specific number of leases,
/// as specified by \ref num_ parameter. Following
/// methods (searchLease4Test(), updateLease4Test(),
/// and deleteLease4Test()) assume that lease creation
/// is successful. The benchmark is expected to create leases
/// starting from BASE_ADDR4 and ending on BASE_ADDR4 + num_.
///
/// The implementation is provided by the DB-specific class.
virtual void createLease4Test() = 0;
/// @brief Benchmarks IPv4 address lease search.
///
/// This is the second benchmark in a series of four.
/// It is called after createLease4Test(), so it expects that the
/// database is populated with at least \ref num_ leases.
/// It repeats search for a lease num_ times.
///
/// The algorithm randomly picks a lease with \ref hitratio_ (typically 90%)
/// chance of finding a lease. During typical DHCP operation the server
/// sometimes wants to check if specific lease is assigned or not and the
/// lease is sometimes not present (e.g. when randomly trying to pick a new
/// lease for a new client or doing confirm). Although rather unlikely,
/// cases when searching for non-existing leases may be more costly,
/// thus should be modelled.
///
/// The implementation is provided by the DB-specific class.
virtual void searchLease4Test() = 0;
/// @brief Benchmarks IPv4 address lease update.
///
/// This is the third benchmark in a series of four.
/// It is called after createLease4Test(), so it expects that the
/// database is populated with at least \ref num_ leases.
///
/// In a normal DHCP operation, search and update operations are used
/// together, but for the benchmarking purposes they are executed
/// separately here. Once a lease is found, it is being updated. Typically
/// the update is just changing lease expiration timers, so that is what
/// the test does. It exploits the fact that there are num_ leases
/// in the database, so it picks randomly an address from
/// BASE_ADDR4 ... BASE_ADDR4 + num_ range and has a guarantee for the lease
/// to be present.
///
/// The implementation is provided by the DB-specific class.
virtual void updateLease4Test() = 0;
/// @brief Benchmarks IPv4 address lease removal.
///
/// This is the last benchmark in a series of four.
/// It is called after createLease4Test(), so it expects that the
/// database is populated with at least \ref num_ leases.
///
/// It is expected to iteratively delete all num_ leases from
/// the database.
///
/// The implementation is provided by the DB-specific class.
virtual void deleteLease4Test() = 0;
/// @brief Utility function for reporting errors.
///
/// Benchmarks should call that function when something goes wrong.
/// details of the problem must be passed as a parameter. As the benchmark
/// is not designed to recover from errors, reporting an error aborts
/// benchmark execution.
///
/// @param operation description of the operation that caused failure
virtual void failure(const char* operation);
/// @brief Prints elapsed time of a specific operation
///
/// This method prints out elapsed time of a specific benchmark, together
/// with additional statistics.
///
/// @param operation name of the operation (usually create, search, update, delete)
/// @param num number or iterations (used for statistics)
/// @param before timestamp before execution
/// @param after timestamp after execution
void printClock(const std::string& operation, uint32_t num,
const struct timespec& before,
const struct timespec& after);
/// @brief Main benchmark execution routine
///
/// This method calls create, search, update and delete benchmarks
/// and measures appropriate timestamps in ts_ table.
///
/// @return 0 if the run was successful, negative value if detected errors
int run();
/// @brief parses command-line parameters
///
/// This method parses command-line parameters and sets up appropriate
/// values. It is ok to pass argc, argv from main() here.
///
/// This method may not return if -h (help) was specified or invalid
/// arguments are passed. Appropriate error and help will be displayed
/// and the program will terminate.
///
/// @param argc number of arguments
/// @param argv array to the arguments
void parseCmdline(int argc, char* const argv[]);
protected:
/// @brief prints out command-line help (list of parameters + version)
void usage();
/// @brief a wrapper around OS-specific method for getting time
struct timespec getTime();
/// Number of operations (e.g. insert lease num times)
uint32_t num_;
/// Synchronous or asynchronous mode?
bool sync_;
/// Should the test print out extra information?
bool verbose_;
// DB parameters
std::string hostname_; // used by MySQL only
std::string user_; // used by MySQL only
std::string passwd_; // used by MySQL only
std::string dbname_; // used by MySQL, SQLite and memfile
/// @brief hit ratio for search test (must be between 0.0 and 1.0)
///
/// This parameter is used in search benchmark. The formula causes the
/// search to find something a lease in 90% cases of hit ratio is 0.9.
float hitratio_;
/// benchmarks must generate the leases starting from 1.0.0.0 address
const static uint32_t BASE_ADDR4 = 0x01000000;
/// five timestamps (1 at the beginning and 4 after each step)
struct timespec ts_[5];
/// should compiled statements be used?
bool compiled_stmt_;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,356 +0,0 @@
// Copyright (C) 2012, 2015 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 <sstream>
#include <iostream>
#include <map>
#include "memfile_ubench.h"
using namespace std;
/// @brief In-memory + lease file database implementation
///
/// This is a simplified in-memory database that mimics ISC DHCP4 implementation.
/// It uses STL and boost: std::map for storage, boost::shared ptr for memory
/// management. It does use C file operations (fopen, fwrite, etc.), because
/// C++ streams does not offer any easy way to flush their contents, like
/// fflush() and fsync() does.
///
/// IPv4 address is used as a key in the hash.
class memfile_LeaseMgr {
public:
/// A hash table for Lease4 leases.
typedef std::map<uint32_t /* addr */, Lease4Ptr /* lease info */> IPv4Hash;
/// An iterator for Lease4 hash table.
typedef std::map<uint32_t, Lease4Ptr>::iterator leaseIt;
/// @brief The sole memfile lease manager constructor
///
/// @param filename name of the lease file (will be overwritten)
/// @param sync should operations be
memfile_LeaseMgr(const std::string& filename, bool sync);
/// @brief Destructor (closes file)
~memfile_LeaseMgr();
/// @brief adds a lease to the hash
///
/// @param lease lease to be added
bool addLease(Lease4Ptr lease);
/// @brief returns existing lease
///
/// @param addr address of the searched lease
///
/// @return smart pointer to the lease (or NULL if lease is not found)
Lease4Ptr getLease(uint32_t addr);
/// @brief Simplified lease update.
///
/// Searches for a lease and then updates its client last transmission
/// time. Writes new lease content to lease file (and calls fflush()/fsync(),
/// if synchronous operation is enabled).
///
/// @param addr IPv4 address
/// @param new_cltt New client last transmission time
///
/// @return pointer to the updated lease (or NULL)
Lease4Ptr updateLease(uint32_t addr, uint32_t new_cltt);
/// @brief Deletes a lease.
///
/// @param addr IPv4 address of the lease to be deleted.
///
/// @return true if deletion was successful, false if no such lease exists
bool deleteLease(uint32_t addr);
protected:
/// @brief Writes updated lease to a file.
///
/// @param lease lease to be written
void writeLease(Lease4Ptr lease);
/// Name of the lease file.
std::string filename_;
/// should we do flush after each operation?
bool sync_;
/// File handle to the open lease file.
FILE * file_;
/// Hash table for IPv4 leases
IPv4Hash ip4Hash_;
};
memfile_LeaseMgr::memfile_LeaseMgr(const std::string& filename, bool sync)
: filename_(filename), sync_(sync) {
file_ = fopen(filename.c_str(), "w");
if (!file_) {
throw "Failed to create file " + filename;
}
}
memfile_LeaseMgr::~memfile_LeaseMgr() {
fclose(file_);
}
void memfile_LeaseMgr::writeLease(Lease4Ptr lease) {
fprintf(file_, "lease %d {\n hw-addr ", lease->addr);
for (std::vector<uint8_t>::const_iterator it = lease->hwaddr.begin();
it != lease->hwaddr.end(); ++it) {
fprintf(file_, "%02x:", *it);
}
fprintf(file_, ";\n client-id ");
for (std::vector<uint8_t>::const_iterator it = lease->client_id.begin();
it != lease->client_id.end(); ++it) {
fprintf(file_, "%02x:", *it);
}
fprintf(file_, ";\n valid-lifetime %d;\n recycle-time %d;\n"
" cltt %d;\n pool-id %d;\n fixed %s; hostname %s;\n"
" fqdn_fwd %s;\n fqdn_rev %s;\n};\n",
lease->valid_lft, lease->recycle_time, (int)lease->cltt,
lease->pool_id, lease->fixed?"true":"false",
lease->hostname.c_str(), lease->fqdn_fwd?"true":"false",
lease->fqdn_rev?"true":"false");
if (sync_) {
fflush(file_);
fsync(fileno(file_));
}
}
bool memfile_LeaseMgr::addLease(Lease4Ptr lease) {
if (ip4Hash_.find(lease->addr) != ip4Hash_.end()) {
// there is such an address already in the hash
return false;
}
ip4Hash_.insert(pair<uint32_t, Lease4Ptr>(lease->addr, lease));
lease->hostname = "add";
writeLease(lease);
return (true);
}
Lease4Ptr memfile_LeaseMgr::getLease(uint32_t addr) {
leaseIt x = ip4Hash_.find(addr);
if (x != ip4Hash_.end()) {
return x->second; // found
}
// not found
return Lease4Ptr();
}
Lease4Ptr memfile_LeaseMgr::updateLease(uint32_t addr, uint32_t new_cltt) {
leaseIt x = ip4Hash_.find(addr);
if (x != ip4Hash_.end()) {
x->second->cltt = new_cltt;
x->second->hostname = "update";
writeLease(x->second);
return x->second;
}
return Lease4Ptr();
}
bool memfile_LeaseMgr::deleteLease(uint32_t addr) {
leaseIt x = ip4Hash_.find(addr);
if (x != ip4Hash_.end()) {
x->second->hostname = "delete";
writeLease(x->second);
ip4Hash_.erase(x);
return true;
}
return false;
}
memfile_uBenchmark::memfile_uBenchmark(const string& filename,
uint32_t num_iterations,
bool sync,
bool verbose)
:uBenchmark(num_iterations, filename, sync, verbose) {
}
void memfile_uBenchmark::connect() {
try {
leaseMgr_ = new memfile_LeaseMgr(dbname_, sync_);
} catch (const std::string& e) {
failure(e.c_str());
}
}
void memfile_uBenchmark::disconnect() {
delete leaseMgr_;
leaseMgr_ = NULL;
}
void memfile_uBenchmark::createLease4Test() {
if (!leaseMgr_) {
throw "No LeaseMgr instantiated.";
}
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_tmp[hwaddr_len];
const uint8_t client_id_len = 128;
char client_id_tmp[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 foreseeable future,
// so keep this as 0
time_t cltt = time(NULL); // 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: ";
// While we could put the data directly into vector, I would like to
// keep the code as similar to other benchmarks as possible
for (uint8_t i = 0; i < hwaddr_len; ++i) {
hwaddr_tmp[i] = 'A' + i; // let's make hwaddr consisting of letter
}
vector<uint8_t> hwaddr(hwaddr_tmp, hwaddr_tmp + hwaddr_len - 1);
for (uint8_t i = 0; i < client_id_len; i++) {
client_id_tmp[i] = 33 + i; // 33 is being the first, non whitespace
// printable ASCII character
}
vector<uint8_t> client_id(client_id_tmp, client_id_tmp + client_id_len - 1);
for (uint32_t i = 0; i < num_; ++i) {
cltt++;
Lease4Ptr lease = boost::shared_ptr<Lease4>(new Lease4());
lease->addr = addr;
lease->hwaddr = hwaddr;
lease->client_id = client_id;
lease->valid_lft = valid_lft;
lease->recycle_time = recycle_time;
lease->cltt = cltt;
lease->pool_id = pool_id;
lease->fixed = fixed;
lease->hostname = hostname;
lease->fqdn_fwd = fqdn_fwd;
lease->fqdn_rev = fqdn_rev;
if (!leaseMgr_->addLease(lease)) {
failure("addLease() failed");
} else {
if (verbose_) {
cout << ".";
}
};
addr++;
}
cout << endl;
}
void memfile_uBenchmark::searchLease4Test() {
if (!leaseMgr_) {
throw "No LeaseMgr instantiated.";
}
cout << "RETRIEVE: ";
for (uint32_t i = 0; i < num_; i++) {
uint32_t x = BASE_ADDR4 + random() % int(num_ / hitratio_);
Lease4Ptr lease = leaseMgr_->getLease(x);
if (verbose_) {
cout << (lease?".":"X");
}
}
cout << endl;
}
void memfile_uBenchmark::updateLease4Test() {
if (!leaseMgr_) {
throw "No LeaseMgr instantiated.";
}
cout << "UPDATE: ";
time_t cltt = time(NULL);
for (uint32_t i = 0; i < num_; i++) {
uint32_t x = BASE_ADDR4 + random() % num_;
Lease4Ptr lease = leaseMgr_->updateLease(x, cltt);
if (!lease) {
stringstream tmp;
tmp << "UPDATE failed for lease " << hex << x << dec;
failure(tmp.str().c_str());
}
if (verbose_) {
cout << ".";
}
}
cout << endl;
}
void memfile_uBenchmark::deleteLease4Test() {
if (!leaseMgr_) {
throw "No LeaseMgr instantiated.";
}
cout << "DELETE: ";
for (uint32_t i = 0; i < num_; i++) {
uint32_t x = BASE_ADDR4 + i;
if (!leaseMgr_->deleteLease(x)) {
stringstream tmp;
tmp << "UPDATE failed for lease " << hex << x << dec;
failure(tmp.str().c_str());
}
if (verbose_) {
cout << ".";
}
}
cout << endl;
}
void memfile_uBenchmark::printInfo() {
cout << "Memory db (using std::map) + write-only file." << endl;
}
int main(int argc, char * const argv[]) {
const char * filename = "dhcpd.leases";
uint32_t num = 100;
bool sync = true;
bool verbose = false;
memfile_uBenchmark bench(filename, num, sync, verbose);
bench.parseCmdline(argc, argv);
int result = bench.run();
return (result);
}

View File

@ -1,103 +0,0 @@
// 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 <string>
#include <fstream>
#include <vector>
#include <boost/shared_ptr.hpp>
#include "benchmark.h"
/// @brief Structure of the Lease4 that is kept in memory
struct Lease4 {
uint32_t addr; /// IPv4 address
std::vector<uint8_t> hwaddr; /// hardware address
std::vector<uint8_t> client_id; /// client-identifier
uint32_t valid_lft; /// valid lifetime timestamp
uint32_t recycle_time; /// timer for keeping lease after expiration/release
/// (currently not used)
time_t cltt; /// client last transmission time
uint32_t pool_id; /// ID of the pool the lease belongs to
bool fixed; /// is this lease fixed?
std::string hostname; /// client hostname (may be empty)
bool fqdn_fwd; /// did we do AAAA update for this lease?
bool fqdn_rev; /// did we do PTR update for this lease?
std::string options; /// additional options stored with this lease
/// (currently not used)
std::string comments; /// comments on that lease
/// (currently not used)
};
/// Pointer to a Lease4 structure
typedef boost::shared_ptr<Lease4> Lease4Ptr;
/// an implementation of in-memory+file database
/// The actual implementation is in memfile_ubench.cc
class memfile_LeaseMgr;
/// @brief In-memory + file micro-benchmark.
///
/// That is a specific backend implementation. See \ref uBenchmark class for
/// detailed explanation of its operations. This class uses custom in-memory
/// pseudo-database and external write-only lease file. That approach simulates
/// modernized model of ISC DHCP4. It uses standard STL maps together with
/// shared_ptr from boost library. The "database" is implemented in the Lease
/// Manager (see \ref LeaseMgr in memfile_ubench.cc). All lease changes are
/// appended to the end of the file, speeding up the process.
class memfile_uBenchmark: public uBenchmark {
public:
/// @brief The sole memfile benchmark constructor.
///
/// @param filename name of the write-only lease file
/// @param num_iterations number of iterations
/// @param sync should fsync() be called after every file write?
/// @param verbose would you like extra logging?
memfile_uBenchmark(const std::string& filename,
uint32_t num_iterations, bool sync, bool verbose);
/// @brief Prints backend info.
virtual void printInfo();
/// @brief Spawns lease manager that create empty lease file, initializes
/// empty STL maps.
virtual void connect();
/// @brief Delete lease manager that closes lease file.
virtual void disconnect();
/// @brief Creates new leases.
///
/// See uBenchmark::createLease4Test() for detailed explanation.
virtual void createLease4Test();
/// @brief Searches for existing leases.
///
/// See uBenchmark::searchLease4Test() for detailed explanation.
virtual void searchLease4Test();
/// @brief Updates existing leases.
///
/// See uBenchmark::updateLease4Test() for detailed explanation.
virtual void updateLease4Test();
/// @brief Deletes existing leases.
///
/// See uBenchmark::deleteLease4Test() for detailed explanation.
virtual void deleteLease4Test();
protected:
/// Lease Manager (concrete backend implementation, based on STL maps)
memfile_LeaseMgr * leaseMgr_;
};

View File

@ -1,86 +0,0 @@
DROP DATABASE kea;
CREATE DATABASE kea;
CONNECT kea;
CREATE TABLE lease4 (
# Primary key (serial = BININT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE)
lease_id SERIAL,
addr INT UNSIGNED UNIQUE,
# The largest hardware address is for Infiniband (20 bytes)
hwaddr VARCHAR(20),
# The largest client-id is DUID in DHCPv6 - up to 128 bytes
client_id VARCHAR(128),
# Expressed in seconds
valid_lft INT,
# Expressed in seconds,
recycle_time INT DEFAULT 0,
cltt TIMESTAMP,
pool_id int,
fixed BOOL,
# DDNS stuff
hostname VARCHAR(255),
fqdn_fwd BOOL DEFAULT false,
fqdn_rev BOOL DEFAULT false,
options TEXT,
comments TEXT
);
CREATE TABLE lease6 (
# Primary key (serial = BININT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE)
lease_id SERIAL,
addr CHAR(16) BYTE UNIQUE,
# The largest hardware address is for Infiniband (20 bytes)
hwaddr VARCHAR(20),
# The largest client-id is DUID in DHCPv6 - up to 128 bytes
client_id VARCHAR(128),
iaid int unsigned,
# Used for IA_PD only (tinyint = 0..255)
prefix_len TINYINT unsigned,
# Expressed in seconds
preferred_lft INT,
# Expressed in seconds
valid_lft INT,
# Expressed in seconds,
recycle_time INT DEFAULT 0,
cltt TIMESTAMP,
pool_id int,
fixed BOOL DEFAULT false,
hostname VARCHAR(255),
fqdn_fwd BOOL DEFAULT false,
fqdn_rev BOOL DEFAULT false,
options TEXT,
comments TEXT
);
CREATE TABLE host (
address BIGINT NULL,
address6 BIGINT NULL,
prefix6 BIGINT NULL,
hostname VARCHAR(255),
options TEXT,
comments TEXT
);

View File

@ -1,674 +0,0 @@
// 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 <iostream>
#include <sstream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <mysql.h>
#include "benchmark.h"
#include "mysql_ubench.h"
using namespace std;
MySQL_uBenchmark::MySQL_uBenchmark(const string& hostname, const string& user,
const string& pass, const string& db,
uint32_t num_iterations, bool sync,
bool verbose)
:uBenchmark(num_iterations, db, sync, verbose, hostname, user, pass),
conn_(NULL) {
}
void MySQL_uBenchmark::stmt_failure(MYSQL_STMT * stmt, const char* operation) {
stringstream tmp;
tmp << "Error " << mysql_stmt_errno(stmt) << " during " << operation
<< ": " << mysql_stmt_error(stmt);
throw tmp.str();
}
void MySQL_uBenchmark::failure(const char* operation) {
stringstream tmp;
tmp << "Error " << mysql_errno(conn_) << " during " << operation
<< ": " << mysql_error(conn_);
throw tmp.str();
}
void MySQL_uBenchmark::connect() {
conn_ = mysql_init(NULL);
if (!conn_) {
failure("initializing MySQL library");
} else {
cout << "MySQL library init successful." << endl;
}
if (!mysql_real_connect(conn_, hostname_.c_str(), user_.c_str(),
passwd_.c_str(), dbname_.c_str(), 0, NULL, 0)) {
failure("connecting to MySQL server");
} else {
cout << "MySQL connection established." << endl;
}
string q = "delete from lease4;";
if (mysql_real_query(conn_, q.c_str(), strlen(q.c_str()))) {
failure("dropping old lease4 entries.");
}
q = "ALTER TABLE lease4 engine=";
if (sync_) {
q += "InnoDB";
} else {
q += "MyISAM";
}
if (mysql_query(conn_, q.c_str())) {
q = "Failed to run query:" + q;
failure(q.c_str());
}
}
void MySQL_uBenchmark::disconnect() {
if (!conn_) {
throw "NULL MySQL connection pointer.";
}
mysql_close(conn_);
conn_ = NULL;
}
void MySQL_uBenchmark::createLease4Test() {
if (!conn_) {
throw "Not connected to MySQL server.";
}
uint32_t addr = BASE_ADDR4; // Let's start with 1.0.0.0 address
char hwaddr[20];
size_t hwaddr_len = 20; // Not a real field
char client_id[128];
size_t client_id_len = 128;
uint32_t valid_lft = 1000; // We can use the same value for all leases
uint32_t recycle_time = 7; // not supported in any foresable future,
char cltt[48]; // timestamp (specified as text)
size_t cltt_len;
sprintf(cltt, "2012-07-11 15:43:00");
cltt_len = strlen(cltt);
uint32_t pool_id = 1000; // Let's use pool-ids greater than zero
bool fixed = false;
char hostname[] = "foo"; // Will generate it dynamically
size_t hostname_len;
hostname_len = strlen(hostname);
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] = 'A' + i; // let's make hwaddr consisting of letters
}
hwaddr[19] = 0; // make it is null-terminated
for (uint8_t i = 0; i < client_id_len; i++) {
client_id[i] = 33 + i; // 33 is being the first, non whitespace
// printable ASCII character
}
client_id[127] = 0; // make it is null-terminated
MYSQL_STMT * stmt = NULL;
MYSQL_BIND bind[11]; // 11 parameters in the insert statement
if (compiled_stmt_) {
// create a statement once
stmt = mysql_stmt_init(conn_);
if (!stmt) {
failure("Unable to create compiled statement, mysql_stmt_init() failed");
}
const char * statement = "INSERT INTO lease4(addr,hwaddr,client_id,"
"valid_lft,recycle_time,cltt,pool_id,fixed,hostname,"
"fqdn_fwd,fqdn_rev) VALUES(?,?,?,?,?,?,?,?,?,?,?)";
if (mysql_stmt_prepare(stmt, statement, strlen(statement) )) {
failure("Failed to prepare statement, mysql_stmt_prepare() returned non-zero");
}
int param_cnt = mysql_stmt_param_count(stmt);
if (param_cnt != 11) {
failure("Parameter count sanity check failed.");
}
memset(bind, 0, sizeof(bind));
// 1st parameter: IPv4 address
bind[0].buffer_type = MYSQL_TYPE_LONG;
bind[0].buffer = (&addr);
bind[0].is_null = 0;
bind[0].length = 0;
// 2nd parameter: Hardware address
bind[1].buffer_type = MYSQL_TYPE_VARCHAR;
bind[1].buffer = hwaddr;
bind[1].buffer_length = hwaddr_len;
bind[1].is_null = 0;
bind[1].length = &hwaddr_len;
// 3rd parameter: Client-id
bind[2].buffer_type = MYSQL_TYPE_VARCHAR;
bind[2].buffer = client_id;
bind[2].buffer_length = client_id_len;
bind[2].is_null = 0;
bind[2].length = &client_id_len;
// 4th parameter: valid-lifetime
bind[3].buffer_type = MYSQL_TYPE_LONG;
bind[3].buffer = (&valid_lft);
bind[3].is_null = 0;
bind[3].length = 0;
// 5th parameter: recycle-time
bind[4].buffer_type = MYSQL_TYPE_LONG;
bind[4].buffer = (&recycle_time);
bind[4].is_null = 0;
bind[4].length = 0;
// 6th parameter: cltt
bind[5].buffer_type = MYSQL_TYPE_TIMESTAMP;
bind[5].buffer = cltt;
bind[2].buffer_length = cltt_len;
bind[5].is_null = 0;
bind[5].length = &cltt_len;
// 7th parameter: pool-id
bind[6].buffer_type = MYSQL_TYPE_LONG;
bind[6].buffer = &pool_id;
bind[6].is_null = 0;
bind[6].length = 0;
// 8th parameter: fixed
bind[7].buffer_type = MYSQL_TYPE_TINY;
bind[7].buffer = &fixed;
bind[7].is_null = 0;
bind[7].length = 0;
// 9th parameter: hostname
bind[8].buffer_type = MYSQL_TYPE_VARCHAR;
bind[8].buffer = hostname;
bind[8].buffer_length = strlen(hostname);
bind[8].is_null = 0;
bind[8].length = &hostname_len;
// 10th parameter: fqdn_fwd
bind[9].buffer_type = MYSQL_TYPE_TINY;
bind[9].buffer = &fqdn_fwd;
bind[9].is_null = 0;
bind[9].length = 0;
// 11th parameter: fqdn_rev
bind[10].buffer_type = MYSQL_TYPE_TINY;
bind[10].buffer = &fqdn_rev;
bind[10].is_null = 0;
bind[10].length = 0;
}
for (uint32_t i = 0; i < num_; i++) {
sprintf(cltt, "2012-07-11 15:43:%02d", i % 60);
addr++;
if (!compiled_stmt_) {
// the first address is 1.0.0.0.
char query[2000], * end;
strcpy(query, "INSERT INTO lease4(addr,hwaddr,client_id,"
"valid_lft,recycle_time,cltt,pool_id,fixed,hostname,"
"fqdn_fwd,fqdn_rev) VALUES(");
end = query + strlen(query);
end += sprintf(end, "%u,\'", addr);
end += mysql_real_escape_string(conn_, end, hwaddr, hwaddr_len);
end += sprintf(end,"\',\'");
end += mysql_real_escape_string(conn_, end, client_id, client_id_len);
end += sprintf(end, "\',%d,%d,'%s',%d,%s,\'%s\',%s,%s);",
valid_lft, recycle_time, cltt,
pool_id, (fixed?"true":"false"), hostname,
(fqdn_fwd?"true":"false"), (fqdn_rev?"true":"false"));
// lease_id field is set automatically
// options and comments fields are not set
unsigned int len = end - query;
if (mysql_real_query(conn_, query, len)) {
// something failed.
failure("INSERT query");
}
} else {
// compiled statement
if (mysql_stmt_bind_param(stmt, bind)) {
failure("Failed to bind parameters: mysql_stmt_bind_param() returned non-zero");
}
if (mysql_stmt_execute(stmt)) {
failure("Failed to execute statement: mysql_stmt_execute() returned non-zero");
}
}
if (verbose_) {
cout << ".";
}
}
if (compiled_stmt_) {
if (mysql_stmt_close(stmt)) {
failure("Failed to close compiled statement, mysql_stmt_close returned non-zero");
}
}
cout << endl;
}
void MySQL_uBenchmark::searchLease4Test() {
if (!conn_) {
throw "Not connected to MySQL server.";
}
cout << "RETRIEVE: ";
uint32_t addr = 0;
MYSQL_STMT * stmt = NULL;
MYSQL_BIND bind[1]; // just a single element
if (compiled_stmt_) {
stmt = mysql_stmt_init(conn_);
if (!stmt) {
failure("Unable to create compiled statement");
}
const char * statement = "SELECT lease_id,addr,hwaddr,client_id,"
"valid_lft, cltt,pool_id,fixed,hostname,fqdn_fwd,fqdn_rev "
"FROM lease4 where addr=?";
if (mysql_stmt_prepare(stmt, statement, strlen(statement))) {
failure("Failed to prepare statement, mysql_stmt_prepare() returned non-zero");
}
int param_cnt = mysql_stmt_param_count(stmt);
if (param_cnt != 1) {
failure("Parameter count sanity check failed.");
}
memset(bind, 0, sizeof(bind));
// 1st parameter: IPv4 address
bind[0].buffer_type = MYSQL_TYPE_LONG;
bind[0].buffer = (&addr);
bind[0].is_null = 0;
bind[0].length = 0;
}
for (uint32_t i = 0; i < num_; i++) {
addr = BASE_ADDR4 + random() % int(num_ / hitratio_);
if (!compiled_stmt_) {
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);
mysql_real_query(conn_, query, strlen(query));
MYSQL_RES * result = mysql_store_result(conn_);
int num_rows = mysql_num_rows(result);
int num_fields = mysql_num_fields(result);
if ( (num_rows > 1) ) {
stringstream tmp;
tmp << "Search: DB returned " << num_rows << " leases for address "
<< hex << addr << dec;
failure(tmp.str().c_str());
}
if (num_rows) {
if (num_fields == 0) {
failure("Query returned empty set");
}
MYSQL_ROW row = mysql_fetch_row(result);
// pretend to do something with it
if (row[0] == NULL) {
failure("SELECT returned NULL data.");
}
mysql_free_result(result);
if (verbose_) {
cout << "."; // hit
}
} else {
if (verbose_) {
cout << "x"; // miss
}
}
} else {
// compiled statement
if (mysql_stmt_bind_param(stmt, bind)) {
failure("Failed to bind parameters: mysql_stmt_bind_param() returned non-zero");
}
if (mysql_stmt_execute(stmt)) {
failure("Failed to execute statement: mysql_stmt_execute() returned non-zero");
}
MYSQL_BIND response[11];
size_t length[11];
my_bool is_null[11];
my_bool error[11];
uint32_t lease_id;
uint32_t lease_addr;
char hwaddr[20];
char client_id[128];
uint32_t valid_lft; // We can use the same value for all leases
MYSQL_TIME cltt;
uint32_t pool_id;
my_bool fixed;
char hostname[255];
my_bool fqdn_fwd;
my_bool fqdn_rev;
for (int j = 0; j < 11; j++) {
response[j].is_null = &is_null[j];
response[j].length = &length[j];
response[j].error = &error[j];
}
// 1th parameter: lease_id
response[0].buffer_type = MYSQL_TYPE_LONG;
response[0].buffer = (&lease_id);
// 2nd parameter: IPv4 address
response[1].buffer_type = MYSQL_TYPE_LONG;
response[1].buffer = (&lease_addr);
// 3rd parameter: Hardware address
response[2].buffer_type = MYSQL_TYPE_STRING;
response[2].buffer = hwaddr;
response[2].buffer_length = sizeof(hwaddr);
// 4th parameter: Client-id
response[3].buffer_type = MYSQL_TYPE_STRING;
response[3].buffer = &client_id;
response[3].buffer_length = sizeof(client_id);
// 5th parameter: valid-lifetime
response[4].buffer_type = MYSQL_TYPE_LONG;
response[4].buffer = &valid_lft;
// 6th parameter: cltt
response[5].buffer_type = MYSQL_TYPE_TIMESTAMP;
response[5].buffer = &cltt;
// 7th parameter: pool-id
response[6].buffer_type = MYSQL_TYPE_LONG;
response[6].buffer = &pool_id;
// 8th parameter: fixed
response[7].buffer_type = MYSQL_TYPE_TINY;
response[7].buffer = &fixed;
// 9th parameter: hostname
response[8].buffer_type = MYSQL_TYPE_STRING;
response[8].buffer = &hostname;
// 10th parameter: fqdn_fwd
response[9].buffer_type = MYSQL_TYPE_TINY;
response[9].buffer = &fqdn_fwd;
// 11th parameter: fqdn_rev
response[10].buffer_type = MYSQL_TYPE_TINY;
response[10].buffer = &fqdn_rev;
if (mysql_stmt_bind_result(stmt, response))
{
cout << "Error:" << mysql_stmt_error(stmt) << endl;
failure("mysql_stmt_bind_result() failed");
}
int num_rows = 0;
int result = mysql_stmt_fetch(stmt);
switch (result) {
case 0: {
if (lease_addr != addr) {
failure("Returned data is bogus!");
}
num_rows++;
break;
}
case MYSQL_NO_DATA:
{
// that's ok. We randomized non-existing address
break;
}
default: {
stmt_failure(stmt, "RETRIEVE (mysql_stmt_fetch())");
}
}
// we could call mysql_stmt_fetch again to check that there are no
// other data for us. But there should be exactly one row of data
// with specified address.
if (num_rows) {
if (verbose_) {
cout << "."; // hit
}
} else {
if (verbose_) {
cout << "X"; // miss
}
}
}
}
if (compiled_stmt_) {
if (mysql_stmt_close(stmt)) {
failure("Failed to close compiled statement, mysql_stmt_close returned non-zero");
}
}
cout << endl;
}
void MySQL_uBenchmark::updateLease4Test() {
if (!conn_) {
throw "Not connected to MySQL server.";
}
cout << "UPDATE: ";
uint32_t valid_lft = 1002; // just some dummy value
char cltt[] = "now()";
size_t cltt_len = strlen(cltt);
uint32_t addr = 0;
MYSQL_STMT * stmt = NULL;
MYSQL_BIND bind[3];
if (compiled_stmt_) {
stmt = mysql_stmt_init(conn_);
if (!stmt) {
failure("Unable to create compiled statement");
}
const char * statement = "UPDATE lease4 SET valid_lft=?, cltt=? WHERE addr=?";
if (mysql_stmt_prepare(stmt, statement, strlen(statement))) {
failure("Failed to prepare statement, mysql_stmt_prepare() returned non-zero");
}
int param_cnt = mysql_stmt_param_count(stmt);
if (param_cnt != 3) {
failure("Parameter count sanity check failed.");
}
memset(bind, 0, sizeof(bind));
// 1st parameter: valid lifetime
bind[0].buffer_type = MYSQL_TYPE_LONG;
bind[0].buffer = &valid_lft;
// 2nd parameter: cltt
bind[1].buffer_type = MYSQL_TYPE_STRING;
bind[1].buffer = &cltt;
bind[1].buffer_length = cltt_len;
bind[2].buffer_type = MYSQL_TYPE_LONG;
bind[2].buffer = &addr;
}
for (uint32_t i = 0; i < num_; i++) {
addr = BASE_ADDR4 + random() % num_;
if (!compiled_stmt_) {
char query[128];
sprintf(query, "UPDATE lease4 SET valid_lft=1002, cltt=now() WHERE addr=%d", addr);
mysql_real_query(conn_, query, strlen(query));
} else {
// compiled statement
if (mysql_stmt_bind_param(stmt, bind)) {
failure("Failed to bind parameters: mysql_stmt_bind_param() returned non-zero");
}
if (mysql_stmt_execute(stmt)) {
failure("Failed to execute statement: mysql_stmt_execute() returned non-zero");
}
}
if (verbose_) {
cout << ".";
}
}
if (compiled_stmt_) {
if (mysql_stmt_close(stmt)) {
failure("Failed to close compiled statement, mysql_stmt_close returned non-zero");
}
}
cout << endl;
}
void MySQL_uBenchmark::deleteLease4Test() {
if (!conn_) {
throw "Not connected to MySQL server.";
}
cout << "DELETE: ";
uint32_t addr = 0;
MYSQL_STMT * stmt = NULL;
MYSQL_BIND bind[1]; // just a single element
if (compiled_stmt_) {
stmt = mysql_stmt_init(conn_);
if (!stmt) {
failure("Unable to create compiled statement, mysql_stmt_init() failed");
}
const char * statement = "DELETE FROM lease4 WHERE addr=?";
if (mysql_stmt_prepare(stmt, statement, strlen(statement) )) {
failure("Failed to prepare statement, mysql_stmt_prepare() returned non-zero");
}
int param_cnt = mysql_stmt_param_count(stmt);
if (param_cnt != 1) {
failure("Parameter count sanity check failed.");
}
memset(bind, 0, sizeof(bind));
// 1st parameter: IPv4 address
bind[0].buffer_type = MYSQL_TYPE_LONG;
bind[0].buffer = (&addr);
bind[0].is_null = 0;
bind[0].length = 0;
}
for (uint32_t i = 0; i < num_; i++) {
addr = BASE_ADDR4 + i;
if (!compiled_stmt_) {
char query[128];
sprintf(query, "DELETE FROM lease4 WHERE addr=%d", addr);
mysql_real_query(conn_, query, strlen(query));
} else {
// compiled statement
if (mysql_stmt_bind_param(stmt, bind)) {
failure("Failed to bind parameters: mysql_stmt_bind_param() returned non-zero");
}
if (mysql_stmt_execute(stmt)) {
failure("Failed to execute statement: mysql_stmt_execute() returned non-zero");
}
}
if (verbose_) {
cout << ".";
}
}
if (compiled_stmt_) {
if (mysql_stmt_close(stmt)) {
failure("Failed to close compiled statement, mysql_stmt_close returned non-zero");
}
}
cout << endl;
}
void MySQL_uBenchmark::printInfo() {
cout << "MySQL client version is " << mysql_get_client_info() << endl;
}
int main(int argc, char * const argv[]) {
const char* hostname ="localhost"; // -m (MySQL server)
const char* user = "root"; // -u
const char* passwd = "secret"; // -p
const char* dbname = "kea"; // -f
uint32_t num = 100; // -n
bool sync = true; // -s
bool verbose = true; // -v
MySQL_uBenchmark bench(hostname, user, passwd, dbname, num, sync, verbose);
bench.parseCmdline(argc, argv);
int result = bench.run();
return (result);
}

View File

@ -1,104 +0,0 @@
// 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 <string>
#include "benchmark.h"
/// @brief MySQL micro-benchmark.
///
/// That is a specific backend implementation. See \ref uBenchmark class for
/// detailed explanation of its operations. This class uses MySQL as database
/// backend.
class MySQL_uBenchmark: public uBenchmark {
public:
/// @brief The sole MySQL micro-benchmark constructor
///
/// To avoid influence of network performance, it is highly recommended
/// to run MySQL engine on the same host as benchmark. Thus hostname
/// is likely to be "localhost". Make sure that the selected database
/// is already created and that it follows expected schema. See mysql.schema
/// and isc-dhcp-perf-guide.html for details.
///
/// Synchronous operation means using InnDB, async is MyISAM.
///
/// @param hostname Name of the host to connect to
/// @param user usename used during MySQL connection
/// @param pass password used during MySQL connection
/// @param db name of the database to connect to
/// @param num_iterations number of iterations for basic operations
/// @param sync synchronous or asynchronous database writes
/// @param verbose should extra information be logged?
MySQL_uBenchmark(const std::string& hostname, const std::string& user,
const std::string& pass, const std::string& db,
uint32_t num_iterations, bool sync,
bool verbose);
/// @brief Prints MySQL version info.
virtual void printInfo();
/// @brief Opens connection to the MySQL database.
virtual void connect();
/// @brief Closes connection to the MySQL database.
virtual void disconnect();
/// @brief Creates new leases.
///
/// See uBenchmark::createLease4Test() for detailed explanation.
virtual void createLease4Test();
/// @brief Searches for existing leases.
///
/// See uBenchmark::searchLease4Test() for detailed explanation.
virtual void searchLease4Test();
/// @brief Updates existing leases.
///
/// See uBenchmark::updateLease4Test() for detailed explanation.
virtual void updateLease4Test();
/// @brief Deletes existing leases.
///
/// See uBenchmark::deleteLease4Test() for detailed explanation.
virtual void deleteLease4Test();
protected:
/// @brief Used to report any database failures.
///
/// Compared to its base version in uBenchmark class, this one logs additional
/// MySQL specific information using mysql_errno() and mysql_error() functions.
/// The outcome is the same: exception is thrown.
///
/// @param operation brief description of the operation that caused error
///
/// @sa stmt_failure()
void failure(const char* operation);
/// @brief Used to report compiled statement failures.
///
/// Compared to its base version in uBenchmark class, this one logs additional
/// MySQL specific information using mysql_stmt_errno() and mysql_stmt_error()
/// functions that are used for compiled statements error reporting.
///
/// @param stmt MySQL compiled statement structure
/// @param operation brief description of the operation that caused error
///
/// @sa failure()
void stmt_failure(MYSQL_STMT * stmt, const char* operation);
/// Handle to MySQL database connection.
MYSQL* conn_;
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

View File

@ -1,85 +0,0 @@
DROP TABLE lease4;
DROP TABLE lease6;
DROP TABLE host;
CREATE TABLE lease4 (
-- Primary key (serial = BININT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE)
lease_id SERIAL,
addr INT UNSIGNED UNIQUE,
-- The largest hardware address is for Infiniband (20 bytes)
hwaddr VARCHAR(20),
-- The largest client-id is DUID in DHCPv6 - up to 128 bytes
client_id VARCHAR(128),
-- Expressed in seconds
valid_lft INT,
-- Expressed in seconds,
recycle_time INT DEFAULT 0,
cltt TIMESTAMP,
pool_id int,
fixed BOOL,
-- DDNS stuff
hostname VARCHAR(255),
fqdn_fwd BOOL DEFAULT false,
fqdn_rev BOOL DEFAULT false,
options TEXT,
comments TEXT
);
CREATE TABLE lease6 (
-- Primary key (serial = BININT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE)
lease_id SERIAL,
addr CHAR(16) UNIQUE,
-- The largest hardware address is for Infiniband (20 bytes)
hwaddr VARCHAR(20),
-- The largest client-id is DUID in DHCPv6 - up to 128 bytes
client_id VARCHAR(128),
iaid int unsigned,
-- Used for IA_PD only (tinyint = 0..255)
prefix_len TINYINT unsigned,
-- Expressed in seconds
preferred_lft INT,
-- Expressed in seconds
valid_lft INT,
-- Expressed in seconds,
recycle_time INT DEFAULT 0,
cltt TIMESTAMP,
pool_id int,
fixed BOOL DEFAULT false,
hostname VARCHAR(255),
fqdn_fwd BOOL DEFAULT false,
fqdn_rev BOOL DEFAULT false,
options TEXT,
comments TEXT
);
CREATE TABLE host (
address BIGINT NULL,
address6 BIGINT NULL,
prefix6 BIGINT NULL,
hostname VARCHAR(255),
options TEXT,
comments TEXT
);

View File

@ -1,513 +0,0 @@
// 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);
}

View File

@ -1,74 +0,0 @@
// 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 <string>
#include "benchmark.h"
/// @brief SQLite benchmark
///
/// That is a specific backend implementation. See \ref uBenchmark class for
/// detailed explanation of its operations. This class uses SQLite as DB backend.
class SQLite_uBenchmark: public uBenchmark {
public:
/// @brief The sole SQL benchmark constructor
///
/// DB file must be present and appropriate database schema must
/// be used. See sqlite.schema script and isc-dhcp-perf-guide.html
/// for details.
///
/// sync flag affects "PRAGMA synchronous" to be ON or OFF.
///
/// @param filename name of the SQLite DB file. Must be present.
/// @param num_iterations number of iterations of basic lease operations
/// @param sync should the operations be synchronous or not?
/// @param verbose would you like extra details be logged?
SQLite_uBenchmark(const std::string& filename,
uint32_t num_iterations,
bool sync, bool verbose);
/// @brief Prints SQLite version info.
virtual void printInfo();
/// @brief Opens connection to the SQLite database.
virtual void connect();
/// @brief Closes connection to the SQLite database.
virtual void disconnect();
/// @brief Creates new leases.
///
/// See uBenchmark::createLease4Test() for detailed explanation.
virtual void createLease4Test();
/// @brief Searches for existing leases.
///
/// See uBenchmark::searchLease4Test() for detailed explanation.
virtual void searchLease4Test();
/// @brief Updates existing leases.
///
/// See uBenchmark::updateLease4Test() for detailed explanation.
virtual void updateLease4Test();
/// @brief Deletes existing leases.
///
/// See uBenchmark::deleteLease4Test() for detailed explanation.
virtual void deleteLease4Test();
protected:
/// Handle to SQLite database connection.
sqlite3 *db_;
};