1 /*-
2 * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved.
3 *
4 * See the file LICENSE for license information.
5 */
6
7 /*
8 * This is the MVCC test for XA. It runs 3 tests, which are as follows:
9 * 1. No MVCC
10 * 2. MVCC enabled by DB_CONFIG
11 * 3. MVCC enabled by flags
12 */
13 #include <sys/types.h>
14 #include <sys/time.h>
15
16 #include <ctype.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <unistd.h>
21
22 #include <tx.h>
23 #include <atmi.h>
24 #include <fml32.h>
25 #include <fml1632.h>
26
27 #include <db.h>
28
29 #include "../utilities/bdb_xa_util.h"
30
31 #define HOME "../data"
32 #define TABLE1 "../data/table1.db"
33 #define TABLE2 "../data/table2.db"
34 #define NUM_CLIENTS 2
35 #define NUM_TESTS 4
36 #define TIMEOUT 60
37
38 static int error = 1;
39
40 char *progname; /* Client run-time name. */
41
42 int
usage()43 usage()
44 {
45 fprintf(stderr, "usage: %s [-v] -t[0|1|2] -n [name]\n", progname);
46 return (EXIT_FAILURE);
47 }
48
49 enum test_type{NO_MVCC, MVCC_DBCONFIG, MVCC_FLAG};
50
51 void init_tests(char *ops[], int success[], int type, int client_num);
52
53 /*
54 *
55 */
call_server(char * client_name,int ttype)56 int call_server(char *client_name, int ttype)
57 {
58 char *ops[NUM_TESTS];
59 int commit, j, success[NUM_TESTS], client_num, ret;
60 TPINIT *initBuf = NULL;
61 FBFR *replyBuf = NULL;
62 long replyLen = 0;
63
64 client_num = atoi(client_name);
65 init_tests(ops, success, ttype, client_num);
66
67 if (verbose)
68 printf("%s:%s: starting client %i\n", progname, client_name,
69 client_num);
70
71 /* Allocate init buffer */
72 if ((initBuf = (TPINIT *)tpalloc("TPINIT", NULL, TPINITNEED(0))) == 0)
73 goto tuxedo_err;
74
75 if (tpinit(initBuf) == -1)
76 goto tuxedo_err;
77 if (verbose)
78 printf("%s:%s: tpinit() OK\n", progname, client_name);
79
80 /* Allocate reply buffer. */
81 replyLen = 1024;
82 if ((replyBuf = (FBFR*)tpalloc("FML32", NULL, replyLen)) == NULL)
83 goto tuxedo_err;
84 if (verbose)
85 printf("%s:%s: tpalloc(\"FML32\"), reply buffer OK\n",
86 progname, client_name);
87
88 for (j = 0; j < NUM_TESTS; j++) {
89 commit = 1;
90
91 /* Sync Apps. */
92 if ((ret = sync_clients(client_num, NUM_CLIENTS, 1, j)) != 0) {
93 fprintf(stderr,
94 "%s:%s: Error syncing clients: %i \n",
95 progname, client_name, ret);
96 goto end;
97 }
98
99 /* Begin the XA transaction. */
100 if (tpbegin(TIMEOUT, 0L) == -1)
101 goto tuxedo_err;
102 if (verbose)
103 printf("%s:%s: tpbegin() OK\n", progname, client_name);
104
105 /* Force client 2 to wait till client 1 does its operation.*/
106 if (client_num == 2) {
107 if ((ret = sync_clients(client_num, NUM_CLIENTS, 2, j)) != 0) {
108 fprintf(stderr,
109 "%s:%s: Error syncing client 1: %i \n",
110 progname, client_name, ret);
111 goto end;
112 }
113 }
114 if (verbose)
115 printf("%s:%s: calling server %s\n", progname,
116 client_name, ops[j]);
117
118 /* Read or insert into the database. */
119 if (tpcall(ops[j], NULL, 0L, (char **)&replyBuf,
120 &replyLen, 0) == -1)
121 goto tuxedo_err;
122
123 /* Wake up client 2.*/
124 if (client_num == 1) {
125 if ((ret = sync_clients(client_num, NUM_CLIENTS, 2, j)) != 0) {
126 fprintf(stderr,
127 "%s:%s: Error syncing client 1: %i \n",
128 progname, client_name, ret);
129 goto end;
130 }
131 }
132
133 /* Sync both clients. */
134 if ((ret = sync_clients(client_num, NUM_CLIENTS, 3, j)) != 0) {
135 fprintf(stderr,
136 "%s:%s: Error syncing clients: %i \n",
137 progname, client_name, ret);
138 goto end;
139 }
140
141 /*
142 * Commit or abort the transaction depending the what the
143 * server returns. Check that it matched expectation
144 * (We abort on LOCK_NOTGRANTED and DEADLOCK errors, and
145 * commit otherwise. Other errors result in returning
146 * without committing or aborting.
147 */
148 commit = !tpurcode;
149 if (commit != success[j]) {
150 fprintf(stderr,
151 "%s:%s: Expected: %i Got: %i.\n",
152 progname, client_name, success[j], commit);
153 if (verbose) {
154 printf("%s:%s: Expected: %i Got: %i.\n",
155 progname, client_name, success[j], commit);
156 }
157 }
158
159 if (commit) {
160 if (tpcommit(0L) == -1)
161 goto tuxedo_err;
162 if (verbose) {
163 printf("%s:%s: tpcommit() OK\n", progname,
164 client_name);
165 }
166 } else {
167 if (tpabort(0L) == -1) {
168 goto tuxedo_err;
169 }
170 if (verbose) {
171 printf("%s:%s: tpabort() OK\n", progname,
172 client_name);
173 }
174 }
175 }
176
177 if (0) {
178 tuxedo_err: fprintf(stderr, "%s:%s: TUXEDO ERROR: %s (code %d)\n",
179 progname, client_name, tpstrerror(tperrno), tperrno);
180 ret = -1;
181 }
182 end: tpterm();
183 if (verbose)
184 printf("%s:%s: tpterm() OK\n", progname, client_name);
185
186 if (initBuf != NULL)
187 tpfree((char *)initBuf);
188
189 if (replyBuf != NULL)
190 tpfree((char *)replyBuf);
191
192 return(ret);
193 }
194
195 /*
196 * Call the servers, and check that data in the two
197 * databases is identical.
198 */
199 int
main(int argc,char * argv[])200 main(int argc, char* argv[])
201 {
202 int ch, i, ret, ttype;
203 char *name;
204
205 progname = argv[0];
206 i = 1;
207 verbose = 0;
208
209 while ((ch = getopt(argc, argv, "vt:n:")) != EOF) {
210 switch (ch) {
211 case 'n':
212 name = argv[++i];
213 break;
214 case 't':
215 ttype = atoi(argv[++i]);
216 break;
217 case 'v':
218 verbose = 1;
219 break;
220 case '?':
221 default:
222 return (usage());
223 }
224 i++;
225 }
226
227 if (ttype > 2 || ttype < 0)
228 return (usage());
229
230 if (verbose)
231 printf("%s: called with type %i\n", progname, ttype);
232
233 if (call_server(name, ttype) != 0)
234 goto err;
235
236 if (0) {
237 err: ret = EXIT_FAILURE;
238 }
239
240 return (ret);
241 }
242
243 static char *rdb1 = "read_db1";
244 static char *wdb1 = "write_db1";
245
246 /*
247 * Operation Success
248 * client 1 client 2 no MVCC MVCC
249 * write write no no
250 * write read no yes
251 * read read yes yes
252 * read write no yes
253 */
init_tests(char * ops[],int success[],int type,int client_num)254 void init_tests(char *ops[], int success[], int type, int client_num)
255 {
256 if (client_num == 1) {
257 ops[0] = wdb1;
258 ops[1] = wdb1;
259 ops[2] = rdb1;
260 ops[3] = rdb1;
261 /* client 1 is always successful. */
262 success[0] = 1;
263 success[1] = 1;
264 success[2] = 1;
265 success[3] = 1;
266 } else {
267 ops[0] = wdb1;
268 ops[1] = rdb1;
269 ops[2] = rdb1;
270 ops[3] = wdb1;
271 if (type == NO_MVCC) {
272 success[0] = 0;
273 success[1] = 0;
274 success[2] = 1;
275 success[3] = 0;
276 } else {
277 success[0] = 0;
278 success[1] = 1;
279 success[2] = 1;
280 success[3] = 1;
281 }
282 }
283 }
284