PageRenderTime 26ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/storage/ndb/ndbapi-examples/ndbapi_simple_dual/main.cpp

https://bitbucket.org/Habibutsu/mysql
C++ | 347 lines | 207 code | 52 blank | 88 comment | 59 complexity | 25d0e48ae506319d6e9b6a0d1bf0f780 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause
  1. /* Copyright (C) 2003 MySQL AB
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation; version 2 of the License.
  5. This program is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License
  10. along with this program; if not, write to the Free Software
  11. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
  12. /*
  13. * ndbapi_simple_dual.cpp: Using synchronous transactions in NDB API
  14. *
  15. * Correct output from this program is:
  16. *
  17. * ATTR1 ATTR2
  18. * 0 10
  19. * 1 1
  20. * 2 12
  21. * Detected that deleted tuple doesn't exist!
  22. * 4 14
  23. * 5 5
  24. * 6 16
  25. * 7 7
  26. * 8 18
  27. * 9 9
  28. * ATTR1 ATTR2
  29. * 0 10
  30. * 1 1
  31. * 2 12
  32. * Detected that deleted tuple doesn't exist!
  33. * 4 14
  34. * 5 5
  35. * 6 16
  36. * 7 7
  37. * 8 18
  38. * 9 9
  39. *
  40. */
  41. #include <mysql.h>
  42. #include <NdbApi.hpp>
  43. // Used for cout
  44. #include <stdio.h>
  45. #include <iostream>
  46. static void run_application(MYSQL &, Ndb_cluster_connection &, const char* table, const char* db);
  47. #define PRINT_ERROR(code,msg) \
  48. std::cout << "Error in " << __FILE__ << ", line: " << __LINE__ \
  49. << ", code: " << code \
  50. << ", msg: " << msg << "." << std::endl
  51. #define MYSQLERROR(mysql) { \
  52. PRINT_ERROR(mysql_errno(&mysql),mysql_error(&mysql)); \
  53. exit(-1); }
  54. #define APIERROR(error) { \
  55. PRINT_ERROR(error.code,error.message); \
  56. exit(-1); }
  57. int main(int argc, char** argv)
  58. {
  59. if (argc != 5)
  60. {
  61. std::cout << "Arguments are <socket mysqld1> <connect_string cluster 1> <socket mysqld2> <connect_string cluster 2>.\n";
  62. exit(-1);
  63. }
  64. // ndb_init must be called first
  65. ndb_init();
  66. {
  67. char * mysqld1_sock = argv[1];
  68. const char *connectstring1 = argv[2];
  69. char * mysqld2_sock = argv[3];
  70. const char *connectstring2 = argv[4];
  71. // Object representing the cluster 1
  72. Ndb_cluster_connection cluster1_connection(connectstring1);
  73. MYSQL mysql1;
  74. // Object representing the cluster 2
  75. Ndb_cluster_connection cluster2_connection(connectstring2);
  76. MYSQL mysql2;
  77. // connect to mysql server and cluster 1 and run application
  78. // Connect to cluster 1 management server (ndb_mgmd)
  79. if (cluster1_connection.connect(4 /* retries */,
  80. 5 /* delay between retries */,
  81. 1 /* verbose */))
  82. {
  83. std::cout << "Cluster 1 management server was not ready within 30 secs.\n";
  84. exit(-1);
  85. }
  86. // Optionally connect and wait for the storage nodes (ndbd's)
  87. if (cluster1_connection.wait_until_ready(30,0) < 0)
  88. {
  89. std::cout << "Cluster 1 was not ready within 30 secs.\n";
  90. exit(-1);
  91. }
  92. // connect to mysql server in cluster 1
  93. if ( !mysql_init(&mysql1) ) {
  94. std::cout << "mysql_init failed\n";
  95. exit(-1);
  96. }
  97. if ( !mysql_real_connect(&mysql1, "localhost", "root", "", "",
  98. 0, mysqld1_sock, 0) )
  99. MYSQLERROR(mysql1);
  100. // connect to mysql server and cluster 2 and run application
  101. // Connect to cluster management server (ndb_mgmd)
  102. if (cluster2_connection.connect(4 /* retries */,
  103. 5 /* delay between retries */,
  104. 1 /* verbose */))
  105. {
  106. std::cout << "Cluster 2 management server was not ready within 30 secs.\n";
  107. exit(-1);
  108. }
  109. // Optionally connect and wait for the storage nodes (ndbd's)
  110. if (cluster2_connection.wait_until_ready(30,0) < 0)
  111. {
  112. std::cout << "Cluster 2 was not ready within 30 secs.\n";
  113. exit(-1);
  114. }
  115. // connect to mysql server in cluster 2
  116. if ( !mysql_init(&mysql2) ) {
  117. std::cout << "mysql_init failed\n";
  118. exit(-1);
  119. }
  120. if ( !mysql_real_connect(&mysql2, "localhost", "root", "", "",
  121. 0, mysqld2_sock, 0) )
  122. MYSQLERROR(mysql2);
  123. // run the application code
  124. run_application(mysql1, cluster1_connection, "MYTABLENAME1", "TEST_DB_1");
  125. run_application(mysql2, cluster2_connection, "MYTABLENAME2", "TEST_DB_2");
  126. }
  127. // Note: all connections must have been destroyed before calling ndb_end()
  128. ndb_end(0);
  129. return 0;
  130. }
  131. static void create_table(MYSQL &, const char* table);
  132. static void drop_table(MYSQL &, const char* table);
  133. static void do_insert(Ndb &, const char* table);
  134. static void do_update(Ndb &, const char* table);
  135. static void do_delete(Ndb &, const char* table);
  136. static void do_read(Ndb &, const char* table);
  137. static void run_application(MYSQL &mysql,
  138. Ndb_cluster_connection &cluster_connection,
  139. const char* table,
  140. const char* db)
  141. {
  142. /********************************************
  143. * Connect to database via mysql-c *
  144. ********************************************/
  145. char db_stmt[256];
  146. sprintf(db_stmt, "CREATE DATABASE %s\n", db);
  147. mysql_query(&mysql, db_stmt);
  148. sprintf(db_stmt, "USE %s", db);
  149. if (mysql_query(&mysql, db_stmt) != 0) MYSQLERROR(mysql);
  150. create_table(mysql, table);
  151. /********************************************
  152. * Connect to database via NdbApi *
  153. ********************************************/
  154. // Object representing the database
  155. Ndb myNdb( &cluster_connection, db );
  156. if (myNdb.init()) APIERROR(myNdb.getNdbError());
  157. /*
  158. * Do different operations on database
  159. */
  160. do_insert(myNdb, table);
  161. do_update(myNdb, table);
  162. do_delete(myNdb, table);
  163. do_read(myNdb, table);
  164. /*
  165. * Drop the table
  166. */
  167. drop_table(mysql, table);
  168. sprintf(db_stmt, "DROP DATABASE %s\n", db);
  169. mysql_query(&mysql, db_stmt);
  170. }
  171. /*********************************************************
  172. * Create a table named by table if it does not exist *
  173. *********************************************************/
  174. static void create_table(MYSQL &mysql, const char* table)
  175. {
  176. char create_stmt[256];
  177. sprintf(create_stmt, "CREATE TABLE %s \
  178. (ATTR1 INT UNSIGNED NOT NULL PRIMARY KEY,\
  179. ATTR2 INT UNSIGNED NOT NULL)\
  180. ENGINE=NDB", table);
  181. if (mysql_query(&mysql, create_stmt))
  182. MYSQLERROR(mysql);
  183. }
  184. /*******************************
  185. * Drop a table named by table
  186. *******************************/
  187. static void drop_table(MYSQL &mysql, const char* table)
  188. {
  189. char drop_stmt[256];
  190. sprintf(drop_stmt, "DROP TABLE IF EXISTS %s", table);
  191. if (mysql_query(&mysql, drop_stmt))
  192. MYSQLERROR(mysql);
  193. }
  194. /**************************************************************************
  195. * Using 5 transactions, insert 10 tuples in table: (0,0),(1,1),...,(9,9) *
  196. **************************************************************************/
  197. static void do_insert(Ndb &myNdb, const char* table)
  198. {
  199. const NdbDictionary::Dictionary* myDict= myNdb.getDictionary();
  200. const NdbDictionary::Table *myTable= myDict->getTable(table);
  201. if (myTable == NULL)
  202. APIERROR(myDict->getNdbError());
  203. for (int i = 0; i < 5; i++) {
  204. NdbTransaction *myTransaction= myNdb.startTransaction();
  205. if (myTransaction == NULL) APIERROR(myNdb.getNdbError());
  206. NdbOperation *myOperation= myTransaction->getNdbOperation(myTable);
  207. if (myOperation == NULL) APIERROR(myTransaction->getNdbError());
  208. myOperation->insertTuple();
  209. myOperation->equal("ATTR1", i);
  210. myOperation->setValue("ATTR2", i);
  211. myOperation= myTransaction->getNdbOperation(myTable);
  212. if (myOperation == NULL) APIERROR(myTransaction->getNdbError());
  213. myOperation->insertTuple();
  214. myOperation->equal("ATTR1", i+5);
  215. myOperation->setValue("ATTR2", i+5);
  216. if (myTransaction->execute( NdbTransaction::Commit ) == -1)
  217. APIERROR(myTransaction->getNdbError());
  218. myNdb.closeTransaction(myTransaction);
  219. }
  220. }
  221. /*****************************************************************
  222. * Update the second attribute in half of the tuples (adding 10) *
  223. *****************************************************************/
  224. static void do_update(Ndb &myNdb, const char* table)
  225. {
  226. const NdbDictionary::Dictionary* myDict= myNdb.getDictionary();
  227. const NdbDictionary::Table *myTable= myDict->getTable(table);
  228. if (myTable == NULL)
  229. APIERROR(myDict->getNdbError());
  230. for (int i = 0; i < 10; i+=2) {
  231. NdbTransaction *myTransaction= myNdb.startTransaction();
  232. if (myTransaction == NULL) APIERROR(myNdb.getNdbError());
  233. NdbOperation *myOperation= myTransaction->getNdbOperation(myTable);
  234. if (myOperation == NULL) APIERROR(myTransaction->getNdbError());
  235. myOperation->updateTuple();
  236. myOperation->equal( "ATTR1", i );
  237. myOperation->setValue( "ATTR2", i+10);
  238. if( myTransaction->execute( NdbTransaction::Commit ) == -1 )
  239. APIERROR(myTransaction->getNdbError());
  240. myNdb.closeTransaction(myTransaction);
  241. }
  242. }
  243. /*************************************************
  244. * Delete one tuple (the one with primary key 3) *
  245. *************************************************/
  246. static void do_delete(Ndb &myNdb, const char* table)
  247. {
  248. const NdbDictionary::Dictionary* myDict= myNdb.getDictionary();
  249. const NdbDictionary::Table *myTable= myDict->getTable(table);
  250. if (myTable == NULL)
  251. APIERROR(myDict->getNdbError());
  252. NdbTransaction *myTransaction= myNdb.startTransaction();
  253. if (myTransaction == NULL) APIERROR(myNdb.getNdbError());
  254. NdbOperation *myOperation= myTransaction->getNdbOperation(myTable);
  255. if (myOperation == NULL) APIERROR(myTransaction->getNdbError());
  256. myOperation->deleteTuple();
  257. myOperation->equal( "ATTR1", 3 );
  258. if (myTransaction->execute(NdbTransaction::Commit) == -1)
  259. APIERROR(myTransaction->getNdbError());
  260. myNdb.closeTransaction(myTransaction);
  261. }
  262. /*****************************
  263. * Read and print all tuples *
  264. *****************************/
  265. static void do_read(Ndb &myNdb, const char* table)
  266. {
  267. const NdbDictionary::Dictionary* myDict= myNdb.getDictionary();
  268. const NdbDictionary::Table *myTable= myDict->getTable(table);
  269. if (myTable == NULL)
  270. APIERROR(myDict->getNdbError());
  271. std::cout << "ATTR1 ATTR2" << std::endl;
  272. for (int i = 0; i < 10; i++) {
  273. NdbTransaction *myTransaction= myNdb.startTransaction();
  274. if (myTransaction == NULL) APIERROR(myNdb.getNdbError());
  275. NdbOperation *myOperation= myTransaction->getNdbOperation(myTable);
  276. if (myOperation == NULL) APIERROR(myTransaction->getNdbError());
  277. myOperation->readTuple(NdbOperation::LM_Read);
  278. myOperation->equal("ATTR1", i);
  279. NdbRecAttr *myRecAttr= myOperation->getValue("ATTR2", NULL);
  280. if (myRecAttr == NULL) APIERROR(myTransaction->getNdbError());
  281. if(myTransaction->execute( NdbTransaction::Commit ) == -1)
  282. if (i == 3) {
  283. std::cout << "Detected that deleted tuple doesn't exist!" << std::endl;
  284. } else {
  285. APIERROR(myTransaction->getNdbError());
  286. }
  287. if (i != 3) {
  288. printf(" %2d %2d\n", i, myRecAttr->u_32_value());
  289. }
  290. myNdb.closeTransaction(myTransaction);
  291. }
  292. }