mirror of
https://github.com/MariaDB/server.git
synced 2025-01-24 07:44:22 +01:00
6386c55cee
BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted
1415 lines
41 KiB
C++
1415 lines
41 KiB
C++
/* Copyright (C) 2003 MySQL AB
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
|
|
static const volatile char cvsid[] = "$Id: tpcb.cpp,v 1.4 2003/09/26 09:04:34 johan Exp $";
|
|
/*
|
|
* $Revision: 1.4 $
|
|
* (c) Copyright 1996-2003, TimesTen, Inc.
|
|
* All rights reserved.
|
|
*/
|
|
|
|
/* This source is best displayed with a tabstop of 4 */
|
|
|
|
#define NDB
|
|
|
|
//#define MYSQL
|
|
|
|
#ifdef WIN32
|
|
#include <windows.h>
|
|
#include "ttRand.h"
|
|
#else
|
|
#if !defined NDB && !defined MYSQL
|
|
#include <sqlunix.h>
|
|
#endif
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#ifdef SB_P_OS_CHORUS
|
|
#include "ttRand.h"
|
|
#endif
|
|
#endif
|
|
|
|
#include <math.h>
|
|
#include <time.h>
|
|
#include <sql.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
|
|
#if !defined NDB && !defined MYSQL
|
|
#include "ttTime.h"
|
|
#include "utils.h"
|
|
#include "tt_version.h"
|
|
#include "timesten.h"
|
|
#endif
|
|
|
|
#if defined NDB || defined MYSQL
|
|
#include <NdbOut.hpp>
|
|
#include <string.h>
|
|
|
|
#include <sqlext.h>
|
|
#include <sql.h>
|
|
extern "C" {
|
|
#include "ttTime.h"
|
|
#include "timesten.h"
|
|
void ttGetWallClockTime(ttWallClockTime* timeP);
|
|
void ttCalcElapsedWallClockTime(ttWallClockTime* beforeP,
|
|
ttWallClockTime* afterP,
|
|
double* nmillisecondsP);
|
|
void ttGetThreadTimes(ttThreadTimes * endRes);
|
|
void ttCalcElapsedThreadTimes(ttThreadTimes* startRes,
|
|
ttThreadTimes * endRes,
|
|
double * kernel,
|
|
double * user);
|
|
}
|
|
|
|
#define app_exit exit
|
|
#define status_msg0 ndbout_c
|
|
#define status_msg1 ndbout_c
|
|
#define status_msg2 ndbout_c
|
|
#define err_msg0 ndbout_c
|
|
#define err_msg1 ndbout_c
|
|
#define err_msg3 ndbout_c
|
|
#define out_msg0 ndbout_c
|
|
#define out_msg1 ndbout_c
|
|
#define out_msg3 ndbout_c
|
|
#define CONN_STR_LEN 255
|
|
#define DBMS_TIMESTEN 1
|
|
#define DBMS_MSSQL 2
|
|
#define DBMS_UNKNOWN 3
|
|
#define ABORT_DISCONNECT_EXIT 1
|
|
#define NO_EXIT 0
|
|
#define ERROR_EXIT 1
|
|
#define DISCONNECT_EXIT 2
|
|
#endif
|
|
|
|
#define VERBOSE_NOMSGS 0
|
|
/* this value is used for results (and err msgs) only */
|
|
#define VERBOSE_RESULTS 1
|
|
/* this value is the default for the cmdline demo */
|
|
#define VERBOSE_DFLT 2
|
|
#define VERBOSE_ALL 3
|
|
|
|
#ifdef MYSQL
|
|
#define DSNNAME "DSN=myodbc3"
|
|
#elif defined NDB
|
|
#define DSNNAME "DSN=ndb"
|
|
#else
|
|
#define DSNNAME "DSN="
|
|
#endif
|
|
|
|
/* number of branches, tellers, and accounts */
|
|
|
|
#define NumBranches 1
|
|
#define TellersPerBranch 10
|
|
#define AccountsPerBranch 10000
|
|
|
|
/* number of transactions to execute */
|
|
|
|
#define NumXacts 25000
|
|
|
|
/* starting seed value for the random number generator */
|
|
|
|
#define SeedVal 84773
|
|
|
|
/* for MS SQL, the drop, create and use database statements */
|
|
|
|
#define DatabaseDropStmt "drop database tpcbDB;"
|
|
#ifdef MYSQL
|
|
#define DatabaseCreateStmt "create database tpcbDB;"
|
|
#else
|
|
#define DatabaseCreateStmt "create database tpcbDB ON DEFAULT = %d;"
|
|
#endif
|
|
#define DatabaseUseStmt "use tpcbDB;"
|
|
|
|
/*
|
|
* Specifications of table columns.
|
|
* Fillers of 80, 80, 84, and 24 bytes, respectively, are used
|
|
* to ensure that rows are the width required by the benchmark.
|
|
*
|
|
* Note: The TimesTen and MS SQL CREATE TABLE statements for the
|
|
* accounts, tellers and branches tables are different.
|
|
*
|
|
*/
|
|
|
|
#define TuplesPerPage 256
|
|
|
|
|
|
#ifdef MYSQL
|
|
|
|
#define AccountCrTblStmt "create table accounts \
|
|
(number integer not null primary key, \
|
|
branchnum integer not null, \
|
|
balance float not null, \
|
|
filler char(80));"
|
|
|
|
#define TellerCrTblStmt "create table tellers \
|
|
(number integer not null primary key, \
|
|
branchnum integer not null, \
|
|
balance float not null, \
|
|
filler char(80));"
|
|
|
|
#define BranchCrTblStmt "create table branches \
|
|
(number integer not null primary key, \
|
|
balance float not null, \
|
|
filler char(84));"
|
|
|
|
#endif
|
|
|
|
|
|
#ifdef NDB
|
|
#define AccountCrTblStmt "create table accounts \
|
|
(number integer not null primary key, \
|
|
branchnum integer not null, \
|
|
balance float not null, \
|
|
filler char(80)) nologging"
|
|
|
|
#define TellerCrTblStmt "create table tellers \
|
|
(number integer not null primary key, \
|
|
branchnum integer not null, \
|
|
balance float not null, \
|
|
filler char(80)) nologging"
|
|
|
|
#define BranchCrTblStmt "create table branches \
|
|
(number integer not null primary key, \
|
|
balance float not null, \
|
|
filler char(84)) nologging"
|
|
#endif
|
|
|
|
#ifdef NDB
|
|
|
|
#define HistoryCrTblStmt "create table History \
|
|
(tellernum integer not null, \
|
|
branchnum integer not null, \
|
|
accountnum integer not null, \
|
|
delta float not null, \
|
|
createtime integer not null, \
|
|
filler char(24), \
|
|
primary key (tellernum, branchnum, accountnum, delta, createtime)) nologging"
|
|
|
|
#else
|
|
|
|
#ifdef MYSQL
|
|
|
|
#define HistoryCrTblStmt "create table History \
|
|
(tellernum integer not null, \
|
|
branchnum integer not null, \
|
|
accountnum integer not null, \
|
|
delta float(53) not null, \
|
|
createtime integer not null, \
|
|
filler char(24))"
|
|
#endif
|
|
|
|
#define HistoryCrTblStmt "create table History \
|
|
(tellernum integer not null, \
|
|
branchnum integer not null, \
|
|
accountnum integer not null, \
|
|
delta float(53) not null, \
|
|
createtime integer not null, \
|
|
filler char(24));"
|
|
#endif
|
|
|
|
#define TTAccountCrTblStmt "create table accounts \
|
|
(number integer not null primary key, \
|
|
branchnum integer not null, \
|
|
balance float(53) not null, \
|
|
filler char(80)) unique hash on (number) pages = %" PTRINT_FMT ";"
|
|
|
|
#define TTTellerCrTblStmt "create table tellers \
|
|
(number integer not null primary key, \
|
|
branchnum integer not null, \
|
|
balance float(53) not null, \
|
|
filler char(80)) unique hash on (number) pages = %" PTRINT_FMT ";"
|
|
|
|
#define TTBranchCrTblStmt "create table branches \
|
|
(number integer not null primary key, \
|
|
balance float(53) not null, \
|
|
filler char(84)) unique hash on (number) pages = %" PTRINT_FMT ";"
|
|
|
|
|
|
/* Insertion statements used to populate the tables */
|
|
|
|
#define NumInsStmts 3
|
|
char* insStmt[NumInsStmts] = {
|
|
"insert into branches values (?, 0.0, NULL)",
|
|
"insert into tellers values (?, ?, 0.0, NULL)",
|
|
"insert into accounts values (?, ?, 0.0, NULL)"
|
|
};
|
|
|
|
/* Transaction statements used to update the tables */
|
|
|
|
#define NumXactStmts 5
|
|
|
|
#ifdef NDB
|
|
char* tpcbXactStmt[NumXactStmts] = {
|
|
"update accounts \
|
|
set balance = balance + ? \
|
|
where number = ?",
|
|
|
|
"select balance \
|
|
from accounts \
|
|
where number = ?",
|
|
|
|
"update tellers \
|
|
set balance = balance + ? \
|
|
where number = ?",
|
|
|
|
"update branches \
|
|
set balance = balance + ? \
|
|
where number = ?",
|
|
|
|
"insert into History(tellernum, branchnum, \
|
|
accountnum, delta, createtime, filler) \
|
|
values (?, ?, ?, ?, ?, NULL)"
|
|
};
|
|
|
|
#else
|
|
char* tpcbXactStmt[NumXactStmts] = {
|
|
"update accounts \
|
|
set balance = balance + ? \
|
|
where number = ?;",
|
|
|
|
"select balance \
|
|
from accounts \
|
|
where number = ?;",
|
|
|
|
"update tellers \
|
|
set balance = balance + ? \
|
|
where number = ?;",
|
|
|
|
"update branches \
|
|
set balance = balance + ? \
|
|
where number = ?;",
|
|
|
|
"insert into History \
|
|
values (?, ?, ?, ?, ?, NULL);"
|
|
};
|
|
|
|
|
|
#endif
|
|
|
|
/* Global parameters and flags (typically set by parse_args()) */
|
|
|
|
int tabFlag = 0; /* Default is NOT tab output mode */
|
|
char szConnStrIn[CONN_STR_LEN]; /* ODBC Connection String */
|
|
int printXactTimes = 0; /* Transaction statistics
|
|
* gathering flag */
|
|
char statFile[FILENAME_MAX]; /* Transaction statistics filename */
|
|
int scaleFactor = 2; /* Default TPS scale factor */
|
|
int numBranchTups; /* Number of branches */
|
|
int numTellerTups; /* Number of tellers */
|
|
int numAccountTups; /* Number of accounts */
|
|
int numNonLocalAccountTups; /* Number of local accounts */
|
|
int numXacts = NumXacts; /* Default number of transactions */
|
|
int verbose = VERBOSE_DFLT; /* Verbose level */
|
|
FILE *statusfp; /* File for status messages */
|
|
|
|
|
|
|
|
int DBMSType; /* DBMS type (DBMS_TIMESTEN, DBMS_MSSQL...) */
|
|
|
|
|
|
SQLHENV henv; /* Environment handle */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void handle_errors( SQLHDBC hdbc, SQLHSTMT hstmt, int errcode, int action, char * msg,
|
|
char * file, int line) {
|
|
|
|
if (errcode == SQL_SUCCESS)
|
|
return;
|
|
|
|
if(errcode == SQL_ERROR) {
|
|
int ret;
|
|
long diagCount=0;
|
|
short length=0;
|
|
SQLCHAR state[10] = "";
|
|
SQLCHAR message[200] = "";
|
|
long native = 0;
|
|
if(hstmt != 0) {
|
|
ret = SQLGetDiagField(SQL_HANDLE_STMT, hstmt, 0, SQL_DIAG_NUMBER, &diagCount, SQL_IS_INTEGER, 0);
|
|
|
|
for(long i = 0; i < diagCount; i++) {
|
|
ret = SQLGetDiagRec(SQL_HANDLE_STMT, hstmt, i, (SQLCHAR*)state, &native, (SQLCHAR*)message, 200, &length);
|
|
ndbout_c("GetDiagRec: Message : %s ", message);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(errcode != SQL_SUCCESS) {
|
|
ndbout_c("Message: %s", msg);
|
|
switch(errcode) {
|
|
case SQL_SUCCESS_WITH_INFO:
|
|
ndbout_c("SQL_SUCCESS_WITH_INFO");
|
|
break;
|
|
case SQL_STILL_EXECUTING:
|
|
ndbout_c("SQL_STILL_EXECUTING");
|
|
break;
|
|
case SQL_ERROR:
|
|
ndbout_c("SQL_ERROR");
|
|
break;
|
|
case SQL_INVALID_HANDLE:
|
|
ndbout_c("SQL_INVALID_HANDLE");
|
|
break;
|
|
default:
|
|
ndbout_c("Some other error");
|
|
}
|
|
exit(1);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*********************************************************************
|
|
* FUNCTION: usage
|
|
*
|
|
* DESCRIPTION: This function prints a usage message describing
|
|
* the command line options of the program.
|
|
*
|
|
* PARAMETERS: char* prog full program path name
|
|
*
|
|
* RETURNS: void
|
|
*
|
|
* NOTES: NONE
|
|
*
|
|
*********************************************************************/
|
|
|
|
static void usage(char *prog)
|
|
{
|
|
char *progname;
|
|
|
|
/* Get the name of the program (sans path). */
|
|
|
|
#ifdef WIN32
|
|
progname = strrchr(prog, '\\');
|
|
#else
|
|
progname = strrchr(prog, '/');
|
|
#endif
|
|
if (progname == 0)
|
|
progname = prog;
|
|
else
|
|
++progname;
|
|
|
|
/* Print the usage message */
|
|
|
|
fprintf(stderr,
|
|
"Usage:\t%s [-h] [-help] [-V] [-connStr <string>] [-v <level>]\n"
|
|
"\t\t[-xact <xacts>] [-scale <scale>] [-tabs] [-s <statfile>]\n\n"
|
|
" -h Prints this message and exits.\n"
|
|
" -help Same as -h.\n"
|
|
" -V Prints version number and exits.\n"
|
|
" -connStr <string> Specifies an ODBC connection string to replace the\n"
|
|
" default DSN for the program. The default is\n"
|
|
" \"DSN=TpcbData<version>;OverWrite=1\".\n"
|
|
" -v <level> Verbose level\n"
|
|
" 0 = errors only\n"
|
|
" 1 = results only\n"
|
|
" 2 = results and some status messages (default)\n"
|
|
" 3 = all messages\n"
|
|
" -xact <xacts> Specifies the number of transactions to be run\n"
|
|
" The default is 25000 transactions.\n"
|
|
" -scale <scale> Specifies a scale factor which determines the\n"
|
|
" number of branches (scale), tellers (scale x 10),\n"
|
|
" accounts (scale x 10000) and non-local accounts\n"
|
|
" ((scale-1) x 10000. The default scale factor is 2.\n"
|
|
" -tabs Specifies that the output be a tab-separated\n"
|
|
" format suitable for import into a spreadsheet.\n"
|
|
" Results only go to stdout; status and other\n"
|
|
" messages go to stderr.\n"
|
|
" -s <statfile> Prints individual transaction times to <statfile>.\n",
|
|
progname);
|
|
}
|
|
|
|
/*********************************************************************
|
|
*
|
|
* FUNCTION: parse_args
|
|
*
|
|
* DESCRIPTION: This function parses the command line arguments
|
|
* passed to main(), setting the appropriate global
|
|
* variables and issuing a usage message for
|
|
* invalid arguments.
|
|
*
|
|
* PARAMETERS: int argc # of arguments from main()
|
|
* char *argv[] arguments from main()
|
|
*
|
|
* RETURNS: void
|
|
*
|
|
* NOTES: NONE
|
|
*
|
|
*********************************************************************/
|
|
|
|
void
|
|
parse_args(int argc, char *argv[])
|
|
{
|
|
int i = 1;
|
|
|
|
*szConnStrIn = 0;
|
|
|
|
while (i < argc) {
|
|
|
|
if ( !strcmp(argv[i], "-h") || !strcmp(argv[i], "-help") ) {
|
|
usage(argv[0]);
|
|
app_exit(0);
|
|
}
|
|
/*
|
|
if (!strcmp(argv[i], "-V")) {
|
|
printf("%s\n", TTVERSION_STRING);
|
|
app_exit(0);
|
|
}
|
|
*/
|
|
if (strcmp(argv[i], "-s") == 0) {
|
|
if (argc < i+2 ) {
|
|
usage(argv[0]);
|
|
app_exit(1);
|
|
}
|
|
if (sscanf(argv[i+1], "%s", statFile) == 0) {
|
|
usage(argv[0]);
|
|
app_exit(1);
|
|
}
|
|
printXactTimes = 1;
|
|
i += 2;
|
|
}
|
|
else if (!strcmp(argv[i], "-connStr")) {
|
|
if (argc < i+2 ) {
|
|
usage(argv[0]);
|
|
app_exit(1);
|
|
}
|
|
strcpy(szConnStrIn, argv[i+1]);
|
|
i += 2;
|
|
continue;
|
|
}
|
|
else if (strcmp("-v", argv[i]) == 0) {
|
|
if (argc < i+2 ) {
|
|
usage(argv[0]);
|
|
app_exit(1);
|
|
}
|
|
if (sscanf(argv[i+1], "%d", &verbose) == -1 ||
|
|
verbose < 0 || verbose > 3) {
|
|
fprintf(stderr, "-v flag requires an integer parameter (0-3)\n");
|
|
usage(argv[0]);
|
|
app_exit(1);
|
|
}
|
|
i += 2;
|
|
}
|
|
else if (strcmp("-xact",argv[i]) == 0) {
|
|
if (argc < i+2 ) {
|
|
usage(argv[0]);
|
|
app_exit(1);
|
|
}
|
|
|
|
if (sscanf(argv[i+1], "%" PTRINT_FMT, &numXacts) == -1 || numXacts < 0) {
|
|
fprintf(stderr, "-xact flag requires a non-negative integer argument\n");
|
|
usage(argv[0]);
|
|
app_exit(1);
|
|
}
|
|
|
|
i += 2;
|
|
}
|
|
else if (strcmp("-scale",argv[i]) == 0) {
|
|
if (argc < i+2 ) {
|
|
usage(argv[0]);
|
|
app_exit(1);
|
|
}
|
|
if (sscanf(argv[i+1], "%d", &scaleFactor) == -1 || scaleFactor < 1) {
|
|
fprintf(stderr, "-scale flag requires an integer argument >= 1\n");
|
|
usage(argv[0]);
|
|
app_exit(1);
|
|
}
|
|
/* Calculate tuple sizes */
|
|
numBranchTups = NumBranches * scaleFactor;
|
|
numTellerTups = TellersPerBranch * scaleFactor;
|
|
numAccountTups = AccountsPerBranch * scaleFactor;
|
|
numNonLocalAccountTups = AccountsPerBranch * (scaleFactor-1);
|
|
i += 2;
|
|
}
|
|
else if (strcmp("-tabs",argv[i]) == 0) {
|
|
tabFlag = 1;
|
|
statusfp = stderr;
|
|
i += 1;
|
|
}
|
|
else {
|
|
usage(argv[0]);
|
|
app_exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
*
|
|
* FUNCTION: doImmed
|
|
*
|
|
* DESCRIPTION: This function executes and frees the specified
|
|
* statement. It is used as a direct means to
|
|
* create the tables used by this benchmark,
|
|
*
|
|
* PARAMETERS: SQLHDBC hdbc SQL Connection handle
|
|
* SQLHSTMT hs SQL Statement handle
|
|
* char* cmd SQL Statement text
|
|
*
|
|
* RETURNS: void
|
|
*
|
|
* NOTES: NONE
|
|
*
|
|
*********************************************************************/
|
|
|
|
void
|
|
doImmed(SQLHDBC hdbc, SQLHSTMT hs, char* cmd)
|
|
{
|
|
SQLRETURN rc;
|
|
|
|
/* Execute the command */
|
|
|
|
rc = SQLExecDirect(hs, (SQLCHAR *) cmd, SQL_NTS);
|
|
handle_errors(hdbc, hs, rc, ABORT_DISCONNECT_EXIT,
|
|
"Error executing statement", __FILE__, __LINE__);
|
|
|
|
/* Close associated cursor and drop pending results */
|
|
|
|
rc = SQLFreeStmt(hs, SQL_CLOSE);
|
|
handle_errors(hdbc, hs, rc, ABORT_DISCONNECT_EXIT,
|
|
"closing statement handle",
|
|
__FILE__, __LINE__);
|
|
|
|
}
|
|
|
|
|
|
/*********************************************************************
|
|
*
|
|
* FUNCTION: main
|
|
*
|
|
* DESCRIPTION: This is the main function of the tpcb benchmark.
|
|
* It connects to an ODBC data source, creates and
|
|
* populates tables, updates the tables in a user-
|
|
* specified number of transactions and reports on
|
|
* on the transaction times.
|
|
*
|
|
* PARAMETERS: int argc # of command line arguments
|
|
* char *argv[] command line arguments
|
|
*
|
|
* RETURNS: void
|
|
*
|
|
* NOTES: NONE
|
|
*
|
|
*********************************************************************/
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
|
|
/* variables used for setting up the tables */
|
|
|
|
char cmdStr[1024];
|
|
char errstr[4096];
|
|
|
|
/* variables used during transactions */
|
|
|
|
int accountNum;
|
|
int tellerNum;
|
|
int branchNum;
|
|
int timeStamp;
|
|
double delta;
|
|
unsigned int lrand;
|
|
unsigned short *srands, localLimit;
|
|
int lp64;
|
|
|
|
/* variables used for timing and statistics */
|
|
|
|
int warmup;
|
|
double kernel, user, real;
|
|
ttThreadTimes startRes, endRes;
|
|
ttWallClockTime startT, endT;
|
|
ttWallClockTime** rtStart;
|
|
ttWallClockTime** rtEnd;
|
|
double** resTime;
|
|
double maxTime, totTime;
|
|
int i;
|
|
int j;
|
|
int numLocalXacts=0, numRemoteXacts=0;
|
|
|
|
/* variables for ODBC */
|
|
|
|
SQLHDBC hdbc;
|
|
SQLHSTMT hstmt;
|
|
SQLHSTMT txstmt[NumXactStmts];
|
|
SQLRETURN rc;
|
|
char DBMSName[32];
|
|
char DBMSVersion[32];
|
|
int databaseSize;
|
|
|
|
int fThreadTime = 1;
|
|
|
|
#ifdef WIN32
|
|
OSVERSIONINFO sysInfo;
|
|
|
|
sysInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
GetVersionEx (&sysInfo);
|
|
|
|
/* GetThreadTimes is not supported on 95/98. Hence,
|
|
we do not support Resource/User/System times */
|
|
if (sysInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
|
|
fThreadTime = 0;
|
|
#endif
|
|
#if defined(TTCLIENTSERVER) && defined(__hpux) && !defined(__LP64__)
|
|
/* HP requires this for C main programs that call aC++ shared libs */
|
|
_main();
|
|
#endif /* hpux32 */
|
|
|
|
/* Set up default signal handlers */
|
|
|
|
#ifndef NDB
|
|
/* StopRequestClear();
|
|
if (HandleSignals() != 0) {
|
|
err_msg0("Unable to set signal handlers\n");
|
|
return 1;
|
|
}
|
|
*/
|
|
#endif
|
|
/* set IO mode for demo */
|
|
/* set_io_mode(); */
|
|
|
|
/* initialize the file for status messages */
|
|
statusfp = stdout;
|
|
|
|
/* set variable for 8-byte longs */
|
|
lp64 = (sizeof(lrand) == 8);
|
|
|
|
/* set the default tuple sizes */
|
|
|
|
numBranchTups = NumBranches * scaleFactor;
|
|
numTellerTups = TellersPerBranch * scaleFactor;
|
|
numAccountTups = AccountsPerBranch * scaleFactor;
|
|
numNonLocalAccountTups = AccountsPerBranch * (scaleFactor-1);
|
|
|
|
/* parse the command arguments */
|
|
parse_args(argc, argv);
|
|
|
|
/* allocate the transaction-based variables */
|
|
|
|
rtStart = (ttWallClockTime**) malloc(numXacts * sizeof(ttWallClockTime*));
|
|
if (!rtStart) {
|
|
err_msg0("Cannot allocate the transaction timing structures");
|
|
app_exit(1);
|
|
}
|
|
for (i = 0; i < numXacts; i++) {
|
|
rtStart[i] = (ttWallClockTime*) malloc(sizeof(ttWallClockTime));
|
|
if (!rtStart[i]) {
|
|
err_msg0("Cannot allocate the transaction timing structures");
|
|
app_exit(1);
|
|
}
|
|
}
|
|
|
|
rtEnd = (ttWallClockTime**) malloc(numXacts * sizeof(ttWallClockTime*));
|
|
if (!rtEnd) {
|
|
err_msg0("Cannot allocate the transaction timing structures");
|
|
app_exit(1);
|
|
}
|
|
for (i = 0; i < numXacts; i++) {
|
|
rtEnd[i] = (ttWallClockTime*) malloc(sizeof(ttWallClockTime));
|
|
if (!rtEnd[i]) {
|
|
err_msg0("Cannot allocate the transaction timing structures");
|
|
app_exit(1);
|
|
}
|
|
}
|
|
|
|
resTime = (double**) malloc(numXacts * sizeof(double*));
|
|
if (!resTime) {
|
|
err_msg0("Cannot allocate the transaction timing structures");
|
|
app_exit(1);
|
|
}
|
|
for (i = 0; i < numXacts; i++) {
|
|
resTime[i] = (double*) malloc(sizeof(double));
|
|
if (!resTime[i]) {
|
|
err_msg0("Cannot allocate the transaction timing structures");
|
|
app_exit(1);
|
|
}
|
|
}
|
|
|
|
/* ODBC initialization */
|
|
|
|
rc = SQLAllocEnv(&henv);
|
|
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
|
|
/* error occurred -- don't bother calling handle_errors, since handle
|
|
* is not valid so SQLError won't work */
|
|
err_msg3("ERROR in %s, line %d: %s\n",
|
|
__FILE__, __LINE__, "allocating an environment handle");
|
|
app_exit(1);
|
|
}
|
|
SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);
|
|
|
|
/* call this in case of warning */
|
|
handle_errors(NULL, NULL, rc, NO_EXIT,
|
|
"allocating execution environment",
|
|
__FILE__, __LINE__);
|
|
|
|
rc = SQLAllocConnect(henv, &hdbc);
|
|
handle_errors(NULL, NULL, rc, ERROR_EXIT,
|
|
"allocating connection handle",
|
|
__FILE__, __LINE__);
|
|
|
|
/* Connect to data store */
|
|
|
|
status_msg0("Connecting to the data source...\n");
|
|
|
|
/* Set up the connection options if not specified on the command line
|
|
* (default to TimesTen settings).
|
|
*/
|
|
|
|
if ( !*szConnStrIn ) {
|
|
/* Running the benchmark with a scale factor creates (scale) branches,
|
|
* (scale x 10) tellers, (scale x 10000) accounts and ((scale-1) x 10000)
|
|
* non-local accounts. The size of the table rows are branches (141)
|
|
* tellers (141) and accounts (141). Therefore the data size requirements
|
|
* of this benchmark is:
|
|
* size ~= 141 * ((scale * 20011) - 10000) (bytes)
|
|
*
|
|
* Multiply data size by 20% to account for additional DB overhead (e.g.
|
|
* indexes), and round up the nearest 10Mb for safety.
|
|
*/
|
|
|
|
int est_size = (int) (3.6 * scaleFactor + 10.0);
|
|
est_size = est_size - (est_size % 10);
|
|
|
|
sprintf(szConnStrIn,"OverWrite=1;PermSize=%d;%s",
|
|
est_size, DSNNAME);
|
|
status_msg0("Connecting to the data source... %s \n", szConnStrIn);
|
|
}
|
|
|
|
rc = SQLDriverConnect(hdbc, NULL, (SQLCHAR *) szConnStrIn, SQL_NTS,
|
|
NULL, 0, NULL,
|
|
SQL_DRIVER_NOPROMPT);
|
|
|
|
status_msg0("Connected to the data source...\n");
|
|
sprintf(errstr, "connecting to driver (connect string %s)\n",
|
|
szConnStrIn);
|
|
handle_errors(hdbc, NULL, rc, ERROR_EXIT,
|
|
errstr, __FILE__, __LINE__);
|
|
|
|
/* Turn auto-commit off */
|
|
|
|
rc = SQLSetConnectOption(hdbc, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF);
|
|
handle_errors(hdbc, NULL, rc, DISCONNECT_EXIT,
|
|
"switching off the AUTO_COMMIT option",
|
|
__FILE__, __LINE__);
|
|
|
|
/* Allocate a statement handle */
|
|
|
|
rc = SQLAllocStmt(hdbc, &hstmt);
|
|
handle_errors(hdbc, NULL, rc, DISCONNECT_EXIT,
|
|
"allocating a statement handle",
|
|
__FILE__, __LINE__);
|
|
|
|
/* (Implicit) Transaction begin */
|
|
|
|
/* Determine the DBMS Type*/
|
|
|
|
DBMSName[0] = '\0';
|
|
rc = SQLGetInfo(hdbc, SQL_DBMS_NAME, (PTR) &DBMSName,
|
|
sizeof(DBMSName), NULL);
|
|
rc = SQLGetInfo(hdbc, SQL_DRIVER_VER, (PTR) &DBMSVersion,
|
|
sizeof(DBMSVersion), NULL);
|
|
|
|
if (strcmp(DBMSName, "TimesTen") == 0)
|
|
DBMSType = DBMS_TIMESTEN;
|
|
else if (strcmp(DBMSName, "Microsoft SQL Server") == 0)
|
|
DBMSType = DBMS_MSSQL;
|
|
else DBMSType = DBMS_UNKNOWN;
|
|
|
|
/* if not TimesTen: delete (if it exists), create & use the new database */
|
|
|
|
if (DBMSType != DBMS_TIMESTEN) {
|
|
status_msg0("Deleting the database...\n");
|
|
rc = SQLExecDirect(hstmt, (SQLCHAR *) DatabaseDropStmt, SQL_NTS);
|
|
|
|
/* estimate database size, size = data space + log space
|
|
* data space = (#tuples)/(tuples per page) * 2K bytes/page
|
|
* tuples per page = useable page size / row size (no index) = 2016/(96+2)
|
|
* log space = #transactions * average log size for the program transaction mix
|
|
* database size is in MB
|
|
*/
|
|
|
|
databaseSize = (int) ceil((((numBranchTups + numTellerTups + numAccountTups)/
|
|
(2016/98)) * 2048 + (numXacts * 600)) / 1000000.0);
|
|
|
|
status_msg1("Creating the database (%dMB)...\n", databaseSize);
|
|
#ifndef NDB
|
|
sprintf(cmdStr, DatabaseCreateStmt, databaseSize);
|
|
doImmed(hdbc, hstmt, cmdStr);
|
|
strcpy(cmdStr, DatabaseUseStmt);
|
|
doImmed(hdbc, hstmt, cmdStr);
|
|
#endif
|
|
}
|
|
|
|
status_msg2("Connected to '%s' version '%s'...\n", DBMSName, DBMSVersion);
|
|
|
|
/* create branches table */
|
|
status_msg0("Creating tasddbles...\n");
|
|
#ifndef NDB
|
|
if (DBMSType == DBMS_TIMESTEN)
|
|
sprintf(cmdStr, TTBranchCrTblStmt, numBranchTups/TuplesPerPage + 1);
|
|
else
|
|
#endif
|
|
sprintf(cmdStr, BranchCrTblStmt);
|
|
doImmed(hdbc, hstmt, cmdStr);
|
|
|
|
/* create tellers table */
|
|
#ifndef NDB
|
|
if (DBMSType == DBMS_TIMESTEN)
|
|
sprintf(cmdStr, TTTellerCrTblStmt, numTellerTups/TuplesPerPage + 1);
|
|
|
|
else
|
|
#endif
|
|
sprintf(cmdStr, TellerCrTblStmt);
|
|
doImmed(hdbc, hstmt, cmdStr);
|
|
|
|
/* create accounts table */
|
|
#ifndef NDB
|
|
if (DBMSType == DBMS_TIMESTEN)
|
|
sprintf(cmdStr, TTAccountCrTblStmt, numAccountTups/TuplesPerPage + 1);
|
|
else
|
|
#endif
|
|
sprintf(cmdStr, AccountCrTblStmt);
|
|
doImmed(hdbc, hstmt, cmdStr);
|
|
|
|
/* create History table */
|
|
|
|
doImmed(hdbc, hstmt, HistoryCrTblStmt);
|
|
|
|
/* lock the database during population */
|
|
#ifndef NDB
|
|
if ( DBMSType == DBMS_TIMESTEN ) {
|
|
rc = SQLExecDirect(hstmt, (SQLCHAR *)"call ttlocklevel('DS')", SQL_NTS);
|
|
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
|
|
"specifying dbs lock usage",
|
|
__FILE__, __LINE__);
|
|
/* make sure dbs lock take effect in next transaction */
|
|
rc = SQLTransact(henv,hdbc,SQL_COMMIT);
|
|
if ( rc != SQL_SUCCESS) {
|
|
handle_errors(hdbc, SQL_NULL_HSTMT, rc, ERROR_EXIT,
|
|
"committing transaction",
|
|
__FILE__, __LINE__);
|
|
}
|
|
}
|
|
#endif
|
|
/* populate branches table */
|
|
|
|
|
|
rc = SQLPrepare(hstmt, (SQLCHAR *) insStmt[0], SQL_NTS);
|
|
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
|
|
"preparing statement",
|
|
__FILE__, __LINE__);
|
|
|
|
rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 10, 0, &branchNum, sizeof branchNum, NULL);
|
|
|
|
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
|
|
"binding parameter",
|
|
__FILE__, __LINE__);
|
|
|
|
|
|
status_msg1("Populating branches table (%" PTRINT_FMT " rows)...\n",
|
|
numBranchTups);
|
|
|
|
|
|
for (i=0; i<numBranchTups; i++) {
|
|
branchNum = i;
|
|
rc = SQLExecute(hstmt);
|
|
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
|
|
"Error executing statement",
|
|
__FILE__, __LINE__);
|
|
}
|
|
|
|
/* Reset all bind-parameters for the statement handle. */
|
|
rc = SQLFreeStmt(hstmt, SQL_RESET_PARAMS);
|
|
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
|
|
"resetting parms on statement handle",
|
|
__FILE__, __LINE__);
|
|
|
|
/* populate tellers table */
|
|
|
|
status_msg1("Populating tellers table (%" PTRINT_FMT " rows)...\n",
|
|
numTellerTups);
|
|
|
|
|
|
rc = SQLPrepare(hstmt, (SQLCHAR *) insStmt[1], SQL_NTS);
|
|
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
|
|
"preparing statement",
|
|
__FILE__, __LINE__);
|
|
|
|
rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER,
|
|
10, 0, &tellerNum, sizeof tellerNum, NULL);
|
|
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
|
|
"binding parameter",
|
|
__FILE__, __LINE__);
|
|
|
|
rc = SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER,
|
|
10, 0, &branchNum, sizeof branchNum, NULL);
|
|
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
|
|
"binding parameter",
|
|
__FILE__, __LINE__);
|
|
|
|
for (i=0; i<numTellerTups; i++) {
|
|
tellerNum = i;
|
|
branchNum = i/TellersPerBranch;
|
|
rc = SQLExecute(hstmt);
|
|
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
|
|
"Error executing statement",
|
|
__FILE__, __LINE__);
|
|
}
|
|
|
|
/* Reset all bind-parameters for the statement handle. */
|
|
|
|
rc = SQLFreeStmt(hstmt, SQL_RESET_PARAMS);
|
|
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
|
|
"resetting parms on statement handle",
|
|
__FILE__, __LINE__);
|
|
|
|
/* populate accounts table */
|
|
|
|
status_msg1("Populating accounts table (%" PTRINT_FMT " rows)...\n",
|
|
numAccountTups);
|
|
|
|
rc = SQLPrepare(hstmt, (SQLCHAR *) insStmt[2], SQL_NTS);
|
|
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
|
|
"preparing statement",
|
|
__FILE__, __LINE__);
|
|
|
|
rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER,
|
|
10, 0, &accountNum, sizeof accountNum, NULL);
|
|
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
|
|
"binding parameter",
|
|
__FILE__, __LINE__);
|
|
|
|
rc = SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER,
|
|
10, 0, &branchNum, sizeof branchNum, NULL);
|
|
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
|
|
"binding parameter",
|
|
__FILE__, __LINE__);
|
|
|
|
for (i=0; i<numAccountTups; i++) {
|
|
accountNum = i;
|
|
branchNum = i/AccountsPerBranch;
|
|
rc = SQLExecute(hstmt);
|
|
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
|
|
"Error executing statement",
|
|
__FILE__, __LINE__);
|
|
}
|
|
status_msg0("Commit...\n");
|
|
rc = SQLTransact(henv, hdbc, SQL_COMMIT);
|
|
status_msg0("Commit done...\n");
|
|
handle_errors(hdbc, NULL, rc, ERROR_EXIT,
|
|
"committing transaction",
|
|
__FILE__, __LINE__);
|
|
|
|
/* compile SQL statements of transaction */
|
|
|
|
status_msg0("Compiling statements of transaction...\n");
|
|
for (i=0; i<NumXactStmts; i++) {
|
|
#ifndef NDB
|
|
rc = SQLAllocStmt(hdbc, &txstmt[i]);
|
|
handle_errors(hdbc, NULL, rc, ABORT_DISCONNECT_EXIT,
|
|
"allocating a statement handle",
|
|
__FILE__, __LINE__);
|
|
#else
|
|
rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &txstmt[i]);
|
|
handle_errors(hdbc, NULL, rc, ABORT_DISCONNECT_EXIT,
|
|
"allocating a statement handle",
|
|
__FILE__, __LINE__);
|
|
|
|
#endif
|
|
|
|
rc = SQLPrepare(txstmt[i], (SQLCHAR *) tpcbXactStmt[i], SQL_NTS);
|
|
handle_errors(hdbc, txstmt[i], rc, ABORT_DISCONNECT_EXIT,
|
|
"preparing statement",
|
|
__FILE__, __LINE__);
|
|
}
|
|
|
|
/* unuse dbs lock */
|
|
#ifndef NDB
|
|
if ( DBMSType == DBMS_TIMESTEN ) {
|
|
rc = SQLExecDirect(hstmt, (SQLCHAR *)"call ttlocklevel('Row')", SQL_NTS);
|
|
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
|
|
"specifying row lock usage",
|
|
__FILE__, __LINE__);
|
|
}
|
|
#endif
|
|
|
|
/* commit transaction */
|
|
|
|
rc = SQLTransact(henv, hdbc, SQL_COMMIT);
|
|
handle_errors(hdbc, NULL, rc, ERROR_EXIT,
|
|
"committing transaction",
|
|
__FILE__, __LINE__);
|
|
|
|
|
|
/* Initialize random seed and timers */
|
|
|
|
srand48(SeedVal);
|
|
localLimit = (unsigned short)((1<<16) * 0.85);
|
|
|
|
/* Initialize parameter lists for each of the transactions */
|
|
|
|
rc = SQLBindParameter(txstmt[0], 1, SQL_PARAM_INPUT, SQL_C_DOUBLE,
|
|
SQL_DOUBLE, 15, 0, &delta, sizeof delta, NULL);
|
|
handle_errors(hdbc, txstmt[0], rc, ABORT_DISCONNECT_EXIT,
|
|
"binding parameter",
|
|
__FILE__, __LINE__);
|
|
|
|
rc = SQLBindParameter(txstmt[0], 2, SQL_PARAM_INPUT, SQL_C_SLONG,
|
|
SQL_INTEGER, 10, 0, &accountNum, sizeof accountNum,
|
|
NULL);
|
|
handle_errors(hdbc, txstmt[0], rc, ABORT_DISCONNECT_EXIT,
|
|
"binding parameter",
|
|
__FILE__, __LINE__);
|
|
|
|
rc = SQLBindParameter(txstmt[1], 1, SQL_PARAM_INPUT, SQL_C_SLONG,
|
|
SQL_INTEGER, 10, 0, &accountNum, sizeof accountNum,
|
|
NULL);
|
|
handle_errors(hdbc, txstmt[1], rc, ABORT_DISCONNECT_EXIT,
|
|
"binding parameter",
|
|
__FILE__, __LINE__);
|
|
|
|
rc = SQLBindParameter(txstmt[2], 1, SQL_PARAM_INPUT, SQL_C_DOUBLE,
|
|
SQL_DOUBLE, 15, 0, &delta, sizeof delta, NULL);
|
|
handle_errors(hdbc, txstmt[2], rc, ABORT_DISCONNECT_EXIT,
|
|
"binding parameter",
|
|
__FILE__, __LINE__);
|
|
|
|
rc = SQLBindParameter(txstmt[2], 2, SQL_PARAM_INPUT, SQL_C_SLONG,
|
|
SQL_INTEGER, 10, 0, &tellerNum, sizeof tellerNum,
|
|
NULL);
|
|
handle_errors(hdbc, txstmt[2], rc, ABORT_DISCONNECT_EXIT,
|
|
"binding parameter",
|
|
__FILE__, __LINE__);
|
|
|
|
rc = SQLBindParameter(txstmt[3], 1, SQL_PARAM_INPUT, SQL_C_DOUBLE,
|
|
SQL_DOUBLE, 15, 0, &delta, sizeof delta, NULL);
|
|
handle_errors(hdbc, txstmt[3], rc, ABORT_DISCONNECT_EXIT,
|
|
"binding parameter",
|
|
__FILE__, __LINE__);
|
|
|
|
rc = SQLBindParameter(txstmt[3], 2, SQL_PARAM_INPUT, SQL_C_SLONG,
|
|
SQL_INTEGER, 10, 0, &branchNum, sizeof branchNum,
|
|
NULL);
|
|
handle_errors(hdbc, txstmt[3], rc, ABORT_DISCONNECT_EXIT,
|
|
"binding parameter",
|
|
__FILE__, __LINE__);
|
|
|
|
rc = SQLBindParameter(txstmt[4], 1, SQL_PARAM_INPUT, SQL_C_SLONG,
|
|
SQL_INTEGER, 10, 0, &tellerNum, sizeof tellerNum,
|
|
NULL);
|
|
handle_errors(hdbc, txstmt[4], rc, ABORT_DISCONNECT_EXIT,
|
|
"binding parameter",
|
|
__FILE__, __LINE__);
|
|
|
|
rc = SQLBindParameter(txstmt[4], 2, SQL_PARAM_INPUT, SQL_C_SLONG,
|
|
SQL_INTEGER, 10, 0, &branchNum, sizeof branchNum,
|
|
NULL);
|
|
handle_errors(hdbc, txstmt[4], rc, ABORT_DISCONNECT_EXIT,
|
|
"binding parameter",
|
|
__FILE__, __LINE__);
|
|
|
|
rc = SQLBindParameter(txstmt[4], 3, SQL_PARAM_INPUT, SQL_C_SLONG,
|
|
SQL_INTEGER, 10, 0, &accountNum, sizeof accountNum,
|
|
NULL);
|
|
handle_errors(hdbc, txstmt[4], rc, ABORT_DISCONNECT_EXIT,
|
|
"binding parameter",
|
|
__FILE__, __LINE__);
|
|
|
|
rc = SQLBindParameter(txstmt[4], 4, SQL_PARAM_INPUT, SQL_C_DOUBLE,
|
|
SQL_DOUBLE, 15, 0, &delta, sizeof delta, NULL);
|
|
handle_errors(hdbc, txstmt[4], rc, ABORT_DISCONNECT_EXIT,
|
|
"binding parameter",
|
|
__FILE__, __LINE__);
|
|
|
|
rc = SQLBindParameter(txstmt[4], 5, SQL_PARAM_INPUT, SQL_C_SLONG,
|
|
SQL_INTEGER, 10, 0, &timeStamp, sizeof timeStamp,
|
|
NULL);
|
|
handle_errors(hdbc, txstmt[4], rc, ABORT_DISCONNECT_EXIT,
|
|
"binding parameter",
|
|
__FILE__, __LINE__);
|
|
|
|
/* Execute transaction loop.
|
|
* Do it twice, once briefly as a warm-up. */
|
|
|
|
|
|
|
|
for (warmup = 1; warmup >= 0; warmup--) {
|
|
|
|
int max_i = (warmup ? numXacts/10 : numXacts);
|
|
|
|
/* Execute tpcb transaction max_i times.*/
|
|
|
|
if (warmup) {
|
|
status_msg1("\nWarming up with %d tpcb transactions...\n", max_i);
|
|
}
|
|
else {
|
|
status_msg1("Executing and timing %d tpcb transactions...\n", max_i);
|
|
}
|
|
|
|
ttGetWallClockTime(&startT);
|
|
ttGetThreadTimes(&startRes);
|
|
|
|
for (i = 0; i < max_i; i++) {
|
|
|
|
lrand = lrand48();
|
|
srands = (unsigned short *)(&lrand);
|
|
if (lp64) srands += 2; /* skip high half -- all zero */
|
|
|
|
/* randomly choose a teller */
|
|
|
|
tellerNum = srands[0] % numTellerTups;
|
|
|
|
/* compute branch */
|
|
|
|
branchNum = (tellerNum / TellersPerBranch);
|
|
|
|
/* randomly choose an account */
|
|
|
|
if (srands[1] < localLimit || numBranchTups == 1) {
|
|
|
|
/* choose account local to selected branch */
|
|
|
|
accountNum = branchNum * AccountsPerBranch +
|
|
(lrand48() % AccountsPerBranch);
|
|
|
|
++numLocalXacts;
|
|
|
|
}
|
|
else {
|
|
/* choose account not local to selected branch */
|
|
|
|
/* first select account in range [0,numNonLocalAccountTups) */
|
|
|
|
accountNum = lrand48() % numNonLocalAccountTups;
|
|
|
|
/* if branch number of selected account is at least as big
|
|
* as local branch number, then increment account number
|
|
* by AccountsPerBranch to skip over local accounts
|
|
*/
|
|
|
|
if ((accountNum/AccountsPerBranch) >= branchNum)
|
|
accountNum += AccountsPerBranch;
|
|
|
|
++numRemoteXacts;
|
|
}
|
|
|
|
/* select delta amount, -999,999 to +999,999 */
|
|
|
|
delta = ((lrand48() % 1999999) - 999999);
|
|
|
|
|
|
/* begin timing the "residence time" */
|
|
|
|
ttGetWallClockTime(rtStart[i]);
|
|
|
|
for ( j = 0; j < NumXactStmts - 2; j++) {
|
|
rc = SQLExecute(txstmt[j]);
|
|
handle_errors(hdbc, txstmt[j], rc, ABORT_DISCONNECT_EXIT,
|
|
"Error executing statement1",
|
|
__FILE__, __LINE__);
|
|
|
|
/* Close the handle after the SELECT statement
|
|
* (txstmt[1]) for non TimesTen DBMS' */
|
|
|
|
if ((DBMSType != DBMS_TIMESTEN) && (j == 1)) {
|
|
SQLFreeStmt(txstmt[1], SQL_CLOSE);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
/* note that time must be taken within the */
|
|
timeStamp = time(NULL);
|
|
|
|
rc = SQLExecute(txstmt[NumXactStmts - 1]);
|
|
handle_errors(hdbc, txstmt[NumXactStmts - 1], rc,
|
|
ABORT_DISCONNECT_EXIT, "Error executing statement2",
|
|
__FILE__, __LINE__);
|
|
|
|
rc = SQLTransact(henv, hdbc, SQL_COMMIT);
|
|
handle_errors(hdbc, NULL, rc, ERROR_EXIT,
|
|
"Error committing transaction",
|
|
__FILE__, __LINE__);
|
|
|
|
ttGetWallClockTime(rtEnd[i]);
|
|
|
|
} /* end fortransaction loop */
|
|
|
|
|
|
|
|
|
|
ttGetThreadTimes(&endRes);
|
|
ttGetWallClockTime(&endT);
|
|
ttCalcElapsedThreadTimes(&startRes, &endRes, &kernel, &user);
|
|
ttCalcElapsedWallClockTime(&startT, &endT, &real);
|
|
|
|
if (warmup) {
|
|
if (!tabFlag) {
|
|
if (verbose) {
|
|
if (fThreadTime) {
|
|
out_msg0(" time user system\n");
|
|
|
|
out_msg3("Warmup time (sec): %12.3f %12.3f %12.3f\n\n",
|
|
real/1000.0, user, kernel);
|
|
} else {
|
|
out_msg1("Warmup time (sec): %12.3f\n\n", real/1000.0);
|
|
}
|
|
}
|
|
} else {
|
|
if (verbose) {
|
|
if (fThreadTime) {
|
|
out_msg0("\ttime\tuser\tsystem\n");
|
|
|
|
out_msg3("Warmup time (sec):\t%12.3f\t%12.3f\t%12.3f\n",
|
|
real/1000.0, user, kernel);
|
|
} else {
|
|
out_msg1("Warmup time (sec):\t%12.3f\n", real/1000.0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
status_msg0("\nExecution completed...\n");
|
|
|
|
/* Compute and report timing statistics */
|
|
|
|
maxTime = 0.0;
|
|
totTime = 0.0;
|
|
|
|
for (i = 0; i < numXacts; i++) {
|
|
ttCalcElapsedWallClockTime(rtStart[i], rtEnd[i], resTime[i]);
|
|
totTime += *(resTime[i]);
|
|
|
|
if (*(resTime[i]) > maxTime) maxTime = *(resTime[i]);
|
|
}
|
|
|
|
if (!tabFlag) {
|
|
if (verbose) {
|
|
if (fThreadTime) {
|
|
out_msg0(" time user system\n");
|
|
out_msg3("Total time (sec): %12.3f %12.3f %12.3f\n",
|
|
real/1000.0, user, kernel);
|
|
} else {
|
|
out_msg1("Total time (sec): %12.3f\n", real/1000.0);
|
|
}
|
|
}
|
|
|
|
if (verbose)
|
|
out_msg1("\nAverage transaction time (msec):%12.3f\n",
|
|
totTime/numXacts);
|
|
if (verbose)
|
|
out_msg1("Maximum transaction time (msec):%12.3f\n", maxTime);
|
|
if (verbose)
|
|
out_msg1("\nLocal transactions: %7" PTRINT_FMT "\n", numLocalXacts);
|
|
if (verbose)
|
|
out_msg1("Remote transactions: %7" PTRINT_FMT "\n", numRemoteXacts);
|
|
|
|
} else {
|
|
if (verbose) {
|
|
if (fThreadTime) {
|
|
out_msg0("\ttime\tuser\tsystem\n");
|
|
out_msg3("Total time (sec):\t%12.3f\t%12.3f\t%12.3f\n",
|
|
real/1000.0, user, kernel);
|
|
} else {
|
|
out_msg1("Total time (sec):\t%12.3f\n", real/1000.0);
|
|
}
|
|
}
|
|
|
|
if (verbose)
|
|
out_msg1("\nAverage transaction time (msec):\t%12.3f\n",
|
|
totTime/numXacts);
|
|
if (verbose)
|
|
out_msg1("Maximum transaction time (msec):\t%12.3f\n", maxTime);
|
|
if (verbose)
|
|
out_msg1("Local transactions:\t%7" PTRINT_FMT "\n", numLocalXacts);
|
|
|
|
if (verbose)
|
|
out_msg1("Remote transactions:\t%7" PTRINT_FMT "\n", numRemoteXacts);
|
|
|
|
|
|
|
|
}
|
|
|
|
/* If the statfile option is selected, print each transaction's time */
|
|
|
|
if (printXactTimes) {
|
|
FILE * fp;
|
|
if ( (fp = fopen (statFile, "w")) == NULL ) {
|
|
err_msg1("Unable to open stat file %s for writing\n\n", statFile);
|
|
} else {
|
|
for (int i = 0; i < numXacts; i++)
|
|
fprintf(fp,"%6d: %12.3f\n", i, *(resTime[i]));
|
|
fclose(fp);
|
|
}
|
|
}
|
|
|
|
/* Disconnect and return */
|
|
|
|
rc = SQLFreeStmt(hstmt, SQL_DROP);
|
|
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
|
|
"dropping the statement handle",
|
|
__FILE__, __LINE__);
|
|
|
|
for (int i=0; i<NumXactStmts; i++) {
|
|
rc = SQLFreeStmt(txstmt[i], SQL_DROP);
|
|
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
|
|
"dropping the statement handle",
|
|
__FILE__, __LINE__);
|
|
}
|
|
|
|
if (verbose >= VERBOSE_DFLT)
|
|
status_msg0("Disconnecting from the data source...\n");
|
|
|
|
rc = SQLDisconnect(hdbc);
|
|
handle_errors(hdbc, NULL, rc, ERROR_EXIT,
|
|
"disconnecting",
|
|
__FILE__, __LINE__);
|
|
|
|
rc = SQLFreeConnect(hdbc);
|
|
handle_errors(hdbc, NULL, rc, ERROR_EXIT,
|
|
"freeing connection handle",
|
|
__FILE__, __LINE__);
|
|
|
|
rc = SQLFreeEnv(henv);
|
|
handle_errors(NULL, NULL, rc, ERROR_EXIT,
|
|
"freeing environment handle",
|
|
__FILE__, __LINE__);
|
|
|
|
app_exit(0);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Emacs variable settings */
|
|
/* Local Variables: */
|
|
/* tab-width:8 */
|
|
/* indent-tabs-mode:nil */
|
|
/* c-basic-offset:2 */
|
|
/* End: */
|
|
|
|
|
|
|