core30Example_main.c
                                            
                                            TPC-B comparing transaction safety settings. This example needs a compiled schema, core30Example.sdl.
#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 "core30Example_structs.h"
                                                    
                                                    /* Generated catalog definition to be used with the RDM rdm_dbSetCatalog() API
                                                    
                                                     */
                                                    
                                                    #include "core30Example_cat.h"
                                                    
                                                    /* Number of records to insert */
                                                    
                                                    #define RAMPUPTIME 15
                                                    
                                                    #define TPS 5
                                                    
                                                    #define NUM_BRANCHES 1
                                                    
                                                    #define NUM_TELLERS 10
                                                    
                                                    #define NUM_ACCOUNTS 100000L
                                                    
                                                    #define STEADYSTATE 60
                                                    
                                                    RDM_CMDLINE cmd;
                                                    const char *const description = "Performance Test using TPC-B test "
                                                    "specifications. Compares durability settings.";
                                                    
                                                    /*
                                                    
                                                     * \mainpage Core30 Popcorn Example
                                                    
                                                     *
                                                    
                                                     * The Core30 example is based on the TPC-B Benchmark published by the
                                                    
                                                     * Transaction Processing Performance Council (TPC) in 1994. The benchmark
                                                    
                                                     * test uses a single, simple, update-intensive transaction to load the
                                                    
                                                     * system.
                                                    
                                                     *
                                                    
                                                     * \par The Transaction Profile
                                                    
                                                     *
                                                    
                                                     * \code
                                                    
                                                     * BEGIN TRANSACTION
                                                    
                                                     *    Update Account where Account_ID = Aid:
                                                    
                                                     *       Read Account_Balance from Account
                                                    
                                                     *       Set Account_Balance = Account_Balance + Delta
                                                    
                                                     *       Write Account_Balance to Account
                                                    
                                                     *    Write to History:
                                                    
                                                     *       Aid, Tid, Bid, Delta, Time_stamp
                                                    
                                                     *    Update Teller where Teller_ID = Tid:
                                                    
                                                     *       Set Teller_Balance = Teller_Balance + Delta
                                                    
                                                     *       Write Teller_Balance to Teller
                                                    
                                                     *    Update Branch where Branch_ID = Bid:
                                                    
                                                     *       Set Branch_Balance = Branch_Balance + Delta
                                                    
                                                     *       Write Branch_Balance to Branch
                                                    
                                                     * COMMIT TRANSACTION Return
                                                    
                                                     * Account_Balance to driver
                                                    
                                                     * \endcode
                                                    
                                                     *
                                                    
                                                     * \par TPS configuration
                                                    
                                                     *
                                                    
                                                     * For each nominal transaction-per-second configured, the test uses:
                                                    
                                                     * \li 1 Branch Row for each TPS
                                                    
                                                     * \li 10 Teller Rows for each Branch
                                                    
                                                     * \li 100,000 Account Rows for each Branch
                                                    
                                                     *
                                                    
                                                     * \par Table of Contents
                                                    
                                                     *
                                                    
                                                     * - \subpage hDB
                                                    
                                                     * - \subpage hPGMfunc
                                                    
                                                     *
                                                    
                                                     * For additional information, please refer to the product documentation at
                                                    
                                                     * http://docs.raima.com/.
                                                    
                                                     *
                                                    
                                                     * \page hDB Database Schema
                                                    
                                                     *
                                                    
                                                     * \par Database Schema Definition
                                                    
                                                     *
                                                    
                                                     * The components of the database are defined to consist of four separate and
                                                    
                                                     * individual files/tables, Account, Branch, Teller, and History.
                                                    
                                                     *
                                                    
                                                     * \include core30.sdl
                                                    
                                                     *
                                                    
                                                     * The schema was compiled using the RDM rdm-compile utility with the -s and -a
                                                    
                                                     * options to generate an embedded database dictionary.
                                                    
                                                     *
                                                    
                                                     * \code rdm-compile -s -a core30.sdl \endcode
                                                    
                                                     *
                                                    
                                                     * The schema catalog information (\c core30_cat.c) is embedded inside the
                                                    
                                                     * application.
                                                    
                                                     *
                                                    
                                                     * \page hPGMfunc Program Functions
                                                    
                                                     *
                                                    
                                                     * For simplicity, this example does not check all return codes, but good
                                                    
                                                     * programming practices would dictate that they are checked after each
                                                    
                                                     * RDM call.
                                                    
                                                     *
                                                    
                                                     * \li populateDatabase() - \copybrief populateDatabase
                                                    
                                                     * \li do_trans() - \copybrief do_trans
                                                    
                                                     * \li delete_records() - \copybrief delete_records
                                                    
                                                     * \li main() - \copybrief main
                                                    
                                                     */
                                                    
                                                    /* \brief Initialize the RDM runtime library for use in the core30 example
                                                    
                                                     *
                                                    
                                                     * This function initializes the RDM Transactional File Server (TFS) to use
                                                    
                                                     * the embedded implementation.  It also creates an RDM database handle
                                                    
                                                     * and opens the "core30" database in exclusive mode.
                                                    
                                                     *
                                                    
                                                     * @return Returns an RDM_RETCODE code (sOKAY if successful)
                                                    
                                                     */
                                                    
                                                    RDM_RETCODE populateDatabase (
                                                    RDM_DB hDB) /*< [in] Pointer to the RDM database handle */
                                                    {
                                                    RDM_RETCODE rc;
                                                    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;
                                                    print_error (rc);
                                                    
                                                            {
                                                                brnRec.bbalance = 0.0;
                                                                brnRec._filler_has_value = RDM_COL_IS_NULL;
                                                                rc = rdm_dbInsertRow (
                                                                    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_COL_IS_NULL;
                                                                    rc = rdm_dbInsertRow (
                                                                        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_COL_IS_NULL;
                                                                    rc = rdm_dbInsertRow (
                                                                        hDB, TABLE_ACCOUNTS, &accRec, sizeof (accRec), NULL);
                                                    print_error (rc);
                                                                }
                                                    rdm_dbEnd (hDB);
                                                            }
                                                        }
                                                    timeMeasureEnd (&timer);
                                                    
                                                    return rc;
                                                    }
                                                    RDM_RETCODE do_trans (
                                                    RDM_DB hDB, /*< [in] Pointer to the RDM database handle */
                                                    unsigned int *elapsedTime)
                                                    {
                                                    RDM_RETCODE rc;
                                                    perfTimer_t timer;
                                                    double bal;
                                                    RDM_TRANS hTrans;
                                                    RDM_CURSOR cursor = NULL;
                                                    RDM_CURSOR brnCursor = NULL;
                                                        HISTORY historyRow;
                                                        TELLERS_TELLERS_PK_KEY tellerKey;
                                                        ACCOUNTS_ACCOUNTS_PK_KEY acctKey;
                                                    /* Selct Delta value in the range of +/- 999999 */
                                                    
                                                        historyRow._filler_has_value = RDM_COL_IS_NULL;
                                                        historyRow.delta = (double) (rand () / (65536.0 * 65536.0));
                                                    /* first teller id = 0, last is Branches*10-1 */
                                                    
                                                        historyRow.tid = (int) ((rand () % (TPS * NUM_TELLERS)));
                                                    /* assign this teller's branch id */
                                                    
                                                        historyRow.bid = historyRow.tid / NUM_TELLERS;
                                                        historyRow.aid = (unsigned int) rand () % NUM_ACCOUNTS;
                                                    rdm_timestampNow (0, &historyRow.tim);
                                                    timeMeasureBegin (&timer);
                                                    do
                                                    
                                                        {
                                                            rc = rdm_dbStartUpdate (hDB, RDM_LOCK_ALL, 0, NULL, 0, &hTrans);
                                                    
                                                    print_error (rc);
                                                    if (rc == sOKAY)
                                                        {
                                                    /* Update Account where Account_ID = Aid: */
                                                    
                                                            acctKey.aid = historyRow.aid;
                                                            rc = rdm_dbGetRowsByKeyAtKey(
                                                                hDB, COL_ACCOUNTS_AID, &acctKey, sizeof(acctKey), &cursor);
                                                    print_error(rc);
                                                    if (rc == sOKAY)
                                                            {
                                                                rc = rdm_cursorReadColumn(
                                                                    cursor, COL_ACCOUNTS_ABALANCE, &bal, sizeof(bal), NULL);
                                                    print_error(rc);
                                                            }
                                                    if (rc == sOKAY)
                                                            {
                                                                bal += historyRow.delta;
                                                                rc = rdm_cursorUpdateColumn(
                                                                    cursor, COL_ACCOUNTS_ABALANCE, &bal, sizeof(bal));
                                                    print_error(rc);
                                                            }
                                                    if (rc == sOKAY)
                                                            {
                                                    /* Write to History */
                                                    
                                                                rc = rdm_dbInsertRow(
                                                                    hDB, TABLE_HISTORY, &historyRow, sizeof(historyRow), NULL);
                                                    print_error(rc);
                                                            }
                                                    if (rc == sOKAY)
                                                            {
                                                    /* Update Teller where Teller_ID = Tid */
                                                    
                                                                tellerKey.tid = historyRow.tid;
                                                                rc = rdm_dbGetRowsByKeyAtKey(
                                                                    hDB, COL_TELLERS_TID, &tellerKey, sizeof(tellerKey), &cursor);
                                                    print_error(rc);
                                                            }
                                                    if (rc == sOKAY)
                                                            {
                                                                rc = rdm_cursorReadColumn(
                                                                    cursor, COL_TELLERS_TBALANCE, &bal, sizeof(bal), NULL);
                                                    print_error(rc);
                                                            }
                                                    if (rc == sOKAY)
                                                            {
                                                                bal += historyRow.delta;
                                                                rc = rdm_cursorUpdateColumn(
                                                                    cursor, COL_TELLERS_TBALANCE, &bal, sizeof(bal));
                                                    print_error(rc);
                                                            }
                                                    if (rc == sOKAY)
                                                            {
                                                    /* Update Branch where Branch_ID = Bid: */
                                                    
                                                                rc = rdm_cursorGetOwnerRow(cursor, REF_TELLERS_FK, &brnCursor);
                                                    print_error(rc);
                                                            }
                                                    if (rc == sOKAY)
                                                            {
                                                                rc = rdm_cursorReadColumn(
                                                                    brnCursor, COL_BRANCHES_BBALANCE, &bal, sizeof(bal), NULL);
                                                    print_error(rc);
                                                            }
                                                    if (rc == sOKAY)
                                                            {
                                                                bal += historyRow.delta;
                                                                rc = rdm_cursorUpdateColumn(
                                                                    brnCursor, COL_BRANCHES_BBALANCE, &bal, sizeof(bal));
                                                    print_error(rc);
                                                            }
                                                    if (rc == sOKAY)
                                                            {
                                                                rc = rdm_transEnd(hTrans);
                                                    print_error(rc);
                                                            }
                                                    else
                                                    
                                                            {
                                                    rdm_transEndRollback(hTrans);
                                                            }
                                                        }
                                                    timeMeasureEnd (&timer);
                                                    if (cursor)
                                                    rdm_cursorFree (cursor);
                                                    if (brnCursor)
                                                    rdm_cursorFree (brnCursor);
                                                    if (elapsedTime)
                                                            *elapsedTime = timeMeasureDiff (&timer);
                                                    return rc;
                                                    }
                                                    /* \brief Main function for core30 example
                                                    
                                                     *
                                                    
                                                     * The function initializes the RDM environment and runs the insert operations.
                                                    
                                                     * over a number of transaction block sizes
                                                    
                                                     *
                                                    
                                                     * @return Returns the RDM_RETCODE on exit.
                                                    
                                                     */
                                                    
                                                    int main_core30 (int argc, const char *const *argv)
                                                    {
                                                    RDM_DB hDB;
                                                    RDM_TFS hTFS;
                                                    RDM_RETCODE rc;
                                                        srand (100);
                                                        rc = rdm_cmdlineInit (&cmd, argc, argv, description, opts);
                                                    
                                                    print_error (rc);
                                                    if (rc == sOKAY)
                                                        {
                                                    /* Initialize the TFS, task, and open/initialize the database */
                                                    
                                                    
                                                    if (rc == sOKAY)
                                                            {
                                                                rc = populateDatabase (hDB);
                                                    if (rc == sOKAY)
                                                                {
                                                    perfTimer_t timer;
                                                    int ii;
                                                    /* 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, NULL);
                                                                    }
                                                    /* Run through the durability settings */
                                                    
                                                    for (ii = 0; ii < 3; ii++)
                                                                    {
                                                    const char *durability[3] = {"durability=durable",
                                                    "durability=consistent",
                                                    "durability=unsafe"};
                                                    unsigned int minTrans = (unsigned int) -1;
                                                    unsigned int maxTrans = 0;
                                                    unsigned int numTrans = 0;
                                                    unsigned int totTrans = 0;
                                                    unsigned int thisTrans;
                                                                        rc = rdm_dbSetOptions (hDB, durability[ii]);
                                                    print_error (rc);
                                                    /* TPC-B measurement */
                                                    
                                                                        printf (
                                                    "\nPerform TPC-B test for %d seconds (%s)\n",
                                                                            STEADYSTATE, durability[ii]);
                                                    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);
                                                                    }
                                                                }
                                                    exampleCleanup (hTFS, hDB);
                                                            }
                                                        }
                                                    return (int) rc;
                                                    }
                                                    RDM_STARTUP_EXAMPLE (core30)
                                                Header for the native RDM Runtime API.
                                        #define exampleOpenEmptyDatabase(tfs, db, name, catalog)
                                            Definition: example_fcns.h:22
                                        void timeMeasureBegin(perfTimer_t *timer)
                                        RDM_RETCODE rdm_transEndRollback(RDM_TRANS trans)
                                            End a transactional operation with a rollback.
                                        RDM_RETCODE rdm_timestampNow(int16_t time_zone, RDM_PACKED_TIMESTAMP_T *ts)
                                            Get the current local timestamp.
                                        void timeMeasureEnd(perfTimer_t *timer)
                                        The buffer used by the command line parser to hold state information.
                                            Definition: rdmcmdlinetypes.h:85
                                        RDM_RETCODE rdm_cursorUpdateColumn(RDM_CURSOR cursor, RDM_COLUMN_ID columnId, const void *columnValue, size_t bytesIn)
                                            Update a single column in a row.
                                        RDM_RETCODE rdm_dbGetRowsByKeyAtKey(RDM_DB db, RDM_KEY_ID keyId, const void *keyValue, size_t len, RDM_CURSOR *pCursor)
                                            Associate an RDM_CURSOR with a row set that is ordered by key value and is initially positioned at th...
                                        RDM_RETCODE rdm_dbSetOption(RDM_DB db, const char *keyword, const char *strValue)
                                            Set a single RDM option from a string.
                                        unsigned int timeMeasureDiff(perfTimer_t *timer)
                                        RDM_RETCODE rdm_dbInsertRow(RDM_DB db, RDM_TABLE_ID tableId, const void *colValues, size_t bytesIn, RDM_CURSOR *pCursor)
                                            Insert a new row into a table at the specified rowId.
                                        RDM_RETCODE rdm_cursorReadColumn(RDM_CURSOR cursor, RDM_COLUMN_ID columnId, void *columnValue, size_t bytesIn, size_t *bytesOut)
                                            Read a single column from a table row.
                                        RDM_RETCODE rdm_cmdlineInit(RDM_CMDLINE *cmd, int32_t argc, const char *const argv[], const char *description, const RDM_CMDLINE_OPT *opts)
                                            Initialize an RDM_CMDLINE buffer and validate the command line.
                                        RDM_RETCODE rdm_cursorGetOwnerRow(RDM_CURSOR memberCursor, RDM_REF_ID refId, RDM_CURSOR *pCursor)
                                            Associate an RDM_CURSOR with a set owner.
                                        RDM_RETCODE rdm_dbStartUpdate(RDM_DB db, const RDM_TABLE_ID *writeTableIds, uint32_t numWriteTableIds, const RDM_TABLE_ID *readTableIds, uint32_t numReadTableIds, RDM_TRANS *pTrans)
                                            Get write locks.
                                        Definition: example_fcns.h:37
                                        Internal RDM Startup API used by startup macros.