<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <title>ndbapi_retries.cpp</title> <link href="doxygen.css" rel="stylesheet" type="text/css"> <link href="tabs.css" rel="stylesheet" type="text/css"> </head><body> <!-- Generated by Doxygen 1.5.5 --> <div class="contents"> <h1><a class="anchor" name="ndbapi_retries.cpp">ndbapi_retries.cpp </a></h1><div class="fragment"><pre class="fragment"><span class="comment">/* Copyright (C) 2003 MySQL AB</span> <span class="comment"></span> <span class="comment"> This program is free software; you can redistribute it and/or modify</span> <span class="comment"> it under the terms of the GNU General Public License as published by</span> <span class="comment"> the Free Software Foundation; version 2 of the License.</span> <span class="comment"></span> <span class="comment"> This program is distributed in the hope that it will be useful,</span> <span class="comment"> but WITHOUT ANY WARRANTY; without even the implied warranty of</span> <span class="comment"> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span> <span class="comment"> GNU General Public License for more details.</span> <span class="comment"></span> <span class="comment"> You should have received a copy of the GNU General Public License</span> <span class="comment"> along with this program; if not, write to the Free Software</span> <span class="comment"> Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */</span> <span class="comment">// </span> <span class="comment">// ndbapi_retries.cpp: Error handling and transaction retries</span> <span class="comment">//</span> <span class="comment">// Execute ndbapi_simple to create the table "MYTABLENAME"</span> <span class="comment">// before executing this program.</span> <span class="comment">//</span> <span class="comment">// There are many ways to program using the NDB API. In this example</span> <span class="comment">// we execute two inserts in the same transaction using </span> <span class="comment">// NdbConnection::execute(NoCommit).</span> <span class="comment">// </span> <span class="comment">// Transaction failing is handled by re-executing the transaction</span> <span class="comment">// in case of non-permanent transaction errors.</span> <span class="comment">// Application errors (i.e. errors at points marked with APIERROR) </span> <span class="comment">// should be handled by the application programmer.</span> <span class="preprocessor">#include <NdbApi.hpp></span> <span class="comment">// Used for cout</span> <span class="preprocessor">#include <iostream></span> <span class="comment">// Used for sleep (use your own version of sleep)</span> <span class="preprocessor">#include <unistd.h></span> <span class="preprocessor">#define TIME_TO_SLEEP_BETWEEN_TRANSACTION_RETRIES 1</span> <span class="preprocessor"></span> <span class="comment">//</span> <span class="comment">// APIERROR prints an NdbError object</span> <span class="comment">//</span> <span class="preprocessor">#define APIERROR(error) \</span> <span class="preprocessor"> { std::cout << "API ERROR: " << error.code << " " << error.message \</span> <span class="preprocessor"> << std::endl \</span> <span class="preprocessor"> << " " << "Status: " << error.status \</span> <span class="preprocessor"> << ", Classification: " << error.classification << std::endl\</span> <span class="preprocessor"> << " " << "File: " << __FILE__ \</span> <span class="preprocessor"> << " (Line: " << __LINE__ << ")" << std::endl \</span> <span class="preprocessor"> ; \</span> <span class="preprocessor"> }</span> <span class="preprocessor"></span> <span class="comment">//</span> <span class="comment">// TRANSERROR prints all error info regarding an NdbTransaction</span> <span class="comment">//</span> <span class="preprocessor">#define TRANSERROR(ndbTransaction) \</span> <span class="preprocessor"> { NdbError error = ndbTransaction->getNdbError(); \</span> <span class="preprocessor"> std::cout << "TRANS ERROR: " << error.code << " " << error.message \</span> <span class="preprocessor"> << std::endl \</span> <span class="preprocessor"> << " " << "Status: " << error.status \</span> <span class="preprocessor"> << ", Classification: " << error.classification << std::endl \</span> <span class="preprocessor"> << " " << "File: " << __FILE__ \</span> <span class="preprocessor"> << " (Line: " << __LINE__ << ")" << std::endl \</span> <span class="preprocessor"> ; \</span> <span class="preprocessor"> printTransactionError(ndbTransaction); \</span> <span class="preprocessor"> }</span> <span class="preprocessor"></span> <span class="keywordtype">void</span> printTransactionError(<a class="code" href="classNdbTransaction.html" title="Represents a transaction.">NdbTransaction</a> *ndbTransaction) { <span class="keyword">const</span> <a class="code" href="classNdbOperation.html" title="Class of operations for use in transactions.">NdbOperation</a> *ndbOp = NULL; <span class="keywordtype">int</span> i=0; <span class="comment">/****************************************************************</span> <span class="comment"> * Print NdbError object of every operations in the transaction *</span> <span class="comment"> ****************************************************************/</span> <span class="keywordflow">while</span> ((ndbOp = ndbTransaction-><a class="code" href="classNdbTransaction.html#cc45eb0b457f25f0615667a16cc44f73">getNextCompletedOperation</a>(ndbOp)) != NULL) { <a class="code" href="structNdbError.html" title="Contains error information.">NdbError</a> error = ndbOp-><a class="code" href="classNdbOperation.html#9e9aa90dcdbdc02066f3b386ebb79d04">getNdbError</a>(); std::cout << <span class="stringliteral">" OPERATION "</span> << i+1 << <span class="stringliteral">": "</span> << error.<a class="code" href="structNdbError.html#87429c24aeeafdee05f41051ba0f2160">code</a> << <span class="stringliteral">" "</span> << error.<a class="code" href="structNdbError.html#59d98203577586394c30cdb01a270c2c">message</a> << std::endl << <span class="stringliteral">" Status: "</span> << error.<a class="code" href="structNdbError.html#f4af76b35a92ccebbb814705578e74e9">status</a> << <span class="stringliteral">", Classification: "</span> << error.<a class="code" href="structNdbError.html#bc9a4841feb45bb8ca5fdaa8e14d20d6">classification</a> << std::endl; i++; } } <span class="comment">//</span> <span class="comment">// Example insert</span> <span class="comment">// @param myNdb Ndb object representing NDB Cluster</span> <span class="comment">// @param myTransaction NdbTransaction used for transaction</span> <span class="comment">// @param myTable Table to insert into</span> <span class="comment">// @param error NdbError object returned in case of errors</span> <span class="comment">// @return -1 in case of failures, 0 otherwise</span> <span class="comment">//</span> <span class="keywordtype">int</span> insert(<span class="keywordtype">int</span> transactionId, <a class="code" href="classNdbTransaction.html" title="Represents a transaction.">NdbTransaction</a>* myTransaction, <span class="keyword">const</span> <a class="code" href="classNdbDictionary_1_1Table.html" title="Represents a table in NDB Cluster.">NdbDictionary::Table</a> *myTable) { <a class="code" href="classNdbOperation.html" title="Class of operations for use in transactions.">NdbOperation</a> *myOperation; <span class="comment">// For other operations</span> myOperation = myTransaction-><a class="code" href="classNdbTransaction.html#2aeb211e54f84bd2de6cfb8fccec8166">getNdbOperation</a>(myTable); <span class="keywordflow">if</span> (myOperation == NULL) <span class="keywordflow">return</span> -1; <span class="keywordflow">if</span> (myOperation-><a class="code" href="classNdbOperation.html#1e06cf9bb1ce1c5357004c32b1e89b15">insertTuple</a>() || myOperation-><a class="code" href="classNdbOperation.html#2839b64df3a181f6023fb36a9fe8ab74">equal</a>(<span class="stringliteral">"ATTR1"</span>, transactionId) || myOperation-><a class="code" href="classNdbOperation.html#e6fd36220eca78873d1d9b59539ab192">setValue</a>(<span class="stringliteral">"ATTR2"</span>, transactionId)) { APIERROR(myOperation-><a class="code" href="classNdbOperation.html#9e9aa90dcdbdc02066f3b386ebb79d04">getNdbError</a>()); exit(-1); } <span class="keywordflow">return</span> myTransaction-><a class="code" href="classNdbTransaction.html#361d5a82078f86a5d18923f56d43cc84">execute</a>(<a class="code" href="classNdbTransaction.html#2d2a5911b91e5cf78da970a1e97f7e3ed2041cab47f522aa4365d70a49267d6d">NdbTransaction::NoCommit</a>); } <span class="comment">//</span> <span class="comment">// Execute function which re-executes (tries 10 times) the transaction </span> <span class="comment">// if there are temporary errors (e.g. the NDB Cluster is overloaded).</span> <span class="comment">// @return -1 failure, 1 success</span> <span class="comment">//</span> <span class="keywordtype">int</span> executeInsertTransaction(<span class="keywordtype">int</span> transactionId, <a class="code" href="classNdb.html" title="Represents the NDB kernel and is the main class of the NDB API.">Ndb</a>* myNdb, <span class="keyword">const</span> <a class="code" href="classNdbDictionary_1_1Table.html" title="Represents a table in NDB Cluster.">NdbDictionary::Table</a> *myTable) { <span class="keywordtype">int</span> result = 0; <span class="comment">// No result yet</span> <span class="keywordtype">int</span> noOfRetriesLeft = 10; <a class="code" href="classNdbTransaction.html" title="Represents a transaction.">NdbTransaction</a> *myTransaction; <span class="comment">// For other transactions</span> <a class="code" href="structNdbError.html" title="Contains error information.">NdbError</a> ndberror; <span class="keywordflow">while</span> (noOfRetriesLeft > 0 && !result) { <span class="comment">/*********************************</span> <span class="comment"> * Start and execute transaction *</span> <span class="comment"> *********************************/</span> myTransaction = myNdb-><a class="code" href="classNdb.html#7e34bb5d8e3d878a54ebb7c0e6d0c5f1">startTransaction</a>(); <span class="keywordflow">if</span> (myTransaction == NULL) { APIERROR(myNdb-><a class="code" href="classNdb.html#80b53a037bb2e93b3cd6830eda58643a">getNdbError</a>()); ndberror = myNdb-><a class="code" href="classNdb.html#80b53a037bb2e93b3cd6830eda58643a">getNdbError</a>(); result = -1; <span class="comment">// Failure</span> } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (insert(transactionId, myTransaction, myTable) || insert(10000+transactionId, myTransaction, myTable) || myTransaction-><a class="code" href="classNdbTransaction.html#361d5a82078f86a5d18923f56d43cc84">execute</a>(<a class="code" href="classNdbTransaction.html#2d2a5911b91e5cf78da970a1e97f7e3ecaba2931e541dd138044b61f38918391" title="Execute and try to commit the transaction.">NdbTransaction::Commit</a>)) { TRANSERROR(myTransaction); ndberror = myTransaction-><a class="code" href="classNdbTransaction.html#f4af91ca21b97c4fe6256a18903020fc">getNdbError</a>(); result = -1; <span class="comment">// Failure</span> } <span class="keywordflow">else</span> { result = 1; <span class="comment">// Success</span> } <span class="comment">/**********************************</span> <span class="comment"> * If failure, then analyze error *</span> <span class="comment"> **********************************/</span> <span class="keywordflow">if</span> (result == -1) { <span class="keywordflow">switch</span> (ndberror.status) { <span class="keywordflow">case</span> <a class="code" href="structNdbError.html#77140bdb323bd821bd517639ad458618eda60d921a6f3415692bc163084cc326">NdbError::Success</a>: <span class="keywordflow">break</span>; <span class="keywordflow">case</span> <a class="code" href="structNdbError.html#77140bdb323bd821bd517639ad4586189d6a4af4ffaf1aed83fdf29ef2c47227">NdbError::TemporaryError</a>: std::cout << <span class="stringliteral">"Retrying transaction..."</span> << std::endl; sleep(TIME_TO_SLEEP_BETWEEN_TRANSACTION_RETRIES); --noOfRetriesLeft; result = 0; <span class="comment">// No completed transaction yet</span> <span class="keywordflow">break</span>; <span class="keywordflow">case</span> <a class="code" href="structNdbError.html#77140bdb323bd821bd517639ad45861895ee56680dca939e370f27de09c92f4c">NdbError::UnknownResult</a>: <span class="keywordflow">case</span> <a class="code" href="structNdbError.html#77140bdb323bd821bd517639ad458618f39e2cb3839afe2ccecc9b44905b3d89">NdbError::PermanentError</a>: std::cout << <span class="stringliteral">"No retry of transaction..."</span> << std::endl; result = -1; <span class="comment">// Permanent failure</span> <span class="keywordflow">break</span>; } } <span class="comment">/*********************</span> <span class="comment"> * Close transaction *</span> <span class="comment"> *********************/</span> <span class="keywordflow">if</span> (myTransaction != NULL) { myNdb-><a class="code" href="classNdb.html#afbf5620c516bf18e0a3d3bacaf38e67">closeTransaction</a>(myTransaction); } } <span class="keywordflow">if</span> (result != 1) exit(-1); <span class="keywordflow">return</span> result; } <span class="keywordtype">int</span> main() { ndb_init(); <a class="code" href="classNdb__cluster__connection.html" title="Represents a connection to a cluster of storage nodes.">Ndb_cluster_connection</a> *cluster_connection= <span class="keyword">new</span> <a class="code" href="classNdb__cluster__connection.html" title="Represents a connection to a cluster of storage nodes.">Ndb_cluster_connection</a>(); <span class="comment">// Object representing the cluster</span> <span class="keywordtype">int</span> r= cluster_connection-><a class="code" href="classNdb__cluster__connection.html#1c1523c47bc56f17beb5c7e9124f7f47">connect</a>(5 <span class="comment">/* retries */</span>, 3 <span class="comment">/* delay between retries */</span>, 1 <span class="comment">/* verbose */</span>); <span class="keywordflow">if</span> (r > 0) { std::cout << <span class="stringliteral">"Cluster connect failed, possibly resolved with more retries.\n"</span>; exit(-1); } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (r < 0) { std::cout << <span class="stringliteral">"Cluster connect failed.\n"</span>; exit(-1); } <span class="keywordflow">if</span> (cluster_connection-><a class="code" href="classNdb__cluster__connection.html#02f01d4e1dba63679a4796838e3c3c7a">wait_until_ready</a>(30,30)) { std::cout << <span class="stringliteral">"Cluster was not ready within 30 secs."</span> << std::endl; exit(-1); } <a class="code" href="classNdb.html" title="Represents the NDB kernel and is the main class of the NDB API.">Ndb</a>* myNdb= <span class="keyword">new</span> <a class="code" href="classNdb.html" title="Represents the NDB kernel and is the main class of the NDB API.">Ndb</a>( cluster_connection, <span class="stringliteral">"TEST_DB_1"</span> ); <span class="comment">// Object representing the database</span> <span class="keywordflow">if</span> (myNdb-><a class="code" href="classNdb.html#b938638f0ced10e31ab67b3a80901270">init</a>() == -1) { APIERROR(myNdb-><a class="code" href="classNdb.html#80b53a037bb2e93b3cd6830eda58643a">getNdbError</a>()); exit(-1); } <span class="keyword">const</span> <a class="code" href="classNdbDictionary_1_1Dictionary.html" title="Dictionary for defining and retreiving meta data.">NdbDictionary::Dictionary</a>* myDict= myNdb-><a class="code" href="classNdb.html#f27ca0f4e5c074211252a7c83060a3a4">getDictionary</a>(); <span class="keyword">const</span> <a class="code" href="classNdbDictionary_1_1Table.html" title="Represents a table in NDB Cluster.">NdbDictionary::Table</a> *myTable= myDict-><a class="code" href="classNdbDictionary_1_1Dictionary.html#1a30b1bb5fa164113cb839eed64eb3b6">getTable</a>(<span class="stringliteral">"MYTABLENAME"</span>); <span class="keywordflow">if</span> (myTable == NULL) { APIERROR(myDict-><a class="code" href="classNdbDictionary_1_1Dictionary.html#0af68ea9b273172b46528ee1bd806f71">getNdbError</a>()); <span class="keywordflow">return</span> -1; } <span class="comment">/************************************</span> <span class="comment"> * Execute some insert transactions *</span> <span class="comment"> ************************************/</span> <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 10000; i < 20000; i++) { executeInsertTransaction(i, myNdb, myTable); } <span class="keyword">delete</span> myNdb; <span class="keyword">delete</span> cluster_connection; ndb_end(0); <span class="keywordflow">return</span> 0; } </pre></div> </div> <hr> <address> <small> <center> Documentation generated Tue Apr 1 13:45:44 2008 from mysql source files.<br> © 2003-2004 <a href="http://www.mysql.com">MySQL AB</a> <br> </center> </small></address> </body> </html>