Bug #39573 Broken error handling in ndbapi_scan.cpp
Submitted: 22 Sep 2008 4:56 Modified: 12 Oct 2009 12:23
Reporter: Gustaf Thorslund Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Cluster: NDB API Severity:S3 (Non-critical)
Version:mysql-5.1-telco-6.3 OS:Any
Assigned to: Jonas Oreland CPU Architecture:Any

[22 Sep 2008 4:56] Gustaf Thorslund
Description:
The error handling in the ndbapi_scan example appears to be
broken. From scan_delete() in ndbapi_scan.cpp:

   /**
    * start of loop: nextResult(true) means that "parallelism" number of
    * rows are fetched from NDB and cached in NDBAPI
    */    
    while((check = myScanOp->nextResult(true)) == 0){
      do 
      {
	if (myScanOp->deleteCurrentTuple() != 0)
	{
	  std::cout << myTrans->getNdbError().message << std::endl;
	  myNdb->closeTransaction(myTrans);
	  return -1;
	}
	deletedRows++;
	
	/**
	 * nextResult(false) means that the records 
	 * cached in the NDBAPI are modified before
	 * fetching more rows from NDB.
	 */    
      } while((check = myScanOp->nextResult(false)) == 0);
      
      /**
       * Commit when all cached tuple have been marked for deletion
       */    
      if(check != -1)
      {
	check = myTrans->execute(NdbTransaction::Commit);   
      }

      if(check == -1)
      {
	/**
	 * Create a new transaction, while keeping scan open
	 */
	check = myTrans->restart(); // [1]
      }

      /**
       * Check for errors
       */
      err = myTrans->getNdbError();    
      if(check == -1) // [2]
      {
	if(err.status == NdbError::TemporaryError) // [3]
	{
	  std::cout << myTrans->getNdbError().message << std::endl;
	  myNdb->closeTransaction(myTrans);
	  milliSleep(50);
	  continue; // [4]
	}	
      }
      /**
       * End of loop 
       */
  
From NdbTransaction.hpp:
   *  @note This method can only be called _directly_ after commit
   *        and only if commit is successful
   */
  int restart();

[1] If the execute(Commit) failed the restart() should not have been
    called.

[2] If restart() return 0 the error checking will not see that there
    was an error in the first place since 'check' have been set to 0
    again.

[3] Why only check for temporary errors?

[4] This will continue the loop and check for nextResult() in an
    operation belonging to a transaction just closed. Is the result of
    this operation known? I fail to find this information in
    NdbScanOperation.hpp anyway. (run.3.txt in bug#39572 looks like
    it got locked up somewhere after this call)

How to repeat:
Read the example and the internal description in NdbTransaction.hpp

Suggested fix:
Fix the example.
[12 Oct 2009 10:17] Jonas Oreland
fixed example in commit for http://bugs.mysql.com/bug.php?id=45964
[12 Oct 2009 10:29] Jonas Oreland
pushed to 6.2.19, 6.3.28 and 7.0.9
[12 Oct 2009 12:23] Jon Stephens
Documented bugfix in the NDB-6.2.19, 6.3.28, and 7.0.9 changelogs, as follows:

        The error handling shown in the example file ndbapi_scan.cpp
        included with the MySQL CLuster distribution was incorrect.

Also updated example code/comments in Cluster API Guide.

Closed.