00001 #include <sys/types.h>
00002 #include <sys/time.h>
00003
00004 #include <ctype.h>
00005 #include <stdio.h>
00006 #include <stdlib.h>
00007 #include <string.h>
00008 #include <unistd.h>
00009
00010 #include <tx.h>
00011 #include <atmi.h>
00012 #include <fml32.h>
00013 #include <fml1632.h>
00014
00015 #include <db.h>
00016
00017 #include "datafml.h"
00018 #include "hdbrec.h"
00019 #include "hcommonxa.h"
00020 #include "htimestampxa.h"
00021
00022 #define HOME "../data"
00023 #define TABLE1 "../data/table1.db"
00024 #define TABLE3 "../data/table3.db"
00025
00026 #ifdef VERBOSE
00027 static int verbose = 1;
00028 #else
00029 static int verbose = 0;
00030 #endif
00031
00032 DB_ENV *dbenv;
00033 char *progname;
00034
00035 int check_data(DB *);
00036 char *db_buf(DBT *);
00037 int usage(void);
00038
00039 int
00040 main(int argc, char* argv[])
00041 {
00042 DB *dbp3;
00043 DBT key, data;
00044 FBFR *buf, *replyBuf;
00045 HDbRec rec;
00046 TPINIT *initBuf;
00047 long len, replyLen, seqNo;
00048 int ch, cnt, cnt_abort, cnt_commit, cnt_server1, i, ret;
00049 char *target;
00050
00051 progname = argv[0];
00052
00053 buf = replyBuf = NULL;
00054 initBuf = NULL;
00055 cnt = 1000;
00056 cnt_abort = cnt_commit = cnt_server1 = 0;
00057
00058 while ((ch = getopt(argc, argv, "n:v")) != EOF)
00059 switch (ch) {
00060 case 'n':
00061 cnt = atoi(optarg);
00062 break;
00063 case 'v':
00064 verbose = 1;
00065 break;
00066 case '?':
00067 default:
00068 return (usage());
00069 }
00070 argc -= optind;
00071 argv += optind;
00072
00073 if (verbose)
00074 printf("%s: called\n", progname);
00075
00076
00077 srand((u_int)(time(NULL) | getpid()));
00078
00079 if (tpinit((TPINIT *)NULL) == -1)
00080 goto tuxedo_err;
00081 if (verbose)
00082 printf("%s: tpinit() OK\n", progname);
00083
00084
00085 if((initBuf = (TPINIT *)tpalloc("TPINIT", NULL, TPINITNEED(0))) == 0)
00086 goto tuxedo_err;
00087 if (verbose)
00088 printf("%s: tpalloc(\"TPINIT\") OK\n", progname);
00089
00090
00091 if ((ret = db_env_create(&dbenv, 0)) != 0 ||
00092 (ret = dbenv->open(dbenv, HOME, DB_JOINENV, 0)) != 0) {
00093 fprintf(stderr,
00094 "%s: %s: %s\n", progname, HOME, db_strerror(ret));
00095 goto err;
00096 }
00097 dbenv->set_errfile(dbenv, stderr);
00098 if (verbose)
00099 printf("%s: opened %s OK\n", progname, HOME);
00100
00101
00102 if ((ret = db_create(&dbp3, dbenv, 0)) != 0 ||
00103 (ret = dbp3->open(dbp3,
00104 NULL, TABLE3, NULL, DB_BTREE, DB_CREATE, 0660)) != 0) {
00105 fprintf(stderr,
00106 "%s: %s %s\n", progname, TABLE3, db_strerror(ret));
00107 goto err;
00108 }
00109 if (verbose)
00110 printf("%s: opened/truncated %s OK\n", progname, TABLE3);
00111
00112
00113 len = Fneeded(1, 3 * sizeof(long));
00114 if ((buf = (FBFR*)tpalloc("FML32", NULL, len)) == 0)
00115 goto tuxedo_err;
00116 if (verbose)
00117 printf("%s: tpalloc(\"FML32\"), send buffer OK\n", progname);
00118
00119
00120 replyLen = 1024;
00121 if ((replyBuf = (FBFR*)tpalloc("FML32", NULL, replyLen)) == NULL)
00122 goto tuxedo_err;
00123 if (verbose)
00124 printf("%s: tpalloc(\"FML32\"), reply buffer OK\n", progname);
00125
00126 memset(&key, 0, sizeof(key));
00127 memset(&data, 0, sizeof(data));
00128 for (rec.SeqNo = 1, i = 0; i < cnt; ++i, ++rec.SeqNo) {
00129 GetTime(&rec.Ts);
00130
00131 if (Fchg(buf, SEQ_NO, 0, (char *)&rec.SeqNo, 0) == -1)
00132 goto tuxedo_fml_err;
00133 if (verbose)
00134 printf("%s: Fchg(), sequence number OK\n", progname);
00135 if (Fchg(buf, TS_SEC, 0, (char *)&rec.Ts.Sec, 0) == -1)
00136 goto tuxedo_fml_err;
00137 if (verbose)
00138 printf("%s: Fchg(), seconds OK\n", progname);
00139 if (Fchg(buf, TS_USEC, 0, (char *)&rec.Ts.Usec, 0) == -1)
00140 goto tuxedo_fml_err;
00141 if (verbose)
00142 printf("%s: Fchg(), microseconds OK\n", progname);
00143
00144 if (tpbegin(60L, 0L) == -1)
00145 goto tuxedo_err;
00146 if (verbose)
00147 printf("%s: tpbegin() OK\n", progname);
00148
00149
00150 if (rand() % 2 > 0) {
00151 ++cnt_server1;
00152 target = "TestTxn1";
00153 } else
00154 target = "TestTxn2";
00155 if (tpcall(target, (char *)buf,
00156 0L, (char **)&replyBuf, &replyLen, TPSIGRSTRT) == -1)
00157 goto tuxedo_err;
00158
00159
00160 if (tpurcode == 0) {
00161 ++cnt_commit;
00162 if (verbose)
00163 printf("%s: txn success\n", progname);
00164
00165 if (tpcommit(0L) == -1)
00166 goto tuxedo_err;
00167 if (verbose)
00168 printf("%s: tpcommit() OK\n", progname);
00169
00170
00171
00172
00173
00174
00175 seqNo = rec.SeqNo;
00176 key.data = &seqNo;
00177 key.size = sizeof(seqNo);
00178 data.data = &rec;
00179 data.size = sizeof(rec);
00180 if ((ret =
00181 dbp3->put(dbp3, NULL, &key, &data, 0)) != 0) {
00182 fprintf(stderr, "%s: DB->put: %s %s\n",
00183 progname, TABLE3, db_strerror(ret));
00184 goto err;
00185 }
00186 } else {
00187 ++cnt_abort;
00188 if (verbose)
00189 printf("%s: txn failure\n", progname);
00190
00191 if (tpabort(0L) == -1)
00192 goto tuxedo_err;
00193 if (verbose)
00194 printf("%s: tpabort() OK\n", progname);
00195 }
00196 }
00197
00198 printf("%s: %d requests: %d committed, %d aborted\n",
00199 progname, cnt, cnt_commit, cnt_abort);
00200 printf("%s: %d sent to server #1, %d sent to server #2\n",
00201 progname, cnt_server1, cnt - cnt_server1);
00202
00203 ret = check_data(dbp3);
00204
00205 if (0) {
00206 tuxedo_err: fprintf(stderr, "%s: TUXEDO ERROR: %s (code %d)\n",
00207 progname, tpstrerror(tperrno), tperrno);
00208 goto err;
00209 }
00210 if (0) {
00211 tuxedo_fml_err: fprintf(stderr, "%s: FML ERROR: %s (code %d)\n",
00212 progname, Fstrerror(Ferror), Ferror);
00213 }
00214 if (0) {
00215 err: ret = EXIT_FAILURE;
00216 }
00217
00218 if (replyBuf != NULL)
00219 tpfree((char *)replyBuf);
00220 if (buf != NULL)
00221 tpfree((char *)buf);
00222 if (initBuf != NULL)
00223 tpfree((char *)initBuf);
00224 if (dbp3 != NULL)
00225 (void)dbp3->close(dbp3, 0);
00226 if (dbenv != NULL)
00227 (void)dbenv->close(dbenv, 0);
00228
00229 tpterm();
00230 if (verbose)
00231 printf("%s: tpterm() OK\n", progname);
00232
00233 return (ret);
00234 }
00235
00236
00237
00238
00239
00240 int
00241 check_data(dbp3)
00242 DB *dbp3;
00243 {
00244 DB *dbp1;
00245 DBC *dbc1, *dbc3;
00246 DBT key1, data1, key3, data3;
00247 int ret, ret1, ret3;
00248
00249 dbp1 = NULL;
00250 dbc1 = dbc3 = NULL;
00251
00252
00253 if ((ret = db_create(&dbp1, dbenv, 0)) != 0 ||
00254 (ret = dbp1->open(
00255 dbp1, NULL, TABLE1, NULL, DB_UNKNOWN, DB_RDONLY, 0)) != 0) {
00256 fprintf(stderr,
00257 "%s: %s: %s\n", progname, TABLE1, db_strerror(ret));
00258 goto err;
00259 }
00260 if (verbose)
00261 printf("%s: opened %s OK\n", progname, TABLE1);
00262
00263
00264 if ((ret = dbp1->cursor(dbp1, NULL, &dbc1, 0)) != 0 ||
00265 (ret = dbp3->cursor(dbp3, NULL, &dbc3, 0)) != 0) {
00266 fprintf(stderr,
00267 "%s: DB->cursor: %s\n", progname, db_strerror(ret));
00268 goto err;
00269 }
00270 if (verbose)
00271 printf("%s: opened cursors OK\n", progname);
00272
00273
00274 memset(&key1, 0, sizeof(key1));
00275 memset(&data1, 0, sizeof(data1));
00276 memset(&key3, 0, sizeof(key3));
00277 memset(&data3, 0, sizeof(data3));
00278 for (;;) {
00279 ret1 = dbc1->c_get(dbc1, &key1, &data1, DB_NEXT);
00280 ret3 = dbc3->c_get(dbc3, &key3, &data3, DB_NEXT);
00281 if (verbose) {
00282 printf("get: key1: %s\n", db_buf(&key1));
00283 printf("get: key3: %s\n", db_buf(&key3));
00284 printf("get: data1: %s\n", db_buf(&data1));
00285 printf("get: data3: %s\n", db_buf(&data3));
00286 }
00287 if (ret1 != 0 || ret3 != 0)
00288 break;
00289
00290
00291
00292
00293 if (key1.size != key3.size ||
00294 memcmp(key1.data, key3.data, key1.size) != 0 ||
00295 data1.size != data3.size ||
00296 memcmp(data1.data, data3.data,
00297 sizeof(long) + sizeof(HTimestampData)) != 0)
00298 goto mismatch;
00299 }
00300 if (ret1 != DB_NOTFOUND || ret3 != DB_NOTFOUND) {
00301 mismatch: fprintf(stderr,
00302 "%s: DB_ERROR: databases 1 and 3 weren't identical\n",
00303 progname);
00304 ret = 1;
00305 }
00306
00307 err: if (dbc1 != NULL)
00308 (void)dbc1->c_close(dbc1);
00309 if (dbc3 != NULL)
00310 (void)dbc3->c_close(dbc1);
00311 if (dbp1 != NULL)
00312 (void)dbp1->close(dbp1, 0);
00313
00314 return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
00315 }
00316
00317 char *
00318 db_buf(dbt)
00319 DBT *dbt;
00320 {
00321 static u_char buf[1024];
00322 size_t len;
00323 u_char *p, *b;
00324
00325 for (p = dbt->data, len = dbt->size, b = buf; len > 0; ++p, --len)
00326 if (isprint(*p))
00327 b += sprintf((char *)b, "%c", *p);
00328 else
00329 b += sprintf((char *)b, "%#o", *p);
00330 return ((char *)buf);
00331 }
00332
00333 int
00334 usage()
00335 {
00336 fprintf(stderr, "usage: %s [-v] [-n txn]\n", progname);
00337 return (EXIT_FAILURE);
00338 }