c-core/29_core/core29Example_main.c
/*
* Raima Database Manager
*
* Copyright (c) 2019 Raima Inc., All rights reserved.
*
* Use of this software, whether in source code format, or in executable,
* binary object code form, is governed by the Raima LICENSE which
* is fully described in the LICENSE.TXT file, included within this
* distribution of files.
*/
#include <stdio.h>
#include <stdlib.h>
#include "example_fcns.h"
#include "rdm.h"
#include "rdmstartupapi.h"
/* Generated \c struct and \c typedef definitions to be used with the RDM APIs
*/
#include "core29_structs.h"
/* Generated catalog definition to be used with the RDM rdm_dbSetCatalog() API
*/
#include "core29_cat.h"
#define RAMPUPTIME 15
#define TPS 5
#define NUM_BRANCHES 1
#define NUM_TELLERS 10
#define NUM_ACCOUNTS 100000L
#define STEADYSTATE 60
const char *const description =
"Performance Test (inmemory) using TPC-B test specifications.";
const RDM_CMDLINE_OPT opts[] = {{NULL, NULL, NULL, NULL}};
RDM_RETCODE populateDatabase (
RDM_DB hDB)
{
perfTimer_t timer;
BRANCHES brnRec;
printf ("Populate database with %d TPS configuration:\t", TPS);
timeMeasureBegin (&timer);
for (brnRec.bid = 0; brnRec.bid < TPS; brnRec.bid++)
{
int ii;
rc = rdm_dbStartUpdate (hDB, RDM_LOCK_ALL, 0, NULL, 0, NULL);
print_error (rc);
if (rc == sOKAY)
{
brnRec.bbalance = 0.0;
brnRec._filler_has_value = RDM_FALSE;
hDB, TABLE_BRANCHES, &brnRec, sizeof (brnRec), NULL);
print_error (rc);
/* insert associated Tellers */
for (ii = 0; rc == sOKAY && ii < NUM_TELLERS; ii++)
{
TELLERS telRec;
telRec.bid = brnRec.bid;
telRec.tbalance = 0.0;
telRec.tid = (NUM_TELLERS * brnRec.bid) + ii;
telRec._filler_has_value = RDM_FALSE;
hDB, TABLE_TELLERS, &telRec, sizeof (telRec), NULL);
print_error (rc);
}
/* insert associated Accounts */
for (ii = 0; rc == sOKAY && ii < NUM_ACCOUNTS; ii++)
{
ACCOUNTS accRec;
accRec.bid = brnRec.bid;
accRec.abalance = 0.0;
accRec.aid = (NUM_ACCOUNTS * brnRec.bid) + ii;
accRec._filler_has_value = RDM_FALSE;
hDB, TABLE_ACCOUNTS, &accRec, sizeof (accRec), NULL);
print_error (rc);
}
rdm_dbEnd (hDB);
}
}
timeMeasureEnd (&timer);
printf ("%u milliseconds\n", timeMeasureDiff (&timer));
return rc;
}
RDM_RETCODE do_trans (
RDM_DB hDB,
unsigned int *elapsedTime)
{
perfTimer_t timer;
double bal;
RDM_TRANS hTrans;
RDM_CURSOR cursor = NULL;
RDM_CURSOR brnCursor = NULL;
struct
{
int bid;
int aid;
int tid;
double delta;
} historyRow;
TELLERS_TELLERS_PK_KEY tellerKey;
ACCOUNTS_ACCOUNTS_PK_KEY acctKey;
/* Selct Delta value in the range of +/- 999999 */
historyRow.delta = (double) (rand () / (65536.0 * 65536.0));
historyRow.tid = (int) ((rand () % (TPS * NUM_TELLERS)));
historyRow.bid = historyRow.tid / NUM_TELLERS;
historyRow.aid = (unsigned int) rand () % NUM_ACCOUNTS;
timeMeasureBegin (&timer);
do
{
rc = rdm_dbStartUpdate (hDB, RDM_LOCK_ALL, 0, NULL, 0, &hTrans);
} while (rc == eUNAVAIL);
print_error (rc);
/* Update Account where Account_ID = Aid: */
acctKey.aid = historyRow.aid;
hDB, COL_ACCOUNTS_AID, &acctKey, sizeof (acctKey), &cursor);
print_error (rc);
cursor, COL_ACCOUNTS_ABALANCE, &bal, sizeof (bal), NULL);
print_error (rc);
bal += historyRow.delta;
cursor, COL_ACCOUNTS_ABALANCE, &bal, sizeof (bal));
print_error (rc);
/* Write to History (removed for inmemory version to save memory space) */
/* Update Teller where Teller_ID = Tid */
tellerKey.tid = historyRow.tid;
hDB, COL_TELLERS_TID, &tellerKey, sizeof (tellerKey), &cursor);
print_error (rc);
cursor, COL_TELLERS_TBALANCE, &bal, sizeof (bal), NULL);
print_error (rc);
bal += historyRow.delta;
cursor, COL_TELLERS_TBALANCE, &bal, sizeof (bal));
print_error (rc);
/* Update Branch where Branch_ID = Bid: */
rc = rdm_cursorGetOwnerRow (cursor, REF_TELLERS_FK, &brnCursor);
print_error (rc);
brnCursor, COL_BRANCHES_BBALANCE, &bal, sizeof (bal), NULL);
print_error (rc);
bal += historyRow.delta;
brnCursor, COL_BRANCHES_BBALANCE, &bal, sizeof (bal));
print_error (rc);
rc = rdm_transEnd (hTrans);
print_error (rc);
timeMeasureEnd (&timer);
if (cursor)
rdm_cursorFree (cursor);
if (brnCursor)
rdm_cursorFree (brnCursor);
*elapsedTime = timeMeasureDiff (&timer);
return rc;
}
RDM_RETCODE readDbStats (RDM_DB hDB)
{
RDM_CURSOR cursor = NULL;
uint64_t count;
printf ("\nTPC-B Database Statistics:\n");
rc = rdm_dbStartRead (hDB, RDM_LOCK_ALL, 0, NULL);
print_error (rc);
if (rc == sOKAY)
{
rc = rdm_dbGetRows (hDB, TABLE_BRANCHES, &cursor);
print_error (rc);
if (rc == sOKAY)
{
rc = rdm_cursorGetCount (cursor, &count);
print_error (rc);
printf (
"\tBRANCHES table contains %u rows\n", (unsigned int) count);
}
if (rc == sOKAY)
{
rc = rdm_dbGetRows (hDB, TABLE_TELLERS, &cursor);
print_error (rc);
}
if (rc == sOKAY)
{
rc = rdm_cursorGetCount (cursor, &count);
print_error (rc);
printf ("\tTELLERS table contains %u rows\n", (unsigned int) count);
}
if (rc == sOKAY)
{
rc = rdm_dbGetRows (hDB, TABLE_ACCOUNTS, &cursor);
print_error (rc);
}
if (rc == sOKAY)
{
rc = rdm_cursorGetCount (cursor, &count);
print_error (rc);
printf (
"\tACCOUNTS table contains %u rows\n", (unsigned int) count);
}
if (cursor)
rdm_cursorFree (cursor);
}
return rc;
}
int main_core29 (int argc, const char *const *argv)
{
RDM_DB hDB;
RDM_TFS hTFS;
srand (100);
rc = rdm_cmdlineInit (&cmd, argc, argv, description, opts);
if (rc != sCMD_USAGE)
print_error (rc);
if (rc == sOKAY)
{
/* Initialize the TFS, task, and open/initialize the database */
rc = exampleOpenEmptyDatabaseInMemory (
&hTFS, &hDB, "core29", core29_cat);
if (rc == sOKAY)
{
rc = populateDatabase (hDB);
if (rc == sOKAY)
{
perfTimer_t timer;
unsigned int thisTrans;
unsigned int minTrans = (unsigned int) -1;
unsigned int maxTrans = 0;
unsigned int numTrans = 0;
unsigned int totTrans = 0;
/* RAMP-UP transactions */
printf ("Perform RAMP-UP for %d seconds\n", RAMPUPTIME);
timeMeasureBegin (&timer);
while (rc == sOKAY)
{
timeMeasureEnd (&timer);
if (timeMeasureDiff (&timer) > (RAMPUPTIME * 1000))
break;
rc = do_trans (hDB, &thisTrans);
}
/* TPC-B measurement */
printf ("Perform TPC-B test for %d seconds\n", STEADYSTATE);
timeMeasureBegin (&timer);
while (rc == sOKAY)
{
timeMeasureEnd (&timer);
if (timeMeasureDiff (&timer) > (STEADYSTATE * 1000))
break;
rc = do_trans (hDB, &thisTrans);
/* update the statistics */
minTrans = RDM_MIN (minTrans, thisTrans);
maxTrans = RDM_MAX (maxTrans, thisTrans);
totTrans += thisTrans;
numTrans++;
}
/* prevent divide by 0 incase totTrans is 0 */
if (totTrans != 0)
{
printf (
"Steady state results: %.2f TPS-B\n\n",
(double) numTrans / (double) totTrans * 1000.0);
}
printf (
"\tMinimum transaction time: %u milliseconds\n", minTrans);
printf (
"\tMaximum transaction time: %u milliseconds\n", maxTrans);
printf (
"\tTotal number of transactions measured: %u\n", numTrans);
readDbStats (hDB);
}
exampleCleanup (hTFS, hDB);
}
}
return (int) rc;
}