summaryrefslogtreecommitdiff
path: root/ndb/test
diff options
context:
space:
mode:
authorunknown <joreland@mysql.com>2005-02-10 11:40:32 +0100
committerunknown <joreland@mysql.com>2005-02-10 11:40:32 +0100
commitcf5816096d8b16d0db56e2a6f291cf91eac5ae42 (patch)
treefb7b605b366124ab5f1b4a58cb82b6fc489af136 /ndb/test
parent30e89d0a48a7bf875b485f8b5987a5ef1bc4bf56 (diff)
downloadmariadb-git-cf5816096d8b16d0db56e2a6f291cf91eac5ae42.tar.gz
ndb - Reenable old benchmark
ndb/test/ndbapi/Makefile.am: Reenable old benchmark
Diffstat (limited to 'ndb/test')
-rw-r--r--ndb/test/ndbapi/Makefile.am5
-rw-r--r--ndb/test/ndbapi/bench/asyncGenerator.cpp571
-rw-r--r--ndb/test/ndbapi/bench/dbGenerator.h63
-rw-r--r--ndb/test/ndbapi/bench/dbPopulate.cpp244
-rw-r--r--ndb/test/ndbapi/bench/dbPopulate.h59
-rw-r--r--ndb/test/ndbapi/bench/macros.h51
-rw-r--r--ndb/test/ndbapi/bench/mainAsyncGenerator.cpp503
-rw-r--r--ndb/test/ndbapi/bench/mainPopulate.cpp84
-rw-r--r--ndb/test/ndbapi/bench/ndb_async1.cpp647
-rw-r--r--ndb/test/ndbapi/bench/ndb_async2.cpp757
-rw-r--r--ndb/test/ndbapi/bench/ndb_error.hpp81
-rw-r--r--ndb/test/ndbapi/bench/ndb_schema.hpp78
-rw-r--r--ndb/test/ndbapi/bench/ndb_user_transaction.cpp825
-rw-r--r--ndb/test/ndbapi/bench/ndb_user_transaction2.cpp825
-rw-r--r--ndb/test/ndbapi/bench/ndb_user_transaction3.cpp793
-rw-r--r--ndb/test/ndbapi/bench/ndb_user_transaction4.cpp770
-rw-r--r--ndb/test/ndbapi/bench/ndb_user_transaction5.cpp769
-rw-r--r--ndb/test/ndbapi/bench/ndb_user_transaction6.cpp561
-rw-r--r--ndb/test/ndbapi/bench/testData.h156
-rw-r--r--ndb/test/ndbapi/bench/testDefinitions.h90
-rw-r--r--ndb/test/ndbapi/bench/userInterface.cpp745
-rw-r--r--ndb/test/ndbapi/bench/userInterface.h151
22 files changed, 8827 insertions, 1 deletions
diff --git a/ndb/test/ndbapi/Makefile.am b/ndb/test/ndbapi/Makefile.am
index 33744cc0f51..0c84db8c068 100644
--- a/ndb/test/ndbapi/Makefile.am
+++ b/ndb/test/ndbapi/Makefile.am
@@ -30,7 +30,8 @@ testSystemRestart \
testTimeout \
testTransactions \
testDeadlock \
-test_event ndbapi_slow_select testReadPerf testLcp
+test_event ndbapi_slow_select testReadPerf testLcp \
+DbCreate DbAsyncGenerator
#flexTimedAsynch
#testBlobs
@@ -69,6 +70,8 @@ test_event_SOURCES = test_event.cpp
ndbapi_slow_select_SOURCES = slow_select.cpp
testReadPerf_SOURCES = testReadPerf.cpp
testLcp_SOURCES = testLcp.cpp
+DbCreate_SOURCES= bench/mainPopulate.cpp bench/dbPopulate.cpp bench/userInterface.cpp
+DbAsyncGenerator_SOURCES= bench/mainAsyncGenerator.cpp bench/asyncGenerator.cpp bench/ndb_async2.cpp
INCLUDES_LOC = -I$(top_srcdir)/ndb/include/kernel
diff --git a/ndb/test/ndbapi/bench/asyncGenerator.cpp b/ndb/test/ndbapi/bench/asyncGenerator.cpp
new file mode 100644
index 00000000000..d91e38dff1a
--- /dev/null
+++ b/ndb/test/ndbapi/bench/asyncGenerator.cpp
@@ -0,0 +1,571 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/***************************************************************
+* I N C L U D E D F I L E S *
+***************************************************************/
+
+#include <ndb_global.h>
+
+#include "dbGenerator.h"
+#include <NdbApi.hpp>
+#include <NdbOut.hpp>
+#include <NdbSleep.h>
+
+/***************************************************************
+* L O C A L C O N S T A N T S *
+***************************************************************/
+
+/***************************************************************
+* L O C A L D A T A S T R U C T U R E S *
+***************************************************************/
+
+/***************************************************************
+* L O C A L F U N C T I O N S *
+***************************************************************/
+
+static void getRandomSubscriberNumber(SubscriberNumber number);
+static void getRandomServerId(ServerId *serverId);
+static void getRandomChangedBy(ChangedBy changedBy);
+static void getRandomChangedTime(ChangedTime changedTime);
+
+static void clearTransaction(TransactionDefinition *trans);
+static void initGeneratorStatistics(GeneratorStatistics *gen);
+
+static void doOneTransaction(ThreadData * td,
+ int parallellism,
+ int millisSendPoll,
+ int minEventSendPoll,
+ int forceSendPoll);
+static void doTransaction_T1(Ndb * pNDB, ThreadData * td, int async);
+static void doTransaction_T2(Ndb * pNDB, ThreadData * td, int async);
+static void doTransaction_T3(Ndb * pNDB, ThreadData * td, int async);
+static void doTransaction_T4(Ndb * pNDB, ThreadData * td, int async);
+static void doTransaction_T5(Ndb * pNDB, ThreadData * td, int async);
+
+/***************************************************************
+* L O C A L D A T A *
+***************************************************************/
+
+static SequenceValues transactionDefinition[] = {
+ {25, 1},
+ {25, 2},
+ {20, 3},
+ {15, 4},
+ {15, 5},
+ {0, 0}
+};
+
+static SequenceValues rollbackDefinition[] = {
+ {98, 0},
+ {2 , 1},
+ {0, 0}
+};
+
+static int maxsize = 0;
+
+/***************************************************************
+* P U B L I C D A T A *
+***************************************************************/
+
+/***************************************************************
+****************************************************************
+* L O C A L F U N C T I O N S C O D E S E C T I O N *
+****************************************************************
+***************************************************************/
+
+static void getRandomSubscriberNumber(SubscriberNumber number)
+{
+ uint32 tmp;
+ char sbuf[SUBSCRIBER_NUMBER_LENGTH + 1];
+ tmp = myRandom48(NO_OF_SUBSCRIBERS);
+ sprintf(sbuf, "%.*d", SUBSCRIBER_NUMBER_LENGTH, tmp);
+ memcpy(number, sbuf, SUBSCRIBER_NUMBER_LENGTH);
+}
+
+static void getRandomServerId(ServerId *serverId)
+{
+ *serverId = myRandom48(NO_OF_SERVERS);
+}
+
+static void getRandomChangedBy(ChangedBy changedBy)
+{
+ memset(changedBy, myRandom48(26)+'A', CHANGED_BY_LENGTH);
+ changedBy[CHANGED_BY_LENGTH] = 0;
+}
+
+static void getRandomChangedTime(ChangedTime changedTime)
+{
+ memset(changedTime, myRandom48(26)+'A', CHANGED_TIME_LENGTH);
+ changedTime[CHANGED_TIME_LENGTH] = 0;
+}
+
+static void clearTransaction(TransactionDefinition *trans)
+{
+ trans->count = 0;
+ trans->branchExecuted = 0;
+ trans->rollbackExecuted = 0;
+ trans->latencyCounter = myRandom48(127);
+ trans->latency.reset();
+}
+
+static int listFull(SessionList *list)
+{
+ return(list->numberInList == SESSION_LIST_LENGTH);
+}
+
+static int listEmpty(SessionList *list)
+{
+ return(list->numberInList == 0);
+}
+
+static void insertSession(SessionList *list,
+ SubscriberNumber number,
+ ServerId serverId)
+{
+ SessionElement *e;
+ if( listFull(list) ) return;
+
+ e = &list->list[list->writeIndex];
+
+ strcpy(e->subscriberNumber, number);
+ e->serverId = serverId;
+
+ list->writeIndex = (list->writeIndex + 1) % SESSION_LIST_LENGTH;
+ list->numberInList++;
+
+ if( list->numberInList > maxsize )
+ maxsize = list->numberInList;
+}
+
+static SessionElement *getNextSession(SessionList *list)
+{
+ if( listEmpty(list) ) return(0);
+
+ return(&list->list[list->readIndex]);
+}
+
+static void deleteSession(SessionList *list)
+{
+ if( listEmpty(list) ) return;
+
+ list->readIndex = (list->readIndex + 1) % SESSION_LIST_LENGTH;
+ list->numberInList--;
+}
+
+static void initGeneratorStatistics(GeneratorStatistics *gen)
+{
+ int i;
+
+ if( initSequence(&gen->transactionSequence,
+ transactionDefinition) != 0 ) {
+ ndbout_c("could not set the transaction types");
+ exit(0);
+ }
+
+ if( initSequence(&gen->rollbackSequenceT4,
+ rollbackDefinition) != 0 ) {
+ ndbout_c("could not set the rollback sequence");
+ exit(0);
+ }
+
+ if( initSequence(&gen->rollbackSequenceT5,
+ rollbackDefinition) != 0 ) {
+ ndbout_c("could not set the rollback sequence");
+ exit(0);
+ }
+
+ for(i = 0; i < NUM_TRANSACTION_TYPES; i++ )
+ clearTransaction(&gen->transactions[i]);
+
+ gen->totalTransactions = 0;
+
+ gen->activeSessions.numberInList = 0;
+ gen->activeSessions.readIndex = 0;
+ gen->activeSessions.writeIndex = 0;
+}
+
+
+static
+void
+doOneTransaction(ThreadData * td, int p, int millis, int minEvents, int force)
+{
+ int i;
+ unsigned int transactionType;
+ int async = 1;
+ if (p == 1) {
+ async = 0;
+ }//if
+ for(i = 0; i<p; i++){
+ if(td[i].runState == Runnable){
+ transactionType = getNextRandom(&td[i].generator.transactionSequence);
+
+ switch(transactionType) {
+ case 1:
+ doTransaction_T1(td[i].pNDB, &td[i], async);
+ break;
+ case 2:
+ doTransaction_T2(td[i].pNDB, &td[i], async);
+ break;
+ case 3:
+ doTransaction_T3(td[i].pNDB, &td[i], async);
+ break;
+ case 4:
+ doTransaction_T4(td[i].pNDB, &td[i], async);
+ break;
+ case 5:
+ doTransaction_T5(td[i].pNDB, &td[i], async);
+ break;
+ default:
+ ndbout_c("Unknown transaction type: %d", transactionType);
+ }
+ }
+ }
+ if (async == 1) {
+ td[0].pNDB->sendPollNdb(millis, minEvents, force);
+ }//if
+}
+
+static
+void
+doTransaction_T1(Ndb * pNDB, ThreadData * td, int async)
+{
+ /*----------------*/
+ /* Init arguments */
+ /*----------------*/
+ getRandomSubscriberNumber(td->transactionData.number);
+ getRandomChangedBy(td->transactionData.changed_by);
+ BaseString::snprintf(td->transactionData.changed_time,
+ sizeof(td->transactionData.changed_time),
+ "%ld - %d", td->changedTime++, myRandom48(65536*1024));
+ //getRandomChangedTime(td->transactionData.changed_time);
+ td->transactionData.location = td->transactionData.changed_by[0];
+
+ /*-----------------*/
+ /* Run transaction */
+ /*-----------------*/
+ td->runState = Running;
+ td->generator.transactions[0].startLatency();
+
+ start_T1(pNDB, td, async);
+}
+
+static
+void
+doTransaction_T2(Ndb * pNDB, ThreadData * td, int async)
+{
+ /*----------------*/
+ /* Init arguments */
+ /*----------------*/
+ getRandomSubscriberNumber(td->transactionData.number);
+
+ /*-----------------*/
+ /* Run transaction */
+ /*-----------------*/
+ td->runState = Running;
+ td->generator.transactions[1].startLatency();
+
+ start_T2(pNDB, td, async);
+}
+
+static
+void
+doTransaction_T3(Ndb * pNDB, ThreadData * td, int async)
+{
+ SessionElement *se;
+
+ /*----------------*/
+ /* Init arguments */
+ /*----------------*/
+ se = getNextSession(&td->generator.activeSessions);
+ if( se ) {
+ strcpy(td->transactionData.number, se->subscriberNumber);
+ td->transactionData.server_id = se->serverId;
+ td->transactionData.sessionElement = 1;
+ } else {
+ getRandomSubscriberNumber(td->transactionData.number);
+ getRandomServerId(&td->transactionData.server_id);
+ td->transactionData.sessionElement = 0;
+ }
+
+ td->transactionData.server_bit = (1 << td->transactionData.server_id);
+
+ /*-----------------*/
+ /* Run transaction */
+ /*-----------------*/
+ td->runState = Running;
+ td->generator.transactions[2].startLatency();
+ start_T3(pNDB, td, async);
+}
+
+static
+void
+doTransaction_T4(Ndb * pNDB, ThreadData * td, int async)
+{
+ /*----------------*/
+ /* Init arguments */
+ /*----------------*/
+ getRandomSubscriberNumber(td->transactionData.number);
+ getRandomServerId(&td->transactionData.server_id);
+
+ td->transactionData.server_bit = (1 << td->transactionData.server_id);
+ td->transactionData.do_rollback =
+ getNextRandom(&td->generator.rollbackSequenceT4);
+
+#if 0
+ memset(td->transactionData.session_details,
+ myRandom48(26)+'A', SESSION_DETAILS_LENGTH);
+#endif
+ td->transactionData.session_details[SESSION_DETAILS_LENGTH] = 0;
+
+ /*-----------------*/
+ /* Run transaction */
+ /*-----------------*/
+ td->runState = Running;
+ td->generator.transactions[3].startLatency();
+ start_T4(pNDB, td, async);
+}
+
+static
+void
+doTransaction_T5(Ndb * pNDB, ThreadData * td, int async)
+{
+ SessionElement * se;
+ se = getNextSession(&td->generator.activeSessions);
+ if( se ) {
+ strcpy(td->transactionData.number, se->subscriberNumber);
+ td->transactionData.server_id = se->serverId;
+ td->transactionData.sessionElement = 1;
+ }
+ else {
+ getRandomSubscriberNumber(td->transactionData.number);
+ getRandomServerId(&td->transactionData.server_id);
+ td->transactionData.sessionElement = 0;
+ }
+
+ td->transactionData.server_bit = (1 << td->transactionData.server_id);
+ td->transactionData.do_rollback
+ = getNextRandom(&td->generator.rollbackSequenceT5);
+
+ /*-----------------*/
+ /* Run transaction */
+ /*-----------------*/
+ td->runState = Running;
+ td->generator.transactions[4].startLatency();
+ start_T5(pNDB, td, async);
+}
+
+void
+complete_T1(ThreadData * data){
+ data->generator.transactions[0].stopLatency();
+ data->generator.transactions[0].count++;
+
+ data->runState = Runnable;
+ data->generator.totalTransactions++;
+}
+
+void
+complete_T2(ThreadData * data){
+ data->generator.transactions[1].stopLatency();
+ data->generator.transactions[1].count++;
+
+ data->runState = Runnable;
+ data->generator.totalTransactions++;
+}
+
+void
+complete_T3(ThreadData * data){
+
+ data->generator.transactions[2].stopLatency();
+ data->generator.transactions[2].count++;
+
+ if(data->transactionData.branchExecuted)
+ data->generator.transactions[2].branchExecuted++;
+
+ data->runState = Runnable;
+ data->generator.totalTransactions++;
+}
+
+void
+complete_T4(ThreadData * data){
+
+ data->generator.transactions[3].stopLatency();
+ data->generator.transactions[3].count++;
+
+ if(data->transactionData.branchExecuted)
+ data->generator.transactions[3].branchExecuted++;
+ if(data->transactionData.do_rollback)
+ data->generator.transactions[3].rollbackExecuted++;
+
+ if(data->transactionData.branchExecuted &&
+ !data->transactionData.do_rollback){
+ insertSession(&data->generator.activeSessions,
+ data->transactionData.number,
+ data->transactionData.server_id);
+ }
+
+ data->runState = Runnable;
+ data->generator.totalTransactions++;
+
+}
+void
+complete_T5(ThreadData * data){
+
+ data->generator.transactions[4].stopLatency();
+ data->generator.transactions[4].count++;
+
+ if(data->transactionData.branchExecuted)
+ data->generator.transactions[4].branchExecuted++;
+ if(data->transactionData.do_rollback)
+ data->generator.transactions[4].rollbackExecuted++;
+
+ if(data->transactionData.sessionElement &&
+ !data->transactionData.do_rollback){
+ deleteSession(&data->generator.activeSessions);
+ }
+
+ data->runState = Runnable;
+ data->generator.totalTransactions++;
+}
+
+/***************************************************************
+****************************************************************
+* P U B L I C F U N C T I O N S C O D E S E C T I O N *
+****************************************************************
+***************************************************************/
+void
+asyncGenerator(ThreadData *data,
+ int parallellism,
+ int millisSendPoll,
+ int minEventSendPoll,
+ int forceSendPoll)
+{
+ ThreadData * startUp;
+
+ GeneratorStatistics *st;
+ double periodStop;
+ double benchTimeStart;
+ double benchTimeEnd;
+ int i, j, done;
+
+ myRandom48Init(data->randomSeed);
+
+ for(i = 0; i<parallellism; i++){
+ initGeneratorStatistics(&data[i].generator);
+ }
+
+ startUp = (ThreadData*)malloc(parallellism * sizeof(ThreadData));
+ memcpy(startUp, data, (parallellism * sizeof(ThreadData)));
+
+ /*----------------*/
+ /* warm up period */
+ /*----------------*/
+ periodStop = userGetTime() + (double)data[0].warmUpSeconds;
+
+ while(userGetTime() < periodStop){
+ doOneTransaction(startUp, parallellism,
+ millisSendPoll, minEventSendPoll, forceSendPoll);
+ }
+
+ ndbout_c("Waiting for startup to finish");
+
+ /**
+ * Wait for all transactions
+ */
+ done = 0;
+ while(!done){
+ done = 1;
+ for(i = 0; i<parallellism; i++){
+ if(startUp[i].runState != Runnable){
+ done = 0;
+ break;
+ }
+ }
+ if(!done){
+ startUp[0].pNDB->sendPollNdb();
+ }
+ }
+ ndbout_c("Benchmark period starts");
+
+ /*-------------------------*/
+ /* normal benchmark period */
+ /*-------------------------*/
+ benchTimeStart = userGetTime();
+
+ periodStop = benchTimeStart + (double)data[0].testSeconds;
+ while(userGetTime() < periodStop)
+ doOneTransaction(data, parallellism,
+ millisSendPoll, minEventSendPoll, forceSendPoll);
+
+ benchTimeEnd = userGetTime();
+
+ ndbout_c("Benchmark period done");
+
+ /**
+ * Wait for all transactions
+ */
+ done = 0;
+ while(!done){
+ done = 1;
+ for(i = 0; i<parallellism; i++){
+ if(data[i].runState != Runnable){
+ done = 0;
+ break;
+ }
+ }
+ if(!done){
+ data[0].pNDB->sendPollNdb();
+ }
+ }
+
+ /*------------------*/
+ /* cool down period */
+ /*------------------*/
+ periodStop = userGetTime() + (double)data[0].coolDownSeconds;
+ while(userGetTime() < periodStop){
+ doOneTransaction(startUp, parallellism,
+ millisSendPoll, minEventSendPoll, forceSendPoll);
+ }
+
+ done = 0;
+ while(!done){
+ done = 1;
+ for(i = 0; i<parallellism; i++){
+ if(startUp[i].runState != Runnable){
+ done = 0;
+ break;
+ }
+ }
+ if(!done){
+ startUp[0].pNDB->sendPollNdb();
+ }
+ }
+
+
+ /*---------------------------------------------------------*/
+ /* add the times for all transaction for inner loop timing */
+ /*---------------------------------------------------------*/
+ for(j = 0; j<parallellism; j++){
+ st = &data[j].generator;
+
+ st->outerLoopTime = benchTimeEnd - benchTimeStart;
+ st->outerTps = getTps(st->totalTransactions, st->outerLoopTime);
+ }
+ /* ndbout_c("maxsize = %d\n",maxsize); */
+
+ free(startUp);
+}
+
diff --git a/ndb/test/ndbapi/bench/dbGenerator.h b/ndb/test/ndbapi/bench/dbGenerator.h
new file mode 100644
index 00000000000..2256498e151
--- /dev/null
+++ b/ndb/test/ndbapi/bench/dbGenerator.h
@@ -0,0 +1,63 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef DBGENERATOR_H
+#define DBGENERATOR_H
+
+/***************************************************************
+* I N C L U D E D F I L E S *
+***************************************************************/
+
+#include "testData.h"
+#include "userInterface.h"
+
+/***************************************************************
+* M A C R O S *
+***************************************************************/
+
+/***************************************************************/
+/* C O N S T A N T S */
+/***************************************************************/
+
+/***************************************************************
+* D A T A S T R U C T U R E S *
+***************************************************************/
+
+/***************************************************************
+* P U B L I C F U N C T I O N S *
+***************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void asyncGenerator(ThreadData *d, int parallellism,
+ int millisSendPoll,
+ int minEventSendPoll,
+ int forceSendPoll);
+
+#ifdef __cplusplus
+}
+#endif
+
+/***************************************************************
+* E X T E R N A L D A T A *
+***************************************************************/
+
+
+
+#endif /* DBGENERATOR_H */
+
diff --git a/ndb/test/ndbapi/bench/dbPopulate.cpp b/ndb/test/ndbapi/bench/dbPopulate.cpp
new file mode 100644
index 00000000000..42fbb52f3b2
--- /dev/null
+++ b/ndb/test/ndbapi/bench/dbPopulate.cpp
@@ -0,0 +1,244 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/***************************************************************
+* I N C L U D E D F I L E S *
+***************************************************************/
+
+#include <ndb_global.h>
+
+#include "userInterface.h"
+
+#include "dbPopulate.h"
+#include <NdbOut.hpp>
+#include <random.h>
+
+/***************************************************************
+* L O C A L C O N S T A N T S *
+***************************************************************/
+
+/***************************************************************
+* L O C A L D A T A S T R U C T U R E S *
+***************************************************************/
+
+/***************************************************************
+* L O C A L F U N C T I O N S *
+***************************************************************/
+
+static void getRandomSubscriberData(int subscriberNo,
+ SubscriberNumber number,
+ SubscriberName name);
+
+static void populate(char *title,
+ int count,
+ void (*func)(UserHandle*,int),
+ UserHandle *uh);
+
+static void populateServers(UserHandle *uh, int count);
+static void populateSubscribers(UserHandle *uh, int count);
+static void populateGroups(UserHandle *uh, int count);
+
+/***************************************************************
+* L O C A L D A T A *
+***************************************************************/
+
+static SequenceValues permissionsDefinition[] = {
+ {90, 1},
+ {10, 0},
+ {0, 0}
+};
+
+/***************************************************************
+* P U B L I C D A T A *
+***************************************************************/
+
+
+/***************************************************************
+****************************************************************
+* L O C A L F U N C T I O N S C O D E S E C T I O N *
+****************************************************************
+***************************************************************/
+
+static void getRandomSubscriberData(int subscriberNo,
+ SubscriberNumber number,
+ SubscriberName name)
+{
+ char sbuf[SUBSCRIBER_NUMBER_LENGTH + 1];
+ sprintf(sbuf, "%.*d", SUBSCRIBER_NUMBER_LENGTH, subscriberNo);
+ memcpy(number, sbuf, SUBSCRIBER_NUMBER_LENGTH);
+
+ memset(name, myRandom48(26)+'A', SUBSCRIBER_NAME_LENGTH);
+}
+
+static void populate(char *title,
+ int count,
+ void (*func)(UserHandle*, int),
+ UserHandle *uh)
+{
+ ndbout_c("Populating %d '%s' ... ",count, title);
+ /* fflush(stdout); */
+ func(uh,count);
+ ndbout_c("done");
+}
+
+static void populateServers(UserHandle *uh, int count)
+{
+ int i, j;
+ int len;
+ char tmp[80];
+ int suffix_length = 1;
+ ServerName serverName;
+ SubscriberSuffix suffix;
+
+ int commitCount = 0;
+
+ for(i = 0; i < SUBSCRIBER_NUMBER_SUFFIX_LENGTH; i++)
+ suffix_length *= 10;
+
+ for(i = 0; i < count; i++) {
+ sprintf(tmp, "-Server %d-", i);
+
+ len = strlen(tmp);
+ for(j = 0; j < SERVER_NAME_LENGTH; j++){
+ serverName[j] = tmp[j % len];
+ }
+ /* serverName[j] = 0; not null-terminated */
+
+ for(j = 0; j < suffix_length; j++){
+ char sbuf[SUBSCRIBER_NUMBER_SUFFIX_LENGTH + 1];
+ sprintf(sbuf, "%.*d", SUBSCRIBER_NUMBER_SUFFIX_LENGTH, j);
+ memcpy(suffix, sbuf, SUBSCRIBER_NUMBER_SUFFIX_LENGTH);
+ userDbInsertServer(uh, i, suffix, serverName);
+ commitCount ++;
+ if((commitCount % OP_PER_TRANS) == 0)
+ userDbCommit(uh);
+ }
+ }
+ if((commitCount % OP_PER_TRANS) != 0)
+ userDbCommit(uh);
+}
+
+static void populateSubscribers(UserHandle *uh, int count)
+{
+ SubscriberNumber number;
+ SubscriberName name;
+ int i, j, k;
+ int res;
+
+ SequenceValues values[NO_OF_GROUPS+1];
+ RandomSequence seq;
+
+ for(i = 0; i < NO_OF_GROUPS; i++) {
+ values[i].length = 1;
+ values[i].value = i;
+ }
+
+ values[i].length = 0;
+ values[i].value = 0;
+
+ if( initSequence(&seq, values) != 0 ) {
+ ndbout_c("could not set the sequence of random groups");
+ exit(0);
+ }
+
+#define RETRIES 25
+
+ for(i = 0; i < count; i+= OP_PER_TRANS) {
+ for(j = 0; j<RETRIES; j++){
+ for(k = 0; k<OP_PER_TRANS && i+k < count; k++){
+ getRandomSubscriberData(i+k, number, name);
+ userDbInsertSubscriber(uh, number, getNextRandom(&seq), name);
+ }
+ res = userDbCommit(uh);
+ if(res == 0)
+ break;
+ if(res != 1){
+ ndbout_c("Terminating");
+ exit(0);
+ }
+ }
+ if(j == RETRIES){
+ ndbout_c("Terminating");
+ exit(0);
+ }
+ }
+}
+
+static void populateGroups(UserHandle *uh, int count)
+{
+ int i;
+ int j;
+ int len;
+ RandomSequence seq;
+ Permission allow[NO_OF_GROUPS];
+ ServerBit serverBit;
+ GroupName groupName;
+ char tmp[80];
+ int commitCount = 0;
+
+ if( initSequence(&seq, permissionsDefinition) != 0 ) {
+ ndbout_c("could not set the sequence of random permissions");
+ exit(0);
+ }
+
+ for(i = 0; i < NO_OF_GROUPS; i++)
+ allow[i] = 0;
+
+ for(i = 0; i < NO_OF_SERVERS; i++) {
+ serverBit = 1 << i;
+
+ for(j = 0; j < NO_OF_GROUPS; j++ ) {
+ if( getNextRandom(&seq) )
+ allow[j] |= serverBit;
+ }
+ }
+
+ for(i = 0; i < NO_OF_GROUPS; i++) {
+ sprintf(tmp, "-Group %d-", i);
+
+ len = strlen(tmp);
+
+ for(j = 0; j < GROUP_NAME_LENGTH; j++) {
+ groupName[j] = tmp[j % len];
+ }
+ /* groupName[j] = 0; not null-terminated */
+
+ userDbInsertGroup(uh,
+ i,
+ groupName,
+ allow[i],
+ allow[i],
+ allow[i]);
+ commitCount ++;
+ if((commitCount % OP_PER_TRANS) == 0)
+ userDbCommit(uh);
+ }
+ if((commitCount % OP_PER_TRANS) != 0)
+ userDbCommit(uh);
+}
+
+/***************************************************************
+****************************************************************
+* P U B L I C F U N C T I O N S C O D E S E C T I O N *
+****************************************************************
+***************************************************************/
+
+void dbPopulate(UserHandle *uh)
+{
+ populate("servers", NO_OF_SERVERS, populateServers, uh);
+ populate("subscribers", NO_OF_SUBSCRIBERS, populateSubscribers, uh);
+ populate("groups", NO_OF_GROUPS, populateGroups, uh);
+}
diff --git a/ndb/test/ndbapi/bench/dbPopulate.h b/ndb/test/ndbapi/bench/dbPopulate.h
new file mode 100644
index 00000000000..1916720e141
--- /dev/null
+++ b/ndb/test/ndbapi/bench/dbPopulate.h
@@ -0,0 +1,59 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef DBPOPULATE_H
+#define DBPOPULATE_H
+
+/***************************************************************
+* I N C L U D E D F I L E S *
+***************************************************************/
+
+#include "userInterface.h"
+
+/***************************************************************
+* M A C R O S *
+***************************************************************/
+
+/***************************************************************/
+/* C O N S T A N T S */
+/***************************************************************/
+
+/***************************************************************
+* D A T A S T R U C T U R E S *
+***************************************************************/
+
+/***************************************************************
+* P U B L I C F U N C T I O N S *
+***************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void dbPopulate(UserHandle *uh);
+
+#ifdef __cplusplus
+}
+#endif
+
+/***************************************************************
+* E X T E R N A L D A T A *
+***************************************************************/
+
+
+
+#endif /* DBPOPULATE_H */
+
diff --git a/ndb/test/ndbapi/bench/macros.h b/ndb/test/ndbapi/bench/macros.h
new file mode 100644
index 00000000000..22b7f564490
--- /dev/null
+++ b/ndb/test/ndbapi/bench/macros.h
@@ -0,0 +1,51 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef MACROS_H
+#define MACROS_H
+
+#include <ndb_global.h>
+#include <NdbOut.hpp>
+
+#define ERROR(x) {ndbout_c((x));}
+#define ERROR1(x,y) {ndbout_c((x), (y));}
+#define ERROR2(x,y,z) {ndbout_c((x), (y), (z));}
+#define ERROR3(x,y,z,u) {ndbout_c((x), (y), (z), (u));}
+#define ERROR4(x,y,z,u,w) {ndbout_c((x), (y), (z), (u), (w));}
+
+#define INIT_RANDOM(x) srand48((x))
+#define UI_RANDOM(x) ((unsigned int)(lrand48()%(x)))
+
+#define ASSERT(cond, message) \
+ { if(!(cond)) { ERROR(message); exit(-1); }}
+
+#ifdef DEBUG_ON
+#define DEBUG(x) {ndbout_c((x));}
+#define DEBUG1(x,y) {ndbout_c((x), (y));}
+#define DEBUG2(x,y,z) {ndbout_c((x), (y), (z));}
+#define DEBUG3(x,y,z,u) {ndbout_c((x), (y), (z), (u));}
+#define DEBUG4(x,y,z,u,w) {ndbout_c((x), (y), (z), (u), (w));}
+#define DEBUG5(x,y,z,u,w, v) {ndbout_c((x), (y), (z), (u), (w), (v));}
+#else
+#define DEBUG(x)
+#define DEBUG1(x,y)
+#define DEBUG2(x,y,z)
+#define DEBUG3(x,y,z,u)
+#define DEBUG4(x,y,z,u,w)
+#define DEBUG5(x,y,z,u,w, v)
+#endif
+
+#endif
diff --git a/ndb/test/ndbapi/bench/mainAsyncGenerator.cpp b/ndb/test/ndbapi/bench/mainAsyncGenerator.cpp
new file mode 100644
index 00000000000..828b924582f
--- /dev/null
+++ b/ndb/test/ndbapi/bench/mainAsyncGenerator.cpp
@@ -0,0 +1,503 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <ndb_global.h>
+
+#include <NdbHost.h>
+#include <NdbSleep.h>
+#include <NdbThread.h>
+#include <NdbMain.h>
+#include <NdbOut.hpp>
+#include <NdbEnv.h>
+#include <NdbTest.hpp>
+
+#include "userInterface.h"
+#include "dbGenerator.h"
+
+static int numProcesses;
+static int numSeconds;
+static int numWarmSeconds;
+static int parallellism;
+static int millisSendPoll;
+static int minEventSendPoll;
+static int forceSendPoll;
+
+static ThreadData *data;
+static Ndb_cluster_connection *g_cluster_connection= 0;
+
+
+static void usage(const char *prog)
+{
+ const char *progname;
+
+ /*--------------------------------------------*/
+ /* Get the name of the program (without path) */
+ /*--------------------------------------------*/
+ progname = strrchr(prog, '/');
+
+ if (progname == 0)
+ progname = prog;
+ else
+ ++progname;
+
+ ndbout_c(
+ "Usage: %s [-proc <num>] [-warm <num>] [-time <num>] [ -p <num>] "
+ "[-t <num> ] [ -e <num> ] [ -f <num>] \n"
+ " -proc <num> Specifies that <num> is the number of\n"
+ " threads. The default is 1.\n"
+ " -time <num> Specifies that the test will run for <num> sec.\n"
+ " The default is 10 sec\n"
+ " -warm <num> Specifies the warm-up/cooldown period of <num> "
+ "sec.\n"
+ " The default is 10 sec\n"
+ " -p <num> The no of parallell transactions started by "
+ "one thread\n"
+ " -e <num> Minimum no of events before wake up in call to "
+ "sendPoll\n"
+ " Default is 1\n"
+ " -f <num> force parameter to sendPoll\n"
+ " Default is 0\n",
+ progname);
+}
+
+static
+int
+parse_args(int argc, const char **argv)
+{
+ int i;
+
+ numProcesses = 1;
+ numSeconds = 10;
+ numWarmSeconds = 10;
+ parallellism = 1;
+ millisSendPoll = 10000;
+ minEventSendPoll = 1;
+ forceSendPoll = 0;
+
+
+ i = 1;
+ while (i < argc){
+ if (strcmp("-proc",argv[i]) == 0) {
+ if (i + 1 >= argc) {
+ return 1;
+ }
+ if (sscanf(argv[i+1], "%d", &numProcesses) == -1 ||
+ numProcesses <= 0 || numProcesses > 127) {
+ ndbout_c("-proc flag requires a positive integer argument [1..127]");
+ return 1;
+ }
+ i += 2;
+ } else if (strcmp("-p", argv[i]) == 0){
+ if(i + 1 >= argc){
+ usage(argv[0]);
+ return 1;
+ }
+ if (sscanf(argv[i+1], "%d", &parallellism) == -1 ||
+ parallellism <= 0){
+ ndbout_c("-p flag requires a positive integer argument");
+ return 1;
+ }
+ i += 2;
+ }
+ else if (strcmp("-time",argv[i]) == 0) {
+ if (i + 1 >= argc) {
+ return 1;
+ }
+ if (sscanf(argv[i+1], "%d", &numSeconds) == -1 ||
+ numSeconds < 0) {
+ ndbout_c("-time flag requires a positive integer argument");
+ return 1;
+ }
+ i += 2;
+ }
+ else if (strcmp("-warm",argv[i]) == 0) {
+ if (i + 1 >= argc) {
+ return 1;
+ }
+ if (sscanf(argv[i+1], "%d", &numWarmSeconds) == -1 ||
+ numWarmSeconds < 0) {
+ ndbout_c("-warm flag requires a positive integer argument");
+ return 1;
+ }
+ i += 2;
+ }
+ else if (strcmp("-e",argv[i]) == 0) {
+ if (i + 1 >= argc) {
+ return 1;
+ }
+ if (sscanf(argv[i+1], "%d", &minEventSendPoll) == -1 ||
+ minEventSendPoll < 0) {
+ ndbout_c("-e flag requires a positive integer argument");
+ return 1;
+ }
+ i += 2;
+ }
+ else if (strcmp("-f",argv[i]) == 0) {
+ if (i + 1 >= argc) {
+ usage(argv[0]);
+ return 1;
+ }
+ if (sscanf(argv[i+1], "%d", &forceSendPoll) == -1 ||
+ forceSendPoll < 0) {
+ ndbout_c("-f flag requires a positive integer argument");
+ return 1;
+ }
+ i += 2;
+ }
+ else {
+ return 1;
+ }
+ }
+
+ if(minEventSendPoll > parallellism){
+ ndbout_c("minEventSendPoll(%d) > parallellism(%d)",
+ minEventSendPoll, parallellism);
+ ndbout_c("not very good...");
+ ndbout_c("very bad...");
+ ndbout_c("exiting...");
+ return 1;
+ }
+ return 0;
+}
+
+static
+void
+print_transaction(const char *header,
+ unsigned long totalCount,
+ TransactionDefinition *trans,
+ unsigned int printBranch,
+ unsigned int printRollback)
+{
+ double f;
+
+ ndbout_c(" %s: %d (%.2f%%) "
+ "Latency(ms) avg: %d min: %d max: %d std: %d n: %d",
+ header,
+ trans->count,
+ (double)trans->count / (double)totalCount * 100.0,
+ (int)trans->latency.getMean(),
+ (int)trans->latency.getMin(),
+ (int)trans->latency.getMax(),
+ (int)trans->latency.getStddev(),
+ (int)trans->latency.getCount()
+ );
+
+ if( printBranch ){
+ if( trans->count == 0 )
+ f = 0.0;
+ else
+ f = (double)trans->branchExecuted / (double)trans->count * 100.0;
+ ndbout_c(" Branches Executed: %d (%.2f%%)", trans->branchExecuted, f);
+ }
+
+ if( printRollback ){
+ if( trans->count == 0 )
+ f = 0.0;
+ else
+ f = (double)trans->rollbackExecuted / (double)trans->count * 100.0;
+ ndbout_c(" Rollback Executed: %d (%.2f%%)",trans->rollbackExecuted,f);
+ }
+}
+
+void
+print_stats(const char *title,
+ unsigned int length,
+ unsigned int transactionFlag,
+ GeneratorStatistics *gen,
+ int numProc, int parallellism)
+{
+ int i;
+ char buf[10];
+ char name[MAXHOSTNAMELEN];
+
+ name[0] = 0;
+ NdbHost_GetHostName(name);
+
+ ndbout_c("\n------ %s ------",title);
+ ndbout_c("Length : %d %s",
+ length,
+ transactionFlag ? "Transactions" : "sec");
+ ndbout_c("Processor : %s", name);
+ ndbout_c("Number of Proc: %d",numProc);
+ ndbout_c("Parallellism : %d", parallellism);
+ ndbout_c("\n");
+
+ if( gen->totalTransactions == 0 ) {
+ ndbout_c(" No Transactions for this test");
+ }
+ else {
+ for(i = 0; i < 5; i++) {
+ sprintf(buf, "T%d",i+1);
+ print_transaction(buf,
+ gen->totalTransactions,
+ &gen->transactions[i],
+ i >= 2,
+ i >= 3 );
+ }
+
+ ndbout_c("\n");
+ ndbout_c(" Overall Statistics:");
+ ndbout_c(" Transactions: %d", gen->totalTransactions);
+ ndbout_c(" Outer : %.0f TPS",gen->outerTps);
+ ndbout_c("\n");
+ }
+}
+
+static
+void *
+threadRoutine(void *arg)
+{
+ int i;
+ ThreadData *data = (ThreadData *)arg;
+ Ndb * pNDB;
+
+ pNDB = asyncDbConnect(parallellism);
+ /* NdbSleep_MilliSleep(rand() % 10); */
+
+ for(i = 0; i<parallellism; i++){
+ data[i].pNDB = pNDB;
+ }
+ millisSendPoll = 30000;
+ asyncGenerator(data, parallellism,
+ millisSendPoll, minEventSendPoll, forceSendPoll);
+
+ asyncDbDisconnect(pNDB);
+
+ return NULL;
+}
+
+NDB_COMMAND(DbAsyncGenerator, "DbAsyncGenerator",
+ "DbAsyncGenerator", "DbAsyncGenerator", 65535)
+{
+ ndb_init();
+ int i;
+ int j;
+ int k;
+ struct NdbThread* pThread = NULL;
+ GeneratorStatistics stats;
+ GeneratorStatistics *p;
+ char threadName[32];
+ int rc = NDBT_OK;
+ void* tmp = NULL;
+ if(parse_args(argc,argv) != 0){
+ usage(argv[0]);
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ }
+
+
+ ndbout_c("\nStarting Test with %d process(es) for %d %s parallellism %d",
+ numProcesses,
+ numSeconds,
+ "sec",
+ parallellism);
+
+ ndbout_c(" WarmUp/coolDown = %d sec", numWarmSeconds);
+
+ Ndb_cluster_connection con;
+ if(con.connect(12, 5, 1) != 0)
+ {
+ ndbout << "Unable to connect to management server." << endl;
+ return 0;
+ }
+ if (con.wait_until_ready(30,0) < 0)
+ {
+ ndbout << "Cluster nodes not ready in 30 seconds." << endl;
+ return 0;
+ }
+
+ g_cluster_connection= &con;
+ data = (ThreadData*)malloc((numProcesses*parallellism)*sizeof(ThreadData));
+
+ for(i = 0; i < numProcesses; i++) {
+ for(j = 0; j<parallellism; j++){
+ data[i*parallellism+j].warmUpSeconds = numWarmSeconds;
+ data[i*parallellism+j].testSeconds = numSeconds;
+ data[i*parallellism+j].coolDownSeconds = numWarmSeconds;
+ data[i*parallellism+j].randomSeed =
+ NdbTick_CurrentMillisecond()+i+j;
+ data[i*parallellism+j].changedTime = 0;
+ data[i*parallellism+j].runState = Runnable;
+ }
+ sprintf(threadName, "AsyncThread[%d]", i);
+ pThread = NdbThread_Create(threadRoutine,
+ (void**)&data[i*parallellism],
+ 65535,
+ threadName,
+ NDB_THREAD_PRIO_LOW);
+ if(pThread != 0 && pThread != NULL){
+ (&data[i*parallellism])->pThread = pThread;
+ } else {
+ perror("Failed to create thread");
+ rc = NDBT_FAILED;
+ }
+ }
+
+ showTime();
+
+ /*--------------------------------*/
+ /* Wait for all processes to exit */
+ /*--------------------------------*/
+ for(i = 0; i < numProcesses; i++) {
+ NdbThread_WaitFor(data[i*parallellism].pThread, &tmp);
+ NdbThread_Destroy(&data[i*parallellism].pThread);
+ }
+
+ ndbout_c("All threads have finished");
+
+ /*-------------------------------------------*/
+ /* Clear all structures for total statistics */
+ /*-------------------------------------------*/
+ stats.totalTransactions = 0;
+ stats.outerTps = 0.0;
+
+ for(i = 0; i < NUM_TRANSACTION_TYPES; i++ ) {
+ stats.transactions[i].count = 0;
+ stats.transactions[i].branchExecuted = 0;
+ stats.transactions[i].rollbackExecuted = 0;
+ stats.transactions[i].latency.reset();
+ }
+
+ /*--------------------------------*/
+ /* Add the values for all Threads */
+ /*--------------------------------*/
+ for(i = 0; i < numProcesses; i++) {
+ for(k = 0; k<parallellism; k++){
+ p = &data[i*parallellism+k].generator;
+
+ stats.totalTransactions += p->totalTransactions;
+ stats.outerTps += p->outerTps;
+
+ for(j = 0; j < NUM_TRANSACTION_TYPES; j++ ) {
+ stats.transactions[j].count +=
+ p->transactions[j].count;
+ stats.transactions[j].branchExecuted +=
+ p->transactions[j].branchExecuted;
+ stats.transactions[j].rollbackExecuted +=
+ p->transactions[j].rollbackExecuted;
+ stats.transactions[j].latency +=
+ p->transactions[j].latency;
+ }
+ }
+ }
+
+ print_stats("Test Results",
+ numSeconds,
+ 0,
+ &stats,
+ numProcesses,
+ parallellism);
+
+ free(data);
+
+ NDBT_ProgramExit(rc);
+}
+/***************************************************************
+* I N C L U D E D F I L E S *
+***************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <time.h>
+
+#include "ndb_schema.hpp"
+#include "ndb_error.hpp"
+#include "userInterface.h"
+#include <NdbMutex.h>
+#include <NdbThread.h>
+#include <NdbTick.h>
+#include <NdbApi.hpp>
+#include <NdbOut.hpp>
+
+/***************************************************************
+* L O C A L C O N S T A N T S *
+***************************************************************/
+
+/***************************************************************
+* L O C A L D A T A S T R U C T U R E S *
+***************************************************************/
+
+/***************************************************************
+* L O C A L F U N C T I O N S *
+***************************************************************/
+
+#ifndef NDB_WIN32
+#include <unistd.h>
+#endif
+
+Ndb*
+asyncDbConnect(int parallellism){
+ Ndb * pNDB = new Ndb(g_cluster_connection, "TEST_DB");
+
+ pNDB->init(parallellism + 1);
+
+ while(pNDB->waitUntilReady() != 0){
+ }
+
+ return pNDB;
+}
+
+void
+asyncDbDisconnect(Ndb* pNDB)
+{
+ delete pNDB;
+}
+
+double
+userGetTime(void)
+{
+ static bool initialized = false;
+ static NDB_TICKS initSecs = 0;
+ static Uint32 initMicros = 0;
+ double timeValue = 0;
+
+ if ( !initialized ) {
+ initialized = true;
+ NdbTick_CurrentMicrosecond(&initSecs, &initMicros);
+ timeValue = 0.0;
+ } else {
+ NDB_TICKS secs = 0;
+ Uint32 micros = 0;
+
+ NdbTick_CurrentMicrosecond(&secs, &micros);
+ double s = (double)secs - (double)initSecs;
+ double us = (double)micros - (double)initMicros;
+
+ timeValue = s + (us / 1000000.0);
+ }
+ return timeValue;
+}
+
+void showTime()
+{
+ char buf[128];
+ struct tm* tm_now;
+ time_t now;
+ now = ::time((time_t*)NULL);
+ tm_now = ::gmtime(&now);
+
+ ::snprintf(buf, 128,
+ "%d-%.2d-%.2d %.2d:%.2d:%.2d",
+ tm_now->tm_year + 1900,
+ tm_now->tm_mon,
+ tm_now->tm_mday,
+ tm_now->tm_hour,
+ tm_now->tm_min,
+ tm_now->tm_sec);
+
+ ndbout_c("Time: %s", buf);
+}
+
diff --git a/ndb/test/ndbapi/bench/mainPopulate.cpp b/ndb/test/ndbapi/bench/mainPopulate.cpp
new file mode 100644
index 00000000000..5f4b73a3eff
--- /dev/null
+++ b/ndb/test/ndbapi/bench/mainPopulate.cpp
@@ -0,0 +1,84 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <ndb_global.h>
+#include <ndb_opts.h>
+
+#include "userInterface.h"
+#include "dbPopulate.h"
+#include <NdbMain.h>
+#include <NdbOut.hpp>
+#include <random.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+int useTableLogging;
+int useIndexTables;
+#ifdef __cplusplus
+}
+#endif
+
+
+static void usage()
+{
+}
+
+static
+void usage(const char *prog)
+{
+
+ ndbout_c(
+ "Usage: %s [-l]\n"
+ " -l Use logging and checkpointing on tables\n",
+ " -i Use index tables\n",
+ prog);
+
+ exit(1);
+}
+
+NDB_STD_OPTS_VARS;
+
+NDB_COMMAND(DbCreate, "DbCreate", "DbCreate", "DbCreate", 16384)
+{
+ int i;
+ UserHandle *uh;
+
+ useTableLogging = useIndexTables = 0;
+ NDB_INIT(argv[0]);
+
+ for(i = 1; i<argc; i++){
+ if(strcmp(argv[i], "-l") == 0){
+ useTableLogging = 1;
+ } else if(strcmp(argv[i], "-i") == 0){
+ useIndexTables = 1;
+ } else {
+ usage(argv[0]);
+ return 0;
+ }
+ }
+
+ ndbout_c("Using %s tables and %s key storage",
+ useTableLogging ? "logging" : "temporary",
+ useIndexTables ? "index" : "normal");
+
+ myRandom48Init(0x3e6f);
+
+ uh = userDbConnect(1, "TEST_DB");
+ dbPopulate(uh);
+ userDbDisconnect(uh);
+ return(0);
+}
diff --git a/ndb/test/ndbapi/bench/ndb_async1.cpp b/ndb/test/ndbapi/bench/ndb_async1.cpp
new file mode 100644
index 00000000000..2a84f6b2aca
--- /dev/null
+++ b/ndb/test/ndbapi/bench/ndb_async1.cpp
@@ -0,0 +1,647 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+//#define DEBUG_ON
+
+#include "userInterface.h"
+
+#include "macros.h"
+#include "ndb_schema.hpp"
+#include "ndb_error.hpp"
+
+#include <NdbApi.hpp>
+
+inline
+NdbConnection *
+startTransaction(Ndb * pNDB,
+ ServerId inServerId,
+ const SubscriberNumber inNumber){
+
+ const int keyDataLenBytes = sizeof(ServerId)+SUBSCRIBER_NUMBER_LENGTH;
+ const int keyDataLen_64Words = keyDataLenBytes >> 3;
+
+ Uint64 keyDataBuf[keyDataLen_64Words+1]; // The "+1" is for rounding...
+
+ char * keyDataBuf_charP = (char *)&keyDataBuf[0];
+ Uint32 * keyDataBuf_wo32P = (Uint32 *)&keyDataBuf[0];
+
+ // Server Id comes first
+ keyDataBuf_wo32P[0] = inServerId;
+ // Then subscriber number
+ memcpy(&keyDataBuf_charP[sizeof(ServerId)], inNumber,
+ SUBSCRIBER_NUMBER_LENGTH);
+
+ return pNDB->startTransaction(0, keyDataBuf_charP, keyDataLenBytes);
+}
+
+void T1_Callback(int result, NdbConnection * pCon, void * threadData);
+void T2_Callback(int result, NdbConnection * pCon, void * threadData);
+void T3_Callback_1(int result, NdbConnection * pCon, void * threadData);
+void T3_Callback_2(int result, NdbConnection * pCon, void * threadData);
+void T3_Callback_3(int result, NdbConnection * pCon, void * threadData);
+void T4_Callback_1(int result, NdbConnection * pCon, void * threadData);
+void T4_Callback_2(int result, NdbConnection * pCon, void * threadData);
+void T4_Callback_3(int result, NdbConnection * pCon, void * threadData);
+void T5_Callback_1(int result, NdbConnection * pCon, void * threadData);
+void T5_Callback_2(int result, NdbConnection * pCon, void * threadData);
+void T5_Callback_3(int result, NdbConnection * pCon, void * threadData);
+
+/**
+ * Transaction 1 - T1
+ *
+ * Update location and changed by/time on a subscriber
+ *
+ * Input:
+ * SubscriberNumber,
+ * Location,
+ * ChangedBy,
+ * ChangedTime
+ *
+ * Output:
+ */
+void
+start_T1(Ndb * pNDB, ThreadData * td){
+
+ DEBUG2("T1(%.*s): - Starting\n", SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number);
+
+ int check;
+ NdbConnection * pCON = pNDB->startTransaction();
+ if (pCON != NULL) {
+ NdbOperation *MyOp = pCON->getNdbOperation(SUBSCRIBER_TABLE);
+ if (MyOp != NULL) {
+ MyOp->updateTuple();
+ MyOp->equal(IND_SUBSCRIBER_NUMBER,
+ td->transactionData.number);
+ MyOp->setValue(IND_SUBSCRIBER_LOCATION,
+ (char *)&td->transactionData.location);
+ MyOp->setValue(IND_SUBSCRIBER_CHANGED_BY,
+ td->transactionData.changed_by);
+ MyOp->setValue(IND_SUBSCRIBER_CHANGED_TIME,
+ td->transactionData.changed_time);
+ pCON->executeAsynchPrepare( Commit , T1_Callback, td);
+ } else {
+ CHECK_NULL(MyOp, "T1: getNdbOperation", pCON);
+ }//if
+ } else {
+ error_handler("T1-1: startTranscation",
+ pNDB->getNdbErrorString(),
+ pNDB->getNdbError());
+ }//if
+}
+
+void
+T1_Callback(int result, NdbConnection * pCON, void * threadData){
+ ThreadData * td = (ThreadData *)threadData;
+
+ DEBUG2("T1(%.*s): - Completing\n", SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number);
+
+ CHECK_MINUS_ONE(result, "T1: Commit",
+ pCON);
+ td->pNDB->closeTransaction(pCON);
+ complete_T1(td);
+}
+
+/**
+ * Transaction 2 - T2
+ *
+ * Read from Subscriber:
+ *
+ * Input:
+ * SubscriberNumber
+ *
+ * Output:
+ * Location
+ * Changed by
+ * Changed Timestamp
+ * Name
+ */
+void
+start_T2(Ndb * pNDB, ThreadData * td){
+
+ DEBUG3("T2(%.*s, %p): - Starting\n", SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.location);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * pCON = pNDB->startTransaction();
+ if (pCON == NULL)
+ error_handler("T2-1: startTransaction",
+ pNDB->getNdbErrorString(),
+ pNDB->getNdbError());
+
+ NdbOperation *MyOp= pCON->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOp, "T2: getNdbOperation",
+ pCON);
+
+ MyOp->readTuple();
+ MyOp->equal(IND_SUBSCRIBER_NUMBER,
+ td->transactionData.number);
+ MyOp->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)&td->transactionData.location);
+ MyOp->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ td->transactionData.changed_by);
+ MyOp->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ td->transactionData.changed_time);
+ MyOp->getValue(IND_SUBSCRIBER_NAME,
+ td->transactionData.name);
+ pCON->executeAsynchPrepare( Commit, T2_Callback, td );
+}
+
+void
+T2_Callback(int result, NdbConnection * pCON, void * threadData){
+ ThreadData * td = (ThreadData *)threadData;
+ DEBUG3("T2(%.*s, %p): - Completing\n", SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.location);
+
+ CHECK_MINUS_ONE(result, "T2: Commit", pCON);
+ td->pNDB->closeTransaction(pCON);
+ complete_T2(td);
+}
+
+/**
+ * Transaction 3 - T3
+ *
+ * Read session details
+ *
+ * Input:
+ * SubscriberNumber
+ * ServerId
+ * ServerBit
+ *
+ * Output:
+ * BranchExecuted
+ * SessionDetails
+ * ChangedBy
+ * ChangedTime
+ * Location
+ */
+void
+start_T3(Ndb * pNDB, ThreadData * td){
+
+ DEBUG3("T3(%.*s, %.2d): - Starting\n", SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * pCON = startTransaction(pNDB,
+ td->transactionData.server_id,
+ td->transactionData.number);
+ if (pCON == NULL)
+ error_handler("T3-1: startTranscation",
+ pNDB->getNdbErrorString(),
+ pNDB->getNdbError());
+
+ NdbOperation *MyOp= pCON->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOp, "T3-1: getNdbOperation",
+ pCON);
+
+ MyOp->readTuple();
+ MyOp->equal(IND_SUBSCRIBER_NUMBER,
+ td->transactionData.number);
+ MyOp->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)&td->transactionData.location);
+ MyOp->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ td->transactionData.changed_by);
+ MyOp->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ td->transactionData.changed_time);
+ MyOp->getValue(IND_SUBSCRIBER_GROUP,
+ (char *)&td->transactionData.group_id);
+ MyOp->getValue(IND_SUBSCRIBER_SESSIONS,
+ (char *)&td->transactionData.sessions);
+ pCON->executeAsynchPrepare( NoCommit , T3_Callback_1, td);
+}
+
+void
+T3_Callback_1(int result, NdbConnection * pCON, void * threadData){
+ ThreadData * td = (ThreadData *)threadData;
+ DEBUG3("T3(%.*s, %.2d): - Callback 1\n", SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id);
+
+ CHECK_MINUS_ONE(result, "T3-1: NoCommit", pCON);
+
+ NdbOperation * MyOp = pCON->getNdbOperation(GROUP_TABLE);
+ CHECK_NULL(MyOp, "T3-2: getNdbOperation",
+ pCON);
+
+ MyOp->readTuple();
+ MyOp->equal(IND_GROUP_ID,
+ (char*)&td->transactionData.group_id);
+ MyOp->getValue(IND_GROUP_ALLOW_READ,
+ (char *)&td->transactionData.permission);
+ pCON->executeAsynchPrepare( NoCommit, T3_Callback_2, td );
+}
+
+void
+T3_Callback_2(int result, NdbConnection * pCON, void * threadData){
+ ThreadData * td = (ThreadData *)threadData;
+
+ CHECK_MINUS_ONE(result, "T3-2: NoCommit", pCON);
+
+ Uint32 permission = td->transactionData.permission;
+ Uint32 sessions = td->transactionData.sessions;
+ Uint32 server_bit = td->transactionData.server_bit;
+
+ if(((permission & server_bit) == server_bit) &&
+ ((sessions & server_bit) == server_bit)){
+
+ memcpy(td->transactionData.suffix,
+ &td->transactionData.number
+ [SUBSCRIBER_NUMBER_LENGTH-SUBSCRIBER_NUMBER_SUFFIX_LENGTH],
+ SUBSCRIBER_NUMBER_SUFFIX_LENGTH);
+ DEBUG5("T3(%.*s, %.2d): - Callback 2 - reading(%.*s)\n",
+ SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id,
+ SUBSCRIBER_NUMBER_SUFFIX_LENGTH,
+ td->transactionData.suffix);
+
+ /* Operation 3 */
+ NdbOperation * MyOp = pCON->getNdbOperation(SESSION_TABLE);
+ CHECK_NULL(MyOp, "T3-3: getNdbOperation",
+ pCON);
+
+ MyOp->simpleRead();
+ MyOp->equal(IND_SESSION_SUBSCRIBER,
+ (char*)td->transactionData.number);
+ MyOp->equal(IND_SESSION_SERVER,
+ (char*)&td->transactionData.server_id);
+ MyOp->getValue(IND_SESSION_DATA,
+ (char *)td->transactionData.session_details);
+
+ /* Operation 4 */
+ MyOp = pCON->getNdbOperation(SERVER_TABLE);
+ CHECK_NULL(MyOp, "T3-4: getNdbOperation",
+ pCON);
+
+ MyOp->interpretedUpdateTuple();
+ MyOp->equal(IND_SERVER_ID,
+ (char*)&td->transactionData.server_id);
+ MyOp->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
+ (char*)td->transactionData.suffix);
+ MyOp->incValue(IND_SERVER_READS, (uint32)1);
+ td->transactionData.branchExecuted = 1;
+ } else {
+ DEBUG3("T3(%.*s, %.2d): - Callback 2 - no read\n",
+ SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id);
+ td->transactionData.branchExecuted = 0;
+ }
+ pCON->executeAsynchPrepare( Commit, T3_Callback_3, td );
+}
+
+void
+T3_Callback_3(int result, NdbConnection * pCON, void * threadData){
+ ThreadData * td = (ThreadData *)threadData;
+ DEBUG3("T3(%.*s, %.2d): - Completing\n", SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id);
+
+ CHECK_MINUS_ONE(result, "T3-3: Commit", pCON);
+
+ td->pNDB->closeTransaction(pCON);
+ complete_T3(td);
+}
+
+/**
+ * Transaction 4 - T4
+ *
+ * Create session
+ *
+ * Input:
+ * SubscriberNumber
+ * ServerId
+ * ServerBit
+ * SessionDetails,
+ * DoRollback
+ * Output:
+ * ChangedBy
+ * ChangedTime
+ * Location
+ * BranchExecuted
+ */
+void
+start_T4(Ndb * pNDB, ThreadData * td){
+
+ DEBUG3("T4(%.*s, %.2d): - Starting\n", SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * pCON = startTransaction(pNDB,
+ td->transactionData.server_id,
+ td->transactionData.number);
+ if (pCON == NULL)
+ error_handler("T4-1: startTranscation",
+ pNDB->getNdbErrorString(),
+ pNDB->getNdbError());
+
+ NdbOperation *MyOp= pCON->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOp, "T4-1: getNdbOperation",
+ pCON);
+
+ MyOp->interpretedUpdateTuple();
+ MyOp->equal(IND_SUBSCRIBER_NUMBER,
+ td->transactionData.number);
+ MyOp->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)&td->transactionData.location);
+ MyOp->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ td->transactionData.changed_by);
+ MyOp->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ td->transactionData.changed_time);
+ MyOp->getValue(IND_SUBSCRIBER_GROUP,
+ (char *)&td->transactionData.group_id);
+ MyOp->getValue(IND_SUBSCRIBER_SESSIONS,
+ (char *)&td->transactionData.sessions);
+ MyOp->incValue(IND_SUBSCRIBER_SESSIONS,
+ (uint32)td->transactionData.server_bit);
+ pCON->executeAsynchPrepare( NoCommit , T4_Callback_1, td);
+}
+
+void
+T4_Callback_1(int result, NdbConnection * pCON, void * threadData){
+ CHECK_MINUS_ONE(result, "T4-1: NoCommit", pCON);
+ ThreadData * td = (ThreadData *)threadData;
+
+ DEBUG3("T4(%.*s, %.2d): - Callback 1\n",
+ SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id);
+
+
+ NdbOperation * MyOp = pCON->getNdbOperation(GROUP_TABLE);
+ CHECK_NULL(MyOp, "T4-2: getNdbOperation",
+ pCON);
+
+ MyOp->readTuple();
+ MyOp->equal(IND_GROUP_ID,
+ (char*)&td->transactionData.group_id);
+ MyOp->getValue(IND_GROUP_ALLOW_INSERT,
+ (char *)&td->transactionData.permission);
+ pCON->executeAsynchPrepare( NoCommit , T4_Callback_2, td);
+}
+
+void
+T4_Callback_2(int result, NdbConnection * pCON, void * threadData){
+ CHECK_MINUS_ONE(result, "T4-2: NoCommit", pCON);
+ ThreadData * td = (ThreadData *)threadData;
+
+ Uint32 permission = td->transactionData.permission;
+ Uint32 sessions = td->transactionData.sessions;
+ Uint32 server_bit = td->transactionData.server_bit;
+
+ if(((permission & server_bit) == server_bit) &&
+ ((sessions & server_bit) == 0)){
+
+ memcpy(td->transactionData.suffix,
+ &td->transactionData.number
+ [SUBSCRIBER_NUMBER_LENGTH-SUBSCRIBER_NUMBER_SUFFIX_LENGTH],
+ SUBSCRIBER_NUMBER_SUFFIX_LENGTH);
+
+ DEBUG5("T4(%.*s, %.2d): - Callback 2 - inserting(%.*s)\n",
+ SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id,
+ SUBSCRIBER_NUMBER_SUFFIX_LENGTH,
+ td->transactionData.suffix);
+
+ /* Operation 3 */
+
+ NdbOperation * MyOp = pCON->getNdbOperation(SESSION_TABLE);
+ CHECK_NULL(MyOp, "T4-3: getNdbOperation",
+ pCON);
+
+ MyOp->insertTuple();
+ MyOp->equal(IND_SESSION_SUBSCRIBER,
+ (char*)td->transactionData.number);
+ MyOp->equal(IND_SESSION_SERVER,
+ (char*)&td->transactionData.server_id);
+ MyOp->setValue(SESSION_DATA,
+ (char *)td->transactionData.session_details);
+ /* Operation 4 */
+
+ /* Operation 5 */
+ MyOp = pCON->getNdbOperation(SERVER_TABLE);
+ CHECK_NULL(MyOp, "T4-5: getNdbOperation",
+ pCON);
+
+ MyOp->interpretedUpdateTuple();
+ MyOp->equal(IND_SERVER_ID,
+ (char*)&td->transactionData.server_id);
+ MyOp->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
+ (char*)td->transactionData.suffix);
+ MyOp->incValue(IND_SERVER_INSERTS, (uint32)1);
+ td->transactionData.branchExecuted = 1;
+ } else {
+ td->transactionData.branchExecuted = 0;
+ DEBUG5("T4(%.*s, %.2d): - Callback 2 - %s %s\n",
+ SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id,
+ ((permission & server_bit) ?
+ "permission - " : "no permission - "),
+ ((sessions & server_bit) ?
+ "in session - " : "no in session - "));
+ }
+
+ if(!td->transactionData.do_rollback && td->transactionData.branchExecuted){
+ pCON->executeAsynchPrepare(Commit, T4_Callback_3, td);
+ } else {
+ pCON->executeAsynchPrepare(Rollback, T4_Callback_3, td);
+ }
+}
+
+void
+T4_Callback_3(int result, NdbConnection * pCON, void * threadData){
+ CHECK_MINUS_ONE(result, "T4-3: Commit", pCON);
+ ThreadData * td = (ThreadData *)threadData;
+
+ DEBUG3("T4(%.*s, %.2d): - Completing\n",
+ SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id);
+
+ td->pNDB->closeTransaction(pCON);
+ complete_T4(td);
+}
+
+/**
+ * Transaction 5 - T5
+ *
+ * Delete session
+ *
+ * Input:
+ * SubscriberNumber
+ * ServerId
+ * ServerBit
+ * DoRollback
+ * Output:
+ * ChangedBy
+ * ChangedTime
+ * Location
+ * BranchExecuted
+ */
+void
+start_T5(Ndb * pNDB, ThreadData * td){
+
+ DEBUG3("T5(%.*s, %.2d): - Starting\n", SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * pCON = pNDB->startTransaction();
+ if (pCON == NULL)
+ error_handler("T5-1: startTranscation",
+ pNDB->getNdbErrorString(),
+ pNDB->getNdbError());
+
+ NdbOperation * MyOp= pCON->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOp, "T5-1: getNdbOperation",
+ pCON);
+
+ MyOp->interpretedUpdateTuple();
+ MyOp->equal(IND_SUBSCRIBER_NUMBER,
+ td->transactionData.number);
+ MyOp->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)&td->transactionData.location);
+ MyOp->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ td->transactionData.changed_by);
+ MyOp->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ td->transactionData.changed_time);
+ MyOp->getValue(IND_SUBSCRIBER_GROUP,
+ (char *)&td->transactionData.group_id);
+ MyOp->getValue(IND_SUBSCRIBER_SESSIONS,
+ (char *)&td->transactionData.sessions);
+ MyOp->subValue(IND_SUBSCRIBER_SESSIONS,
+ (uint32)td->transactionData.server_bit);
+ pCON->executeAsynchPrepare( NoCommit, T5_Callback_1, td );
+}
+
+void
+T5_Callback_1(int result, NdbConnection * pCON, void * threadData){
+ CHECK_MINUS_ONE(result, "T5-1: NoCommit", pCON);
+ ThreadData * td = (ThreadData *)threadData;
+
+ DEBUG3("T5(%.*s, %.2d): - Callback 1\n",
+ SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id);
+
+ NdbOperation * MyOp = pCON->getNdbOperation(GROUP_TABLE);
+ CHECK_NULL(MyOp, "T5-2: getNdbOperation",
+ pCON);
+
+ MyOp->readTuple();
+ MyOp->equal(IND_GROUP_ID,
+ (char*)&td->transactionData.group_id);
+ MyOp->getValue(IND_GROUP_ALLOW_DELETE,
+ (char *)&td->transactionData.permission);
+ pCON->executeAsynchPrepare( NoCommit, T5_Callback_2, td );
+}
+
+void
+T5_Callback_2(int result, NdbConnection * pCON, void * threadData){
+ CHECK_MINUS_ONE(result, "T5-2: NoCommit", pCON);
+ ThreadData * td = (ThreadData *)threadData;
+
+ Uint32 permission = td->transactionData.permission;
+ Uint32 sessions = td->transactionData.sessions;
+ Uint32 server_bit = td->transactionData.server_bit;
+
+ if(((permission & server_bit) == server_bit) &&
+ ((sessions & server_bit) == server_bit)){
+
+ memcpy(td->transactionData.suffix,
+ &td->transactionData.number
+ [SUBSCRIBER_NUMBER_LENGTH-SUBSCRIBER_NUMBER_SUFFIX_LENGTH],
+ SUBSCRIBER_NUMBER_SUFFIX_LENGTH);
+
+ DEBUG5("T5(%.*s, %.2d): - Callback 2 - deleting(%.*s)\n",
+ SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id,
+ SUBSCRIBER_NUMBER_SUFFIX_LENGTH,
+ td->transactionData.suffix);
+
+ /* Operation 3 */
+ NdbOperation * MyOp = pCON->getNdbOperation(SESSION_TABLE);
+ CHECK_NULL(MyOp, "T5-3: getNdbOperation",
+ pCON);
+
+ MyOp->deleteTuple();
+ MyOp->equal(IND_SESSION_SUBSCRIBER,
+ (char*)td->transactionData.number);
+ MyOp->equal(IND_SESSION_SERVER,
+ (char*)&td->transactionData.server_id);
+ /* Operation 4 */
+
+ /* Operation 5 */
+ MyOp = pCON->getNdbOperation(SERVER_TABLE);
+ CHECK_NULL(MyOp, "T5-5: getNdbOperation",
+ pCON);
+
+ MyOp->interpretedUpdateTuple();
+ MyOp->equal(IND_SERVER_ID,
+ (char*)&td->transactionData.server_id);
+ MyOp->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
+ (char*)td->transactionData.suffix);
+ MyOp->incValue(IND_SERVER_DELETES, (uint32)1);
+ td->transactionData.branchExecuted = 1;
+ } else {
+ td->transactionData.branchExecuted = 0;
+
+ DEBUG5("T5(%.*s, %.2d): - Callback 2 - no delete - %s %s\n",
+ SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id,
+ ((permission & server_bit) ?
+ "permission - " : "no permission - "),
+ ((sessions & server_bit) ?
+ "in session - " : "no in session - "));
+ }
+
+ if(!td->transactionData.do_rollback && td->transactionData.branchExecuted){
+ pCON->executeAsynchPrepare(Commit, T5_Callback_3, td);
+ } else {
+ pCON->executeAsynchPrepare(Rollback, T5_Callback_3, td);
+ }
+}
+
+void
+T5_Callback_3(int result, NdbConnection * pCON, void * threadData){
+ CHECK_MINUS_ONE(result, "T5-3: Commit", pCON);
+ ThreadData * td = (ThreadData *)threadData;
+
+ DEBUG3("T5(%.*s, %.2d): - Completing\n",
+ SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id);
+
+ td->pNDB->closeTransaction(pCON);
+ complete_T5(td);
+}
diff --git a/ndb/test/ndbapi/bench/ndb_async2.cpp b/ndb/test/ndbapi/bench/ndb_async2.cpp
new file mode 100644
index 00000000000..31cf1d8310a
--- /dev/null
+++ b/ndb/test/ndbapi/bench/ndb_async2.cpp
@@ -0,0 +1,757 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+//#define DEBUG_ON
+
+#include <string.h>
+#include "userInterface.h"
+
+#include "macros.h"
+#include "ndb_schema.hpp"
+#include "ndb_error.hpp"
+#include <NdbSleep.h>
+
+#include <NdbApi.hpp>
+
+void T1_Callback(int result, NdbConnection * pCon, void * threadData);
+void T2_Callback(int result, NdbConnection * pCon, void * threadData);
+void T3_Callback_1(int result, NdbConnection * pCon, void * threadData);
+void T3_Callback_2(int result, NdbConnection * pCon, void * threadData);
+void T3_Callback_3(int result, NdbConnection * pCon, void * threadData);
+void T4_Callback_1(int result, NdbConnection * pCon, void * threadData);
+void T4_Callback_2(int result, NdbConnection * pCon, void * threadData);
+void T4_Callback_3(int result, NdbConnection * pCon, void * threadData);
+void T5_Callback_1(int result, NdbConnection * pCon, void * threadData);
+void T5_Callback_2(int result, NdbConnection * pCon, void * threadData);
+void T5_Callback_3(int result, NdbConnection * pCon, void * threadData);
+
+static int stat_async = 0;
+
+/**
+ * Transaction 1 - T1
+ *
+ * Update location and changed by/time on a subscriber
+ *
+ * Input:
+ * SubscriberNumber,
+ * Location,
+ * ChangedBy,
+ * ChangedTime
+ *
+ * Output:
+ */
+
+#define SFX_START (SUBSCRIBER_NUMBER_LENGTH - SUBSCRIBER_NUMBER_SUFFIX_LENGTH)
+
+inline
+NdbConnection *
+startTransaction(Ndb * pNDB, ThreadData * td){
+ return pNDB->startTransaction();
+#ifdef OLD_CODE
+ return pNDB->startTransactionDGroup (0,
+ &td->transactionData.number[SFX_START],
+ 1);
+#endif
+}
+
+void
+start_T1(Ndb * pNDB, ThreadData * td, int async){
+
+ DEBUG2("T1(%.*s): - Starting", SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number);
+
+ NdbConnection * pCON = 0;
+ while((pCON = startTransaction(pNDB, td)) == 0){
+ CHECK_ALLOWED_ERROR("T1: startTransaction", td, pNDB->getNdbError());
+ NdbSleep_MilliSleep(10);
+ }
+
+ NdbOperation *MyOp = pCON->getNdbOperation(SUBSCRIBER_TABLE);
+ if (MyOp != NULL) {
+ MyOp->updateTuple();
+ MyOp->equal(IND_SUBSCRIBER_NUMBER,
+ td->transactionData.number);
+ MyOp->setValue(IND_SUBSCRIBER_LOCATION,
+ (char *)&td->transactionData.location);
+ MyOp->setValue(IND_SUBSCRIBER_CHANGED_BY,
+ td->transactionData.changed_by);
+ MyOp->setValue(IND_SUBSCRIBER_CHANGED_TIME,
+ td->transactionData.changed_time);
+ if (async == 1) {
+ pCON->executeAsynchPrepare( Commit , T1_Callback, td);
+ } else {
+ int result = pCON->execute(Commit);
+ T1_Callback(result, pCON, (void*)td);
+ return;
+ }//if
+ } else {
+ CHECK_NULL(MyOp, "T1: getNdbOperation", td, pCON->getNdbError());
+ }//if
+}
+
+void
+T1_Callback(int result, NdbConnection * pCON, void * threadData) {
+ ThreadData * td = (ThreadData *)threadData;
+
+ DEBUG2("T1(%.*s): - Completing", SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number);
+
+ if (result == -1) {
+ CHECK_ALLOWED_ERROR("T1: Commit", td, pCON->getNdbError());
+ td->pNDB->closeTransaction(pCON);
+ start_T1(td->pNDB, td, stat_async);
+ return;
+ }//if
+ td->pNDB->closeTransaction(pCON);
+ complete_T1(td);
+}
+
+/**
+ * Transaction 2 - T2
+ *
+ * Read from Subscriber:
+ *
+ * Input:
+ * SubscriberNumber
+ *
+ * Output:
+ * Location
+ * Changed by
+ * Changed Timestamp
+ * Name
+ */
+void
+start_T2(Ndb * pNDB, ThreadData * td, int async){
+
+ DEBUG3("T2(%.*s, %d): - Starting", SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.location);
+
+ NdbConnection * pCON = 0;
+
+ while((pCON = startTransaction(pNDB, td)) == 0){
+ CHECK_ALLOWED_ERROR("T2-1: startTransaction", td, pNDB->getNdbError());
+ NdbSleep_MilliSleep(10);
+ }
+
+ NdbOperation *MyOp= pCON->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOp, "T2: getNdbOperation", td,
+ pCON->getNdbError());
+
+ MyOp->readTuple();
+ MyOp->equal(IND_SUBSCRIBER_NUMBER,
+ td->transactionData.number);
+ MyOp->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)&td->transactionData.location);
+ MyOp->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ td->transactionData.changed_by);
+ MyOp->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ td->transactionData.changed_time);
+ MyOp->getValue(IND_SUBSCRIBER_NAME,
+ td->transactionData.name);
+ if (async == 1) {
+ pCON->executeAsynchPrepare( Commit , T2_Callback, td);
+ } else {
+ int result = pCON->execute(Commit);
+ T2_Callback(result, pCON, (void*)td);
+ return;
+ }//if
+}
+
+void
+T2_Callback(int result, NdbConnection * pCON, void * threadData){
+ ThreadData * td = (ThreadData *)threadData;
+ DEBUG3("T2(%.*s, %d): - Completing", SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.location);
+
+ if (result == -1) {
+ CHECK_ALLOWED_ERROR("T2: Commit", td, pCON->getNdbError());
+ td->pNDB->closeTransaction(pCON);
+ start_T2(td->pNDB, td, stat_async);
+ return;
+ }//if
+ td->pNDB->closeTransaction(pCON);
+ complete_T2(td);
+}
+
+/**
+ * Transaction 3 - T3
+ *
+ * Read session details
+ *
+ * Input:
+ * SubscriberNumber
+ * ServerId
+ * ServerBit
+ *
+ * Output:
+ * BranchExecuted
+ * SessionDetails
+ * ChangedBy
+ * ChangedTime
+ * Location
+ */
+void
+start_T3(Ndb * pNDB, ThreadData * td, int async){
+
+ DEBUG3("T3(%.*s, %.2d): - Starting", SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id);
+
+ NdbConnection * pCON = 0;
+
+ while((pCON = startTransaction(pNDB, td)) == 0){
+ CHECK_ALLOWED_ERROR("T3-1: startTransaction", td, pNDB->getNdbError());
+ NdbSleep_MilliSleep(10);
+ }
+
+ NdbOperation *MyOp= pCON->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOp, "T3-1: getNdbOperation", td,
+ pCON->getNdbError());
+
+ MyOp->readTuple();
+ MyOp->equal(IND_SUBSCRIBER_NUMBER,
+ td->transactionData.number);
+ MyOp->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)&td->transactionData.location);
+ MyOp->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ td->transactionData.changed_by);
+ MyOp->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ td->transactionData.changed_time);
+ MyOp->getValue(IND_SUBSCRIBER_GROUP,
+ (char *)&td->transactionData.group_id);
+ MyOp->getValue(IND_SUBSCRIBER_SESSIONS,
+ (char *)&td->transactionData.sessions);
+ stat_async = async;
+ if (async == 1) {
+ pCON->executeAsynchPrepare( NoCommit , T3_Callback_1, td);
+ } else {
+ int result = pCON->execute( NoCommit );
+ T3_Callback_1(result, pCON, (void*)td);
+ return;
+ }//if
+}
+
+void
+T3_Callback_1(int result, NdbConnection * pCON, void * threadData){
+ ThreadData * td = (ThreadData *)threadData;
+ DEBUG3("T3(%.*s, %.2d): - Callback 1", SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id);
+
+ if (result == -1) {
+ CHECK_ALLOWED_ERROR("T3-1: execute", td, pCON->getNdbError());
+ td->pNDB->closeTransaction(pCON);
+ start_T3(td->pNDB, td, stat_async);
+ return;
+ }//if
+
+ NdbOperation * MyOp = pCON->getNdbOperation(GROUP_TABLE);
+ CHECK_NULL(MyOp, "T3-2: getNdbOperation", td,
+ pCON->getNdbError());
+
+ MyOp->readTuple();
+ MyOp->equal(IND_GROUP_ID,
+ (char*)&td->transactionData.group_id);
+ MyOp->getValue(IND_GROUP_ALLOW_READ,
+ (char *)&td->transactionData.permission);
+ if (stat_async == 1) {
+ pCON->executeAsynchPrepare( NoCommit , T3_Callback_2, td);
+ } else {
+ int result = pCON->execute( NoCommit );
+ T3_Callback_2(result, pCON, (void*)td);
+ return;
+ }//if
+}
+
+void
+T3_Callback_2(int result, NdbConnection * pCON, void * threadData){
+ ThreadData * td = (ThreadData *)threadData;
+
+ if (result == -1) {
+ CHECK_ALLOWED_ERROR("T3-2: execute", td, pCON->getNdbError());
+ td->pNDB->closeTransaction(pCON);
+ start_T3(td->pNDB, td, stat_async);
+ return;
+ }//if
+
+ Uint32 permission = td->transactionData.permission;
+ Uint32 sessions = td->transactionData.sessions;
+ Uint32 server_bit = td->transactionData.server_bit;
+
+ if(((permission & server_bit) == server_bit) &&
+ ((sessions & server_bit) == server_bit)){
+
+ memcpy(td->transactionData.suffix,
+ &td->transactionData.number[SFX_START],
+ SUBSCRIBER_NUMBER_SUFFIX_LENGTH);
+ DEBUG5("T3(%.*s, %.2d): - Callback 2 - reading(%.*s)",
+ SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id,
+ SUBSCRIBER_NUMBER_SUFFIX_LENGTH,
+ td->transactionData.suffix);
+
+ /* Operation 3 */
+ NdbOperation * MyOp = pCON->getNdbOperation(SESSION_TABLE);
+ CHECK_NULL(MyOp, "T3-3: getNdbOperation", td,
+ pCON->getNdbError());
+
+ MyOp->simpleRead();
+ MyOp->equal(IND_SESSION_SUBSCRIBER,
+ (char*)td->transactionData.number);
+ MyOp->equal(IND_SESSION_SERVER,
+ (char*)&td->transactionData.server_id);
+ MyOp->getValue(IND_SESSION_DATA,
+ (char *)td->transactionData.session_details);
+
+ /* Operation 4 */
+ MyOp = pCON->getNdbOperation(SERVER_TABLE);
+ CHECK_NULL(MyOp, "T3-4: getNdbOperation", td,
+ pCON->getNdbError());
+
+ MyOp->interpretedUpdateTuple();
+ MyOp->equal(IND_SERVER_ID,
+ (char*)&td->transactionData.server_id);
+ MyOp->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
+ (char*)td->transactionData.suffix);
+ MyOp->incValue(IND_SERVER_READS, (uint32)1);
+ td->transactionData.branchExecuted = 1;
+ } else {
+ DEBUG3("T3(%.*s, %.2d): - Callback 2 - no read",
+ SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id);
+ td->transactionData.branchExecuted = 0;
+ }
+ if (stat_async == 1) {
+ pCON->executeAsynchPrepare( Commit , T3_Callback_3, td);
+ } else {
+ int result = pCON->execute( Commit );
+ T3_Callback_3(result, pCON, (void*)td);
+ return;
+ }//if
+}
+
+void
+T3_Callback_3(int result, NdbConnection * pCON, void * threadData){
+ ThreadData * td = (ThreadData *)threadData;
+ DEBUG3("T3(%.*s, %.2d): - Completing", SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id);
+
+ if (result == -1) {
+ CHECK_ALLOWED_ERROR("T3-3: Commit", td, pCON->getNdbError());
+ td->pNDB->closeTransaction(pCON);
+ start_T3(td->pNDB, td, stat_async);
+ return;
+ }//if
+ td->pNDB->closeTransaction(pCON);
+ complete_T3(td);
+}
+
+/**
+ * Transaction 4 - T4
+ *
+ * Create session
+ *
+ * Input:
+ * SubscriberNumber
+ * ServerId
+ * ServerBit
+ * SessionDetails,
+ * DoRollback
+ * Output:
+ * ChangedBy
+ * ChangedTime
+ * Location
+ * BranchExecuted
+ */
+void
+start_T4(Ndb * pNDB, ThreadData * td, int async){
+
+ DEBUG3("T4(%.*s, %.2d): - Starting", SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id);
+
+ NdbConnection * pCON = 0;
+ while((pCON = startTransaction(pNDB, td)) == 0){
+ CHECK_ALLOWED_ERROR("T4-1: startTransaction", td, pNDB->getNdbError());
+ NdbSleep_MilliSleep(10);
+ }
+
+ NdbOperation *MyOp= pCON->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOp, "T4-1: getNdbOperation", td,
+ pCON->getNdbError());
+
+ MyOp->interpretedUpdateTuple();
+ MyOp->equal(IND_SUBSCRIBER_NUMBER,
+ td->transactionData.number);
+ MyOp->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)&td->transactionData.location);
+ MyOp->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ td->transactionData.changed_by);
+ MyOp->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ td->transactionData.changed_time);
+ MyOp->getValue(IND_SUBSCRIBER_GROUP,
+ (char *)&td->transactionData.group_id);
+ MyOp->getValue(IND_SUBSCRIBER_SESSIONS,
+ (char *)&td->transactionData.sessions);
+ MyOp->incValue(IND_SUBSCRIBER_SESSIONS,
+ (uint32)td->transactionData.server_bit);
+ stat_async = async;
+ if (async == 1) {
+ pCON->executeAsynchPrepare( NoCommit , T4_Callback_1, td);
+ } else {
+ int result = pCON->execute( NoCommit );
+ T4_Callback_1(result, pCON, (void*)td);
+ return;
+ }//if
+}
+
+void
+T4_Callback_1(int result, NdbConnection * pCON, void * threadData){
+ ThreadData * td = (ThreadData *)threadData;
+ if (result == -1) {
+ CHECK_ALLOWED_ERROR("T4-1: execute", td, pCON->getNdbError());
+ td->pNDB->closeTransaction(pCON);
+ start_T4(td->pNDB, td, stat_async);
+ return;
+ }//if
+
+ DEBUG3("T4(%.*s, %.2d): - Callback 1",
+ SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id);
+
+
+ NdbOperation * MyOp = pCON->getNdbOperation(GROUP_TABLE);
+ CHECK_NULL(MyOp, "T4-2: getNdbOperation", td,
+ pCON->getNdbError());
+
+ MyOp->readTuple();
+ MyOp->equal(IND_GROUP_ID,
+ (char*)&td->transactionData.group_id);
+ MyOp->getValue(IND_GROUP_ALLOW_INSERT,
+ (char *)&td->transactionData.permission);
+ if (stat_async == 1) {
+ pCON->executeAsynchPrepare( NoCommit , T4_Callback_2, td);
+ } else {
+ int result = pCON->execute( NoCommit );
+ T4_Callback_2(result, pCON, (void*)td);
+ return;
+ }//if
+}
+
+void
+T4_Callback_2(int result, NdbConnection * pCON, void * threadData){
+ ThreadData * td = (ThreadData *)threadData;
+ if (result == -1) {
+ CHECK_ALLOWED_ERROR("T4-2: execute", td, pCON->getNdbError());
+ td->pNDB->closeTransaction(pCON);
+ start_T4(td->pNDB, td, stat_async);
+ return;
+ }//if
+
+ Uint32 permission = td->transactionData.permission;
+ Uint32 sessions = td->transactionData.sessions;
+ Uint32 server_bit = td->transactionData.server_bit;
+
+ if(((permission & server_bit) == server_bit) &&
+ ((sessions & server_bit) == 0)){
+
+ memcpy(td->transactionData.suffix,
+ &td->transactionData.number[SFX_START],
+ SUBSCRIBER_NUMBER_SUFFIX_LENGTH);
+
+ DEBUG5("T4(%.*s, %.2d): - Callback 2 - inserting(%.*s)",
+ SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id,
+ SUBSCRIBER_NUMBER_SUFFIX_LENGTH,
+ td->transactionData.suffix);
+
+ /* Operation 3 */
+
+ NdbOperation * MyOp = pCON->getNdbOperation(SESSION_TABLE);
+ CHECK_NULL(MyOp, "T4-3: getNdbOperation", td,
+ pCON->getNdbError());
+
+ MyOp->insertTuple();
+ MyOp->equal(IND_SESSION_SUBSCRIBER,
+ (char*)td->transactionData.number);
+ MyOp->equal(IND_SESSION_SERVER,
+ (char*)&td->transactionData.server_id);
+ MyOp->setValue(SESSION_DATA,
+ (char *)td->transactionData.session_details);
+ /* Operation 4 */
+
+ /* Operation 5 */
+ MyOp = pCON->getNdbOperation(SERVER_TABLE);
+ CHECK_NULL(MyOp, "T4-5: getNdbOperation", td,
+ pCON->getNdbError());
+
+ MyOp->interpretedUpdateTuple();
+ MyOp->equal(IND_SERVER_ID,
+ (char*)&td->transactionData.server_id);
+ MyOp->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
+ (char*)td->transactionData.suffix);
+ MyOp->incValue(IND_SERVER_INSERTS, (uint32)1);
+ td->transactionData.branchExecuted = 1;
+ } else {
+ td->transactionData.branchExecuted = 0;
+ DEBUG5("T4(%.*s, %.2d): - Callback 2 - %s %s",
+ SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id,
+ ((permission & server_bit) ?
+ "permission - " : "no permission - "),
+ ((sessions & server_bit) ?
+ "in session - " : "no in session - "));
+ }
+
+ if(!td->transactionData.do_rollback && td->transactionData.branchExecuted){
+ if (stat_async == 1) {
+ pCON->executeAsynchPrepare( Commit , T4_Callback_3, td);
+ } else {
+ int result = pCON->execute( Commit );
+ T4_Callback_3(result, pCON, (void*)td);
+ return;
+ }//if
+ } else {
+ if (stat_async == 1) {
+ pCON->executeAsynchPrepare( Rollback , T4_Callback_3, td);
+ } else {
+ int result = pCON->execute( Rollback );
+ T4_Callback_3(result, pCON, (void*)td);
+ return;
+ }//if
+ }
+}
+
+void
+T4_Callback_3(int result, NdbConnection * pCON, void * threadData){
+ ThreadData * td = (ThreadData *)threadData;
+ if (result == -1) {
+ CHECK_ALLOWED_ERROR("T4-3: Commit", td, pCON->getNdbError());
+ td->pNDB->closeTransaction(pCON);
+ start_T4(td->pNDB, td, stat_async);
+ return;
+ }//if
+
+ DEBUG3("T4(%.*s, %.2d): - Completing",
+ SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id);
+
+ td->pNDB->closeTransaction(pCON);
+ complete_T4(td);
+}
+
+/**
+ * Transaction 5 - T5
+ *
+ * Delete session
+ *
+ * Input:
+ * SubscriberNumber
+ * ServerId
+ * ServerBit
+ * DoRollback
+ * Output:
+ * ChangedBy
+ * ChangedTime
+ * Location
+ * BranchExecuted
+ */
+void
+start_T5(Ndb * pNDB, ThreadData * td, int async){
+
+ DEBUG3("T5(%.*s, %.2d): - Starting", SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id);
+
+ NdbConnection * pCON = 0;
+ while((pCON = startTransaction(pNDB, td)) == 0){
+ CHECK_ALLOWED_ERROR("T5-1: startTransaction", td, pNDB->getNdbError());
+ NdbSleep_MilliSleep(10);
+ }
+
+ NdbOperation * MyOp= pCON->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOp, "T5-1: getNdbOperation", td,
+ pCON->getNdbError());
+
+ MyOp->interpretedUpdateTuple();
+ MyOp->equal(IND_SUBSCRIBER_NUMBER,
+ td->transactionData.number);
+ MyOp->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)&td->transactionData.location);
+ MyOp->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ td->transactionData.changed_by);
+ MyOp->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ td->transactionData.changed_time);
+ MyOp->getValue(IND_SUBSCRIBER_GROUP,
+ (char *)&td->transactionData.group_id);
+ MyOp->getValue(IND_SUBSCRIBER_SESSIONS,
+ (char *)&td->transactionData.sessions);
+ MyOp->subValue(IND_SUBSCRIBER_SESSIONS,
+ (uint32)td->transactionData.server_bit);
+ stat_async = async;
+ if (async == 1) {
+ pCON->executeAsynchPrepare( NoCommit , T5_Callback_1, td);
+ } else {
+ int result = pCON->execute( NoCommit );
+ T5_Callback_1(result, pCON, (void*)td);
+ return;
+ }//if
+}
+
+void
+T5_Callback_1(int result, NdbConnection * pCON, void * threadData){
+ ThreadData * td = (ThreadData *)threadData;
+ if (result == -1) {
+ CHECK_ALLOWED_ERROR("T5-1: execute", td, pCON->getNdbError());
+ td->pNDB->closeTransaction(pCON);
+ start_T5(td->pNDB, td, stat_async);
+ return;
+ }//if
+
+ DEBUG3("T5(%.*s, %.2d): - Callback 1",
+ SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id);
+
+ NdbOperation * MyOp = pCON->getNdbOperation(GROUP_TABLE);
+ CHECK_NULL(MyOp, "T5-2: getNdbOperation", td,
+ pCON->getNdbError());
+
+ MyOp->readTuple();
+ MyOp->equal(IND_GROUP_ID,
+ (char*)&td->transactionData.group_id);
+ MyOp->getValue(IND_GROUP_ALLOW_DELETE,
+ (char *)&td->transactionData.permission);
+ if (stat_async == 1) {
+ pCON->executeAsynchPrepare( NoCommit , T5_Callback_2, td);
+ } else {
+ int result = pCON->execute( NoCommit );
+ T5_Callback_2(result, pCON, (void*)td);
+ return;
+ }//if
+}
+
+void
+T5_Callback_2(int result, NdbConnection * pCON, void * threadData){
+ ThreadData * td = (ThreadData *)threadData;
+ if (result == -1) {
+ CHECK_ALLOWED_ERROR("T5-2: execute", td, pCON->getNdbError());
+ td->pNDB->closeTransaction(pCON);
+ start_T5(td->pNDB, td, stat_async);
+ return;
+ }//if
+
+ Uint32 permission = td->transactionData.permission;
+ Uint32 sessions = td->transactionData.sessions;
+ Uint32 server_bit = td->transactionData.server_bit;
+
+ if(((permission & server_bit) == server_bit) &&
+ ((sessions & server_bit) == server_bit)){
+
+ memcpy(td->transactionData.suffix,
+ &td->transactionData.number[SFX_START],
+ SUBSCRIBER_NUMBER_SUFFIX_LENGTH);
+
+ DEBUG5("T5(%.*s, %.2d): - Callback 2 - deleting(%.*s)",
+ SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id,
+ SUBSCRIBER_NUMBER_SUFFIX_LENGTH,
+ td->transactionData.suffix);
+
+ /* Operation 3 */
+ NdbOperation * MyOp = pCON->getNdbOperation(SESSION_TABLE);
+ CHECK_NULL(MyOp, "T5-3: getNdbOperation", td,
+ pCON->getNdbError());
+
+ MyOp->deleteTuple();
+ MyOp->equal(IND_SESSION_SUBSCRIBER,
+ (char*)td->transactionData.number);
+ MyOp->equal(IND_SESSION_SERVER,
+ (char*)&td->transactionData.server_id);
+ /* Operation 4 */
+
+ /* Operation 5 */
+ MyOp = pCON->getNdbOperation(SERVER_TABLE);
+ CHECK_NULL(MyOp, "T5-5: getNdbOperation", td,
+ pCON->getNdbError());
+
+ MyOp->interpretedUpdateTuple();
+ MyOp->equal(IND_SERVER_ID,
+ (char*)&td->transactionData.server_id);
+ MyOp->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
+ (char*)td->transactionData.suffix);
+ MyOp->incValue(IND_SERVER_DELETES, (uint32)1);
+ td->transactionData.branchExecuted = 1;
+ } else {
+ td->transactionData.branchExecuted = 0;
+
+ DEBUG5("T5(%.*s, %.2d): - Callback 2 - no delete - %s %s",
+ SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id,
+ ((permission & server_bit) ?
+ "permission - " : "no permission - "),
+ ((sessions & server_bit) ?
+ "in session - " : "no in session - "));
+ }
+
+ if(!td->transactionData.do_rollback && td->transactionData.branchExecuted){
+ if (stat_async == 1) {
+ pCON->executeAsynchPrepare( Commit , T5_Callback_3, td);
+ } else {
+ int result = pCON->execute( Commit );
+ T5_Callback_3(result, pCON, (void*)td);
+ return;
+ }//if
+ } else {
+ if (stat_async == 1) {
+ pCON->executeAsynchPrepare( Rollback , T5_Callback_3, td);
+ } else {
+ int result = pCON->execute( Rollback );
+ T5_Callback_3(result, pCON, (void*)td);
+ return;
+ }//if
+ }
+}
+
+void
+T5_Callback_3(int result, NdbConnection * pCON, void * threadData){
+ ThreadData * td = (ThreadData *)threadData;
+ if (result == -1) {
+ CHECK_ALLOWED_ERROR("T5-3: Commit", td, pCON->getNdbError());
+ td->pNDB->closeTransaction(pCON);
+ start_T5(td->pNDB, td, stat_async);
+ return;
+ }//if
+
+ DEBUG3("T5(%.*s, %.2d): - Completing",
+ SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number,
+ td->transactionData.server_id);
+
+ td->pNDB->closeTransaction(pCON);
+ complete_T5(td);
+}
diff --git a/ndb/test/ndbapi/bench/ndb_error.hpp b/ndb/test/ndbapi/bench/ndb_error.hpp
new file mode 100644
index 00000000000..d90f5506813
--- /dev/null
+++ b/ndb/test/ndbapi/bench/ndb_error.hpp
@@ -0,0 +1,81 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef NDB_ERROR_H
+#define NDB_ERROR_H
+
+#include <ndb_global.h>
+#include <NdbOut.hpp>
+#include "userInterface.h"
+#include <NdbError.hpp>
+#include <NdbApi.hpp>
+
+#define error_handler(x,y, z) { \
+ ndbout << x << " " << y << endl; \
+ exit(-1); }
+
+#define CHECK_MINUS_ONE(x, y, z) if(x == -1) \
+ error_handler(y,(z->getNdbError()), 0)
+
+inline
+void
+CHECK_ALLOWED_ERROR(const char * str,
+ const ThreadData * td,
+ const struct NdbError & error){
+
+ char buf[100];
+ snprintf(buf, sizeof(buf), "subscriber = %.*s ",
+ SUBSCRIBER_NUMBER_LENGTH,
+ td->transactionData.number);
+ ndbout << str << " " << error << endl
+ << buf;
+ showTime();
+
+ switch(error.classification) {
+ case NdbError::TimeoutExpired:
+ case NdbError::OverloadError:
+ case NdbError::TemporaryResourceError:
+ case NdbError::NodeRecoveryError:
+ break;
+ default:
+ if(error.status != NdbError::TemporaryError)
+ exit(-1);
+ }
+}
+
+inline
+void
+CHECK_NULL(void * null,
+ const char * str,
+ const ThreadData * td,
+ const struct NdbError & err){
+ if(null == 0){
+ CHECK_ALLOWED_ERROR(str, td, err);
+ exit(-1);
+ }
+}
+
+inline
+void
+CHECK_NULL(void * null, const char* msg, NdbConnection* obj)
+{
+ if(null == 0)
+ {
+ error_handler(msg, obj->getNdbError(), 0);
+ }
+}
+
+#endif
diff --git a/ndb/test/ndbapi/bench/ndb_schema.hpp b/ndb/test/ndbapi/bench/ndb_schema.hpp
new file mode 100644
index 00000000000..af08bc2eecd
--- /dev/null
+++ b/ndb/test/ndbapi/bench/ndb_schema.hpp
@@ -0,0 +1,78 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef NDB_SCHEMA_H
+#define NDB_SCHEMA_H
+
+#include "testDefinitions.h"
+
+#define SUBSCRIBER_TABLE "SUBSCRIBER"
+#define SUBSCRIBER_NUMBER "NUMBER"
+#define SUBSCRIBER_LOCATION "LOCATION"
+#define SUBSCRIBER_NAME "NAME"
+#define SUBSCRIBER_GROUP "GROUP_ID"
+#define SUBSCRIBER_SESSIONS "SESSIONS"
+#define SUBSCRIBER_CHANGED_BY "CHANGED_BY"
+#define SUBSCRIBER_CHANGED_TIME "CHANGED_TIME"
+
+#define SERVER_TABLE "SERVER"
+#define SERVER_ID "SERVER_ID"
+#define SERVER_SUBSCRIBER_SUFFIX "SUFFIX"
+#define SERVER_NAME "NAME"
+#define SERVER_READS "NO_OF_READ"
+#define SERVER_INSERTS "NO_OF_INSERT"
+#define SERVER_DELETES "NO_OF_DELETE"
+
+#define GROUP_TABLE "GROUP"
+#define GROUP_ID "GROUP_ID"
+#define GROUP_NAME "GROUP_NAME"
+#define GROUP_ALLOW_READ "ALLOW_READ"
+#define GROUP_ALLOW_INSERT "ALLOW_INSERT"
+#define GROUP_ALLOW_DELETE "ALLOW_DELETE"
+
+#define SESSION_TABLE "SESSION"
+#define SESSION_SERVER "SERVER_ID"
+#define SESSION_SUBSCRIBER "NUMBER"
+#define SESSION_DATA "DATA"
+
+/** Numbers */
+
+#define IND_SUBSCRIBER_NUMBER (unsigned)0
+#define IND_SUBSCRIBER_NAME (unsigned)1
+#define IND_SUBSCRIBER_GROUP (unsigned)2
+#define IND_SUBSCRIBER_LOCATION (unsigned)3
+#define IND_SUBSCRIBER_SESSIONS (unsigned)4
+#define IND_SUBSCRIBER_CHANGED_BY (unsigned)5
+#define IND_SUBSCRIBER_CHANGED_TIME (unsigned)6
+
+#define IND_SERVER_SUBSCRIBER_SUFFIX (unsigned)0
+#define IND_SERVER_ID (unsigned)1
+#define IND_SERVER_NAME (unsigned)2
+#define IND_SERVER_READS (unsigned)3
+#define IND_SERVER_INSERTS (unsigned)4
+#define IND_SERVER_DELETES (unsigned)5
+
+#define IND_GROUP_ID (unsigned)0
+#define IND_GROUP_NAME (unsigned)1
+#define IND_GROUP_ALLOW_READ (unsigned)2
+#define IND_GROUP_ALLOW_INSERT (unsigned)3
+#define IND_GROUP_ALLOW_DELETE (unsigned)4
+
+#define IND_SESSION_SUBSCRIBER (unsigned)0
+#define IND_SESSION_SERVER (unsigned)1
+#define IND_SESSION_DATA (unsigned)2
+
+#endif
diff --git a/ndb/test/ndbapi/bench/ndb_user_transaction.cpp b/ndb/test/ndbapi/bench/ndb_user_transaction.cpp
new file mode 100644
index 00000000000..182f1f99586
--- /dev/null
+++ b/ndb/test/ndbapi/bench/ndb_user_transaction.cpp
@@ -0,0 +1,825 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+//#define DEBUG_ON
+
+extern "C" {
+#include "user_transaction.h"
+};
+
+#include "macros.h"
+#include "ndb_schema.hpp"
+#include "ndb_error.hpp"
+
+#include <time.h>
+#include <NdbApi.hpp>
+
+/**
+ * Transaction 1 - T1
+ *
+ * Update location and changed by/time on a subscriber
+ *
+ * Input:
+ * SubscriberNumber,
+ * Location,
+ * ChangedBy,
+ * ChangedTime
+ *
+ * Output:
+ */
+int
+T1(void * obj,
+ const SubscriberNumber number,
+ const Location new_location,
+ const ChangedBy changed_by,
+ const ChangedTime changed_time,
+ BenchmarkTime * transaction_time){
+
+ Ndb * pNDB = (Ndb *) obj;
+
+ BenchmarkTime start;
+ get_time(&start);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T1: startTranscation", pNDB->getNdbErrorString(), 0);
+
+ NdbOperation *MyOperation = MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T1: getNdbOperation", MyTransaction);
+
+ check = MyOperation->updateTuple();
+ CHECK_MINUS_ONE(check, "T1: updateTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(SUBSCRIBER_NUMBER,
+ number);
+ CHECK_MINUS_ONE(check, "T1: equal subscriber",
+ MyTransaction);
+
+ check = MyOperation->setValue(SUBSCRIBER_LOCATION,
+ (char *)&new_location);
+ CHECK_MINUS_ONE(check, "T1: setValue location",
+ MyTransaction);
+
+ check = MyOperation->setValue(SUBSCRIBER_CHANGED_BY,
+ changed_by);
+ CHECK_MINUS_ONE(check, "T1: setValue changed_by",
+ MyTransaction);
+
+ check = MyOperation->setValue(SUBSCRIBER_CHANGED_TIME,
+ changed_time);
+ CHECK_MINUS_ONE(check, "T1: setValue changed_time",
+ MyTransaction);
+
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T1: Commit",
+ MyTransaction);
+
+ pNDB->closeTransaction(MyTransaction);
+
+ get_time(transaction_time);
+ time_diff(transaction_time, &start);
+ return 0;
+}
+
+/**
+ * Transaction 2 - T2
+ *
+ * Read from Subscriber:
+ *
+ * Input:
+ * SubscriberNumber
+ *
+ * Output:
+ * Location
+ * Changed by
+ * Changed Timestamp
+ * Name
+ */
+int
+T2(void * obj,
+ const SubscriberNumber number,
+ Location * readLocation,
+ ChangedBy changed_by,
+ ChangedTime changed_time,
+ SubscriberName subscriberName,
+ BenchmarkTime * transaction_time){
+
+ Ndb * pNDB = (Ndb *) obj;
+
+ BenchmarkTime start;
+ get_time(&start);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T2: startTranscation", pNDB->getNdbErrorString(), 0);
+
+ NdbOperation *MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T2: getNdbOperation",
+ MyTransaction);
+
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T2: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(SUBSCRIBER_NUMBER,
+ number);
+ CHECK_MINUS_ONE(check, "T2: equal subscriber",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(SUBSCRIBER_LOCATION,
+ (char *)readLocation);
+ CHECK_NULL(check2, "T2: getValue location",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(SUBSCRIBER_CHANGED_BY,
+ changed_by);
+ CHECK_NULL(check2, "T2: getValue changed_by",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(SUBSCRIBER_CHANGED_TIME,
+ changed_time);
+ CHECK_NULL(check2, "T2: getValue changed_time",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(SUBSCRIBER_NAME,
+ subscriberName);
+ CHECK_NULL(check2, "T2: getValue name",
+ MyTransaction);
+
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T2: Commit",
+ MyTransaction);
+
+ pNDB->closeTransaction(MyTransaction);
+
+ get_time(transaction_time);
+ time_diff(transaction_time, &start);
+ return 0;
+}
+
+/**
+ * Transaction 3 - T3
+ *
+ * Read session details
+ *
+ * Input:
+ * SubscriberNumber
+ * ServerId
+ * ServerBit
+ *
+ * Output:
+ * BranchExecuted
+ * SessionDetails
+ * ChangedBy
+ * ChangedTime
+ * Location
+ */
+int
+T3(void * obj,
+ const SubscriberNumber inNumber,
+ const SubscriberSuffix inSuffix,
+ const ServerId inServerId,
+ const ServerBit inServerBit,
+ SessionDetails outSessionDetails,
+ ChangedBy outChangedBy,
+ ChangedTime outChangedTime,
+ Location * outLocation,
+ BranchExecuted * outBranchExecuted,
+ BenchmarkTime * outTransactionTime){
+
+ Ndb * pNDB = (Ndb *) obj;
+
+ GroupId groupId;
+ ActiveSessions sessions;
+ Permission permission;
+
+ BenchmarkTime start;
+ get_time(&start);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T3-1: startTranscation", pNDB->getNdbErrorString(), 0);
+
+ NdbOperation *MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T3-1: getNdbOperation",
+ MyTransaction);
+
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T3-1: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(SUBSCRIBER_NUMBER,
+ inNumber);
+ CHECK_MINUS_ONE(check, "T3-1: equal subscriber",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(SUBSCRIBER_LOCATION,
+ (char *)outLocation);
+ CHECK_NULL(check2, "T3-1: getValue location",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(SUBSCRIBER_CHANGED_BY,
+ outChangedBy);
+ CHECK_NULL(check2, "T3-1: getValue changed_by",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(SUBSCRIBER_CHANGED_TIME,
+ outChangedTime);
+ CHECK_NULL(check2, "T3-1: getValue changed_time",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(SUBSCRIBER_GROUP,
+ (char *)&groupId);
+ CHECK_NULL(check2, "T3-1: getValue group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(SUBSCRIBER_SESSIONS,
+ (char *)&sessions);
+ CHECK_NULL(check2, "T3-1: getValue sessions",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T3-1: NoCommit",
+ MyTransaction);
+
+ /* Operation 2 */
+
+ MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
+ CHECK_NULL(MyOperation, "T3-2: getNdbOperation",
+ MyTransaction);
+
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T3-2: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(GROUP_ID,
+ (char*)&groupId);
+ CHECK_MINUS_ONE(check, "T3-2: equal group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(GROUP_ALLOW_READ,
+ (char *)&permission);
+ CHECK_NULL(check2, "T3-2: getValue allow_read",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T3-2: NoCommit",
+ MyTransaction);
+
+ DEBUG3("T3(%.*s, %.2d): ", SUBSCRIBER_NUMBER_LENGTH, inNumber, inServerId);
+
+ if(((permission & inServerBit) == inServerBit) &&
+ ((sessions & inServerBit) == inServerBit)){
+
+ DEBUG("reading - ");
+
+ /* Operation 3 */
+
+ MyOperation = MyTransaction->getNdbOperation(SESSION_TABLE);
+ CHECK_NULL(MyOperation, "T3-3: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T3-3: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(SESSION_SUBSCRIBER,
+ (char*)inNumber);
+ CHECK_MINUS_ONE(check, "T3-3: equal number",
+ MyTransaction);
+
+ check = MyOperation->equal(SESSION_SERVER,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T3-3: equal server id",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(SESSION_DATA,
+ (char *)outSessionDetails);
+ CHECK_NULL(check2, "T3-3: getValue session details",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T3-3: NoCommit",
+ MyTransaction);
+
+ /* Operation 4 */
+
+ MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
+ CHECK_NULL(MyOperation, "T3-4: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->interpretedUpdateTuple();
+ CHECK_MINUS_ONE(check, "T3-4: interpretedUpdateTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(SERVER_ID,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T3-4: equal serverId",
+ MyTransaction);
+
+ check = MyOperation->equal(SERVER_SUBSCRIBER_SUFFIX,
+ (char*)inSuffix);
+ CHECK_MINUS_ONE(check, "T3-4: equal suffix",
+ MyTransaction);
+
+ check = MyOperation->incValue(SERVER_READS, (uint32)1);
+ CHECK_MINUS_ONE(check, "T3-4: inc value",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T3-4: NoCommit",
+ MyTransaction);
+
+ (* outBranchExecuted) = 1;
+ } else {
+ (* outBranchExecuted) = 0;
+ }
+ DEBUG("commit\n");
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T3: Commit",
+ MyTransaction);
+
+ pNDB->closeTransaction(MyTransaction);
+
+ get_time(outTransactionTime);
+ time_diff(outTransactionTime, &start);
+ return 0;
+}
+
+
+/**
+ * Transaction 4 - T4
+ *
+ * Create session
+ *
+ * Input:
+ * SubscriberNumber
+ * ServerId
+ * ServerBit
+ * SessionDetails,
+ * DoRollback
+ * Output:
+ * ChangedBy
+ * ChangedTime
+ * Location
+ * BranchExecuted
+ */
+int
+T4(void * obj,
+ const SubscriberNumber inNumber,
+ const SubscriberSuffix inSuffix,
+ const ServerId inServerId,
+ const ServerBit inServerBit,
+ const SessionDetails inSessionDetails,
+ ChangedBy outChangedBy,
+ ChangedTime outChangedTime,
+ Location * outLocation,
+ DoRollback inDoRollback,
+ BranchExecuted * outBranchExecuted,
+ BenchmarkTime * outTransactionTime){
+
+ Ndb * pNDB = (Ndb *) obj;
+
+ GroupId groupId;
+ ActiveSessions sessions;
+ Permission permission;
+
+ BenchmarkTime start;
+ get_time(&start);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T4-1: startTranscation", pNDB->getNdbErrorString(), 0);
+
+ DEBUG3("T4(%.*s, %.2d): ", SUBSCRIBER_NUMBER_LENGTH, inNumber, inServerId);
+
+ NdbOperation * MyOperation = 0;
+
+ MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T4-1: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->readTupleExclusive();
+ CHECK_MINUS_ONE(check, "T4-1: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(SUBSCRIBER_NUMBER,
+ inNumber);
+ CHECK_MINUS_ONE(check, "T4-1: equal subscriber",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(SUBSCRIBER_LOCATION,
+ (char *)outLocation);
+ CHECK_NULL(check2, "T4-1: getValue location",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(SUBSCRIBER_CHANGED_BY,
+ outChangedBy);
+ CHECK_NULL(check2, "T4-1: getValue changed_by",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(SUBSCRIBER_CHANGED_TIME,
+ outChangedTime);
+ CHECK_NULL(check2, "T4-1: getValue changed_time",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(SUBSCRIBER_GROUP,
+ (char *)&groupId);
+ CHECK_NULL(check2, "T4-1: getValue group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(SUBSCRIBER_SESSIONS,
+ (char *)&sessions);
+ CHECK_NULL(check2, "T4-1: getValue sessions",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T4-1: NoCommit",
+ MyTransaction);
+
+ /* Operation 2 */
+ MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
+ CHECK_NULL(MyOperation, "T4-2: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T4-2: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(GROUP_ID,
+ (char*)&groupId);
+ CHECK_MINUS_ONE(check, "T4-2: equal group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(GROUP_ALLOW_INSERT,
+ (char *)&permission);
+ CHECK_NULL(check2, "T4-2: getValue allow_insert",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T4-2: NoCommit",
+ MyTransaction);
+
+ if(((permission & inServerBit) == inServerBit) &&
+ ((sessions & inServerBit) == 0)){
+
+ DEBUG("inserting - ");
+
+ /* Operation 3 */
+ MyOperation = MyTransaction->getNdbOperation(SESSION_TABLE);
+ CHECK_NULL(MyOperation, "T4-3: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->insertTuple();
+ CHECK_MINUS_ONE(check, "T4-3: insertTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(SESSION_SUBSCRIBER,
+ (char*)inNumber);
+ CHECK_MINUS_ONE(check, "T4-3: equal number",
+ MyTransaction);
+
+ check = MyOperation->equal(SESSION_SERVER,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T4-3: equal server id",
+ MyTransaction);
+
+ check = MyOperation->setValue(SESSION_DATA,
+ (char *)inSessionDetails);
+ CHECK_MINUS_ONE(check, "T4-3: setValue session details",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T4-3: NoCommit",
+ MyTransaction);
+
+ /* Operation 4 */
+ MyOperation = MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T4-4: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->interpretedUpdateTuple();
+ CHECK_MINUS_ONE(check, "T4-4: interpretedUpdateTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(SUBSCRIBER_NUMBER,
+ (char*)inNumber);
+ CHECK_MINUS_ONE(check, "T4-4: equal number",
+ MyTransaction);
+
+ check = MyOperation->incValue(SUBSCRIBER_SESSIONS,
+ (uint32)inServerBit);
+ CHECK_MINUS_ONE(check, "T4-4: inc value",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T4-4: NoCommit",
+ MyTransaction);
+
+ /* Operation 5 */
+ MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
+ CHECK_NULL(MyOperation, "T4-5: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->interpretedUpdateTuple();
+ CHECK_MINUS_ONE(check, "T4-5: interpretedUpdateTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(SERVER_ID,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T4-5: equal serverId",
+ MyTransaction);
+
+ check = MyOperation->equal(SERVER_SUBSCRIBER_SUFFIX,
+ (char*)inSuffix);
+ CHECK_MINUS_ONE(check, "T4-5: equal suffix",
+ MyTransaction);
+
+ check = MyOperation->incValue(SERVER_INSERTS, (uint32)1);
+ CHECK_MINUS_ONE(check, "T4-5: inc value",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T4-5: NoCommit",
+ MyTransaction);
+
+ (* outBranchExecuted) = 1;
+ } else {
+ DEBUG1("%s", ((permission & inServerBit) ? "permission - " : "no permission - "));
+ DEBUG1("%s", ((sessions & inServerBit) ? "in session - " : "no in session - "));
+ (* outBranchExecuted) = 0;
+ }
+
+ if(!inDoRollback){
+ DEBUG("commit\n");
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T4: Commit",
+ MyTransaction);
+ } else {
+ DEBUG("rollback\n");
+ check = MyTransaction->execute(Rollback);
+ CHECK_MINUS_ONE(check, "T4:Rollback",
+ MyTransaction);
+
+ }
+
+ pNDB->closeTransaction(MyTransaction);
+
+ get_time(outTransactionTime);
+ time_diff(outTransactionTime, &start);
+ return 0;
+}
+
+
+/**
+ * Transaction 5 - T5
+ *
+ * Delete session
+ *
+ * Input:
+ * SubscriberNumber
+ * ServerId
+ * ServerBit
+ * DoRollback
+ * Output:
+ * ChangedBy
+ * ChangedTime
+ * Location
+ * BranchExecuted
+ */
+int
+T5(void * obj,
+ const SubscriberNumber inNumber,
+ const SubscriberSuffix inSuffix,
+ const ServerId inServerId,
+ const ServerBit inServerBit,
+ ChangedBy outChangedBy,
+ ChangedTime outChangedTime,
+ Location * outLocation,
+ DoRollback inDoRollback,
+ BranchExecuted * outBranchExecuted,
+ BenchmarkTime * outTransactionTime){
+
+ Ndb * pNDB = (Ndb *) obj;
+ NdbConnection * MyTransaction = 0;
+ NdbOperation * MyOperation = 0;
+
+ GroupId groupId;
+ ActiveSessions sessions;
+ Permission permission;
+
+ BenchmarkTime start;
+ get_time(&start);
+
+ int check;
+ NdbRecAttr * check2;
+
+ MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T5-1: startTranscation", pNDB->getNdbErrorString(), 0);
+
+ MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T5-1: getNdbOperation",
+ MyTransaction);
+
+
+ check = MyOperation->readTupleExclusive();
+ CHECK_MINUS_ONE(check, "T5-1: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(SUBSCRIBER_NUMBER,
+ inNumber);
+ CHECK_MINUS_ONE(check, "T5-1: equal subscriber",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(SUBSCRIBER_LOCATION,
+ (char *)outLocation);
+ CHECK_NULL(check2, "T5-1: getValue location",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(SUBSCRIBER_CHANGED_BY,
+ outChangedBy);
+ CHECK_NULL(check2, "T5-1: getValue changed_by",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(SUBSCRIBER_CHANGED_TIME,
+ outChangedTime);
+ CHECK_NULL(check2, "T5-1: getValue changed_time",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(SUBSCRIBER_GROUP,
+ (char *)&groupId);
+ CHECK_NULL(check2, "T5-1: getValue group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(SUBSCRIBER_SESSIONS,
+ (char *)&sessions);
+ CHECK_NULL(check2, "T5-1: getValue sessions",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T5-1: NoCommit",
+ MyTransaction);
+
+ /* Operation 2 */
+
+ MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
+ CHECK_NULL(MyOperation, "T5-2: getNdbOperation",
+ MyTransaction);
+
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T5-2: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(GROUP_ID,
+ (char*)&groupId);
+ CHECK_MINUS_ONE(check, "T5-2: equal group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(GROUP_ALLOW_DELETE,
+ (char *)&permission);
+ CHECK_NULL(check2, "T5-2: getValue allow_delete",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T5-2: NoCommit",
+ MyTransaction);
+
+ DEBUG3("T5(%.*s, %.2d): ", SUBSCRIBER_NUMBER_LENGTH, inNumber, inServerId);
+
+ if(((permission & inServerBit) == inServerBit) &&
+ ((sessions & inServerBit) == inServerBit)){
+
+ DEBUG("deleting - ");
+
+ /* Operation 3 */
+ MyOperation = MyTransaction->getNdbOperation(SESSION_TABLE);
+ CHECK_NULL(MyOperation, "T5-3: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->deleteTuple();
+ CHECK_MINUS_ONE(check, "T5-3: deleteTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(SESSION_SUBSCRIBER,
+ (char*)inNumber);
+ CHECK_MINUS_ONE(check, "T5-3: equal number",
+ MyTransaction);
+
+ check = MyOperation->equal(SESSION_SERVER,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T5-3: equal server id",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T5-3: NoCommit",
+ MyTransaction);
+
+ /* Operation 4 */
+ MyOperation = MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T5-4: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->interpretedUpdateTuple();
+ CHECK_MINUS_ONE(check, "T5-4: interpretedUpdateTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(SUBSCRIBER_NUMBER,
+ (char*)inNumber);
+ CHECK_MINUS_ONE(check, "T5-4: equal number",
+ MyTransaction);
+
+ check = MyOperation->subValue(SUBSCRIBER_SESSIONS,
+ (uint32)inServerBit);
+ CHECK_MINUS_ONE(check, "T5-4: dec value",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T5-4: NoCommit",
+ MyTransaction);
+
+ /* Operation 5 */
+ MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
+ CHECK_NULL(MyOperation, "T5-5: getNdbOperation",
+ MyTransaction);
+
+
+ check = MyOperation->interpretedUpdateTuple();
+ CHECK_MINUS_ONE(check, "T5-5: interpretedUpdateTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(SERVER_ID,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T5-5: equal serverId",
+ MyTransaction);
+
+ check = MyOperation->equal(SERVER_SUBSCRIBER_SUFFIX,
+ (char*)inSuffix);
+ CHECK_MINUS_ONE(check, "T5-5: equal suffix",
+ MyTransaction);
+
+ check = MyOperation->incValue(SERVER_DELETES, (uint32)1);
+ CHECK_MINUS_ONE(check, "T5-5: inc value",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T5-5: NoCommit",
+ MyTransaction);
+
+ (* outBranchExecuted) = 1;
+ } else {
+ DEBUG1("%s", ((permission & inServerBit) ? "permission - " : "no permission - "));
+ DEBUG1("%s", ((sessions & inServerBit) ? "in session - " : "no in session - "));
+ (* outBranchExecuted) = 0;
+ }
+
+ if(!inDoRollback){
+ DEBUG("commit\n");
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T5: Commit",
+ MyTransaction);
+ } else {
+ DEBUG("rollback\n");
+ check = MyTransaction->execute(Rollback);
+ CHECK_MINUS_ONE(check, "T5:Rollback",
+ MyTransaction);
+
+ }
+
+ pNDB->closeTransaction(MyTransaction);
+
+ get_time(outTransactionTime);
+ time_diff(outTransactionTime, &start);
+ return 0;
+}
+
diff --git a/ndb/test/ndbapi/bench/ndb_user_transaction2.cpp b/ndb/test/ndbapi/bench/ndb_user_transaction2.cpp
new file mode 100644
index 00000000000..df3c7a7989e
--- /dev/null
+++ b/ndb/test/ndbapi/bench/ndb_user_transaction2.cpp
@@ -0,0 +1,825 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+//#define DEBUG_ON
+
+extern "C" {
+#include "user_transaction.h"
+};
+
+#include "macros.h"
+#include "ndb_schema.hpp"
+#include "ndb_error.hpp"
+
+#include <time.h>
+#include <NdbApi.hpp>
+
+/**
+ * Transaction 1 - T1
+ *
+ * Update location and changed by/time on a subscriber
+ *
+ * Input:
+ * SubscriberNumber,
+ * Location,
+ * ChangedBy,
+ * ChangedTime
+ *
+ * Output:
+ */
+int
+T1(void * obj,
+ const SubscriberNumber number,
+ const Location new_location,
+ const ChangedBy changed_by,
+ const ChangedTime changed_time,
+ BenchmarkTime * transaction_time){
+
+ Ndb * pNDB = (Ndb *) obj;
+
+ BenchmarkTime start;
+ get_time(&start);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T1: startTranscation", pNDB->getNdbErrorString(), 0);
+
+ NdbOperation *MyOperation = MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T1: getNdbOperation", MyTransaction);
+
+ check = MyOperation->updateTuple();
+ CHECK_MINUS_ONE(check, "T1: updateTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ number);
+ CHECK_MINUS_ONE(check, "T1: equal subscriber",
+ MyTransaction);
+
+ check = MyOperation->setValue(IND_SUBSCRIBER_LOCATION,
+ (char *)&new_location);
+ CHECK_MINUS_ONE(check, "T1: setValue location",
+ MyTransaction);
+
+ check = MyOperation->setValue(IND_SUBSCRIBER_CHANGED_BY,
+ changed_by);
+ CHECK_MINUS_ONE(check, "T1: setValue changed_by",
+ MyTransaction);
+
+ check = MyOperation->setValue(IND_SUBSCRIBER_CHANGED_TIME,
+ changed_time);
+ CHECK_MINUS_ONE(check, "T1: setValue changed_time",
+ MyTransaction);
+
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T1: Commit",
+ MyTransaction);
+
+ pNDB->closeTransaction(MyTransaction);
+
+ get_time(transaction_time);
+ time_diff(transaction_time, &start);
+ return 0;
+}
+
+/**
+ * Transaction 2 - T2
+ *
+ * Read from Subscriber:
+ *
+ * Input:
+ * SubscriberNumber
+ *
+ * Output:
+ * Location
+ * Changed by
+ * Changed Timestamp
+ * Name
+ */
+int
+T2(void * obj,
+ const SubscriberNumber number,
+ Location * readLocation,
+ ChangedBy changed_by,
+ ChangedTime changed_time,
+ SubscriberName subscriberName,
+ BenchmarkTime * transaction_time){
+
+ Ndb * pNDB = (Ndb *) obj;
+
+ BenchmarkTime start;
+ get_time(&start);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T2: startTranscation", pNDB->getNdbErrorString(), 0);
+
+ NdbOperation *MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T2: getNdbOperation",
+ MyTransaction);
+
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T2: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ number);
+ CHECK_MINUS_ONE(check, "T2: equal subscriber",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)readLocation);
+ CHECK_NULL(check2, "T2: getValue location",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ changed_by);
+ CHECK_NULL(check2, "T2: getValue changed_by",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ changed_time);
+ CHECK_NULL(check2, "T2: getValue changed_time",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_NAME,
+ subscriberName);
+ CHECK_NULL(check2, "T2: getValue name",
+ MyTransaction);
+
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T2: Commit",
+ MyTransaction);
+
+ pNDB->closeTransaction(MyTransaction);
+
+ get_time(transaction_time);
+ time_diff(transaction_time, &start);
+ return 0;
+}
+
+/**
+ * Transaction 3 - T3
+ *
+ * Read session details
+ *
+ * Input:
+ * SubscriberNumber
+ * ServerId
+ * ServerBit
+ *
+ * Output:
+ * BranchExecuted
+ * SessionDetails
+ * ChangedBy
+ * ChangedTime
+ * Location
+ */
+int
+T3(void * obj,
+ const SubscriberNumber inNumber,
+ const SubscriberSuffix inSuffix,
+ const ServerId inServerId,
+ const ServerBit inServerBit,
+ SessionDetails outSessionDetails,
+ ChangedBy outChangedBy,
+ ChangedTime outChangedTime,
+ Location * outLocation,
+ BranchExecuted * outBranchExecuted,
+ BenchmarkTime * outTransactionTime){
+
+ Ndb * pNDB = (Ndb *) obj;
+
+ GroupId groupId;
+ ActiveSessions sessions;
+ Permission permission;
+
+ BenchmarkTime start;
+ get_time(&start);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T3-1: startTranscation", pNDB->getNdbErrorString(), 0);
+
+ NdbOperation *MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T3-1: getNdbOperation",
+ MyTransaction);
+
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T3-1: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ inNumber);
+ CHECK_MINUS_ONE(check, "T3-1: equal subscriber",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)outLocation);
+ CHECK_NULL(check2, "T3-1: getValue location",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ outChangedBy);
+ CHECK_NULL(check2, "T3-1: getValue changed_by",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ outChangedTime);
+ CHECK_NULL(check2, "T3-1: getValue changed_time",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_GROUP,
+ (char *)&groupId);
+ CHECK_NULL(check2, "T3-1: getValue group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_SESSIONS,
+ (char *)&sessions);
+ CHECK_NULL(check2, "T3-1: getValue sessions",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T3-1: NoCommit",
+ MyTransaction);
+
+ /* Operation 2 */
+
+ MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
+ CHECK_NULL(MyOperation, "T3-2: getNdbOperation",
+ MyTransaction);
+
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T3-2: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_GROUP_ID,
+ (char*)&groupId);
+ CHECK_MINUS_ONE(check, "T3-2: equal group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_GROUP_ALLOW_READ,
+ (char *)&permission);
+ CHECK_NULL(check2, "T3-2: getValue allow_read",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T3-2: NoCommit",
+ MyTransaction);
+
+ DEBUG3("T3(%.*s, %.2d): ", SUBSCRIBER_NUMBER_LENGTH, inNumber, inServerId);
+
+ if(((permission & inServerBit) == inServerBit) &&
+ ((sessions & inServerBit) == inServerBit)){
+
+ DEBUG("reading - ");
+
+ /* Operation 3 */
+
+ MyOperation = MyTransaction->getNdbOperation(SESSION_TABLE);
+ CHECK_NULL(MyOperation, "T3-3: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T3-3: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SESSION_SUBSCRIBER,
+ (char*)inNumber);
+ CHECK_MINUS_ONE(check, "T3-3: equal number",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SESSION_SERVER,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T3-3: equal server id",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SESSION_DATA,
+ (char *)outSessionDetails);
+ CHECK_NULL(check2, "T3-3: getValue session details",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T3-3: NoCommit",
+ MyTransaction);
+
+ /* Operation 4 */
+
+ MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
+ CHECK_NULL(MyOperation, "T3-4: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->interpretedUpdateTuple();
+ CHECK_MINUS_ONE(check, "T3-4: interpretedUpdateTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SERVER_ID,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T3-4: equal serverId",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
+ (char*)inSuffix);
+ CHECK_MINUS_ONE(check, "T3-4: equal suffix",
+ MyTransaction);
+
+ check = MyOperation->incValue(IND_SERVER_READS, (uint32)1);
+ CHECK_MINUS_ONE(check, "T3-4: inc value",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T3-4: NoCommit",
+ MyTransaction);
+
+ (* outBranchExecuted) = 1;
+ } else {
+ (* outBranchExecuted) = 0;
+ }
+ DEBUG("commit\n");
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T3: Commit",
+ MyTransaction);
+
+ pNDB->closeTransaction(MyTransaction);
+
+ get_time(outTransactionTime);
+ time_diff(outTransactionTime, &start);
+ return 0;
+}
+
+
+/**
+ * Transaction 4 - T4
+ *
+ * Create session
+ *
+ * Input:
+ * SubscriberNumber
+ * ServerId
+ * ServerBit
+ * SessionDetails,
+ * DoRollback
+ * Output:
+ * ChangedBy
+ * ChangedTime
+ * Location
+ * BranchExecuted
+ */
+int
+T4(void * obj,
+ const SubscriberNumber inNumber,
+ const SubscriberSuffix inSuffix,
+ const ServerId inServerId,
+ const ServerBit inServerBit,
+ const SessionDetails inSessionDetails,
+ ChangedBy outChangedBy,
+ ChangedTime outChangedTime,
+ Location * outLocation,
+ DoRollback inDoRollback,
+ BranchExecuted * outBranchExecuted,
+ BenchmarkTime * outTransactionTime){
+
+ Ndb * pNDB = (Ndb *) obj;
+
+ GroupId groupId;
+ ActiveSessions sessions;
+ Permission permission;
+
+ BenchmarkTime start;
+ get_time(&start);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T4-1: startTranscation", pNDB->getNdbErrorString(), 0);
+
+ DEBUG3("T4(%.*s, %.2d): ", SUBSCRIBER_NUMBER_LENGTH, inNumber, inServerId);
+
+ NdbOperation * MyOperation = 0;
+
+ MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T4-1: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->readTupleExclusive();
+ CHECK_MINUS_ONE(check, "T4-1: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ inNumber);
+ CHECK_MINUS_ONE(check, "T4-1: equal subscriber",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)outLocation);
+ CHECK_NULL(check2, "T4-1: getValue location",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ outChangedBy);
+ CHECK_NULL(check2, "T4-1: getValue changed_by",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ outChangedTime);
+ CHECK_NULL(check2, "T4-1: getValue changed_time",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_GROUP,
+ (char *)&groupId);
+ CHECK_NULL(check2, "T4-1: getValue group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_SESSIONS,
+ (char *)&sessions);
+ CHECK_NULL(check2, "T4-1: getValue sessions",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T4-1: NoCommit",
+ MyTransaction);
+
+ /* Operation 2 */
+ MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
+ CHECK_NULL(MyOperation, "T4-2: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T4-2: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_GROUP_ID,
+ (char*)&groupId);
+ CHECK_MINUS_ONE(check, "T4-2: equal group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_GROUP_ALLOW_INSERT,
+ (char *)&permission);
+ CHECK_NULL(check2, "T4-2: getValue allow_insert",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T4-2: NoCommit",
+ MyTransaction);
+
+ if(((permission & inServerBit) == inServerBit) &&
+ ((sessions & inServerBit) == 0)){
+
+ DEBUG("inserting - ");
+
+ /* Operation 3 */
+ MyOperation = MyTransaction->getNdbOperation(SESSION_TABLE);
+ CHECK_NULL(MyOperation, "T4-3: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->insertTuple();
+ CHECK_MINUS_ONE(check, "T4-3: insertTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SESSION_SUBSCRIBER,
+ (char*)inNumber);
+ CHECK_MINUS_ONE(check, "T4-3: equal number",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SESSION_SERVER,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T4-3: equal server id",
+ MyTransaction);
+
+ check = MyOperation->setValue(SESSION_DATA,
+ (char *)inSessionDetails);
+ CHECK_MINUS_ONE(check, "T4-3: setValue session details",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T4-3: NoCommit",
+ MyTransaction);
+
+ /* Operation 4 */
+ MyOperation = MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T4-4: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->interpretedUpdateTuple();
+ CHECK_MINUS_ONE(check, "T4-4: interpretedUpdateTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ (char*)inNumber);
+ CHECK_MINUS_ONE(check, "T4-4: equal number",
+ MyTransaction);
+
+ check = MyOperation->incValue(IND_SUBSCRIBER_SESSIONS,
+ (uint32)inServerBit);
+ CHECK_MINUS_ONE(check, "T4-4: inc value",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T4-4: NoCommit",
+ MyTransaction);
+
+ /* Operation 5 */
+ MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
+ CHECK_NULL(MyOperation, "T4-5: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->interpretedUpdateTuple();
+ CHECK_MINUS_ONE(check, "T4-5: interpretedUpdateTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SERVER_ID,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T4-5: equal serverId",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
+ (char*)inSuffix);
+ CHECK_MINUS_ONE(check, "T4-5: equal suffix",
+ MyTransaction);
+
+ check = MyOperation->incValue(IND_SERVER_INSERTS, (uint32)1);
+ CHECK_MINUS_ONE(check, "T4-5: inc value",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T4-5: NoCommit",
+ MyTransaction);
+
+ (* outBranchExecuted) = 1;
+ } else {
+ DEBUG1("%s", ((permission & inServerBit) ? "permission - " : "no permission - "));
+ DEBUG1("%s", ((sessions & inServerBit) ? "in session - " : "no in session - "));
+ (* outBranchExecuted) = 0;
+ }
+
+ if(!inDoRollback){
+ DEBUG("commit\n");
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T4: Commit",
+ MyTransaction);
+ } else {
+ DEBUG("rollback\n");
+ check = MyTransaction->execute(Rollback);
+ CHECK_MINUS_ONE(check, "T4:Rollback",
+ MyTransaction);
+
+ }
+
+ pNDB->closeTransaction(MyTransaction);
+
+ get_time(outTransactionTime);
+ time_diff(outTransactionTime, &start);
+ return 0;
+}
+
+
+/**
+ * Transaction 5 - T5
+ *
+ * Delete session
+ *
+ * Input:
+ * SubscriberNumber
+ * ServerId
+ * ServerBit
+ * DoRollback
+ * Output:
+ * ChangedBy
+ * ChangedTime
+ * Location
+ * BranchExecuted
+ */
+int
+T5(void * obj,
+ const SubscriberNumber inNumber,
+ const SubscriberSuffix inSuffix,
+ const ServerId inServerId,
+ const ServerBit inServerBit,
+ ChangedBy outChangedBy,
+ ChangedTime outChangedTime,
+ Location * outLocation,
+ DoRollback inDoRollback,
+ BranchExecuted * outBranchExecuted,
+ BenchmarkTime * outTransactionTime){
+
+ Ndb * pNDB = (Ndb *) obj;
+ NdbConnection * MyTransaction = 0;
+ NdbOperation * MyOperation = 0;
+
+ GroupId groupId;
+ ActiveSessions sessions;
+ Permission permission;
+
+ BenchmarkTime start;
+ get_time(&start);
+
+ int check;
+ NdbRecAttr * check2;
+
+ MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T5-1: startTranscation", pNDB->getNdbErrorString(), 0);
+
+ MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T5-1: getNdbOperation",
+ MyTransaction);
+
+
+ check = MyOperation->readTupleExclusive();
+ CHECK_MINUS_ONE(check, "T5-1: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ inNumber);
+ CHECK_MINUS_ONE(check, "T5-1: equal subscriber",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)outLocation);
+ CHECK_NULL(check2, "T5-1: getValue location",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ outChangedBy);
+ CHECK_NULL(check2, "T5-1: getValue changed_by",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ outChangedTime);
+ CHECK_NULL(check2, "T5-1: getValue changed_time",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_GROUP,
+ (char *)&groupId);
+ CHECK_NULL(check2, "T5-1: getValue group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_SESSIONS,
+ (char *)&sessions);
+ CHECK_NULL(check2, "T5-1: getValue sessions",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T5-1: NoCommit",
+ MyTransaction);
+
+ /* Operation 2 */
+
+ MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
+ CHECK_NULL(MyOperation, "T5-2: getNdbOperation",
+ MyTransaction);
+
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T5-2: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_GROUP_ID,
+ (char*)&groupId);
+ CHECK_MINUS_ONE(check, "T5-2: equal group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_GROUP_ALLOW_DELETE,
+ (char *)&permission);
+ CHECK_NULL(check2, "T5-2: getValue allow_delete",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T5-2: NoCommit",
+ MyTransaction);
+
+ DEBUG3("T5(%.*s, %.2d): ", SUBSCRIBER_NUMBER_LENGTH, inNumber, inServerId);
+
+ if(((permission & inServerBit) == inServerBit) &&
+ ((sessions & inServerBit) == inServerBit)){
+
+ DEBUG("deleting - ");
+
+ /* Operation 3 */
+ MyOperation = MyTransaction->getNdbOperation(SESSION_TABLE);
+ CHECK_NULL(MyOperation, "T5-3: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->deleteTuple();
+ CHECK_MINUS_ONE(check, "T5-3: deleteTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SESSION_SUBSCRIBER,
+ (char*)inNumber);
+ CHECK_MINUS_ONE(check, "T5-3: equal number",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SESSION_SERVER,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T5-3: equal server id",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T5-3: NoCommit",
+ MyTransaction);
+
+ /* Operation 4 */
+ MyOperation = MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T5-4: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->interpretedUpdateTuple();
+ CHECK_MINUS_ONE(check, "T5-4: interpretedUpdateTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ (char*)inNumber);
+ CHECK_MINUS_ONE(check, "T5-4: equal number",
+ MyTransaction);
+
+ check = MyOperation->subValue(IND_SUBSCRIBER_SESSIONS,
+ (uint32)inServerBit);
+ CHECK_MINUS_ONE(check, "T5-4: dec value",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T5-4: NoCommit",
+ MyTransaction);
+
+ /* Operation 5 */
+ MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
+ CHECK_NULL(MyOperation, "T5-5: getNdbOperation",
+ MyTransaction);
+
+
+ check = MyOperation->interpretedUpdateTuple();
+ CHECK_MINUS_ONE(check, "T5-5: interpretedUpdateTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SERVER_ID,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T5-5: equal serverId",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
+ (char*)inSuffix);
+ CHECK_MINUS_ONE(check, "T5-5: equal suffix",
+ MyTransaction);
+
+ check = MyOperation->incValue(IND_SERVER_DELETES, (uint32)1);
+ CHECK_MINUS_ONE(check, "T5-5: inc value",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T5-5: NoCommit",
+ MyTransaction);
+
+ (* outBranchExecuted) = 1;
+ } else {
+ DEBUG1("%s", ((permission & inServerBit) ? "permission - " : "no permission - "));
+ DEBUG1("%s", ((sessions & inServerBit) ? "in session - " : "no in session - "));
+ (* outBranchExecuted) = 0;
+ }
+
+ if(!inDoRollback){
+ DEBUG("commit\n");
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T5: Commit",
+ MyTransaction);
+ } else {
+ DEBUG("rollback\n");
+ check = MyTransaction->execute(Rollback);
+ CHECK_MINUS_ONE(check, "T5:Rollback",
+ MyTransaction);
+
+ }
+
+ pNDB->closeTransaction(MyTransaction);
+
+ get_time(outTransactionTime);
+ time_diff(outTransactionTime, &start);
+ return 0;
+}
+
diff --git a/ndb/test/ndbapi/bench/ndb_user_transaction3.cpp b/ndb/test/ndbapi/bench/ndb_user_transaction3.cpp
new file mode 100644
index 00000000000..d2c92ecd424
--- /dev/null
+++ b/ndb/test/ndbapi/bench/ndb_user_transaction3.cpp
@@ -0,0 +1,793 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+//#define DEBUG_ON
+
+extern "C" {
+#include "user_transaction.h"
+};
+
+#include "macros.h"
+#include "ndb_schema.hpp"
+#include "ndb_error.hpp"
+
+#include <time.h>
+#include <NdbApi.hpp>
+
+/**
+ * Transaction 1 - T1
+ *
+ * Update location and changed by/time on a subscriber
+ *
+ * Input:
+ * SubscriberNumber,
+ * Location,
+ * ChangedBy,
+ * ChangedTime
+ *
+ * Output:
+ */
+int
+T1(void * obj,
+ const SubscriberNumber number,
+ const Location new_location,
+ const ChangedBy changed_by,
+ const ChangedTime changed_time,
+ BenchmarkTime * transaction_time){
+
+ Ndb * pNDB = (Ndb *) obj;
+
+ BenchmarkTime start;
+ get_time(&start);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T1: startTranscation", pNDB->getNdbErrorString(), 0);
+
+ NdbOperation *MyOperation = MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T1: getNdbOperation", MyTransaction);
+
+ check = MyOperation->updateTuple();
+ CHECK_MINUS_ONE(check, "T1: updateTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ number);
+ CHECK_MINUS_ONE(check, "T1: equal subscriber",
+ MyTransaction);
+
+ check = MyOperation->setValue(IND_SUBSCRIBER_LOCATION,
+ (char *)&new_location);
+ CHECK_MINUS_ONE(check, "T1: setValue location",
+ MyTransaction);
+
+ check = MyOperation->setValue(IND_SUBSCRIBER_CHANGED_BY,
+ changed_by);
+ CHECK_MINUS_ONE(check, "T1: setValue changed_by",
+ MyTransaction);
+
+ check = MyOperation->setValue(IND_SUBSCRIBER_CHANGED_TIME,
+ changed_time);
+ CHECK_MINUS_ONE(check, "T1: setValue changed_time",
+ MyTransaction);
+
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T1: Commit",
+ MyTransaction);
+
+ pNDB->closeTransaction(MyTransaction);
+
+ get_time(transaction_time);
+ time_diff(transaction_time, &start);
+ return 0;
+}
+
+/**
+ * Transaction 2 - T2
+ *
+ * Read from Subscriber:
+ *
+ * Input:
+ * SubscriberNumber
+ *
+ * Output:
+ * Location
+ * Changed by
+ * Changed Timestamp
+ * Name
+ */
+int
+T2(void * obj,
+ const SubscriberNumber number,
+ Location * readLocation,
+ ChangedBy changed_by,
+ ChangedTime changed_time,
+ SubscriberName subscriberName,
+ BenchmarkTime * transaction_time){
+
+ Ndb * pNDB = (Ndb *) obj;
+
+ BenchmarkTime start;
+ get_time(&start);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T2: startTranscation", pNDB->getNdbErrorString(), 0);
+
+ NdbOperation *MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T2: getNdbOperation",
+ MyTransaction);
+
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T2: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ number);
+ CHECK_MINUS_ONE(check, "T2: equal subscriber",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)readLocation);
+ CHECK_NULL(check2, "T2: getValue location",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ changed_by);
+ CHECK_NULL(check2, "T2: getValue changed_by",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ changed_time);
+ CHECK_NULL(check2, "T2: getValue changed_time",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_NAME,
+ subscriberName);
+ CHECK_NULL(check2, "T2: getValue name",
+ MyTransaction);
+
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T2: Commit",
+ MyTransaction);
+
+ pNDB->closeTransaction(MyTransaction);
+
+ get_time(transaction_time);
+ time_diff(transaction_time, &start);
+ return 0;
+}
+
+/**
+ * Transaction 3 - T3
+ *
+ * Read session details
+ *
+ * Input:
+ * SubscriberNumber
+ * ServerId
+ * ServerBit
+ *
+ * Output:
+ * BranchExecuted
+ * SessionDetails
+ * ChangedBy
+ * ChangedTime
+ * Location
+ */
+int
+T3(void * obj,
+ const SubscriberNumber inNumber,
+ const SubscriberSuffix inSuffix,
+ const ServerId inServerId,
+ const ServerBit inServerBit,
+ SessionDetails outSessionDetails,
+ ChangedBy outChangedBy,
+ ChangedTime outChangedTime,
+ Location * outLocation,
+ BranchExecuted * outBranchExecuted,
+ BenchmarkTime * outTransactionTime){
+
+ Ndb * pNDB = (Ndb *) obj;
+
+ GroupId groupId;
+ ActiveSessions sessions;
+ Permission permission;
+
+ BenchmarkTime start;
+ get_time(&start);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T3-1: startTranscation", pNDB->getNdbErrorString(), 0);
+
+ NdbOperation *MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T3-1: getNdbOperation",
+ MyTransaction);
+
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T3-1: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ inNumber);
+ CHECK_MINUS_ONE(check, "T3-1: equal subscriber",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)outLocation);
+ CHECK_NULL(check2, "T3-1: getValue location",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ outChangedBy);
+ CHECK_NULL(check2, "T3-1: getValue changed_by",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ outChangedTime);
+ CHECK_NULL(check2, "T3-1: getValue changed_time",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_GROUP,
+ (char *)&groupId);
+ CHECK_NULL(check2, "T3-1: getValue group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_SESSIONS,
+ (char *)&sessions);
+ CHECK_NULL(check2, "T3-1: getValue sessions",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T3-1: NoCommit",
+ MyTransaction);
+
+ /* Operation 2 */
+
+ MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
+ CHECK_NULL(MyOperation, "T3-2: getNdbOperation",
+ MyTransaction);
+
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T3-2: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_GROUP_ID,
+ (char*)&groupId);
+ CHECK_MINUS_ONE(check, "T3-2: equal group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_GROUP_ALLOW_READ,
+ (char *)&permission);
+ CHECK_NULL(check2, "T3-2: getValue allow_read",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T3-2: NoCommit",
+ MyTransaction);
+
+ DEBUG3("T3(%.*s, %.2d): ", SUBSCRIBER_NUMBER_LENGTH, inNumber, inServerId);
+
+ if(((permission & inServerBit) == inServerBit) &&
+ ((sessions & inServerBit) == inServerBit)){
+
+ DEBUG("reading - ");
+
+ /* Operation 3 */
+
+ MyOperation = MyTransaction->getNdbOperation(SESSION_TABLE);
+ CHECK_NULL(MyOperation, "T3-3: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T3-3: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SESSION_SUBSCRIBER,
+ (char*)inNumber);
+ CHECK_MINUS_ONE(check, "T3-3: equal number",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SESSION_SERVER,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T3-3: equal server id",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SESSION_DATA,
+ (char *)outSessionDetails);
+ CHECK_NULL(check2, "T3-3: getValue session details",
+ MyTransaction);
+
+ /* Operation 4 */
+
+ MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
+ CHECK_NULL(MyOperation, "T3-4: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->interpretedUpdateTuple();
+ CHECK_MINUS_ONE(check, "T3-4: interpretedUpdateTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SERVER_ID,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T3-4: equal serverId",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
+ (char*)inSuffix);
+ CHECK_MINUS_ONE(check, "T3-4: equal suffix",
+ MyTransaction);
+
+ check = MyOperation->incValue(IND_SERVER_READS, (uint32)1);
+ CHECK_MINUS_ONE(check, "T3-4: inc value",
+ MyTransaction);
+
+ (* outBranchExecuted) = 1;
+ } else {
+ (* outBranchExecuted) = 0;
+ }
+ DEBUG("commit\n");
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T3: Commit",
+ MyTransaction);
+
+ pNDB->closeTransaction(MyTransaction);
+
+ get_time(outTransactionTime);
+ time_diff(outTransactionTime, &start);
+ return 0;
+}
+
+
+/**
+ * Transaction 4 - T4
+ *
+ * Create session
+ *
+ * Input:
+ * SubscriberNumber
+ * ServerId
+ * ServerBit
+ * SessionDetails,
+ * DoRollback
+ * Output:
+ * ChangedBy
+ * ChangedTime
+ * Location
+ * BranchExecuted
+ */
+int
+T4(void * obj,
+ const SubscriberNumber inNumber,
+ const SubscriberSuffix inSuffix,
+ const ServerId inServerId,
+ const ServerBit inServerBit,
+ const SessionDetails inSessionDetails,
+ ChangedBy outChangedBy,
+ ChangedTime outChangedTime,
+ Location * outLocation,
+ DoRollback inDoRollback,
+ BranchExecuted * outBranchExecuted,
+ BenchmarkTime * outTransactionTime){
+
+ Ndb * pNDB = (Ndb *) obj;
+
+ GroupId groupId;
+ ActiveSessions sessions;
+ Permission permission;
+
+ BenchmarkTime start;
+ get_time(&start);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T4-1: startTranscation", pNDB->getNdbErrorString(), 0);
+
+ DEBUG3("T4(%.*s, %.2d): ", SUBSCRIBER_NUMBER_LENGTH, inNumber, inServerId);
+
+ NdbOperation * MyOperation = 0;
+
+ MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T4-1: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->readTupleExclusive();
+ CHECK_MINUS_ONE(check, "T4-1: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ inNumber);
+ CHECK_MINUS_ONE(check, "T4-1: equal subscriber",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)outLocation);
+ CHECK_NULL(check2, "T4-1: getValue location",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ outChangedBy);
+ CHECK_NULL(check2, "T4-1: getValue changed_by",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ outChangedTime);
+ CHECK_NULL(check2, "T4-1: getValue changed_time",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_GROUP,
+ (char *)&groupId);
+ CHECK_NULL(check2, "T4-1: getValue group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_SESSIONS,
+ (char *)&sessions);
+ CHECK_NULL(check2, "T4-1: getValue sessions",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T4-1: NoCommit",
+ MyTransaction);
+
+ /* Operation 2 */
+ MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
+ CHECK_NULL(MyOperation, "T4-2: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T4-2: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_GROUP_ID,
+ (char*)&groupId);
+ CHECK_MINUS_ONE(check, "T4-2: equal group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_GROUP_ALLOW_INSERT,
+ (char *)&permission);
+ CHECK_NULL(check2, "T4-2: getValue allow_insert",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T4-2: NoCommit",
+ MyTransaction);
+
+ if(((permission & inServerBit) == inServerBit) &&
+ ((sessions & inServerBit) == 0)){
+
+ DEBUG("inserting - ");
+
+ /* Operation 3 */
+ MyOperation = MyTransaction->getNdbOperation(SESSION_TABLE);
+ CHECK_NULL(MyOperation, "T4-3: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->insertTuple();
+ CHECK_MINUS_ONE(check, "T4-3: insertTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SESSION_SUBSCRIBER,
+ (char*)inNumber);
+ CHECK_MINUS_ONE(check, "T4-3: equal number",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SESSION_SERVER,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T4-3: equal server id",
+ MyTransaction);
+
+ check = MyOperation->setValue(SESSION_DATA,
+ (char *)inSessionDetails);
+ CHECK_MINUS_ONE(check, "T4-3: setValue session details",
+ MyTransaction);
+
+ /* Operation 4 */
+ MyOperation = MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T4-4: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->interpretedUpdateTuple();
+ CHECK_MINUS_ONE(check, "T4-4: interpretedUpdateTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ (char*)inNumber);
+ CHECK_MINUS_ONE(check, "T4-4: equal number",
+ MyTransaction);
+
+ check = MyOperation->incValue(IND_SUBSCRIBER_SESSIONS,
+ (uint32)inServerBit);
+ CHECK_MINUS_ONE(check, "T4-4: inc value",
+ MyTransaction);
+
+ /* Operation 5 */
+ MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
+ CHECK_NULL(MyOperation, "T4-5: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->interpretedUpdateTuple();
+ CHECK_MINUS_ONE(check, "T4-5: interpretedUpdateTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SERVER_ID,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T4-5: equal serverId",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
+ (char*)inSuffix);
+ CHECK_MINUS_ONE(check, "T4-5: equal suffix",
+ MyTransaction);
+
+ check = MyOperation->incValue(IND_SERVER_INSERTS, (uint32)1);
+ CHECK_MINUS_ONE(check, "T4-5: inc value",
+ MyTransaction);
+
+ (* outBranchExecuted) = 1;
+ } else {
+ DEBUG1("%s", ((permission & inServerBit) ? "permission - " : "no permission - "));
+ DEBUG1("%s", ((sessions & inServerBit) ? "in session - " : "no in session - "));
+ (* outBranchExecuted) = 0;
+ }
+
+ if(!inDoRollback){
+ DEBUG("commit\n");
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T4: Commit",
+ MyTransaction);
+ } else {
+ DEBUG("rollback\n");
+ check = MyTransaction->execute(Rollback);
+ CHECK_MINUS_ONE(check, "T4:Rollback",
+ MyTransaction);
+
+ }
+
+ pNDB->closeTransaction(MyTransaction);
+
+ get_time(outTransactionTime);
+ time_diff(outTransactionTime, &start);
+ return 0;
+}
+
+
+/**
+ * Transaction 5 - T5
+ *
+ * Delete session
+ *
+ * Input:
+ * SubscriberNumber
+ * ServerId
+ * ServerBit
+ * DoRollback
+ * Output:
+ * ChangedBy
+ * ChangedTime
+ * Location
+ * BranchExecuted
+ */
+int
+T5(void * obj,
+ const SubscriberNumber inNumber,
+ const SubscriberSuffix inSuffix,
+ const ServerId inServerId,
+ const ServerBit inServerBit,
+ ChangedBy outChangedBy,
+ ChangedTime outChangedTime,
+ Location * outLocation,
+ DoRollback inDoRollback,
+ BranchExecuted * outBranchExecuted,
+ BenchmarkTime * outTransactionTime){
+
+ Ndb * pNDB = (Ndb *) obj;
+ NdbConnection * MyTransaction = 0;
+ NdbOperation * MyOperation = 0;
+
+ GroupId groupId;
+ ActiveSessions sessions;
+ Permission permission;
+
+ BenchmarkTime start;
+ get_time(&start);
+
+ int check;
+ NdbRecAttr * check2;
+
+ MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T5-1: startTranscation", pNDB->getNdbErrorString(), 0);
+
+ MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T5-1: getNdbOperation",
+ MyTransaction);
+
+
+ check = MyOperation->readTupleExclusive();
+ CHECK_MINUS_ONE(check, "T5-1: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ inNumber);
+ CHECK_MINUS_ONE(check, "T5-1: equal subscriber",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)outLocation);
+ CHECK_NULL(check2, "T5-1: getValue location",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ outChangedBy);
+ CHECK_NULL(check2, "T5-1: getValue changed_by",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ outChangedTime);
+ CHECK_NULL(check2, "T5-1: getValue changed_time",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_GROUP,
+ (char *)&groupId);
+ CHECK_NULL(check2, "T5-1: getValue group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_SESSIONS,
+ (char *)&sessions);
+ CHECK_NULL(check2, "T5-1: getValue sessions",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T5-1: NoCommit",
+ MyTransaction);
+
+ /* Operation 2 */
+
+ MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
+ CHECK_NULL(MyOperation, "T5-2: getNdbOperation",
+ MyTransaction);
+
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T5-2: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_GROUP_ID,
+ (char*)&groupId);
+ CHECK_MINUS_ONE(check, "T5-2: equal group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_GROUP_ALLOW_DELETE,
+ (char *)&permission);
+ CHECK_NULL(check2, "T5-2: getValue allow_delete",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T5-2: NoCommit",
+ MyTransaction);
+
+ DEBUG3("T5(%.*s, %.2d): ", SUBSCRIBER_NUMBER_LENGTH, inNumber, inServerId);
+
+ if(((permission & inServerBit) == inServerBit) &&
+ ((sessions & inServerBit) == inServerBit)){
+
+ DEBUG("deleting - ");
+
+ /* Operation 3 */
+ MyOperation = MyTransaction->getNdbOperation(SESSION_TABLE);
+ CHECK_NULL(MyOperation, "T5-3: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->deleteTuple();
+ CHECK_MINUS_ONE(check, "T5-3: deleteTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SESSION_SUBSCRIBER,
+ (char*)inNumber);
+ CHECK_MINUS_ONE(check, "T5-3: equal number",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SESSION_SERVER,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T5-3: equal server id",
+ MyTransaction);
+
+ /* Operation 4 */
+ MyOperation = MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T5-4: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->interpretedUpdateTuple();
+ CHECK_MINUS_ONE(check, "T5-4: interpretedUpdateTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ (char*)inNumber);
+ CHECK_MINUS_ONE(check, "T5-4: equal number",
+ MyTransaction);
+
+ check = MyOperation->subValue(IND_SUBSCRIBER_SESSIONS,
+ (uint32)inServerBit);
+ CHECK_MINUS_ONE(check, "T5-4: dec value",
+ MyTransaction);
+
+ /* Operation 5 */
+ MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
+ CHECK_NULL(MyOperation, "T5-5: getNdbOperation",
+ MyTransaction);
+
+
+ check = MyOperation->interpretedUpdateTuple();
+ CHECK_MINUS_ONE(check, "T5-5: interpretedUpdateTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SERVER_ID,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T5-5: equal serverId",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
+ (char*)inSuffix);
+ CHECK_MINUS_ONE(check, "T5-5: equal suffix",
+ MyTransaction);
+
+ check = MyOperation->incValue(IND_SERVER_DELETES, (uint32)1);
+ CHECK_MINUS_ONE(check, "T5-5: inc value",
+ MyTransaction);
+
+ (* outBranchExecuted) = 1;
+ } else {
+ DEBUG1("%s", ((permission & inServerBit) ? "permission - " : "no permission - "));
+ DEBUG1("%s", ((sessions & inServerBit) ? "in session - " : "no in session - "));
+ (* outBranchExecuted) = 0;
+ }
+
+ if(!inDoRollback){
+ DEBUG("commit\n");
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T5: Commit",
+ MyTransaction);
+ } else {
+ DEBUG("rollback\n");
+ check = MyTransaction->execute(Rollback);
+ CHECK_MINUS_ONE(check, "T5:Rollback",
+ MyTransaction);
+
+ }
+
+ pNDB->closeTransaction(MyTransaction);
+
+ get_time(outTransactionTime);
+ time_diff(outTransactionTime, &start);
+ return 0;
+}
+
diff --git a/ndb/test/ndbapi/bench/ndb_user_transaction4.cpp b/ndb/test/ndbapi/bench/ndb_user_transaction4.cpp
new file mode 100644
index 00000000000..e652c7bfed8
--- /dev/null
+++ b/ndb/test/ndbapi/bench/ndb_user_transaction4.cpp
@@ -0,0 +1,770 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+//#define DEBUG_ON
+
+extern "C" {
+#include "user_transaction.h"
+};
+
+#include "macros.h"
+#include "ndb_schema.hpp"
+#include "ndb_error.hpp"
+
+#include <time.h>
+#include <NdbApi.hpp>
+
+/**
+ * Transaction 1 - T1
+ *
+ * Update location and changed by/time on a subscriber
+ *
+ * Input:
+ * SubscriberNumber,
+ * Location,
+ * ChangedBy,
+ * ChangedTime
+ *
+ * Output:
+ */
+int
+T1(void * obj,
+ const SubscriberNumber number,
+ const Location new_location,
+ const ChangedBy changed_by,
+ const ChangedTime changed_time,
+ BenchmarkTime * transaction_time){
+
+ Ndb * pNDB = (Ndb *) obj;
+
+ DEBUG2("T1(%.*s):\n", SUBSCRIBER_NUMBER_LENGTH, number);
+
+ BenchmarkTime start;
+ get_time(&start);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T1-1: startTranscation", pNDB->getNdbErrorString(), 0);
+
+ NdbOperation *MyOperation = MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T1: getNdbOperation", MyTransaction);
+
+ check = MyOperation->updateTuple();
+ CHECK_MINUS_ONE(check, "T1: updateTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ number);
+ CHECK_MINUS_ONE(check, "T1: equal subscriber",
+ MyTransaction);
+
+ check = MyOperation->setValue(IND_SUBSCRIBER_LOCATION,
+ (char *)&new_location);
+ CHECK_MINUS_ONE(check, "T1: setValue location",
+ MyTransaction);
+
+ check = MyOperation->setValue(IND_SUBSCRIBER_CHANGED_BY,
+ changed_by);
+ CHECK_MINUS_ONE(check, "T1: setValue changed_by",
+ MyTransaction);
+
+ check = MyOperation->setValue(IND_SUBSCRIBER_CHANGED_TIME,
+ changed_time);
+ CHECK_MINUS_ONE(check, "T1: setValue changed_time",
+ MyTransaction);
+
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T1: Commit",
+ MyTransaction);
+
+ pNDB->closeTransaction(MyTransaction);
+
+ get_time(transaction_time);
+ time_diff(transaction_time, &start);
+ return 0;
+}
+
+/**
+ * Transaction 2 - T2
+ *
+ * Read from Subscriber:
+ *
+ * Input:
+ * SubscriberNumber
+ *
+ * Output:
+ * Location
+ * Changed by
+ * Changed Timestamp
+ * Name
+ */
+int
+T2(void * obj,
+ const SubscriberNumber number,
+ Location * readLocation,
+ ChangedBy changed_by,
+ ChangedTime changed_time,
+ SubscriberName subscriberName,
+ BenchmarkTime * transaction_time){
+
+ Ndb * pNDB = (Ndb *) obj;
+
+ DEBUG2("T2(%.*s):\n", SUBSCRIBER_NUMBER_LENGTH, number);
+
+ BenchmarkTime start;
+ get_time(&start);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T2-1: startTranscation", pNDB->getNdbErrorString(), 0);
+
+ NdbOperation *MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T2: getNdbOperation",
+ MyTransaction);
+
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T2: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ number);
+ CHECK_MINUS_ONE(check, "T2: equal subscriber",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)readLocation);
+ CHECK_NULL(check2, "T2: getValue location",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ changed_by);
+ CHECK_NULL(check2, "T2: getValue changed_by",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ changed_time);
+ CHECK_NULL(check2, "T2: getValue changed_time",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_NAME,
+ subscriberName);
+ CHECK_NULL(check2, "T2: getValue name",
+ MyTransaction);
+
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T2: Commit",
+ MyTransaction);
+
+ pNDB->closeTransaction(MyTransaction);
+
+ get_time(transaction_time);
+ time_diff(transaction_time, &start);
+ return 0;
+}
+
+/**
+ * Transaction 3 - T3
+ *
+ * Read session details
+ *
+ * Input:
+ * SubscriberNumber
+ * ServerId
+ * ServerBit
+ *
+ * Output:
+ * BranchExecuted
+ * SessionDetails
+ * ChangedBy
+ * ChangedTime
+ * Location
+ */
+int
+T3(void * obj,
+ const SubscriberNumber inNumber,
+ const SubscriberSuffix inSuffix,
+ const ServerId inServerId,
+ const ServerBit inServerBit,
+ SessionDetails outSessionDetails,
+ ChangedBy outChangedBy,
+ ChangedTime outChangedTime,
+ Location * outLocation,
+ BranchExecuted * outBranchExecuted,
+ BenchmarkTime * outTransactionTime){
+
+ DEBUG3("T3(%.*s, %.2d): ", SUBSCRIBER_NUMBER_LENGTH, inNumber, inServerId);
+
+ Ndb * pNDB = (Ndb *) obj;
+
+ GroupId groupId;
+ ActiveSessions sessions;
+ Permission permission;
+
+ BenchmarkTime start;
+ get_time(&start);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T3-1: startTranscation", pNDB->getNdbErrorString(), 0);
+
+ NdbOperation *MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T3-1: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T3-1: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ inNumber);
+ CHECK_MINUS_ONE(check, "T3-1: equal subscriber",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)outLocation);
+ CHECK_NULL(check2, "T3-1: getValue location",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ outChangedBy);
+ CHECK_NULL(check2, "T3-1: getValue changed_by",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ outChangedTime);
+ CHECK_NULL(check2, "T3-1: getValue changed_time",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_GROUP,
+ (char *)&groupId);
+ CHECK_NULL(check2, "T3-1: getValue group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_SESSIONS,
+ (char *)&sessions);
+ CHECK_NULL(check2, "T3-1: getValue sessions",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T3-1: NoCommit",
+ MyTransaction);
+
+ /* Operation 2 */
+
+ MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
+ CHECK_NULL(MyOperation, "T3-2: getNdbOperation",
+ MyTransaction);
+
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T3-2: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_GROUP_ID,
+ (char*)&groupId);
+ CHECK_MINUS_ONE(check, "T3-2: equal group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_GROUP_ALLOW_READ,
+ (char *)&permission);
+ CHECK_NULL(check2, "T3-2: getValue allow_read",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T3-2: NoCommit",
+ MyTransaction);
+
+ if(((permission & inServerBit) == inServerBit) &&
+ ((sessions & inServerBit) == inServerBit)){
+
+ DEBUG("reading - ");
+
+ /* Operation 3 */
+
+ MyOperation = MyTransaction->getNdbOperation(SESSION_TABLE);
+ CHECK_NULL(MyOperation, "T3-3: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T3-3: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SESSION_SUBSCRIBER,
+ (char*)inNumber);
+ CHECK_MINUS_ONE(check, "T3-3: equal number",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SESSION_SERVER,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T3-3: equal server id",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SESSION_DATA,
+ (char *)outSessionDetails);
+ CHECK_NULL(check2, "T3-3: getValue session details",
+ MyTransaction);
+
+ /* Operation 4 */
+ MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
+ CHECK_NULL(MyOperation, "T3-4: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->interpretedUpdateTuple();
+ CHECK_MINUS_ONE(check, "T3-4: interpretedUpdateTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SERVER_ID,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T3-4: equal serverId",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
+ (char*)inSuffix);
+ CHECK_MINUS_ONE(check, "T3-4: equal suffix",
+ MyTransaction);
+
+ check = MyOperation->incValue(IND_SERVER_READS, (uint32)1);
+ CHECK_MINUS_ONE(check, "T3-4: inc value",
+ MyTransaction);
+ (* outBranchExecuted) = 1;
+ } else {
+ (* outBranchExecuted) = 0;
+ }
+ DEBUG("commit...");
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T3: Commit",
+ MyTransaction);
+
+ pNDB->closeTransaction(MyTransaction);
+
+ DEBUG("done\n");
+ get_time(outTransactionTime);
+ time_diff(outTransactionTime, &start);
+ return 0;
+}
+
+
+/**
+ * Transaction 4 - T4
+ *
+ * Create session
+ *
+ * Input:
+ * SubscriberNumber
+ * ServerId
+ * ServerBit
+ * SessionDetails,
+ * DoRollback
+ * Output:
+ * ChangedBy
+ * ChangedTime
+ * Location
+ * BranchExecuted
+ */
+int
+T4(void * obj,
+ const SubscriberNumber inNumber,
+ const SubscriberSuffix inSuffix,
+ const ServerId inServerId,
+ const ServerBit inServerBit,
+ const SessionDetails inSessionDetails,
+ ChangedBy outChangedBy,
+ ChangedTime outChangedTime,
+ Location * outLocation,
+ DoRollback inDoRollback,
+ BranchExecuted * outBranchExecuted,
+ BenchmarkTime * outTransactionTime){
+
+ DEBUG3("T4(%.*s, %.2d): ", SUBSCRIBER_NUMBER_LENGTH, inNumber, inServerId);
+
+ Ndb * pNDB = (Ndb *) obj;
+
+ GroupId groupId;
+ ActiveSessions sessions;
+ Permission permission;
+
+ BenchmarkTime start;
+ get_time(&start);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T4-1: startTranscation", pNDB->getNdbErrorString(), 0);
+
+ NdbOperation *MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T4-1: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->interpretedUpdateTuple();
+ CHECK_MINUS_ONE(check, "T4-1: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ inNumber);
+ CHECK_MINUS_ONE(check, "T4-1: equal subscriber",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)outLocation);
+ CHECK_NULL(check2, "T4-1: getValue location",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ outChangedBy);
+ CHECK_NULL(check2, "T4-1: getValue changed_by",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ outChangedTime);
+ CHECK_NULL(check2, "T4-1: getValue changed_time",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_GROUP,
+ (char *)&groupId);
+ CHECK_NULL(check2, "T4-1: getValue group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_SESSIONS,
+ (char *)&sessions);
+ CHECK_NULL(check2, "T4-1: getValue sessions",
+ MyTransaction);
+
+ check = MyOperation->incValue(IND_SUBSCRIBER_SESSIONS,
+ (uint32)inServerBit);
+ CHECK_MINUS_ONE(check, "T4-4: inc value",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T4-1: NoCommit",
+ MyTransaction);
+
+ /* Operation 2 */
+
+ MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
+ CHECK_NULL(MyOperation, "T4-2: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T4-2: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_GROUP_ID,
+ (char*)&groupId);
+ CHECK_MINUS_ONE(check, "T4-2: equal group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_GROUP_ALLOW_INSERT,
+ (char *)&permission);
+ CHECK_NULL(check2, "T4-2: getValue allow_insert",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T4-2: NoCommit",
+ MyTransaction);
+
+ if(((permission & inServerBit) == inServerBit) &&
+ ((sessions & inServerBit) == 0)){
+
+ DEBUG("inserting - ");
+
+ /* Operation 3 */
+
+ MyOperation = MyTransaction->getNdbOperation(SESSION_TABLE);
+ CHECK_NULL(MyOperation, "T4-3: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->insertTuple();
+ CHECK_MINUS_ONE(check, "T4-3: insertTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SESSION_SUBSCRIBER,
+ (char*)inNumber);
+ CHECK_MINUS_ONE(check, "T4-3: equal number",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SESSION_SERVER,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T4-3: equal server id",
+ MyTransaction);
+
+ check = MyOperation->setValue(SESSION_DATA,
+ (char *)inSessionDetails);
+ CHECK_MINUS_ONE(check, "T4-3: setValue session details",
+ MyTransaction);
+
+ /* Operation 4 */
+
+ /* Operation 5 */
+ MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
+ CHECK_NULL(MyOperation, "T4-5: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->interpretedUpdateTuple();
+ CHECK_MINUS_ONE(check, "T4-5: interpretedUpdateTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SERVER_ID,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T4-5: equal serverId",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
+ (char*)inSuffix);
+ CHECK_MINUS_ONE(check, "T4-5: equal suffix",
+ MyTransaction);
+
+ check = MyOperation->incValue(IND_SERVER_INSERTS, (uint32)1);
+ CHECK_MINUS_ONE(check, "T4-5: inc value",
+ MyTransaction);
+
+ (* outBranchExecuted) = 1;
+ } else {
+ DEBUG1("%s", ((permission & inServerBit) ? "permission - " : "no permission - "));
+ DEBUG1("%s", ((sessions & inServerBit) ? "in session - " : "no in session - "));
+ (* outBranchExecuted) = 0;
+ }
+
+ if(!inDoRollback && (* outBranchExecuted)){
+ DEBUG("commit\n");
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T4: Commit",
+ MyTransaction);
+ } else {
+ DEBUG("rollback\n");
+ check = MyTransaction->execute(Rollback);
+ CHECK_MINUS_ONE(check, "T4:Rollback",
+ MyTransaction);
+
+ }
+
+ pNDB->closeTransaction(MyTransaction);
+
+ get_time(outTransactionTime);
+ time_diff(outTransactionTime, &start);
+ return 0;
+}
+
+
+/**
+ * Transaction 5 - T5
+ *
+ * Delete session
+ *
+ * Input:
+ * SubscriberNumber
+ * ServerId
+ * ServerBit
+ * DoRollback
+ * Output:
+ * ChangedBy
+ * ChangedTime
+ * Location
+ * BranchExecuted
+ */
+int
+T5(void * obj,
+ const SubscriberNumber inNumber,
+ const SubscriberSuffix inSuffix,
+ const ServerId inServerId,
+ const ServerBit inServerBit,
+ ChangedBy outChangedBy,
+ ChangedTime outChangedTime,
+ Location * outLocation,
+ DoRollback inDoRollback,
+ BranchExecuted * outBranchExecuted,
+ BenchmarkTime * outTransactionTime){
+
+ DEBUG3("T5(%.*s, %.2d): ", SUBSCRIBER_NUMBER_LENGTH, inNumber, inServerId);
+
+ Ndb * pNDB = (Ndb *) obj;
+ NdbConnection * MyTransaction = 0;
+ NdbOperation * MyOperation = 0;
+
+ GroupId groupId;
+ ActiveSessions sessions;
+ Permission permission;
+
+ BenchmarkTime start;
+ get_time(&start);
+
+ int check;
+ NdbRecAttr * check2;
+
+ MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T5-1: startTranscation", pNDB->getNdbErrorString(), 0);
+
+ MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T5-1: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->interpretedUpdateTuple();
+ CHECK_MINUS_ONE(check, "T5-1: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ inNumber);
+ CHECK_MINUS_ONE(check, "T5-1: equal subscriber",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)outLocation);
+ CHECK_NULL(check2, "T5-1: getValue location",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ outChangedBy);
+ CHECK_NULL(check2, "T5-1: getValue changed_by",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ outChangedTime);
+ CHECK_NULL(check2, "T5-1: getValue changed_time",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_GROUP,
+ (char *)&groupId);
+ CHECK_NULL(check2, "T5-1: getValue group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_SESSIONS,
+ (char *)&sessions);
+ CHECK_NULL(check2, "T5-1: getValue sessions",
+ MyTransaction);
+
+ check = MyOperation->subValue(IND_SUBSCRIBER_SESSIONS,
+ (uint32)inServerBit);
+ CHECK_MINUS_ONE(check, "T5-4: dec value",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T5-1: NoCommit",
+ MyTransaction);
+
+ /* Operation 2 */
+
+ MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
+ CHECK_NULL(MyOperation, "T5-2: getNdbOperation",
+ MyTransaction);
+
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T5-2: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_GROUP_ID,
+ (char*)&groupId);
+ CHECK_MINUS_ONE(check, "T5-2: equal group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_GROUP_ALLOW_DELETE,
+ (char *)&permission);
+ CHECK_NULL(check2, "T5-2: getValue allow_delete",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T5-2: NoCommit",
+ MyTransaction);
+
+ if(((permission & inServerBit) == inServerBit) &&
+ ((sessions & inServerBit) == inServerBit)){
+
+ DEBUG("deleting - ");
+
+ /* Operation 3 */
+ MyOperation = MyTransaction->getNdbOperation(SESSION_TABLE);
+ CHECK_NULL(MyOperation, "T5-3: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->deleteTuple();
+ CHECK_MINUS_ONE(check, "T5-3: deleteTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SESSION_SUBSCRIBER,
+ (char*)inNumber);
+ CHECK_MINUS_ONE(check, "T5-3: equal number",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SESSION_SERVER,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T5-3: equal server id",
+ MyTransaction);
+
+ /* Operation 4 */
+
+ /* Operation 5 */
+ MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
+ CHECK_NULL(MyOperation, "T5-5: getNdbOperation",
+ MyTransaction);
+
+
+ check = MyOperation->interpretedUpdateTuple();
+ CHECK_MINUS_ONE(check, "T5-5: interpretedUpdateTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SERVER_ID,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T5-5: equal serverId",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
+ (char*)inSuffix);
+ CHECK_MINUS_ONE(check, "T5-5: equal suffix",
+ MyTransaction);
+
+ check = MyOperation->incValue(IND_SERVER_DELETES, (uint32)1);
+ CHECK_MINUS_ONE(check, "T5-5: inc value",
+ MyTransaction);
+
+ (* outBranchExecuted) = 1;
+ } else {
+ DEBUG1("%s", ((permission & inServerBit) ? "permission - " : "no permission - "));
+ DEBUG1("%s", ((sessions & inServerBit) ? "in session - " : "no in session - "));
+ (* outBranchExecuted) = 0;
+ }
+
+ if(!inDoRollback && (* outBranchExecuted)){
+ DEBUG("commit\n");
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T5: Commit",
+ MyTransaction);
+ } else {
+ DEBUG("rollback\n");
+ check = MyTransaction->execute(Rollback);
+ CHECK_MINUS_ONE(check, "T5:Rollback",
+ MyTransaction);
+
+ }
+
+ pNDB->closeTransaction(MyTransaction);
+
+ get_time(outTransactionTime);
+ time_diff(outTransactionTime, &start);
+ return 0;
+}
+
diff --git a/ndb/test/ndbapi/bench/ndb_user_transaction5.cpp b/ndb/test/ndbapi/bench/ndb_user_transaction5.cpp
new file mode 100644
index 00000000000..86580008d10
--- /dev/null
+++ b/ndb/test/ndbapi/bench/ndb_user_transaction5.cpp
@@ -0,0 +1,769 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+//#define DEBUG_ON
+
+extern "C" {
+#include "user_transaction.h"
+};
+
+#include "macros.h"
+#include "ndb_schema.hpp"
+#include "ndb_error.hpp"
+
+#include <time.h>
+#include <NdbApi.hpp>
+
+/**
+ * Transaction 1 - T1
+ *
+ * Update location and changed by/time on a subscriber
+ *
+ * Input:
+ * SubscriberNumber,
+ * Location,
+ * ChangedBy,
+ * ChangedTime
+ *
+ * Output:
+ */
+int
+T1(void * obj,
+ const SubscriberNumber number,
+ const Location new_location,
+ const ChangedBy changed_by,
+ const ChangedTime changed_time,
+ BenchmarkTime * transaction_time){
+
+ Ndb * pNDB = (Ndb *) obj;
+
+ DEBUG2("T1(%.*s):\n", SUBSCRIBER_NUMBER_LENGTH, number);
+
+ BenchmarkTime start;
+ get_time(&start);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T1-1: startTranscation", pNDB->getNdbErrorString(), 0);
+
+ NdbOperation *MyOperation = MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T1: getNdbOperation", MyTransaction);
+
+ check = MyOperation->updateTuple();
+ CHECK_MINUS_ONE(check, "T1: updateTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ number);
+ CHECK_MINUS_ONE(check, "T1: equal subscriber",
+ MyTransaction);
+
+ check = MyOperation->setValue(IND_SUBSCRIBER_LOCATION,
+ (char *)&new_location);
+ CHECK_MINUS_ONE(check, "T1: setValue location",
+ MyTransaction);
+
+ check = MyOperation->setValue(IND_SUBSCRIBER_CHANGED_BY,
+ changed_by);
+ CHECK_MINUS_ONE(check, "T1: setValue changed_by",
+ MyTransaction);
+
+ check = MyOperation->setValue(IND_SUBSCRIBER_CHANGED_TIME,
+ changed_time);
+ CHECK_MINUS_ONE(check, "T1: setValue changed_time",
+ MyTransaction);
+
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T1: Commit",
+ MyTransaction);
+
+ pNDB->closeTransaction(MyTransaction);
+
+ get_time(transaction_time);
+ time_diff(transaction_time, &start);
+ return 0;
+}
+
+/**
+ * Transaction 2 - T2
+ *
+ * Read from Subscriber:
+ *
+ * Input:
+ * SubscriberNumber
+ *
+ * Output:
+ * Location
+ * Changed by
+ * Changed Timestamp
+ * Name
+ */
+int
+T2(void * obj,
+ const SubscriberNumber number,
+ Location * readLocation,
+ ChangedBy changed_by,
+ ChangedTime changed_time,
+ SubscriberName subscriberName,
+ BenchmarkTime * transaction_time){
+
+ Ndb * pNDB = (Ndb *) obj;
+
+ DEBUG2("T2(%.*s):\n", SUBSCRIBER_NUMBER_LENGTH, number);
+
+ BenchmarkTime start;
+ get_time(&start);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T2-1: startTranscation", pNDB->getNdbErrorString(), 0);
+
+ NdbOperation *MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T2: getNdbOperation",
+ MyTransaction);
+
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T2: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ number);
+ CHECK_MINUS_ONE(check, "T2: equal subscriber",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)readLocation);
+ CHECK_NULL(check2, "T2: getValue location",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ changed_by);
+ CHECK_NULL(check2, "T2: getValue changed_by",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ changed_time);
+ CHECK_NULL(check2, "T2: getValue changed_time",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_NAME,
+ subscriberName);
+ CHECK_NULL(check2, "T2: getValue name",
+ MyTransaction);
+
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T2: Commit",
+ MyTransaction);
+
+ pNDB->closeTransaction(MyTransaction);
+
+ get_time(transaction_time);
+ time_diff(transaction_time, &start);
+ return 0;
+}
+
+/**
+ * Transaction 3 - T3
+ *
+ * Read session details
+ *
+ * Input:
+ * SubscriberNumber
+ * ServerId
+ * ServerBit
+ *
+ * Output:
+ * BranchExecuted
+ * SessionDetails
+ * ChangedBy
+ * ChangedTime
+ * Location
+ */
+int
+T3(void * obj,
+ const SubscriberNumber inNumber,
+ const SubscriberSuffix inSuffix,
+ const ServerId inServerId,
+ const ServerBit inServerBit,
+ SessionDetails outSessionDetails,
+ ChangedBy outChangedBy,
+ ChangedTime outChangedTime,
+ Location * outLocation,
+ BranchExecuted * outBranchExecuted,
+ BenchmarkTime * outTransactionTime){
+
+ Ndb * pNDB = (Ndb *) obj;
+
+ GroupId groupId;
+ ActiveSessions sessions;
+ Permission permission;
+
+ BenchmarkTime start;
+ get_time(&start);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T3-1: startTranscation", pNDB->getNdbErrorString(), 0);
+
+ NdbOperation *MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T3-1: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T3-1: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ inNumber);
+ CHECK_MINUS_ONE(check, "T3-1: equal subscriber",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)outLocation);
+ CHECK_NULL(check2, "T3-1: getValue location",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ outChangedBy);
+ CHECK_NULL(check2, "T3-1: getValue changed_by",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ outChangedTime);
+ CHECK_NULL(check2, "T3-1: getValue changed_time",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_GROUP,
+ (char *)&groupId);
+ CHECK_NULL(check2, "T3-1: getValue group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_SESSIONS,
+ (char *)&sessions);
+ CHECK_NULL(check2, "T3-1: getValue sessions",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T3-1: NoCommit",
+ MyTransaction);
+
+ /* Operation 2 */
+
+ MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
+ CHECK_NULL(MyOperation, "T3-2: getNdbOperation",
+ MyTransaction);
+
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T3-2: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_GROUP_ID,
+ (char*)&groupId);
+ CHECK_MINUS_ONE(check, "T3-2: equal group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_GROUP_ALLOW_READ,
+ (char *)&permission);
+ CHECK_NULL(check2, "T3-2: getValue allow_read",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T3-2: NoCommit",
+ MyTransaction);
+
+ DEBUG3("T3(%.*s, %.2d): ", SUBSCRIBER_NUMBER_LENGTH, inNumber, inServerId);
+
+ if(((permission & inServerBit) == inServerBit) &&
+ ((sessions & inServerBit) == inServerBit)){
+
+ DEBUG("reading - ");
+
+ /* Operation 3 */
+ MyOperation = MyTransaction->getNdbOperation(SESSION_TABLE);
+ CHECK_NULL(MyOperation, "T3-3: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->simpleRead();
+ CHECK_MINUS_ONE(check, "T3-3: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SESSION_SUBSCRIBER,
+ (char*)inNumber);
+ CHECK_MINUS_ONE(check, "T3-3: equal number",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SESSION_SERVER,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T3-3: equal server id",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SESSION_DATA,
+ (char *)outSessionDetails);
+ CHECK_NULL(check2, "T3-3: getValue session details",
+ MyTransaction);
+
+ /* Operation 4 */
+ MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
+ CHECK_NULL(MyOperation, "T3-4: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->interpretedUpdateTuple();
+ CHECK_MINUS_ONE(check, "T3-4: interpretedUpdateTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SERVER_ID,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T3-4: equal serverId",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
+ (char*)inSuffix);
+ CHECK_MINUS_ONE(check, "T3-4: equal suffix",
+ MyTransaction);
+
+ check = MyOperation->incValue(IND_SERVER_READS, (uint32)1);
+ CHECK_MINUS_ONE(check, "T3-4: inc value",
+ MyTransaction);
+ (* outBranchExecuted) = 1;
+ } else {
+ (* outBranchExecuted) = 0;
+ }
+ DEBUG("commit...");
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T3: Commit",
+ MyTransaction);
+
+ pNDB->closeTransaction(MyTransaction);
+
+ DEBUG("done\n");
+ get_time(outTransactionTime);
+ time_diff(outTransactionTime, &start);
+ return 0;
+}
+
+
+/**
+ * Transaction 4 - T4
+ *
+ * Create session
+ *
+ * Input:
+ * SubscriberNumber
+ * ServerId
+ * ServerBit
+ * SessionDetails,
+ * DoRollback
+ * Output:
+ * ChangedBy
+ * ChangedTime
+ * Location
+ * BranchExecuted
+ */
+int
+T4(void * obj,
+ const SubscriberNumber inNumber,
+ const SubscriberSuffix inSuffix,
+ const ServerId inServerId,
+ const ServerBit inServerBit,
+ const SessionDetails inSessionDetails,
+ ChangedBy outChangedBy,
+ ChangedTime outChangedTime,
+ Location * outLocation,
+ DoRollback inDoRollback,
+ BranchExecuted * outBranchExecuted,
+ BenchmarkTime * outTransactionTime){
+
+ Ndb * pNDB = (Ndb *) obj;
+
+ GroupId groupId;
+ ActiveSessions sessions;
+ Permission permission;
+
+ BenchmarkTime start;
+ get_time(&start);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T4-1: startTranscation", pNDB->getNdbErrorString(), 0);
+
+ NdbOperation *MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T4-1: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->interpretedUpdateTuple();
+ CHECK_MINUS_ONE(check, "T4-1: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ inNumber);
+ CHECK_MINUS_ONE(check, "T4-1: equal subscriber",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)outLocation);
+ CHECK_NULL(check2, "T4-1: getValue location",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ outChangedBy);
+ CHECK_NULL(check2, "T4-1: getValue changed_by",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ outChangedTime);
+ CHECK_NULL(check2, "T4-1: getValue changed_time",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_GROUP,
+ (char *)&groupId);
+ CHECK_NULL(check2, "T4-1: getValue group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_SESSIONS,
+ (char *)&sessions);
+ CHECK_NULL(check2, "T4-1: getValue sessions",
+ MyTransaction);
+
+ check = MyOperation->incValue(IND_SUBSCRIBER_SESSIONS,
+ (uint32)inServerBit);
+ CHECK_MINUS_ONE(check, "T4-4: inc value",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T4-1: NoCommit",
+ MyTransaction);
+
+ /* Operation 2 */
+
+ MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
+ CHECK_NULL(MyOperation, "T4-2: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T4-2: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_GROUP_ID,
+ (char*)&groupId);
+ CHECK_MINUS_ONE(check, "T4-2: equal group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_GROUP_ALLOW_INSERT,
+ (char *)&permission);
+ CHECK_NULL(check2, "T4-2: getValue allow_insert",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T4-2: NoCommit",
+ MyTransaction);
+
+ DEBUG3("T4(%.*s, %.2d): ", SUBSCRIBER_NUMBER_LENGTH, inNumber, inServerId);
+
+ if(((permission & inServerBit) == inServerBit) &&
+ ((sessions & inServerBit) == 0)){
+
+ DEBUG("inserting - ");
+
+ /* Operation 3 */
+
+ MyOperation = MyTransaction->getNdbOperation(SESSION_TABLE);
+ CHECK_NULL(MyOperation, "T4-3: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->insertTuple();
+ CHECK_MINUS_ONE(check, "T4-3: insertTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SESSION_SUBSCRIBER,
+ (char*)inNumber);
+ CHECK_MINUS_ONE(check, "T4-3: equal number",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SESSION_SERVER,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T4-3: equal server id",
+ MyTransaction);
+
+ check = MyOperation->setValue(SESSION_DATA,
+ (char *)inSessionDetails);
+ CHECK_MINUS_ONE(check, "T4-3: setValue session details",
+ MyTransaction);
+
+ /* Operation 4 */
+
+ /* Operation 5 */
+ MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
+ CHECK_NULL(MyOperation, "T4-5: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->interpretedUpdateTuple();
+ CHECK_MINUS_ONE(check, "T4-5: interpretedUpdateTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SERVER_ID,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T4-5: equal serverId",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
+ (char*)inSuffix);
+ CHECK_MINUS_ONE(check, "T4-5: equal suffix",
+ MyTransaction);
+
+ check = MyOperation->incValue(IND_SERVER_INSERTS, (uint32)1);
+ CHECK_MINUS_ONE(check, "T4-5: inc value",
+ MyTransaction);
+
+ (* outBranchExecuted) = 1;
+ } else {
+ DEBUG1("%s", ((permission & inServerBit) ? "permission - " : "no permission - "));
+ DEBUG1("%s", ((sessions & inServerBit) ? "in session - " : "no in session - "));
+ (* outBranchExecuted) = 0;
+ }
+
+ if(!inDoRollback && (* outBranchExecuted)){
+ DEBUG("commit\n");
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T4: Commit",
+ MyTransaction);
+ } else {
+ DEBUG("rollback\n");
+ check = MyTransaction->execute(Rollback);
+ CHECK_MINUS_ONE(check, "T4:Rollback",
+ MyTransaction);
+
+ }
+
+ pNDB->closeTransaction(MyTransaction);
+
+ get_time(outTransactionTime);
+ time_diff(outTransactionTime, &start);
+ return 0;
+}
+
+
+/**
+ * Transaction 5 - T5
+ *
+ * Delete session
+ *
+ * Input:
+ * SubscriberNumber
+ * ServerId
+ * ServerBit
+ * DoRollback
+ * Output:
+ * ChangedBy
+ * ChangedTime
+ * Location
+ * BranchExecuted
+ */
+int
+T5(void * obj,
+ const SubscriberNumber inNumber,
+ const SubscriberSuffix inSuffix,
+ const ServerId inServerId,
+ const ServerBit inServerBit,
+ ChangedBy outChangedBy,
+ ChangedTime outChangedTime,
+ Location * outLocation,
+ DoRollback inDoRollback,
+ BranchExecuted * outBranchExecuted,
+ BenchmarkTime * outTransactionTime){
+
+ Ndb * pNDB = (Ndb *) obj;
+ NdbConnection * MyTransaction = 0;
+ NdbOperation * MyOperation = 0;
+
+ GroupId groupId;
+ ActiveSessions sessions;
+ Permission permission;
+
+ BenchmarkTime start;
+ get_time(&start);
+
+ int check;
+ NdbRecAttr * check2;
+
+ MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T5-1: startTranscation", pNDB->getNdbErrorString(), 0);
+
+ MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T5-1: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->interpretedUpdateTuple();
+ CHECK_MINUS_ONE(check, "T5-1: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ inNumber);
+ CHECK_MINUS_ONE(check, "T5-1: equal subscriber",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)outLocation);
+ CHECK_NULL(check2, "T5-1: getValue location",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ outChangedBy);
+ CHECK_NULL(check2, "T5-1: getValue changed_by",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ outChangedTime);
+ CHECK_NULL(check2, "T5-1: getValue changed_time",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_GROUP,
+ (char *)&groupId);
+ CHECK_NULL(check2, "T5-1: getValue group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_SUBSCRIBER_SESSIONS,
+ (char *)&sessions);
+ CHECK_NULL(check2, "T5-1: getValue sessions",
+ MyTransaction);
+
+ check = MyOperation->subValue(IND_SUBSCRIBER_SESSIONS,
+ (uint32)inServerBit);
+ CHECK_MINUS_ONE(check, "T5-4: dec value",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T5-1: NoCommit",
+ MyTransaction);
+
+ /* Operation 2 */
+
+ MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
+ CHECK_NULL(MyOperation, "T5-2: getNdbOperation",
+ MyTransaction);
+
+
+ check = MyOperation->readTuple();
+ CHECK_MINUS_ONE(check, "T5-2: readTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_GROUP_ID,
+ (char*)&groupId);
+ CHECK_MINUS_ONE(check, "T5-2: equal group",
+ MyTransaction);
+
+ check2 = MyOperation->getValue(IND_GROUP_ALLOW_DELETE,
+ (char *)&permission);
+ CHECK_NULL(check2, "T5-2: getValue allow_delete",
+ MyTransaction);
+
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T5-2: NoCommit",
+ MyTransaction);
+
+ DEBUG3("T5(%.*s, %.2d): ", SUBSCRIBER_NUMBER_LENGTH, inNumber, inServerId);
+
+ if(((permission & inServerBit) == inServerBit) &&
+ ((sessions & inServerBit) == inServerBit)){
+
+ DEBUG("deleting - ");
+
+ /* Operation 3 */
+ MyOperation = MyTransaction->getNdbOperation(SESSION_TABLE);
+ CHECK_NULL(MyOperation, "T5-3: getNdbOperation",
+ MyTransaction);
+
+ check = MyOperation->deleteTuple();
+ CHECK_MINUS_ONE(check, "T5-3: deleteTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SESSION_SUBSCRIBER,
+ (char*)inNumber);
+ CHECK_MINUS_ONE(check, "T5-3: equal number",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SESSION_SERVER,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T5-3: equal server id",
+ MyTransaction);
+
+ /* Operation 4 */
+
+ /* Operation 5 */
+ MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
+ CHECK_NULL(MyOperation, "T5-5: getNdbOperation",
+ MyTransaction);
+
+
+ check = MyOperation->interpretedUpdateTuple();
+ CHECK_MINUS_ONE(check, "T5-5: interpretedUpdateTuple",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SERVER_ID,
+ (char*)&inServerId);
+ CHECK_MINUS_ONE(check, "T5-5: equal serverId",
+ MyTransaction);
+
+ check = MyOperation->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
+ (char*)inSuffix);
+ CHECK_MINUS_ONE(check, "T5-5: equal suffix",
+ MyTransaction);
+
+ check = MyOperation->incValue(IND_SERVER_DELETES, (uint32)1);
+ CHECK_MINUS_ONE(check, "T5-5: inc value",
+ MyTransaction);
+
+ (* outBranchExecuted) = 1;
+ } else {
+ DEBUG1("%s", ((permission & inServerBit) ? "permission - " : "no permission - "));
+ DEBUG1("%s", ((sessions & inServerBit) ? "in session - " : "no in session - "));
+ (* outBranchExecuted) = 0;
+ }
+
+ if(!inDoRollback && (* outBranchExecuted)){
+ DEBUG("commit\n");
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T5: Commit",
+ MyTransaction);
+ } else {
+ DEBUG("rollback\n");
+ check = MyTransaction->execute(Rollback);
+ CHECK_MINUS_ONE(check, "T5:Rollback",
+ MyTransaction);
+
+ }
+
+ pNDB->closeTransaction(MyTransaction);
+
+ get_time(outTransactionTime);
+ time_diff(outTransactionTime, &start);
+ return 0;
+}
+
diff --git a/ndb/test/ndbapi/bench/ndb_user_transaction6.cpp b/ndb/test/ndbapi/bench/ndb_user_transaction6.cpp
new file mode 100644
index 00000000000..262f38e9ffb
--- /dev/null
+++ b/ndb/test/ndbapi/bench/ndb_user_transaction6.cpp
@@ -0,0 +1,561 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+//#define DEBUG_ON
+
+#include <string.h>
+#include "userHandle.h"
+#include "userInterface.h"
+
+#include "macros.h"
+#include "ndb_schema.hpp"
+#include "ndb_error.hpp"
+
+#include <NdbApi.hpp>
+
+
+void
+userCheckpoint(UserHandle *uh){
+}
+
+inline
+NdbConnection *
+startTransaction(Ndb * pNDB, ServerId inServerId, const SubscriberNumber inNumber){
+
+ const int keyDataLenBytes = sizeof(ServerId)+SUBSCRIBER_NUMBER_LENGTH;
+ const int keyDataLen_64Words = keyDataLenBytes >> 3;
+
+ Uint64 keyDataBuf[keyDataLen_64Words+1]; // The "+1" is for rounding...
+
+ char * keyDataBuf_charP = (char *)&keyDataBuf[0];
+ Uint32 * keyDataBuf_wo32P = (Uint32 *)&keyDataBuf[0];
+
+ // Server Id comes first
+ keyDataBuf_wo32P[0] = inServerId;
+ // Then subscriber number
+ memcpy(&keyDataBuf_charP[sizeof(ServerId)], inNumber, SUBSCRIBER_NUMBER_LENGTH);
+
+ return pNDB->startTransaction(0, keyDataBuf_charP, keyDataLenBytes);
+}
+
+/**
+ * Transaction 1 - T1
+ *
+ * Update location and changed by/time on a subscriber
+ *
+ * Input:
+ * SubscriberNumber,
+ * Location,
+ * ChangedBy,
+ * ChangedTime
+ *
+ * Output:
+ */
+void
+userTransaction_T1(UserHandle * uh,
+ SubscriberNumber number,
+ Location new_location,
+ ChangedBy changed_by,
+ ChangedTime changed_time){
+ Ndb * pNDB = uh->pNDB;
+
+ DEBUG2("T1(%.*s):\n", SUBSCRIBER_NUMBER_LENGTH, number);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * MyTransaction = pNDB->startTransaction();
+ if (MyTransaction != NULL) {
+ NdbOperation *MyOperation = MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ if (MyOperation != NULL) {
+ MyOperation->updateTuple();
+ MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ number);
+ MyOperation->setValue(IND_SUBSCRIBER_LOCATION,
+ (char *)&new_location);
+ MyOperation->setValue(IND_SUBSCRIBER_CHANGED_BY,
+ changed_by);
+ MyOperation->setValue(IND_SUBSCRIBER_CHANGED_TIME,
+ changed_time);
+ check = MyTransaction->execute( Commit );
+ if (check != -1) {
+ pNDB->closeTransaction(MyTransaction);
+ return;
+ } else {
+ CHECK_MINUS_ONE(check, "T1: Commit",
+ MyTransaction);
+ }//if
+ } else {
+ CHECK_NULL(MyOperation, "T1: getNdbOperation", MyTransaction);
+ }//if
+ } else {
+ error_handler("T1-1: startTranscation", pNDB->getNdbErrorString(), pNDB->getNdbError());
+ }//if
+}
+
+/**
+ * Transaction 2 - T2
+ *
+ * Read from Subscriber:
+ *
+ * Input:
+ * SubscriberNumber
+ *
+ * Output:
+ * Location
+ * Changed by
+ * Changed Timestamp
+ * Name
+ */
+void
+userTransaction_T2(UserHandle * uh,
+ SubscriberNumber number,
+ Location * readLocation,
+ ChangedBy changed_by,
+ ChangedTime changed_time,
+ SubscriberName subscriberName){
+ Ndb * pNDB = uh->pNDB;
+
+ DEBUG2("T2(%.*s):\n", SUBSCRIBER_NUMBER_LENGTH, number);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T2-1: startTransaction", pNDB->getNdbErrorString(), pNDB->getNdbError());
+
+ NdbOperation *MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T2: getNdbOperation",
+ MyTransaction);
+
+ MyOperation->readTuple();
+ MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ number);
+ MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)readLocation);
+ MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ changed_by);
+ MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ changed_time);
+ MyOperation->getValue(IND_SUBSCRIBER_NAME,
+ subscriberName);
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T2: Commit",
+ MyTransaction);
+ pNDB->closeTransaction(MyTransaction);
+}
+
+/**
+ * Transaction 3 - T3
+ *
+ * Read session details
+ *
+ * Input:
+ * SubscriberNumber
+ * ServerId
+ * ServerBit
+ *
+ * Output:
+ * BranchExecuted
+ * SessionDetails
+ * ChangedBy
+ * ChangedTime
+ * Location
+ */
+void
+userTransaction_T3(UserHandle * uh,
+ SubscriberNumber inNumber,
+ ServerId inServerId,
+ ServerBit inServerBit,
+ SessionDetails outSessionDetails,
+ BranchExecuted * outBranchExecuted){
+ Ndb * pNDB = uh->pNDB;
+
+ char outChangedBy [sizeof(ChangedBy) +(4-(sizeof(ChangedBy) & 3))];
+ char outChangedTime [sizeof(ChangedTime)+(4-(sizeof(ChangedTime) & 3))];
+ Location outLocation;
+ GroupId groupId;
+ ActiveSessions sessions;
+ Permission permission;
+ SubscriberSuffix inSuffix;
+
+ DEBUG3("T3(%.*s, %.2d): ", SUBSCRIBER_NUMBER_LENGTH, inNumber, inServerId);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * MyTransaction = startTransaction(pNDB, inServerId, inNumber);
+ if (MyTransaction == NULL)
+ error_handler("T3-1: startTranscation", pNDB->getNdbErrorString(), pNDB->getNdbError());
+
+ NdbOperation *MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T3-1: getNdbOperation",
+ MyTransaction);
+
+ MyOperation->readTuple();
+ MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ inNumber);
+ MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)&outLocation);
+ MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ outChangedBy);
+ MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ outChangedTime);
+ MyOperation->getValue(IND_SUBSCRIBER_GROUP,
+ (char *)&groupId);
+ MyOperation->getValue(IND_SUBSCRIBER_SESSIONS,
+ (char *)&sessions);
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T3-1: NoCommit",
+ MyTransaction);
+
+ /* Operation 2 */
+
+ MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
+ CHECK_NULL(MyOperation, "T3-2: getNdbOperation",
+ MyTransaction);
+
+
+ MyOperation->readTuple();
+ MyOperation->equal(IND_GROUP_ID,
+ (char*)&groupId);
+ MyOperation->getValue(IND_GROUP_ALLOW_READ,
+ (char *)&permission);
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T3-2: NoCommit",
+ MyTransaction);
+
+ if(((permission & inServerBit) == inServerBit) &&
+ ((sessions & inServerBit) == inServerBit)){
+
+ memcpy(inSuffix,
+ &inNumber[SUBSCRIBER_NUMBER_LENGTH-SUBSCRIBER_NUMBER_SUFFIX_LENGTH], SUBSCRIBER_NUMBER_SUFFIX_LENGTH);
+ DEBUG2("reading(%.*s) - ", SUBSCRIBER_NUMBER_SUFFIX_LENGTH, inSuffix);
+
+ /* Operation 3 */
+ MyOperation = MyTransaction->getNdbOperation(SESSION_TABLE);
+ CHECK_NULL(MyOperation, "T3-3: getNdbOperation",
+ MyTransaction);
+
+ MyOperation->simpleRead();
+
+ MyOperation->equal(IND_SESSION_SUBSCRIBER,
+ (char*)inNumber);
+ MyOperation->equal(IND_SESSION_SERVER,
+ (char*)&inServerId);
+ MyOperation->getValue(IND_SESSION_DATA,
+ (char *)outSessionDetails);
+ /* Operation 4 */
+ MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
+ CHECK_NULL(MyOperation, "T3-4: getNdbOperation",
+ MyTransaction);
+
+ MyOperation->interpretedUpdateTuple();
+ MyOperation->equal(IND_SERVER_ID,
+ (char*)&inServerId);
+ MyOperation->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
+ (char*)inSuffix);
+ MyOperation->incValue(IND_SERVER_READS, (uint32)1);
+ (* outBranchExecuted) = 1;
+ } else {
+ (* outBranchExecuted) = 0;
+ }
+ DEBUG("commit...");
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T3: Commit",
+ MyTransaction);
+
+ pNDB->closeTransaction(MyTransaction);
+
+ DEBUG("done\n");
+}
+
+
+/**
+ * Transaction 4 - T4
+ *
+ * Create session
+ *
+ * Input:
+ * SubscriberNumber
+ * ServerId
+ * ServerBit
+ * SessionDetails,
+ * DoRollback
+ * Output:
+ * ChangedBy
+ * ChangedTime
+ * Location
+ * BranchExecuted
+ */
+void
+userTransaction_T4(UserHandle * uh,
+ SubscriberNumber inNumber,
+ ServerId inServerId,
+ ServerBit inServerBit,
+ SessionDetails inSessionDetails,
+ DoRollback inDoRollback,
+ BranchExecuted * outBranchExecuted){
+
+ Ndb * pNDB = uh->pNDB;
+
+ char outChangedBy [sizeof(ChangedBy) +(4-(sizeof(ChangedBy) & 3))];
+ char outChangedTime [sizeof(ChangedTime)+(4-(sizeof(ChangedTime) & 3))];
+ Location outLocation;
+ GroupId groupId;
+ ActiveSessions sessions;
+ Permission permission;
+ SubscriberSuffix inSuffix;
+
+ DEBUG3("T4(%.*s, %.2d): ", SUBSCRIBER_NUMBER_LENGTH, inNumber, inServerId);
+
+ int check;
+ NdbRecAttr * check2;
+
+ NdbConnection * MyTransaction = startTransaction(pNDB, inServerId, inNumber);
+ if (MyTransaction == NULL)
+ error_handler("T4-1: startTranscation", pNDB->getNdbErrorString(), pNDB->getNdbError());
+
+ NdbOperation *MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T4-1: getNdbOperation",
+ MyTransaction);
+
+ MyOperation->interpretedUpdateTuple();
+ MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ inNumber);
+ MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)&outLocation);
+ MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ outChangedBy);
+ MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ outChangedTime);
+ MyOperation->getValue(IND_SUBSCRIBER_GROUP,
+ (char *)&groupId);
+ MyOperation->getValue(IND_SUBSCRIBER_SESSIONS,
+ (char *)&sessions);
+ MyOperation->incValue(IND_SUBSCRIBER_SESSIONS,
+ (uint32)inServerBit);
+ check = MyTransaction->execute( NoCommit );
+
+ /* Operation 2 */
+
+ MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
+ CHECK_NULL(MyOperation, "T4-2: getNdbOperation",
+ MyTransaction);
+
+ MyOperation->readTuple();
+ MyOperation->equal(IND_GROUP_ID,
+ (char*)&groupId);
+ MyOperation->getValue(IND_GROUP_ALLOW_INSERT,
+ (char *)&permission);
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T4-2: NoCommit",
+ MyTransaction);
+
+ if(((permission & inServerBit) == inServerBit) &&
+ ((sessions & inServerBit) == 0)){
+
+ memcpy(inSuffix,
+ &inNumber[SUBSCRIBER_NUMBER_LENGTH-SUBSCRIBER_NUMBER_SUFFIX_LENGTH], SUBSCRIBER_NUMBER_SUFFIX_LENGTH);
+
+ DEBUG2("inserting(%.*s) - ", SUBSCRIBER_NUMBER_SUFFIX_LENGTH, inSuffix);
+
+ /* Operation 3 */
+
+ MyOperation = MyTransaction->getNdbOperation(SESSION_TABLE);
+ CHECK_NULL(MyOperation, "T4-3: getNdbOperation",
+ MyTransaction);
+
+ MyOperation->insertTuple();
+ MyOperation->equal(IND_SESSION_SUBSCRIBER,
+ (char*)inNumber);
+ MyOperation->equal(IND_SESSION_SERVER,
+ (char*)&inServerId);
+ MyOperation->setValue(SESSION_DATA,
+ (char *)inSessionDetails);
+ /* Operation 4 */
+
+ /* Operation 5 */
+ MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
+ CHECK_NULL(MyOperation, "T4-5: getNdbOperation",
+ MyTransaction);
+
+ MyOperation->interpretedUpdateTuple();
+ MyOperation->equal(IND_SERVER_ID,
+ (char*)&inServerId);
+ MyOperation->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
+ (char*)inSuffix);
+ MyOperation->incValue(IND_SERVER_INSERTS, (uint32)1);
+ (* outBranchExecuted) = 1;
+ } else {
+ (* outBranchExecuted) = 0;
+ DEBUG1("%s", ((permission & inServerBit) ? "permission - " : "no permission - "));
+ DEBUG1("%s", ((sessions & inServerBit) ? "in session - " : "no in session - "));
+ }
+
+ if(!inDoRollback && (* outBranchExecuted)){
+ DEBUG("commit\n");
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T4: Commit",
+ MyTransaction);
+ } else {
+ DEBUG("rollback\n");
+ check = MyTransaction->execute(Rollback);
+ CHECK_MINUS_ONE(check, "T4:Rollback",
+ MyTransaction);
+
+ }
+
+ pNDB->closeTransaction(MyTransaction);
+}
+
+
+/**
+ * Transaction 5 - T5
+ *
+ * Delete session
+ *
+ * Input:
+ * SubscriberNumber
+ * ServerId
+ * ServerBit
+ * DoRollback
+ * Output:
+ * ChangedBy
+ * ChangedTime
+ * Location
+ * BranchExecuted
+ */
+void
+userTransaction_T5(UserHandle * uh,
+ SubscriberNumber inNumber,
+ ServerId inServerId,
+ ServerBit inServerBit,
+ DoRollback inDoRollback,
+ BranchExecuted * outBranchExecuted){
+ Ndb * pNDB = uh->pNDB;
+
+ DEBUG3("T5(%.*s, %.2d): ", SUBSCRIBER_NUMBER_LENGTH, inNumber, inServerId);
+
+ NdbConnection * MyTransaction = 0;
+ NdbOperation * MyOperation = 0;
+
+ char outChangedBy [sizeof(ChangedBy) +(4-(sizeof(ChangedBy) & 3))];
+ char outChangedTime [sizeof(ChangedTime)+(4-(sizeof(ChangedTime) & 3))];
+ Location outLocation;
+ GroupId groupId;
+ ActiveSessions sessions;
+ Permission permission;
+ SubscriberSuffix inSuffix;
+
+ int check;
+ NdbRecAttr * check2;
+
+ MyTransaction = pNDB->startTransaction();
+ if (MyTransaction == NULL)
+ error_handler("T5-1: startTranscation", pNDB->getNdbErrorString(), pNDB->getNdbError());
+
+ MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "T5-1: getNdbOperation",
+ MyTransaction);
+
+ MyOperation->interpretedUpdateTuple();
+ MyOperation->equal(IND_SUBSCRIBER_NUMBER,
+ inNumber);
+ MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
+ (char *)&outLocation);
+ MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
+ &outChangedBy[0]);
+ MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
+ &outChangedTime[0]);
+ MyOperation->getValue(IND_SUBSCRIBER_GROUP,
+ (char *)&groupId);
+ MyOperation->getValue(IND_SUBSCRIBER_SESSIONS,
+ (char *)&sessions);
+ MyOperation->subValue(IND_SUBSCRIBER_SESSIONS,
+ (uint32)inServerBit);
+ MyTransaction->execute( NoCommit );
+ /* Operation 2 */
+
+ MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
+ CHECK_NULL(MyOperation, "T5-2: getNdbOperation",
+ MyTransaction);
+
+ MyOperation->readTuple();
+ MyOperation->equal(IND_GROUP_ID,
+ (char*)&groupId);
+ MyOperation->getValue(IND_GROUP_ALLOW_DELETE,
+ (char *)&permission);
+ check = MyTransaction->execute( NoCommit );
+ CHECK_MINUS_ONE(check, "T5-2: NoCommit",
+ MyTransaction);
+
+ if(((permission & inServerBit) == inServerBit) &&
+ ((sessions & inServerBit) == inServerBit)){
+
+ memcpy(inSuffix,
+ &inNumber[SUBSCRIBER_NUMBER_LENGTH-SUBSCRIBER_NUMBER_SUFFIX_LENGTH], SUBSCRIBER_NUMBER_SUFFIX_LENGTH);
+
+ DEBUG2("deleting(%.*s) - ", SUBSCRIBER_NUMBER_SUFFIX_LENGTH, inSuffix);
+
+ /* Operation 3 */
+ MyOperation = MyTransaction->getNdbOperation(SESSION_TABLE);
+ CHECK_NULL(MyOperation, "T5-3: getNdbOperation",
+ MyTransaction);
+
+ MyOperation->deleteTuple();
+ MyOperation->equal(IND_SESSION_SUBSCRIBER,
+ (char*)inNumber);
+ MyOperation->equal(IND_SESSION_SERVER,
+ (char*)&inServerId);
+ /* Operation 4 */
+
+ /* Operation 5 */
+ MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
+ CHECK_NULL(MyOperation, "T5-5: getNdbOperation",
+ MyTransaction);
+
+
+ MyOperation->interpretedUpdateTuple();
+ MyOperation->equal(IND_SERVER_ID,
+ (char*)&inServerId);
+ MyOperation->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
+ (char*)inSuffix);
+ MyOperation->incValue(IND_SERVER_DELETES, (uint32)1);
+ (* outBranchExecuted) = 1;
+ } else {
+ (* outBranchExecuted) = 0;
+ DEBUG1("%s", ((permission & inServerBit) ? "permission - " : "no permission - "));
+ DEBUG1("%s", ((sessions & inServerBit) ? "in session - " : "no in session - "));
+ }
+
+ if(!inDoRollback && (* outBranchExecuted)){
+ DEBUG("commit\n");
+ check = MyTransaction->execute( Commit );
+ CHECK_MINUS_ONE(check, "T5: Commit",
+ MyTransaction);
+ } else {
+ DEBUG("rollback\n");
+ check = MyTransaction->execute(Rollback);
+ CHECK_MINUS_ONE(check, "T5:Rollback",
+ MyTransaction);
+
+ }
+
+ pNDB->closeTransaction(MyTransaction);
+}
+
diff --git a/ndb/test/ndbapi/bench/testData.h b/ndb/test/ndbapi/bench/testData.h
new file mode 100644
index 00000000000..3db85e7342e
--- /dev/null
+++ b/ndb/test/ndbapi/bench/testData.h
@@ -0,0 +1,156 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef TESTDATA_H
+#define TESTDATA_H
+
+/***************************************************************
+* I N C L U D E D F I L E S *
+***************************************************************/
+#include <NdbTick.h>
+#include <NdbThread.h>
+#include <NDBT_Stats.hpp>
+#include <random.h>
+#include "testDefinitions.h"
+
+/***************************************************************
+* M A C R O S *
+***************************************************************/
+
+/***************************************************************/
+/* C O N S T A N T S */
+/***************************************************************/
+
+#define NUM_TRANSACTION_TYPES 5
+#define SESSION_LIST_LENGTH 1000
+
+/***************************************************************
+* D A T A S T R U C T U R E S *
+***************************************************************/
+
+typedef struct {
+ SubscriberNumber subscriberNumber;
+ ServerId serverId;
+} SessionElement;
+
+typedef struct {
+ SessionElement list[SESSION_LIST_LENGTH];
+ unsigned int readIndex;
+ unsigned int writeIndex;
+ unsigned int numberInList;
+} SessionList;
+
+typedef struct {
+ unsigned int count;
+ unsigned int branchExecuted;
+ unsigned int rollbackExecuted;
+
+ /**
+ * Latency measures
+ */
+ NDB_TICKS startTime;
+ NDBT_Stats latency;
+ unsigned int latencyCounter;
+
+ inline void startLatency(){
+ if((latencyCounter & 127) == 127)
+ startTime = NdbTick_CurrentMillisecond();
+ }
+
+ inline void stopLatency(){
+ if((latencyCounter & 127) == 127){
+ const NDB_TICKS tmp = NdbTick_CurrentMillisecond() - startTime;
+ latency.addObservation(tmp);
+ }
+ latencyCounter++;
+ }
+} TransactionDefinition;
+
+typedef struct {
+ RandomSequence transactionSequence;
+ RandomSequence rollbackSequenceT4;
+ RandomSequence rollbackSequenceT5;
+
+ TransactionDefinition transactions[NUM_TRANSACTION_TYPES];
+
+ unsigned int totalTransactions;
+
+ double outerLoopTime;
+ double outerTps;
+
+ SessionList activeSessions;
+
+} GeneratorStatistics;
+
+typedef enum{
+ Runnable,
+ Running
+} RunState ;
+
+typedef struct {
+ SubscriberNumber number;
+ SubscriberSuffix suffix;
+ SubscriberName name;
+ Location location;
+ ChangedBy changed_by;
+ ChangedTime changed_time;
+ ServerId server_id;
+ ServerBit server_bit;
+ SessionDetails session_details;
+
+ GroupId group_id;
+ ActiveSessions sessions;
+ Permission permission;
+
+ unsigned int do_rollback;
+
+ unsigned int branchExecuted;
+ unsigned int sessionElement;
+} TransactionData ;
+
+typedef struct {
+ struct NdbThread* pThread;
+
+ unsigned long randomSeed;
+ unsigned long changedTime;
+
+ unsigned int warmUpSeconds;
+ unsigned int testSeconds;
+ unsigned int coolDownSeconds;
+
+ GeneratorStatistics generator;
+
+ /**
+ * For async execution
+ */
+ RunState runState;
+ double startTime;
+ TransactionData transactionData;
+ struct Ndb * pNDB;
+} ThreadData;
+
+/***************************************************************
+ * P U B L I C F U N C T I O N S *
+ ***************************************************************/
+
+/***************************************************************
+ * E X T E R N A L D A T A *
+ ***************************************************************/
+
+
+
+#endif /* TESTDATA_H */
+
diff --git a/ndb/test/ndbapi/bench/testDefinitions.h b/ndb/test/ndbapi/bench/testDefinitions.h
new file mode 100644
index 00000000000..2f4aeb30975
--- /dev/null
+++ b/ndb/test/ndbapi/bench/testDefinitions.h
@@ -0,0 +1,90 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef TESTDEFINITIONS_H
+#define TESTDEFINITIONS_H
+
+/***************************************************************/
+/* I N C L U D E D F I L E S */
+/***************************************************************/
+
+#include <ndb_types.h>
+
+/***************************************************************/
+/* C O N S T A N T S */
+/***************************************************************/
+
+#define OP_PER_TRANS 200
+#define NO_OF_SUBSCRIBERS 500000
+#define NO_OF_GROUPS 100
+#define NO_OF_SERVERS 20
+
+#define SUBSCRIBER_NUMBER_LENGTH 12
+#define SUBSCRIBER_NUMBER_SUFFIX_LENGTH 2
+
+#define SUBSCRIBER_NAME_LENGTH 32
+#define CHANGED_BY_LENGTH 32
+#define CHANGED_TIME_LENGTH 32
+#define SESSION_DETAILS_LENGTH 2000
+#define SERVER_NAME_LENGTH 32
+#define GROUP_NAME_LENGTH 32
+
+/***************************************************************
+* D A T A S T R U C T U R E S *
+***************************************************************/
+
+#define PADDING 4
+
+typedef char SubscriberNumber[SUBSCRIBER_NUMBER_LENGTH];
+typedef char SubscriberSuffix[SUBSCRIBER_NUMBER_SUFFIX_LENGTH + 2];
+typedef char SubscriberName[SUBSCRIBER_NAME_LENGTH];
+typedef char ServerName[SERVER_NAME_LENGTH];
+typedef char GroupName[GROUP_NAME_LENGTH];
+typedef char ChangedBy[CHANGED_BY_LENGTH];
+typedef char ChangedTime[CHANGED_TIME_LENGTH];
+typedef char SessionDetails[SESSION_DETAILS_LENGTH];
+typedef Uint32 ServerId;
+typedef Uint32 ServerBit;
+typedef Uint32 GroupId;
+typedef Uint32 Location;
+typedef Uint32 Permission;
+
+typedef Uint32 Counter;
+typedef Uint32 ActiveSessions;
+typedef unsigned int BranchExecuted;
+typedef unsigned int DoRollback;
+
+/***************************************************************
+* P U B L I C F U N C T I O N S *
+***************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/***************************************************************
+* E X T E R N A L D A T A *
+***************************************************************/
+
+
+
+#endif /* TESTDEFINITIONS_H */
+
diff --git a/ndb/test/ndbapi/bench/userInterface.cpp b/ndb/test/ndbapi/bench/userInterface.cpp
new file mode 100644
index 00000000000..128d20dc9bb
--- /dev/null
+++ b/ndb/test/ndbapi/bench/userInterface.cpp
@@ -0,0 +1,745 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/***************************************************************
+* I N C L U D E D F I L E S *
+***************************************************************/
+
+#include <ndb_global.h>
+#ifndef NDB_WIN32
+#include <sys/time.h>
+#endif
+
+#include "ndb_error.hpp"
+#include "userInterface.h"
+#include <NdbThread.h>
+#include <NdbTick.h>
+#include <NdbMutex.h>
+#include <NdbSleep.h>
+#include "ndb_schema.hpp"
+#include <NDBT.hpp>
+#include <NdbSchemaCon.hpp>
+
+/***************************************************************
+* L O C A L C O N S T A N T S *
+***************************************************************/
+
+/***************************************************************
+* L O C A L D A T A S T R U C T U R E S *
+***************************************************************/
+
+/***************************************************************
+* L O C A L F U N C T I O N S *
+***************************************************************/
+
+extern int localDbPrepare(UserHandle *uh);
+
+static int dbCreate(UserHandle *uh);
+
+/***************************************************************
+* L O C A L D A T A *
+***************************************************************/
+
+/***************************************************************
+* P U B L I C D A T A *
+***************************************************************/
+
+
+/***************************************************************
+****************************************************************
+* L O C A L F U N C T I O N S C O D E S E C T I O N *
+****************************************************************
+***************************************************************/
+
+/***************************************************************
+****************************************************************
+* P U B L I C F U N C T I O N S C O D E S E C T I O N *
+****************************************************************
+***************************************************************/
+
+/*-----------------------------------*/
+/* Time related Functions */
+/* */
+/* Returns a double value in seconds */
+/*-----------------------------------*/
+double userGetTimeSync(void)
+{
+ static int initialized = 0;
+ static NDB_TICKS initSecs = 0;
+ static Uint32 initMicros = 0;
+ double timeValue = 0;
+
+ if ( !initialized ) {
+ initialized = 1;
+ NdbTick_CurrentMicrosecond(&initSecs, &initMicros);
+ timeValue = 0.0;
+ } else {
+ NDB_TICKS secs = 0;
+ Uint32 micros = 0;
+
+ NdbTick_CurrentMicrosecond(&secs, &micros);
+
+ double s = (double)secs - (double)initSecs;
+ double us = (double)secs - (double)initMicros;
+
+ timeValue = s + (us / 1000000.0);
+ }
+
+ return timeValue;
+}
+
+// 0 - OK
+// 1 - Retry transaction
+// 2 - Permanent
+int
+userDbCommit(UserHandle *uh){
+ if(uh->pCurrTrans != 0){
+ int check = uh->pCurrTrans->execute( Commit );
+ NdbError err = uh->pCurrTrans->getNdbError();
+ uh->pNDB->closeTransaction(uh->pCurrTrans);
+ uh->pCurrTrans = 0;
+
+ if(err.status != NdbError::Success)
+ ndbout << err << endl;
+
+ if(err.status == NdbError::TemporaryError &&
+ err.classification == NdbError::OverloadError){
+ NdbSleep_SecSleep(3);
+ }
+
+ return err.status;
+ }
+ return 2;
+}
+
+/**
+ * TRUE - Normal table
+ * FALSE - Table w.o. checkpoing and logging
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern int useTableLogging;
+extern int useIndexTables;
+#ifdef __cplusplus
+}
+#endif
+
+
+int
+create_table_server(Ndb * pNdb){
+ int check;
+ NdbSchemaCon * MySchemaTransaction = NdbSchemaCon::startSchemaTrans(pNdb);
+ if( MySchemaTransaction == NULL )
+ error_handler("startSchemaTransaction", pNdb->getNdbError(), 0);
+
+ NdbSchemaOp * MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
+ if( MySchemaOp == NULL )
+ error_handler("getNdbSchemaOp", MySchemaTransaction->getNdbError(), 0);
+
+ // Create table
+ check = MySchemaOp->createTable( SERVER_TABLE,
+ 8, // Table size
+ TupleKey, // Key Type
+ 1 // Nr of Pages
+ ,DistributionGroup,
+ 6,
+ 78,
+ 80,
+ 1,
+ useTableLogging
+ );
+ if( check == -1 )
+ error_handler("createTable", MySchemaTransaction->getNdbError(), 0);
+
+ check = MySchemaOp->createAttribute
+ ( SERVER_SUBSCRIBER_SUFFIX,
+ TupleKey,
+ sizeof(char) << 3,
+ SUBSCRIBER_NUMBER_SUFFIX_LENGTH,
+ String,
+ MMBased,
+ NotNullAttribute,
+ NormalStorageAttribute,
+ 0,
+ 1,
+ 16);
+ if( check == -1 )
+ error_handler("createAttribute (subscriber suffix)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ // Create first column, primary key
+ check = MySchemaOp->createAttribute( SERVER_ID,
+ TupleKey,
+ sizeof(ServerId) << 3,
+ 1,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (serverid)",
+ MySchemaTransaction->getNdbError(), 0);
+
+
+ check = MySchemaOp->createAttribute( SERVER_NAME,
+ NoKey,
+ sizeof(char) << 3,
+ SERVER_NAME_LENGTH,
+ String,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (server name)",
+ MySchemaTransaction->getNdbError(), 0);
+
+
+ check = MySchemaOp->createAttribute( SERVER_READS,
+ NoKey,
+ sizeof(Counter) << 3,
+ 1,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (server reads)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ check = MySchemaOp->createAttribute( SERVER_INSERTS,
+ NoKey,
+ sizeof(Counter) << 3,
+ 1,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (server inserts)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ check = MySchemaOp->createAttribute( SERVER_DELETES,
+ NoKey,
+ sizeof(Counter) << 3,
+ 1,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (server deletes)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ if( MySchemaTransaction->execute() == -1 ) {
+ error_handler("schemaTransaction->execute()",
+ MySchemaTransaction->getNdbError(), 0);
+ }
+ NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
+ return 0;
+}
+
+int
+create_table_group(Ndb * pNdb){
+ int check;
+
+ NdbSchemaCon * MySchemaTransaction = NdbSchemaCon::startSchemaTrans(pNdb);
+ if( MySchemaTransaction == NULL )
+ error_handler("startSchemaTransaction", pNdb->getNdbError(), 0);
+
+ NdbSchemaOp * MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
+ if( MySchemaOp == NULL )
+ error_handler("getNdbSchemaOp", MySchemaTransaction->getNdbError(), 0);
+
+ // Create table
+ check = MySchemaOp->createTable( GROUP_TABLE,
+ 8, // Table size
+ TupleKey, // Key Type
+ 1 // Nr of Pages
+ ,All,
+ 6,
+ 78,
+ 80,
+ 1,
+ useTableLogging
+ );
+
+ if( check == -1 )
+ error_handler("createTable", MySchemaTransaction->getNdbError(), 0);
+
+ // Create first column, primary key
+ check = MySchemaOp->createAttribute( GROUP_ID,
+ TupleKey,
+ sizeof(GroupId) << 3,
+ 1,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (group id)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ check = MySchemaOp->createAttribute( GROUP_NAME,
+ NoKey,
+ sizeof(char) << 3,
+ GROUP_NAME_LENGTH,
+ String,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (group name)",
+ MySchemaTransaction->getNdbError(), 0);
+
+
+ check = MySchemaOp->createAttribute( GROUP_ALLOW_READ,
+ NoKey,
+ sizeof(Permission) << 3,
+ 1,
+ String,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (group read)",
+ MySchemaTransaction->getNdbError(), 0);
+
+
+ check = MySchemaOp->createAttribute( GROUP_ALLOW_INSERT,
+ NoKey,
+ sizeof(Permission) << 3,
+ 1,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (group insert)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ check = MySchemaOp->createAttribute( GROUP_ALLOW_DELETE,
+ NoKey,
+ sizeof(Permission) << 3,
+ 1,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (group delete)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ if( MySchemaTransaction->execute() == -1 ) {
+ error_handler("schemaTransaction->execute()",
+ MySchemaTransaction->getNdbError(), 0);
+ }
+ NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
+ return 0;
+}
+
+int
+create_table_subscriber(Ndb * pNdb){
+ int check;
+ NdbSchemaCon * MySchemaTransaction = NdbSchemaCon::startSchemaTrans(pNdb);
+ if( MySchemaTransaction == NULL )
+ error_handler("startSchemaTransaction", pNdb->getNdbError(), 0);
+
+ NdbSchemaOp * MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
+ if( MySchemaOp == NULL )
+ error_handler("getNdbSchemaOp", MySchemaTransaction->getNdbError(), 0);
+
+ // Create table
+ check = MySchemaOp->createTable( SUBSCRIBER_TABLE,
+ 8, // Table size
+ TupleKey, // Key Type
+ 1 // Nr of Pages
+ ,DistributionGroup,
+ 6,
+ 78,
+ 80,
+ 1,
+ useTableLogging
+ );
+ if( check == -1 )
+ error_handler("createTable", MySchemaTransaction->getNdbError(), 0);
+
+ // Create first column, primary key
+ check = MySchemaOp->createAttribute
+ ( SUBSCRIBER_NUMBER,
+ TupleKey,
+ sizeof(char) << 3,
+ SUBSCRIBER_NUMBER_LENGTH,
+ String,
+ MMBased,
+ NotNullAttribute,
+ (useIndexTables ? IndexStorageAttribute : NormalStorageAttribute),
+ 0,
+ 1,
+ 16);
+ if( check == -1 )
+ error_handler("createAttribute (subscriber number)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ check = MySchemaOp->createAttribute( SUBSCRIBER_NAME,
+ NoKey,
+ sizeof(char) << 3,
+ SUBSCRIBER_NAME_LENGTH,
+ String,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (subscriber name)",
+ MySchemaTransaction->getNdbError(), 0);
+
+
+ check = MySchemaOp->createAttribute( SUBSCRIBER_GROUP,
+ NoKey,
+ sizeof(GroupId) << 3,
+ 1,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (subscriber_group)",
+ MySchemaTransaction->getNdbError(), 0);
+
+
+ check = MySchemaOp->createAttribute( SUBSCRIBER_LOCATION,
+ NoKey,
+ sizeof(Location) << 3,
+ 1,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (server reads)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ check = MySchemaOp->createAttribute( SUBSCRIBER_SESSIONS,
+ NoKey,
+ sizeof(ActiveSessions) << 3,
+ 1,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (subscriber_sessions)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ check = MySchemaOp->createAttribute( SUBSCRIBER_CHANGED_BY,
+ NoKey,
+ sizeof(char) << 3,
+ CHANGED_BY_LENGTH,
+ String,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (subscriber_changed_by)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ check = MySchemaOp->createAttribute( SUBSCRIBER_CHANGED_TIME,
+ NoKey,
+ sizeof(char) << 3,
+ CHANGED_TIME_LENGTH,
+ String,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (subscriber_changed_time)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ if( MySchemaTransaction->execute() == -1 ) {
+ error_handler("schemaTransaction->execute()",
+ MySchemaTransaction->getNdbError(), 0);
+ }
+ NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
+ return 0;
+}
+
+int
+create_table_session(Ndb * pNdb){
+ int check;
+ NdbSchemaCon * MySchemaTransaction = NdbSchemaCon::startSchemaTrans(pNdb);
+ if( MySchemaTransaction == NULL )
+ error_handler("startSchemaTransaction", pNdb->getNdbError(), 0);
+
+ NdbSchemaOp * MySchemaOp = MySchemaTransaction->getNdbSchemaOp();
+ if( MySchemaOp == NULL )
+ error_handler("getNdbSchemaOp",
+ MySchemaTransaction->getNdbError(), 0);
+
+ // Create table
+ check = MySchemaOp->createTable( SESSION_TABLE,
+ 8, // Table size
+ TupleKey, // Key Type
+ 1 // Nr of Pages
+ ,DistributionGroup,
+ 6,
+ 78,
+ 80,
+ 1,
+ useTableLogging
+ );
+ if( check == -1 )
+ error_handler("createTable", MySchemaTransaction->getNdbError(), 0);
+
+ check = MySchemaOp->createAttribute( SESSION_SUBSCRIBER,
+ TupleKey,
+ sizeof(char) << 3,
+ SUBSCRIBER_NUMBER_LENGTH,
+ String,
+ MMBased,
+ NotNullAttribute,
+ NormalStorageAttribute,
+ 0,
+ 1,
+ 16);
+ if( check == -1 )
+ error_handler("createAttribute (session_subscriber)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ // Create first column, primary key
+ check = MySchemaOp->createAttribute( SESSION_SERVER,
+ TupleKey,
+ sizeof(ServerId) << 3,
+ 1,
+ UnSigned,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (session_server)",
+ MySchemaTransaction->getNdbError(), 0);
+
+
+ check = MySchemaOp->createAttribute( SESSION_DATA,
+ NoKey,
+ sizeof(char) << 3,
+ SESSION_DETAILS_LENGTH,
+ String,
+ MMBased,
+ NotNullAttribute );
+ if( check == -1 )
+ error_handler("createAttribute (session_data)",
+ MySchemaTransaction->getNdbError(), 0);
+
+ if( MySchemaTransaction->execute() == -1 ) {
+ error_handler("schemaTransaction->execute()",
+ MySchemaTransaction->getNdbError(), 0);
+ }
+ NdbSchemaCon::closeSchemaTrans(MySchemaTransaction);
+ return 0;
+}
+
+void
+create_table(const char * name, int (* function)(Ndb * pNdb), Ndb* pNdb){
+ printf("creating table %s...", name);
+ if(pNdb->getDictionary()->getTable(name) != 0){
+ printf(" it already exists\n");
+ return;
+ } else {
+ printf("\n");
+ }
+ function(pNdb);
+ printf("creating table %s... done\n", name);
+}
+
+static int dbCreate(Ndb * pNdb)
+{
+ create_table(SUBSCRIBER_TABLE, create_table_subscriber, pNdb);
+ create_table(GROUP_TABLE , create_table_group, pNdb);
+ create_table(SESSION_TABLE , create_table_session, pNdb);
+ create_table(SERVER_TABLE , create_table_server, pNdb);
+ return 0;
+}
+
+#ifndef NDB_WIN32
+#include <unistd.h>
+#endif
+
+UserHandle*
+userDbConnect(uint32 createDb, char *dbName)
+{
+ Ndb_cluster_connection *con= new Ndb_cluster_connection();
+ if(con->connect(12, 5, 1) != 0)
+ {
+ ndbout << "Unable to connect to management server." << endl;
+ return 0;
+ }
+ if (con->wait_until_ready(30,0) < 0)
+ {
+ ndbout << "Cluster nodes not ready in 30 seconds." << endl;
+ return 0;
+ }
+
+ Ndb * pNdb = new Ndb(con, dbName);
+
+ //printf("Initializing...\n");
+ pNdb->init();
+
+ //printf("Waiting...");
+ while(pNdb->waitUntilReady() != 0){
+ //printf("...");
+ }
+ // printf("done\n");
+
+ if( createDb )
+ dbCreate(pNdb);
+
+
+ UserHandle * uh = new UserHandle;
+ uh->pNCC = con;
+ uh->pNDB = pNdb;
+ uh->pCurrTrans = 0;
+
+ return uh;
+}
+
+void userDbDisconnect(UserHandle *uh)
+{
+ delete uh;
+}
+
+int userDbInsertServer(UserHandle *uh,
+ ServerId serverId,
+ SubscriberSuffix suffix,
+ ServerName name)
+{
+ int check;
+
+ uint32 noOfRead = 0;
+ uint32 noOfInsert = 0;
+ uint32 noOfDelete = 0;
+
+ NdbConnection * MyTransaction = 0;
+ if(uh->pCurrTrans != 0){
+ MyTransaction = uh->pCurrTrans;
+ } else {
+ uh->pCurrTrans = MyTransaction = uh->pNDB->startTransaction();
+ }
+ if (MyTransaction == NULL)
+ error_handler("startTranscation", uh->pNDB->getNdbError(), 0);
+
+ NdbOperation *MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
+ CHECK_NULL(MyOperation, "getNdbOperation", MyTransaction);
+
+ check = MyOperation->insertTuple();
+ CHECK_MINUS_ONE(check, "insert tuple", MyTransaction);
+
+ check = MyOperation->equal(SERVER_ID, (char*)&serverId);
+ CHECK_MINUS_ONE(check, "setValue id", MyTransaction);
+
+ check = MyOperation->setValue(SERVER_SUBSCRIBER_SUFFIX, suffix);
+ CHECK_MINUS_ONE(check, "setValue suffix", MyTransaction);
+
+ check = MyOperation->setValue(SERVER_NAME, name);
+ CHECK_MINUS_ONE(check, "setValue name", MyTransaction);
+
+ check = MyOperation->setValue(SERVER_READS, (char*)&noOfRead);
+ CHECK_MINUS_ONE(check, "setValue reads", MyTransaction);
+
+ check = MyOperation->setValue(SERVER_INSERTS, (char*)&noOfInsert);
+ CHECK_MINUS_ONE(check, "setValue inserts", MyTransaction);
+
+ check = MyOperation->setValue(SERVER_DELETES, (char*)&noOfDelete);
+ CHECK_MINUS_ONE(check, "setValue deletes", MyTransaction);
+
+ return 0;
+}
+
+int userDbInsertSubscriber(UserHandle *uh,
+ SubscriberNumber number,
+ uint32 groupId,
+ SubscriberName name)
+{
+ int check;
+ uint32 activeSessions = 0;
+ Location l = 0;
+ ChangedBy changedBy; snprintf(changedBy, sizeof(changedBy), "ChangedBy");
+ ChangedTime changedTime; snprintf(changedTime, sizeof(changedTime), "ChangedTime");
+
+ NdbConnection * MyTransaction = 0;
+ if(uh->pCurrTrans != 0){
+ MyTransaction = uh->pCurrTrans;
+ } else {
+ uh->pCurrTrans = MyTransaction = uh->pNDB->startTransaction();
+ }
+ if (MyTransaction == NULL)
+ error_handler("startTranscation", uh->pNDB->getNdbError(), 0);
+
+ NdbOperation *MyOperation = MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
+ CHECK_NULL(MyOperation, "getNdbOperation", MyTransaction);
+
+ check = MyOperation->insertTuple();
+ CHECK_MINUS_ONE(check, "insertTuple", MyTransaction);
+
+ check = MyOperation->equal(SUBSCRIBER_NUMBER, number);
+ CHECK_MINUS_ONE(check, "equal", MyTransaction);
+
+ check = MyOperation->setValue(SUBSCRIBER_NAME, name);
+ CHECK_MINUS_ONE(check, "setValue name", MyTransaction);
+
+ check = MyOperation->setValue(SUBSCRIBER_GROUP, (char*)&groupId);
+ CHECK_MINUS_ONE(check, "setValue group", MyTransaction);
+
+ check = MyOperation->setValue(SUBSCRIBER_LOCATION, (char*)&l);
+ CHECK_MINUS_ONE(check, "setValue location", MyTransaction);
+
+ check = MyOperation->setValue(SUBSCRIBER_SESSIONS, (char*)&activeSessions);
+ CHECK_MINUS_ONE(check, "setValue sessions", MyTransaction);
+
+ check = MyOperation->setValue(SUBSCRIBER_CHANGED_BY, changedBy);
+ CHECK_MINUS_ONE(check, "setValue changedBy", MyTransaction);
+
+ check = MyOperation->setValue(SUBSCRIBER_CHANGED_TIME, changedTime);
+ CHECK_MINUS_ONE(check, "setValue changedTime", MyTransaction);
+
+ return 0;
+}
+
+int userDbInsertGroup(UserHandle *uh,
+ GroupId groupId,
+ GroupName name,
+ Permission allowRead,
+ Permission allowInsert,
+ Permission allowDelete)
+{
+ int check;
+
+ NdbConnection * MyTransaction = 0;
+ if(uh->pCurrTrans != 0){
+ MyTransaction = uh->pCurrTrans;
+ } else {
+ uh->pCurrTrans = MyTransaction = uh->pNDB->startTransaction();
+ }
+ if (MyTransaction == NULL)
+ error_handler("startTranscation", uh->pNDB->getNdbError(), 0);
+
+ NdbOperation *MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
+ CHECK_NULL(MyOperation, "getNdbOperation", MyTransaction);
+
+ check = MyOperation->insertTuple();
+ CHECK_MINUS_ONE(check, "insertTuple", MyTransaction);
+
+ check = MyOperation->equal(GROUP_ID, (char*)&groupId);
+ CHECK_MINUS_ONE(check, "equal", MyTransaction);
+
+ check = MyOperation->setValue(GROUP_NAME, name);
+ CHECK_MINUS_ONE(check, "setValue name", MyTransaction);
+
+ check = MyOperation->setValue(GROUP_ALLOW_READ, (char*)&allowRead);
+ CHECK_MINUS_ONE(check, "setValue allowRead", MyTransaction);
+
+ check = MyOperation->setValue(GROUP_ALLOW_INSERT, (char*)&allowInsert);
+ CHECK_MINUS_ONE(check, "setValue allowInsert", MyTransaction);
+
+ check = MyOperation->setValue(GROUP_ALLOW_DELETE, (char*)&allowDelete);
+ CHECK_MINUS_ONE(check, "setValue allowDelete", MyTransaction);
+
+ return 0;
+}
+
diff --git a/ndb/test/ndbapi/bench/userInterface.h b/ndb/test/ndbapi/bench/userInterface.h
new file mode 100644
index 00000000000..9e3b6f8f2a5
--- /dev/null
+++ b/ndb/test/ndbapi/bench/userInterface.h
@@ -0,0 +1,151 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef DBINTERFACE_H
+#define DBINTERFACE_H
+
+/***************************************************************/
+/* I N C L U D E D F I L E S */
+/***************************************************************/
+
+#include "testDefinitions.h"
+#include "testData.h"
+
+/***************************************************************
+* M A C R O S *
+***************************************************************/
+
+/***************************************************************/
+/* C O N S T A N T S */
+/***************************************************************/
+
+/*-----------------------*/
+/* Default Database Name */
+/*-----------------------*/
+#define DEFAULTDB "TestDbClient"
+
+/***************************************************************
+* D A T A S T R U C T U R E S *
+***************************************************************/
+
+/***************************************************************
+* P U B L I C F U N C T I O N S *
+***************************************************************/
+
+typedef struct Ndb Ndb;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ extern void showTime();
+ extern double userGetTime(void);
+ extern Ndb *asyncDbConnect(int parallellism);
+ extern void asyncDbDisconnect(Ndb* pNDB);
+
+ extern void start_T1(Ndb * uh, ThreadData * data, int async);
+ extern void start_T2(Ndb * uh, ThreadData * data, int async);
+ extern void start_T3(Ndb * uh, ThreadData * data, int async);
+ extern void start_T4(Ndb * uh, ThreadData * data, int async);
+ extern void start_T5(Ndb * uh, ThreadData * data, int async);
+
+ extern void complete_T1(ThreadData * data);
+ extern void complete_T2(ThreadData * data);
+ extern void complete_T3(ThreadData * data);
+ extern void complete_T4(ThreadData * data);
+ extern void complete_T5(ThreadData * data);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+/***************************************************************/
+/* I N C L U D E D F I L E S */
+/***************************************************************/
+
+#include "testDefinitions.h"
+
+/***************************************************************
+* M A C R O S *
+***************************************************************/
+
+/***************************************************************/
+/* C O N S T A N T S */
+/***************************************************************/
+
+/*-----------------------*/
+/* Default Database Name */
+/*-----------------------*/
+#define DEFAULTDB "TestDbClient"
+
+/***************************************************************
+* D A T A S T R U C T U R E S *
+***************************************************************/
+
+typedef struct {
+ struct Ndb_cluster_connection* pNCC;
+ struct Ndb * pNDB;
+ struct NdbConnection * pCurrTrans;
+} UserHandle;
+
+/***************************************************************
+* P U B L I C F U N C T I O N S *
+***************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern double userGetTimeSync(void);
+
+extern void userCheckpoint(UserHandle *uh);
+
+extern UserHandle *userDbConnect(uint32 createDb, char *dbName);
+extern void userDbDisconnect(UserHandle *uh);
+
+extern int userDbInsertServer(UserHandle *uh,
+ ServerId serverId,
+ SubscriberSuffix suffix,
+ ServerName name);
+
+extern int userDbInsertSubscriber(UserHandle *uh,
+ SubscriberNumber number,
+ uint32 groupId,
+ SubscriberName name);
+
+extern int userDbInsertGroup(UserHandle *uh,
+ GroupId groupId,
+ GroupName name,
+ Permission allowRead,
+ Permission allowInsert,
+ Permission allowDelete);
+
+ extern int userDbCommit(UserHandle *uh);
+ extern int userDbRollback(UserHandle *uh);
+
+#ifdef __cplusplus
+}
+#endif
+
+/***************************************************************
+* E X T E R N A L D A T A *
+***************************************************************/
+
+#endif /* DBINTERFACE_H */
+