123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674 |
- // 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);
- }
|