1 /*
2 Copyright (c) 2007, 2021, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #include <ndb_global.h>
26 #include <ndb_opts.h>
27 #include <NDBT.hpp>
28 #include <NdbApi.hpp>
29 #include <NdbSleep.h>
30
31 static int opt_loop = 25;
32 static int opt_sleep = 25;
33 static int opt_drop = 1;
34 static int opt_subloop = 5;
35 static int opt_wait_all = 0;
36
37 static struct my_option my_long_options[] =
38 {
39 NDB_STD_OPTS("ndb_connect"),
40 { "loop", 'l', "loops",
41 (uchar**) &opt_loop, (uchar**) &opt_loop, 0,
42 GET_INT, REQUIRED_ARG, opt_loop, 0, 0, 0, 0, 0 },
43 { "sleep", 's', "Sleep (ms) between connection attempt",
44 (uchar**) &opt_sleep, (uchar**) &opt_sleep, 0,
45 GET_INT, REQUIRED_ARG, opt_sleep, 0, 0, 0, 0, 0 },
46 { "drop", 'd',
47 "Drop event operations before disconnect (0 = no, 1 = yes, else rand",
48 (uchar**) &opt_drop, (uchar**) &opt_drop, 0,
49 GET_INT, REQUIRED_ARG, opt_drop, 0, 0, 0, 0, 0 },
50 { "subscribe-loop", NDB_OPT_NOSHORT,
51 "Loop in subscribe/unsubscribe",
52 (uchar**) &opt_subloop, (uchar**) &opt_subloop, 0,
53 GET_INT, REQUIRED_ARG, opt_subloop, 0, 0, 0, 0, 0 },
54 { "wait-all", NDB_OPT_NOSHORT,
55 "Wait for all ndb-nodes (i.e not only some)",
56 (uchar**) &opt_wait_all, (uchar**) &opt_wait_all, 0,
57 GET_INT, REQUIRED_ARG, opt_wait_all, 0, 0, 0, 0, 0 },
58 { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
59 };
60
main(int argc,char ** argv)61 int main(int argc, char** argv){
62 NDB_INIT(argv[0]);
63
64 const char *load_default_groups[]= { "mysql_cluster",0 };
65 ndb_load_defaults(NULL, load_default_groups,&argc,&argv);
66 int ho_error;
67 #ifndef NDEBUG
68 opt_debug= "d:t:O,/tmp/ndb_connect.trace";
69 #endif
70 if ((ho_error=handle_options(&argc, &argv, my_long_options,
71 ndb_std_get_one_option)))
72 return NDBT_ProgramExit(NDBT_WRONGARGS);
73
74 for (int i = 0; i<opt_loop; i++)
75 {
76 Ndb_cluster_connection con(opt_ndb_connectstring, opt_ndb_nodeid);
77 if(con.connect(12, 5, 1) != 0)
78 {
79 ndbout << "Unable to connect to management server."
80 << "loop: " << i << "(of " << opt_loop << ")"
81 << endl;
82 return NDBT_ProgramExit(NDBT_FAILED);
83 }
84
85 int res = con.wait_until_ready(30,30);
86 if (res < 0 || (opt_wait_all && res != 0))
87 {
88 ndbout
89 << "nodeid: " << con.node_id()
90 << "loop: " << i << "(of " << opt_loop << ")"
91 << " - Cluster nodes not ready in 30 seconds." << endl;
92 return NDBT_ProgramExit(NDBT_FAILED);
93 }
94
95 Ndb MyNdb(&con, "TEST_DB");
96 if(MyNdb.init() != 0){
97 NDB_ERR(MyNdb.getNdbError());
98 return NDBT_ProgramExit(NDBT_FAILED);
99 }
100
101 for (int k = opt_subloop; k >= 1; k--)
102 {
103 if (k > 1 && ((k % 25) == 0))
104 {
105 ndbout_c("subscribe/unsubscribe: %u", opt_subloop - k);
106 }
107 Vector<NdbEventOperation*> ops;
108 const NdbDictionary::Dictionary * dict= MyNdb.getDictionary();
109 for (int j = 0; j < argc; j++)
110 {
111 const NdbDictionary::Table * pTab = dict->getTable(argv[j]);
112 if (pTab == 0)
113 {
114 ndbout_c("Failed to retreive table: \"%s\"", argv[j]);
115 }
116
117 BaseString tmp;
118 tmp.appfmt("EV-%s", argv[j]);
119 NdbEventOperation* pOp = MyNdb.createEventOperation(tmp.c_str());
120 if ( pOp == NULL )
121 {
122 ndbout << "Event operation creation failed: " <<
123 MyNdb.getNdbError() << endl;
124 return NDBT_ProgramExit(NDBT_FAILED);
125 }
126
127 for (int a = 0; a < pTab->getNoOfColumns(); a++)
128 {
129 pOp->getValue(pTab->getColumn(a)->getName());
130 pOp->getPreValue(pTab->getColumn(a)->getName());
131 }
132
133 ops.push_back(pOp);
134 if (pOp->execute())
135 {
136 ndbout << "operation execution failed: " << pOp->getNdbError()
137 << endl;
138 k = 1;
139 }
140 }
141
142 if (opt_sleep)
143 {
144 NdbSleep_MilliSleep(10 + rand() % opt_sleep);
145 }
146 else
147 {
148 ndbout_c("NDBT_ProgramExit: SLEEPING OK");
149 while(true) NdbSleep_SecSleep(5);
150 }
151
152 for (Uint32 i = 0; i<ops.size(); i++)
153 {
154 switch(k == 1 ? opt_drop : 1){
155 case 0:
156 break;
157 do_drop:
158 case 1:
159 if (MyNdb.dropEventOperation(ops[i]))
160 {
161 ndbout << "drop event operation failed "
162 << MyNdb.getNdbError() << endl;
163 return NDBT_ProgramExit(NDBT_FAILED);
164 }
165 break;
166 default:
167 if ((rand() % 100) > 50)
168 goto do_drop;
169 }
170 }
171 }
172 }
173
174 return NDBT_ProgramExit(NDBT_OK);
175 }
176
177 template class Vector<NdbEventOperation*>;
178