MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
main.cpp
1 /*
2  Copyright (c) 2006, 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 /*
19  * ndbapi_simple_dual.cpp: Using synchronous transactions in NDB API
20  *
21  * Correct output from this program is:
22  *
23  * ATTR1 ATTR2
24  * 0 10
25  * 1 1
26  * 2 12
27  * Detected that deleted tuple doesn't exist!
28  * 4 14
29  * 5 5
30  * 6 16
31  * 7 7
32  * 8 18
33  * 9 9
34  * ATTR1 ATTR2
35  * 0 10
36  * 1 1
37  * 2 12
38  * Detected that deleted tuple doesn't exist!
39  * 4 14
40  * 5 5
41  * 6 16
42  * 7 7
43  * 8 18
44  * 9 9
45  *
46  */
47 
48 #include <mysql.h>
49 #include <NdbApi.hpp>
50 // Used for cout
51 #include <stdio.h>
52 #include <iostream>
53 
54 static void run_application(MYSQL &, Ndb_cluster_connection &, const char* table, const char* db);
55 
56 #define PRINT_ERROR(code,msg) \
57  std::cout << "Error in " << __FILE__ << ", line: " << __LINE__ \
58  << ", code: " << code \
59  << ", msg: " << msg << "." << std::endl
60 #define MYSQLERROR(mysql) { \
61  PRINT_ERROR(mysql_errno(&mysql),mysql_error(&mysql)); \
62  exit(-1); }
63 #define APIERROR(error) { \
64  PRINT_ERROR(error.code,error.message); \
65  exit(-1); }
66 
67 int main(int argc, char** argv)
68 {
69  if (argc != 5)
70  {
71  std::cout << "Arguments are <socket mysqld1> <connect_string cluster 1> <socket mysqld2> <connect_string cluster 2>.\n";
72  exit(-1);
73  }
74  // ndb_init must be called first
75  ndb_init();
76  {
77  char * mysqld1_sock = argv[1];
78  const char *connectstring1 = argv[2];
79  char * mysqld2_sock = argv[3];
80  const char *connectstring2 = argv[4];
81 
82  // Object representing the cluster 1
83  Ndb_cluster_connection cluster1_connection(connectstring1);
84  MYSQL mysql1;
85  // Object representing the cluster 2
86  Ndb_cluster_connection cluster2_connection(connectstring2);
87  MYSQL mysql2;
88 
89  // connect to mysql server and cluster 1 and run application
90  // Connect to cluster 1 management server (ndb_mgmd)
91  if (cluster1_connection.connect(4 /* retries */,
92  5 /* delay between retries */,
93  1 /* verbose */))
94  {
95  std::cout << "Cluster 1 management server was not ready within 30 secs.\n";
96  exit(-1);
97  }
98  // Optionally connect and wait for the storage nodes (ndbd's)
99  if (cluster1_connection.wait_until_ready(30,0) < 0)
100  {
101  std::cout << "Cluster 1 was not ready within 30 secs.\n";
102  exit(-1);
103  }
104  // connect to mysql server in cluster 1
105  if ( !mysql_init(&mysql1) ) {
106  std::cout << "mysql_init failed\n";
107  exit(-1);
108  }
109  if ( !mysql_real_connect(&mysql1, "localhost", "root", "", "",
110  0, mysqld1_sock, 0) )
111  MYSQLERROR(mysql1);
112 
113 
114  // connect to mysql server and cluster 2 and run application
115 
116  // Connect to cluster management server (ndb_mgmd)
117  if (cluster2_connection.connect(4 /* retries */,
118  5 /* delay between retries */,
119  1 /* verbose */))
120  {
121  std::cout << "Cluster 2 management server was not ready within 30 secs.\n";
122  exit(-1);
123  }
124  // Optionally connect and wait for the storage nodes (ndbd's)
125  if (cluster2_connection.wait_until_ready(30,0) < 0)
126  {
127  std::cout << "Cluster 2 was not ready within 30 secs.\n";
128  exit(-1);
129  }
130  // connect to mysql server in cluster 2
131  if ( !mysql_init(&mysql2) ) {
132  std::cout << "mysql_init failed\n";
133  exit(-1);
134  }
135  if ( !mysql_real_connect(&mysql2, "localhost", "root", "", "",
136  0, mysqld2_sock, 0) )
137  MYSQLERROR(mysql2);
138 
139  // run the application code
140  run_application(mysql1, cluster1_connection, "api_simple_dual_1", "ndb_examples");
141  run_application(mysql2, cluster2_connection, "api_simple_dual_2", "ndb_examples");
142  }
143  // Note: all connections must have been destroyed before calling ndb_end()
144  ndb_end(0);
145 
146  return 0;
147 }
148 
149 static void create_table(MYSQL &, const char* table);
150 static void do_insert(Ndb &, const char* table);
151 static void do_update(Ndb &, const char* table);
152 static void do_delete(Ndb &, const char* table);
153 static void do_read(Ndb &, const char* table);
154 
155 static void run_application(MYSQL &mysql,
156  Ndb_cluster_connection &cluster_connection,
157  const char* table,
158  const char* db)
159 {
160  /********************************************
161  * Connect to database via mysql-c *
162  ********************************************/
163  char db_stmt[256];
164  sprintf(db_stmt, "CREATE DATABASE %s\n", db);
165  mysql_query(&mysql, db_stmt);
166  sprintf(db_stmt, "USE %s", db);
167  if (mysql_query(&mysql, db_stmt) != 0) MYSQLERROR(mysql);
168  create_table(mysql, table);
169 
170  /********************************************
171  * Connect to database via NdbApi *
172  ********************************************/
173  // Object representing the database
174  Ndb myNdb( &cluster_connection, db );
175  if (myNdb.init()) APIERROR(myNdb.getNdbError());
176 
177  /*
178  * Do different operations on database
179  */
180  do_insert(myNdb, table);
181  do_update(myNdb, table);
182  do_delete(myNdb, table);
183  do_read(myNdb, table);
184  /*
185  * Drop the table
186  */
187  mysql_query(&mysql, db_stmt);
188 }
189 
190 /*********************************************************
191  * Create a table named by table if it does not exist *
192  *********************************************************/
193 static void create_table(MYSQL &mysql, const char* table)
194 {
195  char create_stmt[256];
196 
197  sprintf(create_stmt, "CREATE TABLE %s \
198  (ATTR1 INT UNSIGNED NOT NULL PRIMARY KEY,\
199  ATTR2 INT UNSIGNED NOT NULL)\
200  ENGINE=NDB", table);
201  if (mysql_query(&mysql, create_stmt))
202  MYSQLERROR(mysql);
203 }
204 
205 
206 /**************************************************************************
207  * Using 5 transactions, insert 10 tuples in table: (0,0),(1,1),...,(9,9) *
208  **************************************************************************/
209 static void do_insert(Ndb &myNdb, const char* table)
210 {
211  const NdbDictionary::Dictionary* myDict= myNdb.getDictionary();
212  const NdbDictionary::Table *myTable= myDict->getTable(table);
213 
214  if (myTable == NULL)
215  APIERROR(myDict->getNdbError());
216 
217  for (int i = 0; i < 5; i++) {
218  NdbTransaction *myTransaction= myNdb.startTransaction();
219  if (myTransaction == NULL) APIERROR(myNdb.getNdbError());
220 
221  NdbOperation *myOperation= myTransaction->getNdbOperation(myTable);
222  if (myOperation == NULL) APIERROR(myTransaction->getNdbError());
223 
224  myOperation->insertTuple();
225  myOperation->equal("ATTR1", i);
226  myOperation->setValue("ATTR2", i);
227 
228  myOperation= myTransaction->getNdbOperation(myTable);
229  if (myOperation == NULL) APIERROR(myTransaction->getNdbError());
230 
231  myOperation->insertTuple();
232  myOperation->equal("ATTR1", i+5);
233  myOperation->setValue("ATTR2", i+5);
234 
235  if (myTransaction->execute( NdbTransaction::Commit ) == -1)
236  APIERROR(myTransaction->getNdbError());
237 
238  myNdb.closeTransaction(myTransaction);
239  }
240 }
241 
242 /*****************************************************************
243  * Update the second attribute in half of the tuples (adding 10) *
244  *****************************************************************/
245 static void do_update(Ndb &myNdb, const char* table)
246 {
247  const NdbDictionary::Dictionary* myDict= myNdb.getDictionary();
248  const NdbDictionary::Table *myTable= myDict->getTable(table);
249 
250  if (myTable == NULL)
251  APIERROR(myDict->getNdbError());
252 
253  for (int i = 0; i < 10; i+=2) {
254  NdbTransaction *myTransaction= myNdb.startTransaction();
255  if (myTransaction == NULL) APIERROR(myNdb.getNdbError());
256 
257  NdbOperation *myOperation= myTransaction->getNdbOperation(myTable);
258  if (myOperation == NULL) APIERROR(myTransaction->getNdbError());
259 
260  myOperation->updateTuple();
261  myOperation->equal( "ATTR1", i );
262  myOperation->setValue( "ATTR2", i+10);
263 
264  if( myTransaction->execute( NdbTransaction::Commit ) == -1 )
265  APIERROR(myTransaction->getNdbError());
266 
267  myNdb.closeTransaction(myTransaction);
268  }
269 }
270 
271 /*************************************************
272  * Delete one tuple (the one with primary key 3) *
273  *************************************************/
274 static void do_delete(Ndb &myNdb, const char* table)
275 {
276  const NdbDictionary::Dictionary* myDict= myNdb.getDictionary();
277  const NdbDictionary::Table *myTable= myDict->getTable(table);
278 
279  if (myTable == NULL)
280  APIERROR(myDict->getNdbError());
281 
282  NdbTransaction *myTransaction= myNdb.startTransaction();
283  if (myTransaction == NULL) APIERROR(myNdb.getNdbError());
284 
285  NdbOperation *myOperation= myTransaction->getNdbOperation(myTable);
286  if (myOperation == NULL) APIERROR(myTransaction->getNdbError());
287 
288  myOperation->deleteTuple();
289  myOperation->equal( "ATTR1", 3 );
290 
291  if (myTransaction->execute(NdbTransaction::Commit) == -1)
292  APIERROR(myTransaction->getNdbError());
293 
294  myNdb.closeTransaction(myTransaction);
295 }
296 
297 /*****************************
298  * Read and print all tuples *
299  *****************************/
300 static void do_read(Ndb &myNdb, const char* table)
301 {
302  const NdbDictionary::Dictionary* myDict= myNdb.getDictionary();
303  const NdbDictionary::Table *myTable= myDict->getTable(table);
304 
305  if (myTable == NULL)
306  APIERROR(myDict->getNdbError());
307 
308  std::cout << "ATTR1 ATTR2" << std::endl;
309 
310  for (int i = 0; i < 10; i++) {
311  NdbTransaction *myTransaction= myNdb.startTransaction();
312  if (myTransaction == NULL) APIERROR(myNdb.getNdbError());
313 
314  NdbOperation *myOperation= myTransaction->getNdbOperation(myTable);
315  if (myOperation == NULL) APIERROR(myTransaction->getNdbError());
316 
317  myOperation->readTuple(NdbOperation::LM_Read);
318  myOperation->equal("ATTR1", i);
319 
320  NdbRecAttr *myRecAttr= myOperation->getValue("ATTR2", NULL);
321  if (myRecAttr == NULL) APIERROR(myTransaction->getNdbError());
322 
323  if(myTransaction->execute( NdbTransaction::Commit ) == -1)
324  if (i == 3) {
325  std::cout << "Detected that deleted tuple doesn't exist!" << std::endl;
326  } else {
327  APIERROR(myTransaction->getNdbError());
328  }
329 
330  if (i != 3) {
331  printf(" %2d %2d\n", i, myRecAttr->u_32_value());
332  }
333  myNdb.closeTransaction(myTransaction);
334  }
335 }