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