Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-03 08:22:01

0001 // $Id: RDBCbench.C,v 1.1.1.1 2004/02/18 20:58:02 dave Exp $
0002 //
0003 //     This file is part of the RDBC
0004 //     Author: Valeriy Onuchin <onuchin@sirius.ihep.su>
0005 /////////////////////////////////////////////////////////////////////
0006 //
0007 //  This is a sample implementation of the 
0008 //  Transaction Processing Performance  Council Benchmark B 
0009 //  coded in Java and ANSI SQL2. 
0010 //
0011 //  This is ROOT adaptation of JAVA code from  
0012 //    http://www.worldserver.com/mm.mysql/
0013 //
0014 //
0015 /////////////////////////////////////////////////////////////////////
0016 //
0017 // usage:
0018 // 
0019 // root[] gSystem->Load("libRDBC.so");    // load library
0020 // root[] .L RDBCbench.C                  // load macro
0021 // root[] bench(dsn,usr,psw,[option],[tpc],[clients]); // execute
0022 //
0023 //    dsn          Data Source Name
0024 //    usr          user name
0025 //    psw          password
0026 //    tpc          transactions per client
0027 //    clients      number of simultaneous clients
0028 //
0029 //    option string can contain:
0030 //       -v           verbose error messages
0031 //       -init        initialize the tables
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;  // the tps scaling factor: here it is 1 
0048 int nbranches =       1;   // number of branches in 1 tps db 
0049 int ntellers  =      10;   // number of tellers in  1 tps db
0050 int naccounts =  100000;   // number of accounts in 1 tps db 
0051 int nhistory  =  864000;   // number of history recs in 1 tps db
0052 int gClients  =  10;       // default number of clients
0053 int gTxnPerClient = 100;   // default number transactions per client
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;      // DataBase connection
0071    TList*            fListOfClients;   // client threads
0072    TStopwatch        fTimer; // benchmark timer
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();  //*SIGNAL*
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); }  // 100 msec period 
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 //      printf("Max/Min memory usage: " + MemoryWatcher.max + " / " + MemoryWatcher.min + " kb");
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()");   // emit signal
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    //  Creates and Initializes a scaled database.     
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))"; /* pad to 100 bytes */ 
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))"; /* pad to 100 bytes */
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))";      /* pad to 100 bytes */
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))"; /* pad to 50 bytes  */
0273             
0274    stmt->ExecuteUpdate(query);
0275    stmt->ClearWarnings();
0276         
0277    // prime database using TPC BM B scaling rules.  
0278    //  Note that for each branch and teller:
0279    //      branch_id = teller_id  / ntellers
0280    //      branch_id = account_id / naccounts
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    //   Drops database.     
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*)");   // set default error handler
0330 }
0331 
0332 //___________________________________________________________________
0333 int RDBCBench::DoOne(int aid, int bid, int tid, int delta)
0334 {
0335    // Executes a single TPC BM B transaction
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*)");   // set back default handler
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 //      e->printStackTrace();
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    // main program:  
0397    //       creates a 1-tps database:  i.e. 1 branch, 10 tellers,...
0398    //       runs one TPC BM B transaction
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*)");   // set default error handler
0437    TSQLConnection* conn = gSQLDriverManager->GetConnection(dsn,usr,psw);
0438    RDBCBench* rdbc_bench = new RDBCBench(conn, initialize_dataset);
0439    // memory leak here: 
0440    //    rdbc_bench should be deleted after the end of test 
0441    //    It can be done by connecting "ReportDone()" signal to
0442    //    some garbage collector
0443 
0444    return;
0445 }
0446 
0447 //___________________________________________________________________
0448 void Catch(TSQLException* e)
0449 {
0450    // handle exceptions
0451    
0452    TString str = e->GetMessage();
0453    printf("SQL Error: %s\n",str.Data()); 
0454 }
0455 
0456 //////////////////////////// Main program ////////////////////////////////////
0457 #ifdef STANDALONE
0458 
0459 #include <TROOT.h>
0460 #include <TSystem.h>
0461 #include <iostream>
0462 #include <TApplication.h>
0463 
0464 //---- Main program ------------------------------------------------------------
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