Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RDBCbench.C
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file RDBCbench.C
1 // $Id: RDBCbench.C,v 1.1.1.1 2004/02/18 20:58:02 dave Exp $
2 //
3 // This file is part of the RDBC
4 // Author: Valeriy Onuchin <onuchin@sirius.ihep.su>
6 //
7 // This is a sample implementation of the
8 // Transaction Processing Performance Council Benchmark B
9 // coded in Java and ANSI SQL2.
10 //
11 // This is ROOT adaptation of JAVA code from
12 // http://www.worldserver.com/mm.mysql/
13 //
14 //
16 //
17 // usage:
18 //
19 // root[] gSystem->Load("libRDBC.so"); // load library
20 // root[] .L RDBCbench.C // load macro
21 // root[] bench(dsn,usr,psw,[option],[tpc],[clients]); // execute
22 //
23 // dsn Data Source Name
24 // usr user name
25 // psw password
26 // tpc transactions per client
27 // clients number of simultaneous clients
28 //
29 // option string can contain:
30 // -v verbose error messages
31 // -init initialize the tables
32 //
33 //
35 
36 #include <RDBC/TSQLConnection.h>
37 #include <RDBC/TSQLStatement.h>
38 #include <RDBC/TSQLDriverManager.h>
39 #include <RDBC/TSQLResultSet.h>
40 #include <TTimer.h>
41 #include <TStopwatch.h>
42 #include <TString.h>
43 #include <TRandom.h>
44 #include <RQ_OBJECT.h>
45 #include <TSystem.h>
46 
47 int tps = 1; // the tps scaling factor: here it is 1
48 int nbranches = 1; // number of branches in 1 tps db
49 int ntellers = 10; // number of tellers in 1 tps db
50 int naccounts = 100000; // number of accounts in 1 tps db
51 int nhistory = 864000; // number of history recs in 1 tps db
52 int gClients = 10; // default number of clients
53 int gTxnPerClient = 100; // default number transactions per client
54 
57 Bool_t gVerbose = kFALSE;
58 long start_time = 0;
60 
61 
63 class RDBCBench
64 {
65 friend class ClientThread;
66 
67 RQ_OBJECT()
68 
69 private:
70  TSQLConnection* fConn; // DataBase connection
71  TList* fListOfClients; // client threads
72  TStopwatch fTimer; // benchmark timer
73 
74  void StopThreads();
75  void CreateDatabase();
76  void DropDatabase();
77  int DoOne(int bid, int tid, int aid, int delta);
78  int GetRandomID(int type);
79  int GetRandomInt(int lo, int hi);
80 
81 public:
82  RDBCBench(TSQLConnection* conn, Bool_t init);
83  ~RDBCBench() { delete fListOfClients; delete fConn; }
84 
85  void ReportDone(); //*SIGNAL*
86 };
87 
90 {
91 private:
92  Int_t fNtrans; //
94  TTimer* fThread; //
95 
96 public:
97  ClientThread(int number_of_txns,RDBCBench* p);
99 
100  void Run();
101  void Start() { fThread->Start(10); } // 100 msec period
102  TTimer* GetThread() const { return fThread; }
103 };
104 
105 //___________________________________________________________________
107 {
108  //
109 
110  fNtrans = number_of_txns;
111  fThread = new TTimer(10);
112  fParent = p;
113  fThread->Connect("Timeout()","ClientThread",this,"Run()");
114 }
115 
116 //___________________________________________________________________
118 {
119  //
120 
121  while (fNtrans-- > 0) {
122 
123  int account = fParent->GetRandomID(kACCOUNT);
124  int branch = fParent->GetRandomID(kBRANCH);
125  int teller = fParent->GetRandomID(kTELLER);
126  int delta = fParent->GetRandomInt(0,1000);
127 
128  fParent->DoOne(account, branch, teller, delta);
130  }
131  fParent->ReportDone();
132 }
133 
135 //___________________________________________________________________
137 {
138  //
139 
140  fConn = conn;
141 
142  if (init) {
143  DropDatabase();
144  printf("Initializing dataset...");
145  CreateDatabase();
146  printf("done.\n");
147  }
148 
149  fListOfClients = new TList();
150 
151  for (int i = 0; i < gClients; i++) {
152  ClientThread* client = new ClientThread(gTxnPerClient,this);
153  fListOfClients->Add(client->GetThread());
154  client->Start();
155  }
156 
157  printf("\n* Starting Benchmark Run *\n");
158  fTimer.Start(kTRUE);
159 }
160 
161 //___________________________________________________________________
163 {
164  //
165 
166  gClients--;
167 
168  if (gClients == 0) {
169  fTimer.Stop();
170  Double_t rtime = fTimer.RealTime();
171  Double_t ctime = fTimer.CpuTime();
172 
173  printf("* Benchmark finished *");
174  printf("\n\n* Benchmark Report *\n" );
175  printf("-------------------------------------------------\n");
176  printf("Time to execute %d transactions: Real time %.3f, CPU time %.3f seconds\n",
177  transaction_count,rtime,ctime );
178 // printf("Max/Min memory usage: " + MemoryWatcher.max + " / " + MemoryWatcher.min + " kb");
179  printf("%d / %d failed to complete.\n",failed_transactions,transaction_count);
180  printf("Transaction rate: %f txn/sec (real time).\n\n",(transaction_count - failed_transactions) / rtime);
181  StopThreads();
182  Emit("ReportDone()"); // emit signal
183  gSystem->Exit(0);
184  }
185 }
186 
187 //___________________________________________________________________
189 {
190  //
191 
192  fListOfClients->Delete();
193 }
194 
195 //___________________________________________________________________
196 int RDBCBench::GetRandomInt(int lo, int hi)
197 {
198  //
199 
200  int ret = 0;
201  ret = gRandom->Integer(hi-lo);
202  ret += lo;
203  return ret;
204 }
205 
206 //___________________________________________________________________
208 {
209  //
210 
211  int min, max, num;
212  max = min = num = 0;
213 
214  switch(type) {
215  case kTELLER:
216  num = ntellers*tps;
217  break;
218  case kBRANCH:
219  num = nbranches*tps;
220  break;
221  case kACCOUNT:
222  num = naccounts*tps;
223  break;
224  }
225 
226  max = min + num;
227  return (GetRandomInt(min, max));
228 }
229 
230 //___________________________________________________________________
232 {
233  // Creates and Initializes a scaled database.
234  //
235 
237 
238  TString query;
239 
240  query = "CREATE TABLE branches (";
241  query+= "Bid INT NOT NULL, PRIMARY KEY(Bid), ";
242  query+= "Bbalance INT,";
243  query+= "filler CHAR(88))"; /* pad to 100 bytes */
244 
245  stmt->ExecuteUpdate(query);
246  stmt->ClearWarnings();
247 
248  query = "CREATE TABLE tellers ( ";
249  query+= "Tid INT NOT NULL, PRIMARY KEY(Tid),";
250  query+= "Bid INT,";
251  query+= "Tbalance INT,";
252  query+= "filler CHAR(84))"; /* pad to 100 bytes */
253 
254  stmt->ExecuteUpdate(query);
255  stmt->ClearWarnings();
256 
257  query = "CREATE TABLE accounts ( ";
258  query+= "Aid INT NOT NULL, PRIMARY KEY(Aid), ";
259  query+= "Bid INT, ";
260  query+= "Abalance INT, ";
261  query+= "filler CHAR(84))"; /* pad to 100 bytes */
262 
263  stmt->ExecuteUpdate(query);
264  stmt->ClearWarnings();
265 
266  query = "CREATE TABLE history ( ";
267  query+= "Tid INT, ";
268  query+= "Bid INT, ";
269  query+= "Aid INT, ";
270  query+= "delta INT, ";
271  query+= "time TIMESTAMP, ";
272  query+= "filler CHAR(22))"; /* pad to 50 bytes */
273 
274  stmt->ExecuteUpdate(query);
275  stmt->ClearWarnings();
276 
277  // prime database using TPC BM B scaling rules.
278  // Note that for each branch and teller:
279  // branch_id = teller_id / ntellers
280  // branch_id = account_id / naccounts
281  //
282 
283  char str[1028];
284 
285  for (int i = 0; i < nbranches * tps; i++) {
286  sprintf(str,"INSERT INTO branches(Bid,Bbalance) VALUES ( %d ,0)",i);
287  stmt->ExecuteUpdate(str);
288  stmt->ClearWarnings();
289  }
290 
291  for (int i = 0; i < ntellers * tps; i++) {
292  sprintf(str,"INSERT INTO tellers(Tid,Bid,Tbalance) VALUES (%d,%d,0)",i,i / ntellers);
293  stmt->ExecuteUpdate(str);
294  stmt->ClearWarnings();
295  }
296 
297  for (int i = 0; i < naccounts*tps; i++) {
298  sprintf(str,"INSERT INTO accounts(Aid,Bid,Abalance) VALUES (%d,%d,0)",i,i / naccounts);
299  stmt->ExecuteUpdate(str);
300  stmt->ClearWarnings();
301  }
302 
303  delete stmt;
304 }
305 
306 //___________________________________________________________________
308 {
309  // Drops database.
310  //
311 
313 
314  TSQL::UnsetHandler(); //
315  TString str;
316  str = "DROP TABLE branches";
317  stmt->ExecuteUpdate(str);
318 
319  str = "DROP TABLE tellers";
320  stmt->ExecuteUpdate(str);
321 
322  str = "DROP TABLE accounts";
323  stmt->ExecuteUpdate(str);
324 
325  str = "DROP TABLE history";
326  stmt->ExecuteUpdate(str);
327 
328  delete stmt;
329  TSQL::SetHandler("Catch(TSQLException*)"); // set default error handler
330 }
331 
332 //___________________________________________________________________
333 int RDBCBench::DoOne(int aid, int bid, int tid, int delta)
334 {
335  // Executes a single TPC BM B transaction
336 
337 
339 
340  char query[1028];
341 
342  TSQL::SetHandler("CatchFailedTransaction(TSQLException*)");
343 
344  sprintf(query,"UPDATE accounts SET Abalance = Abalance + %d WHERE Aid = %d",delta,aid);
345  stmt->ExecuteUpdate(query);
346  stmt->ClearWarnings();
347 
348  sprintf(query,"SELECT Abalance FROM accounts WHERE Aid = %d",aid);
349  TSQLResultSet* rs = stmt->ExecuteQuery(query);
350  stmt->ClearWarnings();
351 
352  int aBalance = 0;
353 
354  while (rs->Next()) {
355  aBalance = rs->GetInt(1);
356  }
357 
358  delete stmt;
359  stmt = fConn->CreateStatement();
360 
361  sprintf(query,"UPDATE tellers SET Tbalance = Tbalance + %d WHERE Tid = %d",delta,tid);
362  stmt->ExecuteUpdate(query);
363  stmt->ClearWarnings();
364 
365  sprintf(query,"UPDATE branches SET Bbalance = Bbalance + %d WHERE Bid = %d",delta,bid);
366  stmt->ExecuteUpdate(query);
367  stmt->ClearWarnings();
368 
369  sprintf(query,"INSERT INTO history(Tid, Bid, Aid, delta) VALUES (%d,%d,%d,%d)", tid,bid,aid,delta);
370  stmt->ExecuteUpdate(query);
371  stmt->ClearWarnings();
372 
373  TSQL::SetHandler("Catch(TSQLException*)"); // set back default handler
374  delete stmt;
375  return aBalance;
376 }
377 
378 //___________________________________________________________________
380 {
381  //
382  TString str = e->GetMessage();
383 
384  if (gVerbose) {
385  printf("Transaction failed: %s\n",str.Data());
386 // e->printStackTrace();
387  }
389 }
390 
392 void bench( const TString& dsn="",const TString& usr="",
393  const TString& psw="",const TString& option="",
394  const TString& tpc_str="100", const TString& clients_str="10")
395 {
396  // main program:
397  // creates a 1-tps database: i.e. 1 branch, 10 tellers,...
398  // runs one TPC BM B transaction
399  //
400 
401  Bool_t initialize_dataset = kFALSE;
403  transaction_count = 0;
404 
405  Int_t tpc = atoi(tpc_str.Data());
406  Int_t clients = atoi(clients_str.Data());
407 
408  if(clients>0) gClients = clients;
409  if(tpc>0) gTxnPerClient = tpc;
410 
411  if(option.Contains("-init")) initialize_dataset = kTRUE;
412  else if(option.Contains("-v")) gVerbose = kTRUE;
413 
414  printf("\n usage: obench(dsn,usr,psw,[option],[tpc],[clients])\n");
415  printf("\n");
416  printf("dsn Data Source Name\n");
417  printf("usr user name\n");
418  printf("psw password\n");
419  printf("tpc transactions per client\n");
420  printf("clients number of simultaneous clients\n");
421  printf("option string:\n");
422  printf("-v verbose error messages\n");
423  printf("-init initialize the tables\n");
424 
425  printf("\n*********************************************************\n");
426  printf("* RDBCBench v1.0 *\n");
427  printf("*********************************************************\n");
428  printf("\n");
429  printf("DSN: %s\n",dsn.Data());
430  printf("User: %s\n",usr.Data());
431  printf("\n");
432  printf("Number of clients: %d\n",gClients);
433  printf("Number of transactions per client: %d\n",gTxnPerClient);
434  printf("\n");
435 
436  TSQL::SetHandler("Catch(TSQLException*)"); // set default error handler
437  TSQLConnection* conn = gSQLDriverManager->GetConnection(dsn,usr,psw);
438  RDBCBench* rdbc_bench = new RDBCBench(conn, initialize_dataset);
439  // memory leak here:
440  // rdbc_bench should be deleted after the end of test
441  // It can be done by connecting "ReportDone()" signal to
442  // some garbage collector
443 
444  return;
445 }
446 
447 //___________________________________________________________________
449 {
450  // handle exceptions
451 
452  TString str = e->GetMessage();
453  printf("SQL Error: %s\n",str.Data());
454 }
455 
457 #ifdef STANDALONE
458 
459 #include <TROOT.h>
460 #include <TSystem.h>
461 #include <iostream>
462 #include <TApplication.h>
463 
464 //---- Main program ------------------------------------------------------------
465 
466 TROOT root("RDBCbench", "RDBC benchmark program");
467 
468 int main(int argc, char **argv)
469 {
470  if(argc < 3) {
471  cerr << "Usage: " << argv[0] << " url username" << endl
472  << "or " << argv[0] << " url username password [option] [tpc] [clients]" << endl;
473  return 0;
474  }
475 
476  TApplication theApp("App", &argc, argv);
477 
478  gSystem->Load("libRDBC");
479  gSystem->Load("./RDBCbench_C");
480 
481  if(argc==3) bench(argv[1],argv[2],"");
482  else if(argc==4) bench(argv[1],argv[2],argv[3]);
483  else if(argc==5) bench(argv[1],argv[2],argv[3],argv[4]);
484  else if(argc==6) bench(argv[1],argv[2],argv[3],argv[4],argv[5]);
485  else if(argc==7) bench(argv[1],argv[2],argv[3],argv[4],argv[5],argv[6]);
486 
487  theApp.Run();
488  return 0;
489 }
490 #endif