ndbapi_example3.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:6k
源码类别:

MySQL数据库

开发平台:

Visual C++

  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; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. // 
  14. //  ndbapi_example3.cpp: Error handling and transaction retries
  15. //
  16. //  Execute ndbapi_example1 to create the table "MYTABLENAME"
  17. //  before executing this program.
  18. //
  19. //  There are many ways to program using the NDB API.  In this example
  20. //  we execute two inserts in the same transaction using 
  21. //  NdbConnection::Ndbexecute(NoCommit).
  22. // 
  23. //  Transaction failing is handled by re-executing the transaction
  24. //  in case of non-permanent transaction errors.
  25. //  Application errors (i.e. errors at points marked with APIERROR) 
  26. //  should be handled by the application programmer.
  27. #include <NdbApi.hpp>
  28. // Used for cout
  29. #include <iostream>  
  30. // Used for sleep (use your own version of sleep)
  31. #include <unistd.h>
  32. #define TIME_TO_SLEEP_BETWEEN_TRANSACTION_RETRIES 1
  33. //
  34. //  APIERROR prints an NdbError object
  35. //
  36. #define APIERROR(error) 
  37.   { std::cout << "API ERROR: " << error.code << " " << error.message 
  38.               << std::endl 
  39.               << "           " << "Status: " << error.status 
  40.               << ", Classification: " << error.classification << std::endl
  41.               << "           " << "File: " << __FILE__ 
  42.               << " (Line: " << __LINE__ << ")" << std::endl 
  43.               ; 
  44.   }
  45. //
  46. //  CONERROR prints all error info regarding an NdbConnection
  47. //
  48. #define CONERROR(ndbConnection) 
  49.   { NdbError error = ndbConnection->getNdbError(); 
  50.     std::cout << "CON ERROR: " << error.code << " " << error.message 
  51.               << std::endl 
  52.               << "           " << "Status: " << error.status 
  53.               << ", Classification: " << error.classification << std::endl 
  54.               << "           " << "File: " << __FILE__ 
  55.               << " (Line: " << __LINE__ << ")" << std::endl 
  56.               ; 
  57.     printTransactionError(ndbConnection); 
  58.   }
  59. void printTransactionError(NdbConnection *ndbConnection) {
  60.   const NdbOperation *ndbOp = NULL;
  61.   int i=0;
  62.   /****************************************************************
  63.    * Print NdbError object of every operations in the transaction *
  64.    ****************************************************************/
  65.   while ((ndbOp = ndbConnection->getNextCompletedOperation(ndbOp)) != NULL) {
  66.     NdbError error = ndbOp->getNdbError();
  67.     std::cout << "           OPERATION " << i+1 << ": " 
  68.       << error.code << " " << error.message << std::endl
  69.       << "           Status: " << error.status 
  70.       << ", Classification: " << error.classification << std::endl;
  71.     i++;
  72.   }
  73. }
  74. //
  75. //  Example insert
  76. //  @param myNdb         Ndb object representing NDB Cluster
  77. //  @param myConnection  NdbConnection used for transaction
  78. //  @param error         NdbError object returned in case of errors
  79. //  @return -1 in case of failures, 0 otherwise
  80. //
  81. int insert(int transactionId, NdbConnection* myConnection) {
  82.   NdbOperation  *myOperation;          // For other operations
  83.   myOperation = myConnection->getNdbOperation("MYTABLENAME");
  84.   if (myOperation == NULL) return -1;
  85.   
  86.   if (myOperation->insertTuple() ||  
  87.       myOperation->equal("ATTR1", transactionId) ||
  88.       myOperation->setValue("ATTR2", transactionId)) {
  89.     APIERROR(myOperation->getNdbError());
  90.     exit(-1);
  91.   }
  92.   return myConnection->execute(NoCommit);
  93. }
  94. //
  95. //  Execute function which re-executes (tries 10 times) the transaction 
  96. //  if there are temporary errors (e.g. the NDB Cluster is overloaded).
  97. //  @return -1 failure, 1 success
  98. //
  99. int executeInsertTransaction(int transactionId, Ndb* myNdb) {
  100.   int result = 0;                       // No result yet
  101.   int noOfRetriesLeft = 10;
  102.   NdbConnection  *myConnection;         // For other transactions
  103.   NdbError ndberror;
  104.   
  105.   while (noOfRetriesLeft > 0 && !result) {
  106.     
  107.     /*********************************
  108.      * Start and execute transaction *
  109.      *********************************/
  110.     myConnection = myNdb->startTransaction();
  111.     if (myConnection == NULL) {
  112.       APIERROR(myNdb->getNdbError());
  113.       ndberror = myNdb->getNdbError();
  114.       result = -1;  // Failure
  115.     } else if (insert(transactionId, myConnection) || 
  116.        insert(10000+transactionId, myConnection) ||
  117.        myConnection->execute(Commit)) {
  118.       CONERROR(myConnection);
  119.       ndberror = myConnection->getNdbError();
  120.       result = -1;  // Failure
  121.     } else {
  122.       result = 1;   // Success
  123.     }
  124.     /**********************************
  125.      * If failure, then analyze error *
  126.      **********************************/
  127.     if (result == -1) {                 
  128.       switch (ndberror.status) {
  129.       case NdbError::Success:
  130. break;
  131.       case NdbError::TemporaryError:
  132. std::cout << "Retrying transaction..." << std::endl;
  133. sleep(TIME_TO_SLEEP_BETWEEN_TRANSACTION_RETRIES);
  134. --noOfRetriesLeft;
  135. result = 0;   // No completed transaction yet
  136. break;
  137.       case NdbError::UnknownResult:
  138.       case NdbError::PermanentError:
  139. std::cout << "No retry of transaction..." << std::endl;
  140. result = -1;  // Permanent failure
  141. break;
  142.       }
  143.     }
  144.     /*********************
  145.      * Close transaction *
  146.      *********************/
  147.     if (myConnection != NULL) {
  148.       myNdb->closeTransaction(myConnection);
  149.     }
  150.   }
  151.   if (result != 1) exit(-1);
  152.   return result;
  153. }
  154. int main()
  155. {
  156.   ndb_init();
  157.   Ndb* myNdb = new Ndb( "TEST_DB_1" );  // Object representing the database
  158.   
  159.   /*******************************************
  160.    * Initialize NDB and wait until its ready *
  161.    *******************************************/
  162.   if (myNdb->init() == -1) { 
  163.     APIERROR(myNdb->getNdbError());
  164.     exit(-1);
  165.   }
  166.   if (myNdb->waitUntilReady(30) != 0) {
  167.     std::cout << "NDB was not ready within 30 secs." << std::endl;
  168.     exit(-1);
  169.   }
  170.   
  171.   /************************************
  172.    * Execute some insert transactions *
  173.    ************************************/
  174.   for (int i = 10000; i < 20000; i++) {
  175.     executeInsertTransaction(i, myNdb);
  176.   }
  177.   
  178.   delete myNdb;
  179. }