File indexing completed on 2025-08-03 08:22:01
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #include <RDBC/TSQLConnection.h>
0037 #include <RDBC/TSQLStatement.h>
0038 #include <RDBC/TSQLDriverManager.h>
0039 #include <RDBC/TSQLResultSet.h>
0040 #include <TTimer.h>
0041 #include <TStopwatch.h>
0042 #include <TString.h>
0043 #include <TRandom.h>
0044 #include <RQ_OBJECT.h>
0045 #include <TSystem.h>
0046
0047 int tps = 1;
0048 int nbranches = 1;
0049 int ntellers = 10;
0050 int naccounts = 100000;
0051 int nhistory = 864000;
0052 int gClients = 10;
0053 int gTxnPerClient = 100;
0054
0055 int failed_transactions = 0;
0056 int transaction_count = 0;
0057 Bool_t gVerbose = kFALSE;
0058 long start_time = 0;
0059 enum { kTELLER, kBRANCH, kACCOUNT };
0060
0061
0062
0063 class RDBCBench
0064 {
0065 friend class ClientThread;
0066
0067 RQ_OBJECT()
0068
0069 private:
0070 TSQLConnection* fConn;
0071 TList* fListOfClients;
0072 TStopwatch fTimer;
0073
0074 void StopThreads();
0075 void CreateDatabase();
0076 void DropDatabase();
0077 int DoOne(int bid, int tid, int aid, int delta);
0078 int GetRandomID(int type);
0079 int GetRandomInt(int lo, int hi);
0080
0081 public:
0082 RDBCBench(TSQLConnection* conn, Bool_t init);
0083 ~RDBCBench() { delete fListOfClients; delete fConn; }
0084
0085 void ReportDone();
0086 };
0087
0088
0089 class ClientThread
0090 {
0091 private:
0092 Int_t fNtrans;
0093 RDBCBench* fParent;
0094 TTimer* fThread;
0095
0096 public:
0097 ClientThread(int number_of_txns,RDBCBench* p);
0098 ~ClientThread() { }
0099
0100 void Run();
0101 void Start() { fThread->Start(10); }
0102 TTimer* GetThread() const { return fThread; }
0103 };
0104
0105
0106 ClientThread::ClientThread(int number_of_txns,RDBCBench* p)
0107 {
0108
0109
0110 fNtrans = number_of_txns;
0111 fThread = new TTimer(10);
0112 fParent = p;
0113 fThread->Connect("Timeout()","ClientThread",this,"Run()");
0114 }
0115
0116
0117 void ClientThread::Run()
0118 {
0119
0120
0121 while (fNtrans-- > 0) {
0122
0123 int account = fParent->GetRandomID(kACCOUNT);
0124 int branch = fParent->GetRandomID(kBRANCH);
0125 int teller = fParent->GetRandomID(kTELLER);
0126 int delta = fParent->GetRandomInt(0,1000);
0127
0128 fParent->DoOne(account, branch, teller, delta);
0129 transaction_count++;
0130 }
0131 fParent->ReportDone();
0132 }
0133
0134
0135
0136 RDBCBench::RDBCBench(TSQLConnection* conn, Bool_t init)
0137 {
0138
0139
0140 fConn = conn;
0141
0142 if (init) {
0143 DropDatabase();
0144 printf("Initializing dataset...");
0145 CreateDatabase();
0146 printf("done.\n");
0147 }
0148
0149 fListOfClients = new TList();
0150
0151 for (int i = 0; i < gClients; i++) {
0152 ClientThread* client = new ClientThread(gTxnPerClient,this);
0153 fListOfClients->Add(client->GetThread());
0154 client->Start();
0155 }
0156
0157 printf("\n* Starting Benchmark Run *\n");
0158 fTimer.Start(kTRUE);
0159 }
0160
0161
0162 void RDBCBench::ReportDone()
0163 {
0164
0165
0166 gClients--;
0167
0168 if (gClients == 0) {
0169 fTimer.Stop();
0170 Double_t rtime = fTimer.RealTime();
0171 Double_t ctime = fTimer.CpuTime();
0172
0173 printf("* Benchmark finished *");
0174 printf("\n\n* Benchmark Report *\n" );
0175 printf("-------------------------------------------------\n");
0176 printf("Time to execute %d transactions: Real time %.3f, CPU time %.3f seconds\n",
0177 transaction_count,rtime,ctime );
0178
0179 printf("%d / %d failed to complete.\n",failed_transactions,transaction_count);
0180 printf("Transaction rate: %f txn/sec (real time).\n\n",(transaction_count - failed_transactions) / rtime);
0181 StopThreads();
0182 Emit("ReportDone()");
0183 gSystem->Exit(0);
0184 }
0185 }
0186
0187
0188 void RDBCBench::StopThreads()
0189 {
0190
0191
0192 fListOfClients->Delete();
0193 }
0194
0195
0196 int RDBCBench::GetRandomInt(int lo, int hi)
0197 {
0198
0199
0200 int ret = 0;
0201 ret = gRandom->Integer(hi-lo);
0202 ret += lo;
0203 return ret;
0204 }
0205
0206
0207 int RDBCBench::GetRandomID(int type)
0208 {
0209
0210
0211 int min, max, num;
0212 max = min = num = 0;
0213
0214 switch(type) {
0215 case kTELLER:
0216 num = ntellers*tps;
0217 break;
0218 case kBRANCH:
0219 num = nbranches*tps;
0220 break;
0221 case kACCOUNT:
0222 num = naccounts*tps;
0223 break;
0224 }
0225
0226 max = min + num;
0227 return (GetRandomInt(min, max));
0228 }
0229
0230
0231 void RDBCBench::CreateDatabase()
0232 {
0233
0234
0235
0236 TSQLStatement* stmt = fConn->CreateStatement();
0237
0238 TString query;
0239
0240 query = "CREATE TABLE branches (";
0241 query+= "Bid INT NOT NULL, PRIMARY KEY(Bid), ";
0242 query+= "Bbalance INT,";
0243 query+= "filler CHAR(88))";
0244
0245 stmt->ExecuteUpdate(query);
0246 stmt->ClearWarnings();
0247
0248 query = "CREATE TABLE tellers ( ";
0249 query+= "Tid INT NOT NULL, PRIMARY KEY(Tid),";
0250 query+= "Bid INT,";
0251 query+= "Tbalance INT,";
0252 query+= "filler CHAR(84))";
0253
0254 stmt->ExecuteUpdate(query);
0255 stmt->ClearWarnings();
0256
0257 query = "CREATE TABLE accounts ( ";
0258 query+= "Aid INT NOT NULL, PRIMARY KEY(Aid), ";
0259 query+= "Bid INT, ";
0260 query+= "Abalance INT, ";
0261 query+= "filler CHAR(84))";
0262
0263 stmt->ExecuteUpdate(query);
0264 stmt->ClearWarnings();
0265
0266 query = "CREATE TABLE history ( ";
0267 query+= "Tid INT, ";
0268 query+= "Bid INT, ";
0269 query+= "Aid INT, ";
0270 query+= "delta INT, ";
0271 query+= "time TIMESTAMP, ";
0272 query+= "filler CHAR(22))";
0273
0274 stmt->ExecuteUpdate(query);
0275 stmt->ClearWarnings();
0276
0277
0278
0279
0280
0281
0282
0283 char str[1028];
0284
0285 for (int i = 0; i < nbranches * tps; i++) {
0286 sprintf(str,"INSERT INTO branches(Bid,Bbalance) VALUES ( %d ,0)",i);
0287 stmt->ExecuteUpdate(str);
0288 stmt->ClearWarnings();
0289 }
0290
0291 for (int i = 0; i < ntellers * tps; i++) {
0292 sprintf(str,"INSERT INTO tellers(Tid,Bid,Tbalance) VALUES (%d,%d,0)",i,i / ntellers);
0293 stmt->ExecuteUpdate(str);
0294 stmt->ClearWarnings();
0295 }
0296
0297 for (int i = 0; i < naccounts*tps; i++) {
0298 sprintf(str,"INSERT INTO accounts(Aid,Bid,Abalance) VALUES (%d,%d,0)",i,i / naccounts);
0299 stmt->ExecuteUpdate(str);
0300 stmt->ClearWarnings();
0301 }
0302
0303 delete stmt;
0304 }
0305
0306
0307 void RDBCBench::DropDatabase()
0308 {
0309
0310
0311
0312 TSQLStatement* stmt = fConn->CreateStatement();
0313
0314 TSQL::UnsetHandler();
0315 TString str;
0316 str = "DROP TABLE branches";
0317 stmt->ExecuteUpdate(str);
0318
0319 str = "DROP TABLE tellers";
0320 stmt->ExecuteUpdate(str);
0321
0322 str = "DROP TABLE accounts";
0323 stmt->ExecuteUpdate(str);
0324
0325 str = "DROP TABLE history";
0326 stmt->ExecuteUpdate(str);
0327
0328 delete stmt;
0329 TSQL::SetHandler("Catch(TSQLException*)");
0330 }
0331
0332
0333 int RDBCBench::DoOne(int aid, int bid, int tid, int delta)
0334 {
0335
0336
0337
0338 TSQLStatement* stmt = fConn->CreateStatement();
0339
0340 char query[1028];
0341
0342 TSQL::SetHandler("CatchFailedTransaction(TSQLException*)");
0343
0344 sprintf(query,"UPDATE accounts SET Abalance = Abalance + %d WHERE Aid = %d",delta,aid);
0345 stmt->ExecuteUpdate(query);
0346 stmt->ClearWarnings();
0347
0348 sprintf(query,"SELECT Abalance FROM accounts WHERE Aid = %d",aid);
0349 TSQLResultSet* rs = stmt->ExecuteQuery(query);
0350 stmt->ClearWarnings();
0351
0352 int aBalance = 0;
0353
0354 while (rs->Next()) {
0355 aBalance = rs->GetInt(1);
0356 }
0357
0358 delete stmt;
0359 stmt = fConn->CreateStatement();
0360
0361 sprintf(query,"UPDATE tellers SET Tbalance = Tbalance + %d WHERE Tid = %d",delta,tid);
0362 stmt->ExecuteUpdate(query);
0363 stmt->ClearWarnings();
0364
0365 sprintf(query,"UPDATE branches SET Bbalance = Bbalance + %d WHERE Bid = %d",delta,bid);
0366 stmt->ExecuteUpdate(query);
0367 stmt->ClearWarnings();
0368
0369 sprintf(query,"INSERT INTO history(Tid, Bid, Aid, delta) VALUES (%d,%d,%d,%d)", tid,bid,aid,delta);
0370 stmt->ExecuteUpdate(query);
0371 stmt->ClearWarnings();
0372
0373 TSQL::SetHandler("Catch(TSQLException*)");
0374 delete stmt;
0375 return aBalance;
0376 }
0377
0378
0379 void CatchFailedTransaction(TSQLException* e)
0380 {
0381
0382 TString str = e->GetMessage();
0383
0384 if (gVerbose) {
0385 printf("Transaction failed: %s\n",str.Data());
0386
0387 }
0388 failed_transactions++;
0389 }
0390
0391
0392 void bench( const TString& dsn="",const TString& usr="",
0393 const TString& psw="",const TString& option="",
0394 const TString& tpc_str="100", const TString& clients_str="10")
0395 {
0396
0397
0398
0399
0400
0401 Bool_t initialize_dataset = kFALSE;
0402 failed_transactions = 0;
0403 transaction_count = 0;
0404
0405 Int_t tpc = atoi(tpc_str.Data());
0406 Int_t clients = atoi(clients_str.Data());
0407
0408 if(clients>0) gClients = clients;
0409 if(tpc>0) gTxnPerClient = tpc;
0410
0411 if(option.Contains("-init")) initialize_dataset = kTRUE;
0412 else if(option.Contains("-v")) gVerbose = kTRUE;
0413
0414 printf("\n usage: obench(dsn,usr,psw,[option],[tpc],[clients])\n");
0415 printf("\n");
0416 printf("dsn Data Source Name\n");
0417 printf("usr user name\n");
0418 printf("psw password\n");
0419 printf("tpc transactions per client\n");
0420 printf("clients number of simultaneous clients\n");
0421 printf("option string:\n");
0422 printf("-v verbose error messages\n");
0423 printf("-init initialize the tables\n");
0424
0425 printf("\n*********************************************************\n");
0426 printf("* RDBCBench v1.0 *\n");
0427 printf("*********************************************************\n");
0428 printf("\n");
0429 printf("DSN: %s\n",dsn.Data());
0430 printf("User: %s\n",usr.Data());
0431 printf("\n");
0432 printf("Number of clients: %d\n",gClients);
0433 printf("Number of transactions per client: %d\n",gTxnPerClient);
0434 printf("\n");
0435
0436 TSQL::SetHandler("Catch(TSQLException*)");
0437 TSQLConnection* conn = gSQLDriverManager->GetConnection(dsn,usr,psw);
0438 RDBCBench* rdbc_bench = new RDBCBench(conn, initialize_dataset);
0439
0440
0441
0442
0443
0444 return;
0445 }
0446
0447
0448 void Catch(TSQLException* e)
0449 {
0450
0451
0452 TString str = e->GetMessage();
0453 printf("SQL Error: %s\n",str.Data());
0454 }
0455
0456
0457 #ifdef STANDALONE
0458
0459 #include <TROOT.h>
0460 #include <TSystem.h>
0461 #include <iostream>
0462 #include <TApplication.h>
0463
0464
0465
0466 TROOT root("RDBCbench", "RDBC benchmark program");
0467
0468 int main(int argc, char **argv)
0469 {
0470 if(argc < 3) {
0471 cerr << "Usage: " << argv[0] << " url username" << endl
0472 << "or " << argv[0] << " url username password [option] [tpc] [clients]" << endl;
0473 return 0;
0474 }
0475
0476 TApplication theApp("App", &argc, argv);
0477
0478 gSystem->Load("libRDBC");
0479 gSystem->Load("./RDBCbench_C");
0480
0481 if(argc==3) bench(argv[1],argv[2],"");
0482 else if(argc==4) bench(argv[1],argv[2],argv[3]);
0483 else if(argc==5) bench(argv[1],argv[2],argv[3],argv[4]);
0484 else if(argc==6) bench(argv[1],argv[2],argv[3],argv[4],argv[5]);
0485 else if(argc==7) bench(argv[1],argv[2],argv[3],argv[4],argv[5],argv[6]);
0486
0487 theApp.Run();
0488 return 0;
0489 }
0490 #endif