MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
delete_all.cpp
1 /*
2  Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
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 as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 #include <ndb_global.h>
19 #include <ndb_opts.h>
20 
21 #include <NdbOut.hpp>
22 #include <NdbApi.hpp>
23 #include <NdbSleep.h>
24 #include <NDBT.hpp>
25 
26 static int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab,
27  bool fetch_across_commit, int parallelism=240);
28 
29 const char *load_default_groups[]= { "mysql_cluster",0 };
30 
31 static const char* _dbname = "TEST_DB";
32 static my_bool _transactional = false;
33 static my_bool _tupscan = 0;
34 static my_bool _diskscan = 0;
35 
36 static struct my_option my_long_options[] =
37 {
38  NDB_STD_OPTS("ndb_desc"),
39  { "database", 'd', "Name of database table is in",
40  (uchar**) &_dbname, (uchar**) &_dbname, 0,
41  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
42  { "transactional", 't', "Single transaction (may run out of operations)",
43  (uchar**) &_transactional, (uchar**) &_transactional, 0,
44  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
45  { "tupscan", NDB_OPT_NOSHORT, "Run tupscan",
46  (uchar**) &_tupscan, (uchar**) &_tupscan, 0,
47  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
48  { "diskscan", NDB_OPT_NOSHORT, "Run diskcan",
49  (uchar**) &_diskscan, (uchar**) &_diskscan, 0,
50  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
51  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
52 };
53 
54 static void short_usage_sub(void)
55 {
56  ndb_short_usage_sub(NULL);
57 }
58 
59 static void usage()
60 {
61  ndb_usage(short_usage_sub, load_default_groups, my_long_options);
62 }
63 
64 int main(int argc, char** argv){
65  NDB_INIT(argv[0]);
66  ndb_opt_set_usage_funcs(short_usage_sub, usage);
67  load_defaults("my",load_default_groups,&argc,&argv);
68  int ho_error;
69 #ifndef DBUG_OFF
70  opt_debug= "d:t:O,/tmp/ndb_delete_all.trace";
71 #endif
72  if ((ho_error=handle_options(&argc, &argv, my_long_options,
73  ndb_std_get_one_option)))
74  return NDBT_ProgramExit(NDBT_WRONGARGS);
75 
76  Ndb_cluster_connection con(opt_ndb_connectstring, opt_ndb_nodeid);
77  con.set_name("ndb_delete_all");
78  if(con.connect(12, 5, 1) != 0)
79  {
80  ndbout << "Unable to connect to management server." << endl;
81  return NDBT_ProgramExit(NDBT_FAILED);
82  }
83  if (con.wait_until_ready(30,0) < 0)
84  {
85  ndbout << "Cluster nodes not ready in 30 seconds." << endl;
86  return NDBT_ProgramExit(NDBT_FAILED);
87  }
88 
89  Ndb MyNdb(&con, _dbname );
90  if(MyNdb.init() != 0){
91  ERR(MyNdb.getNdbError());
92  return NDBT_ProgramExit(NDBT_FAILED);
93  }
94 
95  // Check if table exists in db
96  int res = NDBT_OK;
97  for(int i = 0; i<argc; i++){
98  const NdbDictionary::Table * pTab = NDBT_Table::discoverTableFromDb(&MyNdb, argv[i]);
99  if(pTab == NULL){
100  ndbout << " Table " << argv[i] << " does not exist!" << endl;
101  return NDBT_ProgramExit(NDBT_WRONGARGS);
102  }
103  ndbout << "Deleting all from " << argv[i];
104  if (! _transactional)
105  ndbout << " (non-transactional)";
106  ndbout << " ...";
107  if(clear_table(&MyNdb, pTab, ! _transactional) == NDBT_FAILED){
108  res = NDBT_FAILED;
109  ndbout << "FAILED" << endl;
110  }
111  }
112  return NDBT_ProgramExit(res);
113 }
114 
115 
116 int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab,
117  bool fetch_across_commit, int parallelism)
118 {
119  // Scan all records exclusive and delete
120  // them one by one
121  int retryAttempt = 0;
122  const int retryMax = 10;
123  int deletedRows = 0;
124  int check;
125  NdbTransaction *pTrans;
126  NdbScanOperation *pOp;
127  NdbError err;
128 
129  int par = parallelism;
130  while (true){
131  restart:
132  if (retryAttempt++ >= retryMax){
133  g_info << "ERROR: has retried this operation " << retryAttempt
134  << " times, failing!" << endl;
135  return NDBT_FAILED;
136  }
137 
138  pTrans = pNdb->startTransaction();
139  if (pTrans == NULL) {
140  err = pNdb->getNdbError();
141  if (err.status == NdbError::TemporaryError){
142  ERR(err);
143  NdbSleep_MilliSleep(50);
144  continue;
145  }
146  goto failed;
147  }
148 
149  pOp = pTrans->getNdbScanOperation(pTab->getName());
150  if (pOp == NULL) {
151  goto failed;
152  }
153 
154  int flags = 0;
155  flags |= _tupscan ? NdbScanOperation::SF_TupScan : 0;
156  flags |= _diskscan ? NdbScanOperation::SF_DiskScan : 0;
158  flags, par) ) {
159  goto failed;
160  }
161 
162  if(pTrans->execute(NdbTransaction::NoCommit) != 0){
163  err = pTrans->getNdbError();
164  if(err.status == NdbError::TemporaryError){
165  ERR(err);
166  pNdb->closeTransaction(pTrans);
167  NdbSleep_MilliSleep(50);
168  continue;
169  }
170  goto failed;
171  }
172 
173  while((check = pOp->nextResult(true)) == 0){
174  do {
175  if (pOp->deleteCurrentTuple() != 0){
176  goto failed;
177  }
178  deletedRows++;
179  } while((check = pOp->nextResult(false)) == 0);
180 
181  if(check != -1){
182  if (fetch_across_commit) {
183  check = pTrans->execute(NdbTransaction::Commit);
184  pTrans->restart(); // new tx id
185  } else {
186  check = pTrans->execute(NdbTransaction::NoCommit);
187  }
188  }
189 
190  err = pTrans->getNdbError();
191  if(check == -1){
192  if(err.status == NdbError::TemporaryError){
193  ERR(err);
194  pNdb->closeTransaction(pTrans);
195  NdbSleep_MilliSleep(50);
196  par = 1;
197  goto restart;
198  }
199  goto failed;
200  }
201  }
202  if(check == -1){
203  err = pTrans->getNdbError();
204  if(err.status == NdbError::TemporaryError){
205  ERR(err);
206  pNdb->closeTransaction(pTrans);
207  NdbSleep_MilliSleep(50);
208  par = 1;
209  goto restart;
210  }
211  goto failed;
212  }
213  if (! fetch_across_commit &&
214  pTrans->execute(NdbTransaction::Commit) != 0) {
215  err = pTrans->getNdbError();
216  goto failed;
217  }
218  pNdb->closeTransaction(pTrans);
219  return NDBT_OK;
220  }
221  return NDBT_FAILED;
222 
223  failed:
224  if(pTrans != 0) pNdb->closeTransaction(pTrans);
225  ERR(err);
226  return (err.code != 0 ? err.code : NDBT_FAILED);
227 }