MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ndbapi_async1.cpp
1 /*
2  Copyright (c) 2005, 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_async1.cpp: Using asynchronous transactions in NDB API
20 //
21 //
22 // Correct output from this program is:
23 //
24 // Successful insert.
25 // Successful insert.
26 
27 #include <mysql.h>
28 #include <mysqld_error.h>
29 #include <NdbApi.hpp>
30 
31 // Used for cout
32 #include <iostream>
33 
34 
35 #define PRINT_ERROR(code,msg) \
36  std::cout << "Error in " << __FILE__ << ", line: " << __LINE__ \
37  << ", code: " << code \
38  << ", msg: " << msg << "." << std::endl
39 #define MYSQLERROR(mysql) { \
40  PRINT_ERROR(mysql_errno(&mysql),mysql_error(&mysql)); \
41  exit(-1); }
42 #define APIERROR(error) \
43  { std::cout << "Error in " << __FILE__ << ", line:" << __LINE__ << ", code:" \
44  << error.code << ", msg: " << error.message << "." << std::endl; \
45  exit(-1); }
46 
47 static void create_table(MYSQL &);
48 static void drop_table(MYSQL &);
49 static void callback(int result, NdbTransaction* NdbObject, void* aObject);
50 
51 int main(int argc, char** argv)
52 {
53  if (argc != 3)
54  {
55  std::cout << "Arguments are <socket mysqld> <connect_string cluster>.\n";
56  exit(-1);
57  }
58  char * mysqld_sock = argv[1];
59  const char *connectstring = argv[2];
60  ndb_init();
61 
62  Ndb_cluster_connection *cluster_connection=
63  new Ndb_cluster_connection(connectstring); // Object representing the cluster
64 
65  int r= cluster_connection->connect(5 /* retries */,
66  3 /* delay between retries */,
67  1 /* verbose */);
68  if (r > 0)
69  {
70  std::cout
71  << "Cluster connect failed, possibly resolved with more retries.\n";
72  exit(-1);
73  }
74  else if (r < 0)
75  {
76  std::cout
77  << "Cluster connect failed.\n";
78  exit(-1);
79  }
80 
81  if (cluster_connection->wait_until_ready(30,0) < 0)
82  {
83  std::cout << "Cluster was not ready within 30 secs." << std::endl;
84  exit(-1);
85  }
86 
87  // connect to mysql server
88  MYSQL mysql;
89  if ( !mysql_init(&mysql) ) {
90  std::cout << "mysql_init failed\n";
91  exit(-1);
92  }
93  if ( !mysql_real_connect(&mysql, "localhost", "root", "", "",
94  0, mysqld_sock, 0) )
95  MYSQLERROR(mysql);
96 
97  /********************************************
98  * Connect to database via mysql-c *
99  ********************************************/
100  mysql_query(&mysql, "CREATE DATABASE ndb_examples");
101  if (mysql_query(&mysql, "USE ndb_examples") != 0) MYSQLERROR(mysql);
102  create_table(mysql);
103 
104  Ndb* myNdb = new Ndb( cluster_connection,
105  "ndb_examples" ); // Object representing the database
106 
107  NdbTransaction* myNdbTransaction[2]; // For transactions
108  NdbOperation* myNdbOperation; // For operations
109 
110  if (myNdb->init(2) == -1) { // Want two parallel insert transactions
111  APIERROR(myNdb->getNdbError());
112  exit(-1);
113  }
114 
115  /******************************************************
116  * Insert (we do two insert transactions in parallel) *
117  ******************************************************/
118  const NdbDictionary::Dictionary* myDict= myNdb->getDictionary();
119  const NdbDictionary::Table *myTable= myDict->getTable("api_async1");
120  if (myTable == NULL)
121  APIERROR(myDict->getNdbError());
122  for (int i = 0; i < 2; i++) {
123  myNdbTransaction[i] = myNdb->startTransaction();
124  if (myNdbTransaction[i] == NULL) APIERROR(myNdb->getNdbError());
125 
126  myNdbOperation = myNdbTransaction[i]->getNdbOperation(myTable);
127  if (myNdbOperation == NULL) APIERROR(myNdbTransaction[i]->getNdbError());
128 
129  myNdbOperation->insertTuple();
130  myNdbOperation->equal("ATTR1", 20 + i);
131  myNdbOperation->setValue("ATTR2", 20 + i);
132 
133  // Prepare transaction (the transaction is NOT yet sent to NDB)
134  myNdbTransaction[i]->executeAsynchPrepare(NdbTransaction::Commit,
135  &callback, NULL);
136  }
137 
138  // Send all transactions to NDB
139  myNdb->sendPreparedTransactions(0);
140 
141  // Poll all transactions
142  myNdb->pollNdb(3000, 2);
143 
144  // Close all transactions
145  for (int i = 0; i < 2; i++)
146  myNdb->closeTransaction(myNdbTransaction[i]);
147 
148  delete myNdb;
149  delete cluster_connection;
150 
151  ndb_end(0);
152  return 0;
153 }
154 
155 /*********************************************************
156  * Create a table named api_async1 if it does not exist *
157  *********************************************************/
158 static void create_table(MYSQL &mysql)
159 {
160  while(mysql_query(&mysql,
161  "CREATE TABLE api_async1"
162  " (ATTR1 INT UNSIGNED NOT NULL PRIMARY KEY,"
163  " ATTR2 INT UNSIGNED NOT NULL)"
164  " ENGINE=NDB"))
165  {
166  if (mysql_errno(&mysql) == ER_TABLE_EXISTS_ERROR)
167  {
168  std::cout << "MySQL Cluster already has example table: api_scan. "
169  << "Dropping it..." << std::endl;
170  drop_table(mysql);
171  }
172  else MYSQLERROR(mysql);
173  }
174 }
175 
176 /***********************************
177  * Drop a table named api_async1
178  ***********************************/
179 static void drop_table(MYSQL &mysql)
180 {
181  if (mysql_query(&mysql,
182  "DROP TABLE"
183  " api_async1"))
184  MYSQLERROR(mysql);
185 }
186 
187 
188 /*
189  * callback : This is called when the transaction is polled
190  *
191  * (This function must have three arguments:
192  * - The result of the transaction,
193  * - The NdbTransaction object, and
194  * - A pointer to an arbitrary object.)
195  */
196 
197 static void
198 callback(int result, NdbTransaction* myTrans, void* aObject)
199 {
200  if (result == -1) {
201  std::cout << "Poll error: " << std::endl;
202  APIERROR(myTrans->getNdbError());
203  } else {
204  std::cout << "Successful insert." << std::endl;
205  }
206 }