Example #1
0
int 
HugoAsynchTransactions::executeAsynchOperation(Ndb* pNdb,		      
					 int records,
					 int batch,
					 int trans,
					 int operations,
					 NDB_OPERATION theOperation,
					 ExecType theType) {

  int             check = 0;
  //  int             retryAttempt = 0;  // Not used at the moment
  //  int             retryMax = 5;      // Not used at the moment
  int             cTrans = 0;
  int             cRecords = 0;
  int             cIndex = 0;
  int a,t,r;

  transactionsCompleted = 0;
  allocTransactions(trans);

  for (int i = 0; i < batch; i++) { // For each batch
    while (cRecords < records*batch) {
      cTrans = 0;
      cIndex = 0;
      for (t = 0; t < trans; t++) { // For each transaction
	transactions[t] = pNdb->startTransaction();
	if (transactions[t] == NULL) {
	  ERR(pNdb->getNdbError());
	  return NDBT_FAILED;
	}	
	for (int k = 0; k < operations; k++) { // For each operation
	  NdbOperation* pOp = transactions[t]->getNdbOperation(tab.getName());
	  if (pOp == NULL) { 
	    ERR(transactions[t]->getNdbError());
	    pNdb->closeTransaction(transactions[t]);
	    return NDBT_FAILED;
	  }
	  
	  switch (theOperation) {
	  case NO_INSERT: 
	    // Insert
	    check = pOp->insertTuple();
	    if (check == -1) { 
	      ERR(transactions[t]->getNdbError());
	      pNdb->closeTransaction(transactions[t]);
	      return NDBT_FAILED;
	    }
	    
	    // Set a calculated value for each attribute in this table	 
	    for (a = 0; a < tab.getNoOfColumns(); a++) {
	      if (setValueForAttr(pOp, a, cRecords, 0 ) != 0) {	  
		ERR(transactions[t]->getNdbError());
		pNdb->closeTransaction(transactions[t]);	  
		return NDBT_FAILED;
	      }
	    } // For each attribute
	    break;
	  case NO_UPDATE:
	    // This is a special case and is handled in the calling client...
	    break;
	  break;
	  case NO_READ:
	    // Define primary keys
	    check = pOp->readTuple();
	    for (a = 0; a < tab.getNoOfColumns(); a++) {
	      if (tab.getColumn(a)->getPrimaryKey() == true) {
		if (equalForAttr(pOp, a, cRecords) != 0){
		  ERR(transactions[t]->getNdbError());
		  pNdb->closeTransaction(transactions[t]);
		  return NDBT_FAILED;
		}
	      }
	    }	    
	    // Define attributes to read  
	    for (a = 0; a < tab.getNoOfColumns(); a++) {
	      if ((rows[cIndex]->attributeStore(a) = 
		   pOp->getValue(tab.getColumn(a)->getName())) == 0) {
		ERR(transactions[t]->getNdbError());
		pNdb->closeTransaction(transactions[t]);
		return NDBT_FAILED;
	      }
	    }	    	  
	    break;
	  case NO_DELETE:
	    // Delete
	    check = pOp->deleteTuple();
	    if (check == -1) { 
	      ERR(transactions[t]->getNdbError());
	      pNdb->closeTransaction(transactions[t]);
	      return NDBT_FAILED;
	    }

	    // Define primary keys
	    for (a = 0; a < tab.getNoOfColumns(); a++) {
	      if (tab.getColumn(a)->getPrimaryKey() == true){
		if (equalForAttr(pOp, a, cRecords) != 0) {
		  ERR(transactions[t]->getNdbError());
		  pNdb->closeTransaction(transactions[t]);		
		  return NDBT_FAILED;
		}
	      }
	    }
	    break;
	  default:
	    // Should not happen...
	    pNdb->closeTransaction(transactions[t]);		
	    return NDBT_FAILED;
	  }

	  cIndex++;
	  cRecords++;

	} // For each operation
    
	// Let's prepare...
	transactions[t]->executeAsynchPrepare(theType, &asynchCallback, 
					this);
	cTrans++;

	if (cRecords >= records) {
	  // No more transactions needed
	  break;
	}      
      } // For each transaction

      // Wait for all outstanding transactions
      pNdb->sendPollNdb(3000, 0, 0);

      // ugly... it's starts to resemble flexXXX ...:(
      switch (theOperation) {
      case NO_READ:
	// Verify the data!
	for (r = 0; r < trans*operations; r++) {
	  if (calc.verifyRowValues(rows[r]) != 0) {
	    g_info << "|- Verify failed..." << endl;
	    // Close all transactions
	    for (int t = 0; t < cTrans; t++) {
	      pNdb->closeTransaction(transactions[t]);
	    }
	    return NDBT_FAILED;
	  }
	}	
	break;
      case NO_INSERT:
      case NO_UPDATE:
      case NO_DELETE:
	break;
      }

      // Close all transactions
      for (t = 0; t < cTrans; t++) {
	pNdb->closeTransaction(transactions[t]);
      }

    } // while (cRecords < records*batch)

  } // For each batch

  deallocTransactions();

  return NDBT_OK;

}
Example #2
0
void BackupRestore::tuple_a(restore_callback_t *cb)
{
  Uint32 partition_id = cb->fragId;
  while (cb->retries < 10) 
  {
    /**
     * start transactions
     */
    cb->connection = m_ndb->startTransaction();
    if (cb->connection == NULL) 
    {
      if (errorHandler(cb)) 
      {
	m_ndb->sendPollNdb(3000, 1);
	continue;
      }
      err << "Cannot start transaction" << endl;
      exitHandler();
    } // if
    
    const TupleS &tup = cb->tup;
    const NdbDictionary::Table * table = get_table(tup.getTable()->m_dictTable);

    NdbOperation * op = cb->connection->getNdbOperation(table);
    
    if (op == NULL) 
    {
      if (errorHandler(cb)) 
	continue;
      err << "Cannot get operation: " << cb->connection->getNdbError() << endl;
      exitHandler();
    } // if
    
    if (op->writeTuple() == -1) 
    {
      if (errorHandler(cb))
	continue;
      err << "Error defining op: " << cb->connection->getNdbError() << endl;
      exitHandler();
    } // if

    if (table->getFragmentType() == NdbDictionary::Object::UserDefined)
    {
      if (table->getDefaultNoPartitionsFlag())
      {
        /*
          This can only happen for HASH partitioning with
          user defined hash function where user hasn't
          specified the number of partitions and we
          have to calculate it. We use the hash value
          stored in the record to calculate the partition
          to use.
        */
        int i = tup.getNoOfAttributes() - 1;
	const AttributeData  *attr_data = tup.getData(i);
        Uint32 hash_value =  *attr_data->u_int32_value;
        op->setPartitionId(get_part_id(table, hash_value));
      }
      else
      {
        /*
          Either RANGE or LIST (with or without subparts)
          OR HASH partitioning with user defined hash
          function but with fixed set of partitions.
        */
        op->setPartitionId(partition_id);
      }
    }
    int ret = 0;
    for (int j = 0; j < 2; j++)
    {
      for (int i = 0; i < tup.getNoOfAttributes(); i++) 
      {
	const AttributeDesc * attr_desc = tup.getDesc(i);
	const AttributeData * attr_data = tup.getData(i);
	int size = attr_desc->size;
	int arraySize = attr_desc->arraySize;
	char * dataPtr = attr_data->string_value;
	Uint32 length = 0;
       
        if (!attr_data->null)
        {
          const unsigned char * src = (const unsigned char *)dataPtr;
          switch(attr_desc->m_column->getType()){
          case NdbDictionary::Column::Varchar:
          case NdbDictionary::Column::Varbinary:
            length = src[0] + 1;
            break;
          case NdbDictionary::Column::Longvarchar:
          case NdbDictionary::Column::Longvarbinary:
            length = src[0] + (src[1] << 8) + 2;
            break;
          default:
            length = attr_data->size;
            break;
          }
        }
	if (j == 0 && tup.getTable()->have_auto_inc(i))
	  tup.getTable()->update_max_auto_val(dataPtr,size*arraySize);
	
	if (attr_desc->m_column->getPrimaryKey())
	{
	  if (j == 1) continue;
	  ret = op->equal(i, dataPtr, length);
	}
	else
	{
	  if (j == 0) continue;
	  if (attr_data->null) 
	    ret = op->setValue(i, NULL, 0);
	  else
	    ret = op->setValue(i, dataPtr, length);
	}
	if (ret < 0) {
	  ndbout_c("Column: %d type %d %d %d %d",i,
		   attr_desc->m_column->getType(),
		   size, arraySize, length);
	  break;
	}
      }
      if (ret < 0)
	break;
    }
    if (ret < 0)
    {
      if (errorHandler(cb)) 
	continue;
      err << "Error defining op: " << cb->connection->getNdbError() << endl;
      exitHandler();
    }

    // Prepare transaction (the transaction is NOT yet sent to NDB)
    cb->connection->executeAsynchPrepare(NdbTransaction::Commit,
					 &callback, cb);
    m_transactions++;
    return;
  }
  err << "Retried transaction " << cb->retries << " times.\nLast error"
      << m_ndb->getNdbError(cb->error_code) << endl
      << "...Unable to recover from errors. Exiting..." << endl;
  exitHandler();
}
Example #3
0
void
BackupRestore::tuple(const TupleS & tup)
{
  if (!m_restore)
    return;
  while (1) 
  {
    NdbTransaction * trans = m_ndb->startTransaction();
    if (trans == NULL) 
    {
      // TODO: handle the error
      ndbout << "Cannot start transaction" << endl;
      exit(-1);
    } // if
    
    const TableS * table = tup.getTable();
    NdbOperation * op = trans->getNdbOperation(table->getTableName());
    if (op == NULL) 
    {
      ndbout << "Cannot get operation: ";
      ndbout << trans->getNdbError() << endl;
      exit(-1);
    } // if
    
    // TODO: check return value and handle error
    if (op->writeTuple() == -1) 
    {
      ndbout << "writeTuple call failed: ";
      ndbout << trans->getNdbError() << endl;
      exit(-1);
    } // if
    
    for (int i = 0; i < tup.getNoOfAttributes(); i++) 
    {
      const AttributeS * attr = tup[i];
      int size = attr->Desc->size;
      int arraySize = attr->Desc->arraySize;
      const char * dataPtr = attr->Data.string_value;
      
      const Uint32 length = (size * arraySize) / 8;
      if (attr->Desc->m_column->getPrimaryKey()) 
	op->equal(i, dataPtr, length);
    }
    
    for (int i = 0; i < tup.getNoOfAttributes(); i++) 
    {
      const AttributeS * attr = tup[i];
      int size = attr->Desc->size;
      int arraySize = attr->Desc->arraySize;
      const char * dataPtr = attr->Data.string_value;
      
      const Uint32 length = (size * arraySize) / 8;
      if (!attr->Desc->m_column->getPrimaryKey())
	if (attr->Data.null)
	  op->setValue(i, NULL, 0);
	else
	  op->setValue(i, dataPtr, length);
    }
    int ret = trans->execute(Commit);
    if (ret != 0)
    {
      ndbout << "execute failed: ";
      ndbout << trans->getNdbError() << endl;
      exit(-1);
    }
    m_ndb->closeTransaction(trans);
    if (ret == 0)
      break;
  }
  m_dataCount++;
}
void
T5_Callback_2(int result, NdbConnection * pCON, void * threadData){
  CHECK_MINUS_ONE(result, "T5-2: NoCommit", pCON); 
  ThreadData * td = (ThreadData *)threadData;  

  Uint32 permission = td->transactionData.permission;
  Uint32 sessions   = td->transactionData.sessions;
  Uint32 server_bit = td->transactionData.server_bit;

  if(((permission & server_bit) == server_bit) &&
     ((sessions   & server_bit) == server_bit)){
    
    memcpy(td->transactionData.suffix,
	   &td->transactionData.number
	   [SUBSCRIBER_NUMBER_LENGTH-SUBSCRIBER_NUMBER_SUFFIX_LENGTH], 
	   SUBSCRIBER_NUMBER_SUFFIX_LENGTH);
  
    DEBUG5("T5(%.*s, %.2d): - Callback 2 - deleting(%.*s)\n", 
	   SUBSCRIBER_NUMBER_LENGTH, 
	   td->transactionData.number, 
	   td->transactionData.server_id,
	   SUBSCRIBER_NUMBER_SUFFIX_LENGTH, 
	   td->transactionData.suffix);
    
    /* Operation 3 */
    NdbOperation * MyOp = pCON->getNdbOperation(SESSION_TABLE);
    CHECK_NULL(MyOp, "T5-3: getNdbOperation", 
	       pCON);
    
    MyOp->deleteTuple();
    MyOp->equal(IND_SESSION_SUBSCRIBER,
		(char*)td->transactionData.number);
    MyOp->equal(IND_SESSION_SERVER,
		(char*)&td->transactionData.server_id);
    /* Operation 4 */
    
    /* Operation 5 */
    MyOp = pCON->getNdbOperation(SERVER_TABLE);
    CHECK_NULL(MyOp, "T5-5: getNdbOperation", 
	       pCON);
    
    MyOp->interpretedUpdateTuple();
    MyOp->equal(IND_SERVER_ID,
		(char*)&td->transactionData.server_id);
    MyOp->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
		(char*)td->transactionData.suffix);
    MyOp->incValue(IND_SERVER_DELETES, (uint32)1);
    td->transactionData.branchExecuted = 1;
  } else {
    td->transactionData.branchExecuted = 0;

    DEBUG5("T5(%.*s, %.2d): - Callback 2 - no delete - %s %s\n", 
	   SUBSCRIBER_NUMBER_LENGTH, 
	   td->transactionData.number, 
	   td->transactionData.server_id,
	   ((permission & server_bit) ? 
	    "permission - " : "no permission - "),
	   ((sessions   & server_bit) ? 
	    "in session - " : "no in session - "));
  }
  
  if(!td->transactionData.do_rollback && td->transactionData.branchExecuted){
    pCON->executeAsynchPrepare(Commit, T5_Callback_3, td); 
  } else {
    pCON->executeAsynchPrepare(Rollback, T5_Callback_3, td);
  }
}
Example #5
0
int HugoOperations::pkReadRecord(Ndb* pNdb,
				 int recordNo,
				 int numRecords,
				 NdbOperation::LockMode lm){
  int a;  
  allocRows(numRecords);
  int check;

  NdbOperation* pOp = 0;
  pIndexScanOp = 0;

  for(int r=0; r < numRecords; r++){
    
    if(pOp == 0)
    {
      pOp = getOperation(pTrans, NdbOperation::ReadRequest);
    }
    if (pOp == NULL) {
      ERR(pTrans->getNdbError());
      return NDBT_FAILED;
    }
    
rand_lock_mode:
    switch(lm){
    case NdbOperation::LM_Read:
    case NdbOperation::LM_Exclusive:
    case NdbOperation::LM_CommittedRead:
    case NdbOperation::LM_SimpleRead:
      if(idx && idx->getType() == NdbDictionary::Index::OrderedIndex && 
	 pIndexScanOp == 0)
      {
	pIndexScanOp = ((NdbIndexScanOperation*)pOp);
	check = pIndexScanOp->readTuples(lm);
      }
      else
	check = pOp->readTuple(lm);
      break;
    default:
      lm = (NdbOperation::LockMode)((rand() >> 16) & 3);
      goto rand_lock_mode;
    }
    
    if( check == -1 ) {
      ERR(pTrans->getNdbError());
      return NDBT_FAILED;
    }
    
    // Define primary keys
    if (equalForRow(pOp, r+recordNo) != 0)
      return NDBT_FAILED;

    if(pIndexScanOp)
      pIndexScanOp->end_of_bound(r);
    
    if(r == 0 || pIndexScanOp == 0)
    {
      // Define attributes to read  
      for(a = 0; a<tab.getNoOfColumns(); a++){
	if((rows[r]->attributeStore(a) = 
	    pOp->getValue(tab.getColumn(a)->getName())) == 0) {
	  ERR(pTrans->getNdbError());
	  return NDBT_FAILED;
	}
      } 
    }
    pOp = pIndexScanOp;
  }
  return NDBT_OK;
}
Example #6
0
/* set all the unique attrs of this objectclass into the table
 */
extern "C" int
ndb_oc_attrs(
	NdbTransaction *txn,
	const NdbDictionary::Table *myTable,
	Entry *e,
	NdbOcInfo *no,
	NdbAttrInfo **attrs,
	int nattrs,
	Attribute *old
)
{
	char buf[65538], *ptr;
	Attribute **an, **ao, *a;
	NdbOperation *myop;
	int i, j, max = 0;
	int changed, rc;
	Uint64 eid = e->e_id;

	if ( !nattrs )
		return 0;

	an = (Attribute **)ch_malloc( 2 * nattrs * sizeof(Attribute *));
	ao = an + nattrs;

	/* Turn lists of attrs into arrays for easier access */
	for ( i=0; i<nattrs; i++ ) {
		if ( attrs[i]->na_oi != no ) {
			an[i] = NULL;
			ao[i] = NULL;
			continue;
		}
		for ( a=e->e_attrs; a; a=a->a_next ) {
			if ( a->a_desc == slap_schema.si_ad_objectClass )
				continue;
			if ( a->a_desc->ad_type == attrs[i]->na_attr ) {
				/* Don't process same attr twice */
				if ( a->a_flags & SLAP_ATTR_IXADD )
					a = NULL;
				else
					a->a_flags |= SLAP_ATTR_IXADD;
				break;
			}
		}
		an[i] = a;
		if ( a && a->a_numvals > max )
			max = a->a_numvals;
		for ( a=old; a; a=a->a_next ) {
			if ( a->a_desc == slap_schema.si_ad_objectClass )
				continue;
			if ( a->a_desc->ad_type == attrs[i]->na_attr )
				break;
		}
		ao[i] = a;
		if ( a && a->a_numvals > max )
			max = a->a_numvals;
	}

	for ( i=0; i<max; i++ ) {
		myop = NULL;
		for ( j=0; j<nattrs; j++ ) {
			if ( !an[j] && !ao[j] )
				continue;
			changed = 0;
			if ( an[j] && an[j]->a_numvals > i ) {
				/* both old and new are present, compare for changes */
				if ( ao[j] && ao[j]->a_numvals > i ) {
					if ( ber_bvcmp( &ao[j]->a_nvals[i], &an[j]->a_nvals[i] ))
						changed = V_REP;
				} else {
					changed = V_INS;
				}
			} else {
				if ( ao[j] && ao[j]->a_numvals > i )
					changed = V_DEL;
			}
			if ( changed ) {
				if ( !myop ) {
					rc = LDAP_OTHER;
					myop = txn->getNdbOperation( myTable );
					if ( !myop ) {
						goto done;
					}
					if ( old ) {
						if ( myop->writeTuple()) {
							goto done;
						}
					} else {
						if ( myop->insertTuple()) {
							goto done;
						}
					}
					if ( myop->equal( EID_COLUMN, eid )) {
						goto done;
					}
					if ( myop->equal( VID_COLUMN, i )) {
						goto done;
					}
				}
				if ( attrs[j]->na_flag & NDB_INFO_ATBLOB ) {
					NdbBlob *myBlob = myop->getBlobHandle( attrs[j]->na_column );
					rc = LDAP_OTHER;
					if ( !myBlob ) {
						Debug( LDAP_DEBUG_TRACE, "ndb_oc_attrs: getBlobHandle failed %s (%d)\n",
							myop->getNdbError().message, myop->getNdbError().code, 0 );
						goto done;
					}
					if ( slapMode & SLAP_TOOL_MODE )
						ndb_flush_blobs = 1;
					if ( changed & V_INS ) {
						if ( myBlob->setValue( an[j]->a_vals[i].bv_val, an[j]->a_vals[i].bv_len )) {
							Debug( LDAP_DEBUG_TRACE, "ndb_oc_attrs: blob->setValue failed %s (%d)\n",
								myBlob->getNdbError().message, myBlob->getNdbError().code, 0 );
							goto done;
						}
					} else {
						if ( myBlob->setValue( NULL, 0 )) {
							Debug( LDAP_DEBUG_TRACE, "ndb_oc_attrs: blob->setValue failed %s (%d)\n",
								myBlob->getNdbError().message, myBlob->getNdbError().code, 0 );
							goto done;
						}
					}
				} else {
					if ( changed & V_INS ) {
						if ( an[j]->a_vals[i].bv_len > attrs[j]->na_len ) {
							Debug( LDAP_DEBUG_ANY, "ndb_oc_attrs: attribute %s too long for column\n",
								attrs[j]->na_name.bv_val, 0, 0 );
							rc = LDAP_CONSTRAINT_VIOLATION;
							goto done;
						}
						ptr = buf;
						*ptr++ = an[j]->a_vals[i].bv_len & 0xff;
						if ( attrs[j]->na_len > 255 ) {
							/* MedVar */
							*ptr++ = an[j]->a_vals[i].bv_len >> 8;
						}
						memcpy( ptr, an[j]->a_vals[i].bv_val, an[j]->a_vals[i].bv_len );
						ptr = buf;
					} else {
						ptr = NULL;
					}
					if ( myop->setValue( attrs[j]->na_column, ptr )) {
						rc = LDAP_OTHER;
						goto done;
					}
				}
			}
		}
Example #7
0
int 
UtilTransactions::readRowFromTableAndIndex(Ndb* pNdb,
					   NdbConnection* scanTrans,
					   const NdbDictionary::Index* pIndex,
					   NDBT_ResultRow& row ){


  NdbDictionary::Index::Type indexType= pIndex->getType();
  int                  retryAttempt = 0;
  const int            retryMax = 100;
  int                  check, a;
  NdbConnection	       *pTrans1=NULL;
  NdbOperation	       *pOp;

  int return_code= NDBT_FAILED;

  // Allocate place to store the result
  NDBT_ResultRow       tabRow(tab);
  NDBT_ResultRow       indexRow(tab);
  const char * indexName = pIndex->getName();

  while (true){
    if(retryAttempt)
      ndbout_c("retryAttempt %d", retryAttempt);
    if (retryAttempt >= retryMax){
      g_info << "ERROR: has retried this operation " << retryAttempt 
	     << " times, failing!" << endl;
	goto close_all;
    }

    pTrans1 = pNdb->hupp(scanTrans); //startTransaction();
    if (pTrans1 == NULL) {
      const NdbError err = pNdb->getNdbError();
      
      if (err.status == NdbError::TemporaryError){
	ERR(err);
	NdbSleep_MilliSleep(50);
	retryAttempt++;
	continue;
      }

      if(err.code == 0){
	return_code = NDBT_OK;
	goto close_all;
      }
      ERR(err);
      goto close_all;
    }

    /**
     * Read the record from TABLE
     */
    pOp = pTrans1->getNdbOperation(tab.getName());	
    if (pOp == NULL) {
      ERR(pTrans1->getNdbError());
      goto close_all;
    }
    
    check = pOp->readTuple();
    if( check == -1 ) {
      ERR(pTrans1->getNdbError());
      goto close_all;
    }
    
    // Define primary keys
#if VERBOSE
    printf("PK: ");
#endif
    for(a = 0; a<tab.getNoOfColumns(); a++){
      const NdbDictionary::Column* attr = tab.getColumn(a);
      if (attr->getPrimaryKey() == true){
	if (pOp->equal(attr->getName(), row.attributeStore(a)->aRef()) != 0){
	  ERR(pTrans1->getNdbError());
	  goto close_all;
	}
#if VERBOSE
	printf("%s = %d: ", attr->getName(), row.attributeStore(a)->aRef());
#endif
      }
    }
#if VERBOSE
    printf("\n");
#endif
    // Read all attributes
#if VERBOSE
    printf("Reading %u attributes: ", tab.getNoOfColumns());
#endif
    for(a = 0; a<tab.getNoOfColumns(); a++){
      if((tabRow.attributeStore(a) = 
	  pOp->getValue(tab.getColumn(a)->getName())) == 0) {
	ERR(pTrans1->getNdbError());
	goto close_all;
      }
#if VERBOSE
      printf("%s ", tab.getColumn(a)->getName());
#endif
    }
#if VERBOSE
    printf("\n");
#endif

    /**
     * Read the record from INDEX_TABLE
     */    
    NdbIndexOperation* pIndexOp= NULL;
    NdbIndexScanOperation *pScanOp= NULL;
    NdbOperation *pIOp= 0;

    bool null_found= false;
    for(a = 0; a<(int)pIndex->getNoOfColumns(); a++){
      const NdbDictionary::Column *  col = pIndex->getColumn(a);
      
      if (row.attributeStore(col->getName())->isNULL())
      {
	null_found= true;
	break;
      }
    }
    
    const char * tabName= tab.getName();
    if(!null_found)
    {
      if (indexType == NdbDictionary::Index::UniqueHashIndex) {
	pIOp= pIndexOp= pTrans1->getNdbIndexOperation(indexName, tabName);
      } else {
	pIOp= pScanOp= pTrans1->getNdbIndexScanOperation(indexName, tabName);
      }
      
      if (pIOp == NULL) {
	ERR(pTrans1->getNdbError());
	goto close_all;
      }
    
      {
	bool not_ok;
	if (pIndexOp) {
	  not_ok = pIndexOp->readTuple() == -1;
	} else {
	  not_ok = pScanOp->readTuples();
	}
	
	if( not_ok ) {
	  ERR(pTrans1->getNdbError());
	  goto close_all;
	}
      }
    
    // Define primary keys for index
#if VERBOSE
      printf("SI: ");
#endif
      for(a = 0; a<(int)pIndex->getNoOfColumns(); a++){
	const NdbDictionary::Column *  col = pIndex->getColumn(a);
	
	int r;
	if ( !row.attributeStore(col->getName())->isNULL() ) {
	  if(pIOp->equal(col->getName(), 
			 row.attributeStore(col->getName())->aRef()) != 0){
	    ERR(pTrans1->getNdbError());
	    goto close_all;
	  }
	}
#if VERBOSE
	printf("%s = %d: ", col->getName(), row.attributeStore(a)->aRef());
#endif
      }
#if VERBOSE
      printf("\n");
#endif
      
      // Read all attributes
#if VERBOSE
      printf("Reading %u attributes: ", tab.getNoOfColumns());
#endif
      for(a = 0; a<tab.getNoOfColumns(); a++){
	void* pCheck;
	
	pCheck= indexRow.attributeStore(a)= 
	  pIOp->getValue(tab.getColumn(a)->getName());
	
	if(pCheck == NULL) {
	  ERR(pTrans1->getNdbError());
	  goto close_all;
	}
#if VERBOSE
	printf("%s ", tab.getColumn(a)->getName());
#endif
      }
    }
#if VERBOSE
    printf("\n");
#endif
    scanTrans->refresh();
    check = pTrans1->execute(Commit, AbortOnError);
    if( check == -1 ) {
      const NdbError err = pTrans1->getNdbError();
      
      if (err.status == NdbError::TemporaryError){
	ERR(err);
	pNdb->closeTransaction(pTrans1);
	NdbSleep_MilliSleep(50);
	retryAttempt++;
	continue;
      }
      ndbout << "Error when comparing records - normal op" << endl;
      ERR(err);
      ndbout << "row: " << row.c_str().c_str() << endl;
      goto close_all;
    } 
    
    /** 
     * Compare the two rows
     */ 
    if(!null_found){
      if (pScanOp) {
	if (pScanOp->nextResult() != 0){
	  const NdbError err = pTrans1->getNdbError();
	  ERR(err);
	  ndbout << "Error when comparing records - index op next_result missing" << endl;
	  ndbout << "row: " << row.c_str().c_str() << endl;
	  goto close_all;
	}
      }
      if (!(tabRow.c_str() == indexRow.c_str())){
	ndbout << "Error when comapring records" << endl;
	ndbout << " tabRow: \n" << tabRow.c_str().c_str() << endl;
	ndbout << " indexRow: \n" << indexRow.c_str().c_str() << endl;
	goto close_all;
      }
      if (pScanOp) {
	if (pScanOp->nextResult() == 0){
	  ndbout << "Error when comparing records - index op next_result to many" << endl;
	  ndbout << "row: " << row.c_str().c_str() << endl;
	  goto close_all;
	}
      }
    }
    return_code= NDBT_OK;
    goto close_all;
  }
  
close_all:
  if (pTrans1)
    pNdb->closeTransaction(pTrans1);
  
  return return_code;
}
Example #8
0
/**
 * Transaction 5 - T5
 * 
 * Delete session
 *
 * Input:
 *   SubscriberNumber
 *   ServerId
 *   ServerBit
 *   DoRollback
 * Output:
 *   ChangedBy
 *   ChangedTime
 *   Location
 *   BranchExecuted
 */
void
userTransaction_T5(UserHandle * uh,
		   SubscriberNumber   inNumber,
		   ServerId           inServerId,
		   ServerBit          inServerBit,
		   DoRollback         inDoRollback,
		   BranchExecuted   * outBranchExecuted){
  Ndb * pNDB = uh->pNDB;

  DEBUG3("T5(%.*s, %.2d): ", SUBSCRIBER_NUMBER_LENGTH, inNumber, inServerId);

  NdbConnection * MyTransaction = 0;
  NdbOperation  * MyOperation = 0;

  char             outChangedBy   [sizeof(ChangedBy)  +(4-(sizeof(ChangedBy)   & 3))];
  char             outChangedTime [sizeof(ChangedTime)+(4-(sizeof(ChangedTime) & 3))];
  Location         outLocation;
  GroupId          groupId;
  ActiveSessions   sessions;
  Permission       permission;
  SubscriberSuffix inSuffix;

  int check;
  NdbRecAttr * check2;

  MyTransaction = pNDB->startTransaction();
  if (MyTransaction == NULL)	  
    error_handler("T5-1: startTranscation", pNDB->getNdbErrorString(), pNDB->getNdbError());
  
  MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
  CHECK_NULL(MyOperation, "T5-1: getNdbOperation", 
	     MyTransaction);
  
  MyOperation->interpretedUpdateTuple();
  MyOperation->equal(IND_SUBSCRIBER_NUMBER, 
		     inNumber);
  MyOperation->getValue(IND_SUBSCRIBER_LOCATION, 
		        (char *)&outLocation);
  MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY, 
			&outChangedBy[0]);
  MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME, 
                        &outChangedTime[0]);
  MyOperation->getValue(IND_SUBSCRIBER_GROUP,
		        (char *)&groupId);
  MyOperation->getValue(IND_SUBSCRIBER_SESSIONS,
		        (char *)&sessions);
  MyOperation->subValue(IND_SUBSCRIBER_SESSIONS, 
		        (uint32)inServerBit);
  MyTransaction->execute( NoCommit ); 
    /* Operation 2 */

  MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
  CHECK_NULL(MyOperation, "T5-2: getNdbOperation", 
	     MyTransaction);
    
  MyOperation->readTuple();
  MyOperation->equal(IND_GROUP_ID,
		     (char*)&groupId);
  MyOperation->getValue(IND_GROUP_ALLOW_DELETE, 
			(char *)&permission);
  check = MyTransaction->execute( NoCommit ); 
  CHECK_MINUS_ONE(check, "T5-2: NoCommit", 
		  MyTransaction);
  
  if(((permission & inServerBit) == inServerBit) &&
     ((sessions   & inServerBit) == inServerBit)){
  
    memcpy(inSuffix,
	   &inNumber[SUBSCRIBER_NUMBER_LENGTH-SUBSCRIBER_NUMBER_SUFFIX_LENGTH], SUBSCRIBER_NUMBER_SUFFIX_LENGTH);
    
    DEBUG2("deleting(%.*s) - ", SUBSCRIBER_NUMBER_SUFFIX_LENGTH, inSuffix);

    /* Operation 3 */
    MyOperation = MyTransaction->getNdbOperation(SESSION_TABLE);
    CHECK_NULL(MyOperation, "T5-3: getNdbOperation", 
	       MyTransaction);
    
    MyOperation->deleteTuple();
    MyOperation->equal(IND_SESSION_SUBSCRIBER,
		       (char*)inNumber);
    MyOperation->equal(IND_SESSION_SERVER,
		       (char*)&inServerId);
    /* Operation 4 */
        
    /* Operation 5 */
    MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
    CHECK_NULL(MyOperation, "T5-5: getNdbOperation", 
	       MyTransaction);
    
    
    MyOperation->interpretedUpdateTuple();
    MyOperation->equal(IND_SERVER_ID,
		       (char*)&inServerId);
    MyOperation->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
		       (char*)inSuffix);
    MyOperation->incValue(IND_SERVER_DELETES, (uint32)1);
    (* outBranchExecuted) = 1;
  } else {
    (* outBranchExecuted) = 0;
    DEBUG1("%s", ((permission & inServerBit) ? "permission - " : "no permission - "));
    DEBUG1("%s", ((sessions   & inServerBit) ? "in session - " : "no in session - "));
  }

  if(!inDoRollback && (* outBranchExecuted)){
    DEBUG("commit\n");
    check = MyTransaction->execute( Commit ); 
    CHECK_MINUS_ONE(check, "T5: Commit", 
		    MyTransaction);
  } else {
    DEBUG("rollback\n");
    check = MyTransaction->execute(Rollback);
    CHECK_MINUS_ONE(check, "T5:Rollback", 
		    MyTransaction);
    
  }
  
  pNDB->closeTransaction(MyTransaction);
}
Example #9
0
int HugoOperations::pkReadRecord(Ndb* pNdb,
				 int recordNo,
				 int numRecords,
				 NdbOperation::LockMode lm,
                                 NdbOperation::LockMode *lmused){
  int a;  
  allocRows(numRecords);
  indexScans.clear();  
  int check;

  NdbOperation* pOp = 0;
  pIndexScanOp = 0;

  for(int r=0; r < numRecords; r++){
    
    if(pOp == 0)
    {
      pOp = getOperation(pTrans, NdbOperation::ReadRequest);
    }
    if (pOp == NULL) {
      ERR(pTrans->getNdbError());
      setNdbError(pTrans->getNdbError());
      return NDBT_FAILED;
    }
    
rand_lock_mode:
    switch(lm){
    case NdbOperation::LM_Read:
    case NdbOperation::LM_Exclusive:
    case NdbOperation::LM_CommittedRead:
    case NdbOperation::LM_SimpleRead:
      if (lmused)
        * lmused = lm;
      if(idx && idx->getType() == NdbDictionary::Index::OrderedIndex)
      {
        if (pIndexScanOp == 0)
        {
          pIndexScanOp = ((NdbIndexScanOperation*)pOp);
          bool mrrScan= (numRecords > 1);
          Uint32 flags= mrrScan? NdbScanOperation::SF_MultiRange : 0; 
          check = pIndexScanOp->readTuples(lm, flags);
          /* Record NdbIndexScanOperation ptr for later... */
          indexScans.push_back(pIndexScanOp);
        }
      }
      else
	check = pOp->readTuple(lm);
      break;
    default:
      lm = (NdbOperation::LockMode)((rand() >> 16) & 3);
      goto rand_lock_mode;
    }
    
    if( check == -1 ) {
      ERR(pTrans->getNdbError());
      setNdbError(pTrans->getNdbError());
      return NDBT_FAILED;
    }
    
    // Define primary keys
    if (equalForRow(pOp, r+recordNo) != 0)
      return NDBT_FAILED;

    Uint32 partId;
    /* Do we need to set the partitionId for this operation? */
    if (getPartIdForRow(pOp, r+recordNo, partId))
    {
      g_info << "Setting operation partition Id" << endl;
      pOp->setPartitionId(partId);
    }

    if(pIndexScanOp)
      pIndexScanOp->end_of_bound(r);
    
    if(r == 0 || pIndexScanOp == 0)
    {
      // Define attributes to read  
      for(a = 0; a<tab.getNoOfColumns(); a++){
	if((rows[r]->attributeStore(a) = 
	    pOp->getValue(tab.getColumn(a)->getName())) == 0) {
	  ERR(pTrans->getNdbError());
          setNdbError(pTrans->getNdbError());
	  return NDBT_FAILED;
	}
      } 
    }
    /* Note pIndexScanOp will point to the 'last' index scan op
     * we used.  The full list is in the indexScans vector
     */
    pOp = pIndexScanOp;
  }
  return NDBT_OK;
}
Example #10
0
void
T4_Callback_2(int result, NdbConnection * pCON, void * threadData) {
    ThreadData * td = (ThreadData *)threadData;
    if (result == -1) {
        CHECK_ALLOWED_ERROR("T4-2: execute", td, pCON->getNdbError());
        td->pNDB->closeTransaction(pCON);
        start_T4(td->pNDB, td, stat_async);
        return;
    }//if

    Uint32 permission = td->transactionData.permission;
    Uint32 sessions   = td->transactionData.sessions;
    Uint32 server_bit = td->transactionData.server_bit;

    if(((permission & server_bit) == server_bit) &&
            ((sessions   & server_bit) == 0)) {

        memcpy(td->transactionData.suffix,
               &td->transactionData.number[SFX_START],
               SUBSCRIBER_NUMBER_SUFFIX_LENGTH);

        DEBUG5("T4(%.*s, %.2d): - Callback 2 - inserting(%.*s)",
               SUBSCRIBER_NUMBER_LENGTH,
               td->transactionData.number,
               td->transactionData.server_id,
               SUBSCRIBER_NUMBER_SUFFIX_LENGTH,
               td->transactionData.suffix);

        /* Operations 3 + 4 */

        if (td->ndbRecordSharedData)
        {
            char* rowPtr= (char*) &td->transactionData;
            const NdbRecord* record= td->ndbRecordSharedData->
                                     sessionTableNdbRecord;
            Uint32 m=0;
            unsigned char* mask= (unsigned char*) &m;

            SET_MASK(mask, IND_SESSION_SUBSCRIBER);
            SET_MASK(mask, IND_SESSION_SERVER);
            SET_MASK(mask, IND_SESSION_DATA);

            const NdbOperation* MyOp= pCON->insertTuple(record, rowPtr, mask);

            CHECK_NULL((void*)MyOp, "T4-3: insertTuple", td,
                       pCON->getNdbError());

            record= td->ndbRecordSharedData->
                    serverTableNdbRecord;
            m= 0;

            NdbOperation::OperationOptions opts;
            opts.optionsPresent= NdbOperation::OperationOptions::OO_INTERPRETED;
            opts.interpretedCode= td->ndbRecordSharedData->incrServerInsertsProg;

            MyOp= pCON->updateTuple(record, rowPtr, record, rowPtr, mask,
                                    &opts, sizeof(opts));

            CHECK_NULL((void*)MyOp, "T4-3: updateTuple", td,
                       pCON->getNdbError());
        }
        else
        {
            NdbOperation * MyOp = pCON->getNdbOperation(SESSION_TABLE);
            CHECK_NULL(MyOp, "T4-3: getNdbOperation", td,
                       pCON->getNdbError());

            MyOp->insertTuple();
            MyOp->equal(IND_SESSION_SUBSCRIBER,
                        (char*)td->transactionData.number);
            MyOp->equal(IND_SESSION_SERVER,
                        (char*)&td->transactionData.server_id);
            MyOp->setValue(IND_SESSION_DATA,
                           (char *)td->transactionData.session_details);
            /* Operation 4 */

            /* Operation 5 */
            MyOp = pCON->getNdbOperation(SERVER_TABLE);
            CHECK_NULL(MyOp, "T4-5: getNdbOperation", td,
                       pCON->getNdbError());

            MyOp->interpretedUpdateTuple();
            MyOp->equal(IND_SERVER_ID,
                        (char*)&td->transactionData.server_id);
            MyOp->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
                        (char*)td->transactionData.suffix);
            MyOp->incValue(IND_SERVER_INSERTS, (uint32)1);
        }
        td->transactionData.branchExecuted = 1;
    } else {
        td->transactionData.branchExecuted = 0;
        DEBUG5("T4(%.*s, %.2d): - Callback 2 - %s %s",
               SUBSCRIBER_NUMBER_LENGTH,
               td->transactionData.number,
               td->transactionData.server_id,
               ((permission & server_bit) ?
                "permission - " : "no permission - "),
               ((sessions   & server_bit) ?
                "in session - " : "no in session - "));
    }

    if(!td->transactionData.do_rollback && td->transactionData.branchExecuted) {
        if (stat_async == 1) {
            pCON->executeAsynchPrepare( Commit , T4_Callback_3, td);
        } else {
            int result = pCON->execute( Commit );
            T4_Callback_3(result, pCON, (void*)td);
            return;
        }//if
    } else {
        if (stat_async == 1) {
            pCON->executeAsynchPrepare( Rollback , T4_Callback_3, td);
        } else {
            int result = pCON->execute( Rollback );
            T4_Callback_3(result, pCON, (void*)td);
            return;
        }//if
    }
}
Example #11
0
void
start_T1(Ndb * pNDB, ThreadData * td, int async) {

    DEBUG2("T1(%.*s): - Starting", SUBSCRIBER_NUMBER_LENGTH,
           td->transactionData.number);

    NdbConnection * pCON = 0;
    while((pCON = startTransaction(pNDB, td)) == 0) {
        CHECK_ALLOWED_ERROR("T1: startTransaction", td, pNDB->getNdbError());
        NdbSleep_MilliSleep(10);
    }

    const NdbOperation* op= NULL;

    if (td->ndbRecordSharedData)
    {
        char* rowPtr= (char*) &td->transactionData;
        const NdbRecord* record= td->ndbRecordSharedData->
                                 subscriberTableNdbRecord;
        Uint32 m=0;
        unsigned char* mask= (unsigned char*) &m;

        //SET_MASK(mask, IND_SUBSCRIBER_NUMBER);
        SET_MASK(mask, IND_SUBSCRIBER_LOCATION);
        SET_MASK(mask, IND_SUBSCRIBER_CHANGED_BY);
        SET_MASK(mask, IND_SUBSCRIBER_CHANGED_TIME);

        op= pCON->updateTuple(record,
                              rowPtr,
                              record,
                              rowPtr,
                              mask);
    }
    else
    {
        NdbOperation *MyOp = pCON->getNdbOperation(SUBSCRIBER_TABLE);
        op= MyOp;
        if (MyOp != NULL) {
            MyOp->updateTuple();
            MyOp->equal(IND_SUBSCRIBER_NUMBER,
                        td->transactionData.number);
            MyOp->setValue(IND_SUBSCRIBER_LOCATION,
                           (char *)&td->transactionData.location);
            MyOp->setValue(IND_SUBSCRIBER_CHANGED_BY,
                           td->transactionData.changed_by);
            MyOp->setValue(IND_SUBSCRIBER_CHANGED_TIME,
                           td->transactionData.changed_time);
        }
    }

    if (op != NULL)
    {
        if (async == 1) {
            pCON->executeAsynchPrepare( Commit , T1_Callback, td);
        } else {
            int result = pCON->execute(Commit);
            T1_Callback(result, pCON, (void*)td);
            return;
        }//if
    } else {
        CHECK_NULL(NULL, "T1: getNdbOperation", td, pCON->getNdbError());
    }//if
}
Example #12
0
void
T3_Callback_2(int result, NdbConnection * pCON, void * threadData) {
    ThreadData * td = (ThreadData *)threadData;

    if (result == -1) {
        CHECK_ALLOWED_ERROR("T3-2: execute", td, pCON->getNdbError());
        td->pNDB->closeTransaction(pCON);
        start_T3(td->pNDB, td, stat_async);
        return;
    }//if

    Uint32 permission = td->transactionData.permission;
    Uint32 sessions   = td->transactionData.sessions;
    Uint32 server_bit = td->transactionData.server_bit;

    if(((permission & server_bit) == server_bit) &&
            ((sessions   & server_bit) == server_bit)) {

        memcpy(td->transactionData.suffix,
               &td->transactionData.number[SFX_START],
               SUBSCRIBER_NUMBER_SUFFIX_LENGTH);
        DEBUG5("T3(%.*s, %.2d): - Callback 2 - reading(%.*s)",
               SUBSCRIBER_NUMBER_LENGTH,
               td->transactionData.number,
               td->transactionData.server_id,
               SUBSCRIBER_NUMBER_SUFFIX_LENGTH,
               td->transactionData.suffix);

        /* Operations 3 + 4 */
        if (td->ndbRecordSharedData)
        {
            /* Op 3 */
            char* rowPtr= (char*) &td->transactionData;
            const NdbRecord* record= td->ndbRecordSharedData->
                                     sessionTableNdbRecord;
            Uint32 m=0;
            unsigned char* mask= (unsigned char*) &m;

            SET_MASK(mask, IND_SESSION_DATA);

            const NdbOperation* MyOp = pCON->readTuple(record, rowPtr, record, rowPtr,
                                       NdbOperation::LM_SimpleRead,
                                       mask);
            CHECK_NULL((void*) MyOp, "T3-3: readTuple", td,
                       pCON->getNdbError());

            /* Op 4 */
            record= td->ndbRecordSharedData->
                    serverTableNdbRecord;
            m= 0;

            /* Attach interpreted program */
            NdbOperation::OperationOptions opts;
            opts.optionsPresent= NdbOperation::OperationOptions::OO_INTERPRETED;
            opts.interpretedCode= td->ndbRecordSharedData->incrServerReadsProg;

            MyOp= pCON->updateTuple(record, rowPtr, record, rowPtr, mask,
                                    &opts,
                                    sizeof(opts));
            CHECK_NULL((void*) MyOp, "T3-3: updateTuple", td,
                       pCON->getNdbError());
        }
        else
        {
            NdbOperation * MyOp = pCON->getNdbOperation(SESSION_TABLE);
            CHECK_NULL(MyOp, "T3-3: getNdbOperation", td,
                       pCON->getNdbError());

            MyOp->simpleRead();
            MyOp->equal(IND_SESSION_SUBSCRIBER,
                        (char*)td->transactionData.number);
            MyOp->equal(IND_SESSION_SERVER,
                        (char*)&td->transactionData.server_id);
            MyOp->getValue(IND_SESSION_DATA,
                           (char *)td->transactionData.session_details);

            MyOp = pCON->getNdbOperation(SERVER_TABLE);
            CHECK_NULL(MyOp, "T3-4: getNdbOperation", td,
                       pCON->getNdbError());

            MyOp->interpretedUpdateTuple();
            MyOp->equal(IND_SERVER_ID,
                        (char*)&td->transactionData.server_id);
            MyOp->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
                        (char*)td->transactionData.suffix);
            MyOp->incValue(IND_SERVER_READS, (uint32)1);
        }

        td->transactionData.branchExecuted = 1;
    } else {
        DEBUG3("T3(%.*s, %.2d): - Callback 2 - no read",
               SUBSCRIBER_NUMBER_LENGTH,
               td->transactionData.number,
               td->transactionData.server_id);
        td->transactionData.branchExecuted = 0;
    }
    if (stat_async == 1) {
        pCON->executeAsynchPrepare( Commit , T3_Callback_3, td);
    } else {
        int result = pCON->execute( Commit );
        T3_Callback_3(result, pCON, (void*)td);
        return;
    }//if
}
int main(int argc, char** argv)
{
  if (argc != 3)
  {
    std::cout << "Arguments are <socket mysqld> <connect_string cluster>.\n";
    exit(-1);
  }
  char * mysqld_sock  = argv[1];
  const char *connectstring = argv[2];
  ndb_init();

  Ndb_cluster_connection *cluster_connection=
    new Ndb_cluster_connection(connectstring); // Object representing the cluster

  int r= cluster_connection->connect(5 /* retries               */,
				     3 /* delay between retries */,
				     1 /* verbose               */);
  if (r > 0)
  {
    std::cout
      << "Cluster connect failed, possibly resolved with more retries.\n";
    exit(-1);
  }
  else if (r < 0)
  {
    std::cout
      << "Cluster connect failed.\n";
    exit(-1);
  }

  if (cluster_connection->wait_until_ready(30,0) < 0)
  {
    std::cout << "Cluster was not ready within 30 secs." << std::endl;
    exit(-1);
  }
					   
  // connect to mysql server
  MYSQL mysql;
  if ( !mysql_init(&mysql) ) {
    std::cout << "mysql_init failed\n";
    exit(-1);
  }
  if ( !mysql_real_connect(&mysql, "localhost", "root", "", "",
			   0, mysqld_sock, 0) )
    MYSQLERROR(mysql);
  
  /********************************************
   * Connect to database via mysql-c          *
   ********************************************/
  mysql_query(&mysql, "CREATE DATABASE TEST_DB_1");
  if (mysql_query(&mysql, "USE TEST_DB_1") != 0) MYSQLERROR(mysql);
  create_table(mysql);

  Ndb* myNdb = new Ndb( cluster_connection,
			"TEST_DB_1" );  // Object representing the database

  NdbTransaction*  myNdbTransaction[2];   // For transactions
  NdbOperation*   myNdbOperation;       // For operations
  
  if (myNdb->init(2) == -1) {          // Want two parallel insert transactions
    APIERROR(myNdb->getNdbError());
    exit(-1);
  }

  /******************************************************
   * Insert (we do two insert transactions in parallel) *
   ******************************************************/
  const NdbDictionary::Dictionary* myDict= myNdb->getDictionary();
  const NdbDictionary::Table *myTable= myDict->getTable("MYTABLENAME");
  if (myTable == NULL)
    APIERROR(myDict->getNdbError());
  for (int i = 0; i < 2; i++) {
    myNdbTransaction[i] = myNdb->startTransaction();
    if (myNdbTransaction[i] == NULL) APIERROR(myNdb->getNdbError());
    
    myNdbOperation = myNdbTransaction[i]->getNdbOperation(myTable);
    if (myNdbOperation == NULL) APIERROR(myNdbTransaction[i]->getNdbError());
    
    myNdbOperation->insertTuple();
    myNdbOperation->equal("ATTR1", 20 + i);
    myNdbOperation->setValue("ATTR2", 20 + i);
    
    // Prepare transaction (the transaction is NOT yet sent to NDB)
    myNdbTransaction[i]->executeAsynchPrepare(NdbTransaction::Commit,
					      &callback, NULL);
  }

  // Send all transactions to NDB 
  myNdb->sendPreparedTransactions(0);
  
  // Poll all transactions
  myNdb->pollNdb(3000, 2);
  
  // Close all transactions
  for (int i = 0; i < 2; i++) 
    myNdb->closeTransaction(myNdbTransaction[i]);

  delete myNdb;
  delete cluster_connection;

  drop_table(mysql);

  ndb_end(0);
  return 0;
}
int main(int argc, const char** argv)
{
  ndb_init();
  int _row = 0;
  int _hex = 0;
  int _primaryKey = 0;
  const char* _tableName = NULL;

  struct getargs args[] = {
    { "row", 'r', 
      arg_integer, &_row, "The row number", "row" },
    { "primarykey", 'p', 
      arg_integer, &_primaryKey, "The primary key", "primarykey" },
    { "hex", 'h', 
      arg_flag, &_hex, "Print hex", "hex" }
  };

  int num_args = sizeof(args) / sizeof(args[0]);
  int optind = 0, i;

  if(getarg(args, num_args, argc, argv, &optind) || argv[optind] == NULL) {
    arg_printusage(args, num_args, argv[0], "table name\n");
    return NDBT_WRONGARGS;
  }
  // Check if table name is supplied
  if (argv[optind] != NULL) 
    _tableName = argv[optind];


  const NdbDictionary::Table* table = NDBT_Tables::getTable(_tableName);
  //  const NDBT_Attribute* attribute = table->getAttribute(_column);

  g_info << "Table " << _tableName << endl
	 << "Row: " << _row << ", PrimaryKey: " << _primaryKey
	 << endl;

  Ndb_cluster_connection con;
  if(con.connect(12, 5, 1) != 0)
  {
    return NDBT_ProgramExit(NDBT_FAILED);
  }
  Ndb* ndb = new Ndb(&con, "TEST_DB");
  if (ndb->init() == 0 && ndb->waitUntilReady(30) == 0)
  {
    NdbConnection* conn = ndb->startTransaction();
    if (conn == NULL)
    {
      g_info << "ERROR: " << ndb->getNdbError() << endl;
      delete ndb;
      return -1;
    }
    NdbOperation* op = conn->getNdbOperation(_tableName);
    if (op == NULL)
    {
      g_info << "ERROR: " << conn->getNdbError() << endl;
      delete ndb;
      return -1;
    }
    op->readTuple();
    NdbRecAttr** data = new NdbRecAttr*[table->getNoOfColumns()];
    for (i = 0; i < table->getNoOfColumns(); i++)
    {
      const NdbDictionary::Column* c = table->getColumn(i);
      if (c->getPrimaryKey())
      {
	op->equal(c->getName(), _primaryKey);
	data[i] = op->getValue(c->getName(), NULL);
      }
      else
      {
	data[i] = op->getValue(c->getName(), NULL);
      }      
    }
    if (conn->execute(Commit) == 0)
    {
      // Print column names
      for (i = 0; i < table->getNoOfColumns(); i++)
      {
	const NdbDictionary::Column* c = table->getColumn(i);
	
	g_info 
	  << c->getName()
	  << "[" << c->getType() << "]   ";	  
      }
      g_info << endl;

      if (_hex)
      {
	g_info << hex;
      }
      for (i = 0; i < table->getNoOfColumns(); i++)
      {
	NdbRecAttr* a = data[i];
	ndbout << (* a) << " ";
      } // for   
      g_info << endl;   
    } // if (conn
    else
    {
      g_info << "Failed to commit read transaction... " 
	     << conn->getNdbError()
	     << ", commitStatus = " << conn->commitStatus()
	     << endl;
    }

    delete[] data;
    
    ndb->closeTransaction(conn);
  } // if (ndb.init
  else
  {
    g_info << "ERROR: Unable to connect to NDB, " 
	   << ndb->getNdbError() << endl;
  }
  delete ndb;

  return 0;
}
Example #15
0
inline
int 
ScanInterpretTest::addRowToInsert(Ndb* pNdb, 
				  NdbConnection* pInsTrans){

  NdbOperation* pOp = 
    pInsTrans->getNdbOperation(restab.getName());	
  if (pOp == NULL) {
    ERR(pInsTrans->getNdbError());
    pNdb->closeTransaction(pInsTrans);
    return NDBT_FAILED;
  }
  
  if( pOp->insertTuple() == -1 ) {
    ERR(pInsTrans->getNdbError());
    pNdb->closeTransaction(pInsTrans);
    return NDBT_FAILED;
  }
  
  // Copy all attribute to the new operation
  for (int a = 0; a<restab.getNoOfColumns(); a++){
    const NdbDictionary::Column* attr = tab.getColumn(a); 
    NdbRecAttr* reca = row.attributeStore(a);
    int check = -1;
    switch (attr->getType()){
    case NdbDictionary::Column::Char:
    case NdbDictionary::Column::Varchar:
    case NdbDictionary::Column::Binary:
    case NdbDictionary::Column::Varbinary:{
      check = pOp->setValue( attr->getName(), 
			     reca->aRef());
      break;
    }
    case NdbDictionary::Column::Int:{
      check = pOp->setValue( attr->getName(), 
			     reca->int32_value());      
    }
      break;
    case NdbDictionary::Column::Bigint:{
      check = pOp->setValue( attr->getName(), 
			     reca->int64_value());
    }
      break;
    case NdbDictionary::Column::Unsigned:{
      check = pOp->setValue( attr->getName(), 
			     reca->u_32_value());
    }
      break;
    case NdbDictionary::Column::Bigunsigned:{
      check = pOp->setValue( attr->getName(), 
			     reca->u_64_value());
    }
      break;
    case NdbDictionary::Column::Float:
      check = pOp->setValue( attr->getName(), 
			     reca->float_value());

      break;
    default:
      check = -1;
      break;
    }
    if(check != 0){
      ERR(pInsTrans->getNdbError());
      pNdb->closeTransaction(pInsTrans);
      return NDBT_FAILED;
    }
  }
  
  return NDBT_OK;
}
Example #16
0
void
T3_Callback_2(int result, NdbConnection * pCON, void * threadData){
  ThreadData * td = (ThreadData *)threadData;
  
  if (result == -1) {
    CHECK_ALLOWED_ERROR("T3-2: execute", td, pCON->getNdbError());
    td->pNDB->closeTransaction(pCON);
    start_T3(td->pNDB, td, stat_async);
    return;
  }//if
  
  Uint32 permission = td->transactionData.permission;
  Uint32 sessions   = td->transactionData.sessions;
  Uint32 server_bit = td->transactionData.server_bit;

  if(((permission & server_bit) == server_bit) &&
     ((sessions   & server_bit) == server_bit)){
    
    memcpy(td->transactionData.suffix,
	   &td->transactionData.number[SFX_START],
	   SUBSCRIBER_NUMBER_SUFFIX_LENGTH);
    DEBUG5("T3(%.*s, %.2d): - Callback 2 - reading(%.*s)", 
	   SUBSCRIBER_NUMBER_LENGTH, 
	   td->transactionData.number, 
	   td->transactionData.server_id,
	   SUBSCRIBER_NUMBER_SUFFIX_LENGTH, 
	   td->transactionData.suffix);
    
    /* Operation 3 */
    NdbOperation * MyOp = pCON->getNdbOperation(SESSION_TABLE);
    CHECK_NULL(MyOp, "T3-3: getNdbOperation", td,
	       pCON->getNdbError());
    
    MyOp->simpleRead();
    MyOp->equal(IND_SESSION_SUBSCRIBER,
		(char*)td->transactionData.number);
    MyOp->equal(IND_SESSION_SERVER,
		(char*)&td->transactionData.server_id);
    MyOp->getValue(IND_SESSION_DATA, 
		   (char *)td->transactionData.session_details);
    
    /* Operation 4 */
    MyOp = pCON->getNdbOperation(SERVER_TABLE);
    CHECK_NULL(MyOp, "T3-4: getNdbOperation", td,
	       pCON->getNdbError());
    
    MyOp->interpretedUpdateTuple();
    MyOp->equal(IND_SERVER_ID,
		(char*)&td->transactionData.server_id);
    MyOp->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
		(char*)td->transactionData.suffix);
    MyOp->incValue(IND_SERVER_READS, (uint32)1);
    td->transactionData.branchExecuted = 1;
  } else {
    DEBUG3("T3(%.*s, %.2d): - Callback 2 - no read",
	   SUBSCRIBER_NUMBER_LENGTH, 
	   td->transactionData.number, 
	   td->transactionData.server_id);
    td->transactionData.branchExecuted = 0;
  }
  if (stat_async == 1) {
    pCON->executeAsynchPrepare( Commit , T3_Callback_3, td);
  } else {
    int result = pCON->execute( Commit );
    T3_Callback_3(result, pCON, (void*)td);
    return;
  }//if
}
Example #17
0
static void run_slave_wait(struct Xxx &xxx, struct XxxR &xxxr)
{
  struct timeval old_end_time = xxxr.start_time, end_time;
  Ndb *ndb = xxx.ndb;
  const NdbDictionary::Table *myTable = xxx.table;
  int retry_sleep= 10; /* 10 milliseconds */
  int retries= 100;
  while (1)
  {
    Uint32 val;
    NdbTransaction *trans = ndb->startTransaction();
    if (trans == NULL)
      goto err;
    {
      NdbOperation *op = trans->getNdbOperation(myTable);
      if (op == NULL)
        APIERROR(trans->getNdbError());
      op->readTuple();
      op->equal(xxx.pk_col, xxxr.pk_val);
      op->getValue(xxx.col, (char *)&val);
      if (trans->execute(NdbTransaction::Commit))
        goto err;
    }
    /* read done, check time of read */
    gettimeofday(&end_time, 0);
    ndb->closeTransaction(trans);
    //fprintf(stderr, "read %u waiting for %u\n", val, xxxr.val);
    if (xxxr.val != val)
    {
      /* expected value not received yet */
      retries = 100;
      NdbSleep_MilliSleep(retry_sleep);
      old_end_time =  end_time;
      continue;
    }
    break;
err:
    const NdbError this_error= trans ?
      trans->getNdbError() : ndb->getNdbError();
    if (this_error.status == NdbError::TemporaryError)
    {
      if (retries--)
      {
        if (trans)
          ndb->closeTransaction(trans);
        NdbSleep_MilliSleep(retry_sleep);
        continue; // retry
      }
    }
    if (trans)
      ndb->closeTransaction(trans);
    APIERROR(this_error);
  }

  Int64 elapsed_usec1 =
    ((Int64)end_time.tv_sec - (Int64)xxxr.start_time.tv_sec)*1000*1000 +
    ((Int64)end_time.tv_usec - (Int64)xxxr.start_time.tv_usec);
  Int64 elapsed_usec2 =
    ((Int64)end_time.tv_sec - (Int64)old_end_time.tv_sec)*1000*1000 +
    ((Int64)end_time.tv_usec - (Int64)old_end_time.tv_usec);
  xxxr.latency =
    ((elapsed_usec1 - elapsed_usec2/2)+999)/1000;
}
Example #18
0
void
T5_Callback_2(int result, NdbConnection * pCON, void * threadData){
  ThreadData * td = (ThreadData *)threadData;  
  if (result == -1) {
    CHECK_ALLOWED_ERROR("T5-2: execute", td, pCON->getNdbError());
    td->pNDB->closeTransaction(pCON);
    start_T5(td->pNDB, td, stat_async);
    return;
  }//if

  Uint32 permission = td->transactionData.permission;
  Uint32 sessions   = td->transactionData.sessions;
  Uint32 server_bit = td->transactionData.server_bit;

  if(((permission & server_bit) == server_bit) &&
     ((sessions   & server_bit) == server_bit)){
    
    memcpy(td->transactionData.suffix,
	   &td->transactionData.number[SFX_START],
	   SUBSCRIBER_NUMBER_SUFFIX_LENGTH);
    
    DEBUG5("T5(%.*s, %.2d): - Callback 2 - deleting(%.*s)", 
	   SUBSCRIBER_NUMBER_LENGTH, 
	   td->transactionData.number, 
	   td->transactionData.server_id,
	   SUBSCRIBER_NUMBER_SUFFIX_LENGTH, 
	   td->transactionData.suffix);
    
    /* Operation 3 */
    NdbOperation * MyOp = pCON->getNdbOperation(SESSION_TABLE);
    CHECK_NULL(MyOp, "T5-3: getNdbOperation", td,
	       pCON->getNdbError());
    
    MyOp->deleteTuple();
    MyOp->equal(IND_SESSION_SUBSCRIBER,
		(char*)td->transactionData.number);
    MyOp->equal(IND_SESSION_SERVER,
		(char*)&td->transactionData.server_id);
    /* Operation 4 */
    
    /* Operation 5 */
    MyOp = pCON->getNdbOperation(SERVER_TABLE);
    CHECK_NULL(MyOp, "T5-5: getNdbOperation", td,
	       pCON->getNdbError());
    
    MyOp->interpretedUpdateTuple();
    MyOp->equal(IND_SERVER_ID,
		(char*)&td->transactionData.server_id);
    MyOp->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
		(char*)td->transactionData.suffix);
    MyOp->incValue(IND_SERVER_DELETES, (uint32)1);
    td->transactionData.branchExecuted = 1;
  } else {
    td->transactionData.branchExecuted = 0;

    DEBUG5("T5(%.*s, %.2d): - Callback 2 - no delete - %s %s", 
	   SUBSCRIBER_NUMBER_LENGTH, 
	   td->transactionData.number, 
	   td->transactionData.server_id,
	   ((permission & server_bit) ? 
	    "permission - " : "no permission - "),
	   ((sessions   & server_bit) ? 
	    "in session - " : "no in session - "));
  }
  
  if(!td->transactionData.do_rollback && td->transactionData.branchExecuted){
    if (stat_async == 1) {
      pCON->executeAsynchPrepare( Commit , T5_Callback_3, td);
    } else {
      int result = pCON->execute( Commit );
      T5_Callback_3(result, pCON, (void*)td);
      return;
    }//if
  } else {
    if (stat_async == 1) {
      pCON->executeAsynchPrepare( Rollback , T5_Callback_3, td);
    } else {
      int result = pCON->execute( Rollback );
      T5_Callback_3(result, pCON, (void*)td);
      return;
    }//if
  }
}
Example #19
0
int 
UtilTransactions::verifyOrderedIndex(Ndb* pNdb,
				     const NdbDictionary::Index* pIndex,
				     int parallelism,
				     bool transactional){
  
  int                  retryAttempt = 0;
  const int            retryMax = 100;
  int                  check;
  NdbScanOperation     *pOp;
  NdbIndexScanOperation * iop = 0;

  NDBT_ResultRow       scanRow(tab);
  NDBT_ResultRow       pkRow(tab);
  NDBT_ResultRow       indexRow(tab);
  const char * indexName = pIndex->getName();

  int res;
  parallelism = 1;
  
  while (true){

    if (retryAttempt >= retryMax){
      g_info << "ERROR: has retried this operation " << retryAttempt 
	     << " times, failing!" << endl;
      return NDBT_FAILED;
    }

    pTrans = pNdb->startTransaction();
    if (pTrans == NULL) {
      const NdbError err = pNdb->getNdbError();

      if (err.status == NdbError::TemporaryError){
	ERR(err);
	NdbSleep_MilliSleep(50);
	retryAttempt++;
	continue;
      }
      ERR(err);
      return NDBT_FAILED;
    }

    pOp = pTrans->getNdbScanOperation(tab.getName());	
    if (pOp == NULL) {
      ERR(pTrans->getNdbError());
      closeTransaction(pNdb);
      return NDBT_FAILED;
    }

    if( pOp->readTuples(NdbScanOperation::LM_Read, 0, parallelism) ) {
      ERR(pTrans->getNdbError());
      closeTransaction(pNdb);
      return NDBT_FAILED;
    }

    check = pOp->interpret_exit_ok();
    if( check == -1 ) {
      ERR(pTrans->getNdbError());
      closeTransaction(pNdb);
      return NDBT_FAILED;
    }

    if(get_values(pOp, scanRow))
    {
      abort();
    }

    check = pTrans->execute(NoCommit, AbortOnError);
    if( check == -1 ) {
      const NdbError err = pTrans->getNdbError();
      
      if (err.status == NdbError::TemporaryError){
	ERR(err);
	closeTransaction(pNdb);
	NdbSleep_MilliSleep(50);
	retryAttempt++;
	continue;
      }
      ERR(err);
      closeTransaction(pNdb);
      return NDBT_FAILED;
    }
        
    int eof;
    int rows = 0;
    while(check == 0 && (eof = pOp->nextResult()) == 0){
      rows++;

      bool null_found= false;
      for(int a = 0; a<(int)pIndex->getNoOfColumns(); a++){
	const NdbDictionary::Column *  col = pIndex->getColumn(a);
	if (scanRow.attributeStore(col->getName())->isNULL())
	{
	  null_found= true;
	  break;
	}
      }
      
      // Do pk lookup
      NdbOperation * pk = pTrans->getNdbOperation(tab.getName());
      if(!pk || pk->readTuple())
	goto error;
      if(equal(&tab, pk, scanRow) || get_values(pk, pkRow))
	goto error;

      if(!null_found)
      {
	if(!iop && (iop= pTrans->getNdbIndexScanOperation(indexName, 
							  tab.getName())))
	{
	  if(iop->readTuples(NdbScanOperation::LM_CommittedRead, 
			     parallelism))
	    goto error;
	  iop->interpret_exit_ok();
	  if(get_values(iop, indexRow))
	    goto error;
	}
	else if(!iop || iop->reset_bounds())
	{
	  goto error;
	}
	
	if(equal(pIndex, iop, scanRow))
	  goto error;
      }     

      check = pTrans->execute(NoCommit, AbortOnError);
      if(check)
	goto error;

      if(scanRow.c_str() != pkRow.c_str()){
	g_err << "Error when comapring records" << endl;
	g_err << " scanRow: \n" << scanRow.c_str().c_str() << endl;
	g_err << " pkRow: \n" << pkRow.c_str().c_str() << endl;
	closeTransaction(pNdb);
	return NDBT_FAILED;
      }

      if(!null_found)
      {
	
	if((res= iop->nextResult()) != 0){
	  g_err << "Failed to find row using index: " << res << endl;
	  ERR(pTrans->getNdbError());
	  closeTransaction(pNdb);
	  return NDBT_FAILED;
	}
	
	if(scanRow.c_str() != indexRow.c_str()){
	  g_err << "Error when comapring records" << endl;
	  g_err << " scanRow: \n" << scanRow.c_str().c_str() << endl;
	  g_err << " indexRow: \n" << indexRow.c_str().c_str() << endl;
	  closeTransaction(pNdb);
	  return NDBT_FAILED;
	}
	
	if(iop->nextResult() == 0){
	  g_err << "Found extra row!!" << endl;
	  g_err << " indexRow: \n" << indexRow.c_str().c_str() << endl;
	  closeTransaction(pNdb);
	  return NDBT_FAILED;
	}
      }
    }
    
    if (eof == -1 || check == -1) {
  error:
      const NdbError err = pTrans->getNdbError();
      
      if (err.status == NdbError::TemporaryError){
	ERR(err);
	iop = 0;
	closeTransaction(pNdb);
	NdbSleep_MilliSleep(50);
	retryAttempt++;
	rows--;
	continue;
      }
      ERR(err);
      closeTransaction(pNdb);
      return NDBT_FAILED;
    }
      
    closeTransaction(pNdb);
    
    return NDBT_OK;
  }
  return NDBT_FAILED;
}
int 
HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb, 
					     int records,
					     int batch){
  int updated = 0;
  int r = 0;
  int retryAttempt = 0;
  int check, a;

  while (r < records){
    
    if (retryAttempt >= m_retryMax){
      g_info << "ERROR: has retried this operation " << retryAttempt 
	     << " times, failing!" << endl;
      return NDBT_FAILED;
    }
    
    pTrans = pNdb->startTransaction();
    if (pTrans == NULL) {
      const NdbError err = pNdb->getNdbError();
      
      if (err.status == NdbError::TemporaryError){
	ERR(err);
	NdbSleep_MilliSleep(50);
	retryAttempt++;
	continue;
      }
      ERR(err);
      return NDBT_FAILED;
    }

   NdbOperation* pOp = pTrans->getNdbOperation(tab.getName());	
   if (pOp == NULL) {
     ERR(pTrans->getNdbError());
     closeTransaction(pNdb);
     return NDBT_FAILED;
   }
   
   check = pOp->readTupleExclusive();
   if( check == -1 ) {
     ERR(pTrans->getNdbError());
     closeTransaction(pNdb);
     return NDBT_FAILED;
   }
   
   // Define primary keys
   if (equalForRow(pOp, r) != 0)
   {
     closeTransaction(pNdb);
     return NDBT_FAILED;
   }
   
   // Read update value
   for(a = 0; a<tab.getNoOfColumns(); a++){
     if (calc.isUpdateCol(a) == true){
       if((row.attributeStore(a) = 
	   pOp->getValue(tab.getColumn(a)->getName())) == 0) {
	 ERR(pTrans->getNdbError());
	 closeTransaction(pNdb);
	 return NDBT_FAILED;
       }
     }
   }
   
    check = pTrans->execute(NoCommit, AbortOnError);   
    if( check == -1 ) {
      const NdbError err = pTrans->getNdbError();

      if (err.status == NdbError::TemporaryError){
	ERR(err);
	closeTransaction(pNdb);
	NdbSleep_MilliSleep(50);
	retryAttempt++;
	continue;
      }
      ERR(err);
      closeTransaction(pNdb);
      return NDBT_FAILED;
    }

    int updates = calc.getUpdatesValue(&row) + 1;

    NdbOperation* pUpdOp;
    pUpdOp = pTrans->getNdbOperation(tab.getName());	
    if (pUpdOp == NULL) {
      ERR(pTrans->getNdbError());
      closeTransaction(pNdb);
      return NDBT_FAILED;
    }

    check = pUpdOp->interpretedUpdateTuple();
    if( check == -1 ) {
      ERR(pTrans->getNdbError());
      closeTransaction(pNdb);
      return NDBT_FAILED;
    }

    // PKs
    if (equalForRow(pUpdOp, r) != 0)
    {
      closeTransaction(pNdb);
      return NDBT_FAILED;
    }

    // Update col
    for(a = 0; a<tab.getNoOfColumns(); a++){
      if ((tab.getColumn(a)->getPrimaryKey() == false) && 
	  (calc.isUpdateCol(a) == true)){
	
	// TODO switch for 32/64 bit
	const NdbDictionary::Column* attr = tab.getColumn(a);
	Uint32 valToIncWith = 1;
	check = pUpdOp->incValue(attr->getName(), valToIncWith);
	if( check == -1 ) {
	  ERR(pTrans->getNdbError());
	  closeTransaction(pNdb);
	  return NDBT_FAILED;
	}
      }
    }

    // Remaining attributes
    for(a = 0; a<tab.getNoOfColumns(); a++){
      if ((tab.getColumn(a)->getPrimaryKey() == false) && 
	  (calc.isUpdateCol(a) == false)){
	if(setValueForAttr(pUpdOp, a, r, updates ) != 0){
	  ERR(pTrans->getNdbError());
	  closeTransaction(pNdb);
	  return NDBT_FAILED;
	}
      }
    }


    
    check = pTrans->execute(Commit, AbortOnError);   
    if( check == -1 ) {
      const NdbError err = pTrans->getNdbError();

      if (err.status == NdbError::TemporaryError){
	ERR(err);
	closeTransaction(pNdb);
	NdbSleep_MilliSleep(50);
	retryAttempt++;
	continue;
      }
      ERR(err);
      ndbout << "r = " << r << endl;
      closeTransaction(pNdb);
      return NDBT_FAILED;
    }
    else{
      updated++;
      m_latest_gci = pTrans->getGCI();
    }
    

    closeTransaction(pNdb);

    r++; // Read next record

  }

  g_info << "|- " << updated << " records updated" << endl;
  return NDBT_OK;
}
int
run_read(){
  int iter = g_paramters[P_LOOPS].value;
  NDB_TICKS start1, stop;
  int sum_time= 0;
  
  const Uint32 rows = g_paramters[P_ROWS].value;
  const Uint32 range = g_paramters[P_RANGE].value;
  
  start1 = NdbTick_CurrentMillisecond();
  NdbConnection * pTrans = g_ndb->startTransaction();
  if(!pTrans){
    g_err << "Failed to start transaction" << endl;
    err(g_ndb->getNdbError());
    return -1;
  }
  
  NdbOperation * pOp;
  NdbScanOperation * pSp;
  NdbIndexOperation * pUp;
  NdbIndexScanOperation * pIp;
  
  Uint32 start_row = rand() % (rows - range);
  Uint32 stop_row = start_row + range;

  /**
   * 0 - serial pk
   * 1 - batch pk
   * 2 - serial uniq 
   * 3 - batch uniq
   * 4 - index eq
   * 5 - range scan
   * 6 - interpreted scan
   */
  int check = 0;
  void* res = (void*)~0;
  const Uint32 pk = 0;
  Uint32 cnt = 0;
  for(; start_row < stop_row; start_row++){
    switch(g_paramters[P_OPER].value){
    case 0:
      pOp = pTrans->getNdbOperation(g_table);
      check = pOp->readTuple();
      check = pOp->equal(pk, start_row);
      break;
    case 1:
      for(; start_row<stop_row; start_row++){
	pOp = pTrans->getNdbOperation(g_table);
	check = pOp->readTuple();
	check = pOp->equal(pk, start_row);
	for(int j = 0; j<g_tab->getNoOfColumns(); j++){
	  res = pOp->getValue(j);
	  assert(res);
	}
      }
      break;
    case 2:
      pOp = pTrans->getNdbIndexOperation(g_unique, g_table);
      check = pOp->readTuple();
      check = pOp->equal(pk, start_row);
      break;
    case 3:
      for(; start_row<stop_row; start_row++){
	pOp = pTrans->getNdbIndexOperation(g_unique, g_table);
	check = pOp->readTuple();
	check = pOp->equal(pk, start_row);
	for(int j = 0; j<g_tab->getNoOfColumns(); j++){
	  res = pOp->getValue(j);
	  assert(res);
	}
      }
      break;
    case 4:
      pOp = pSp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table);
      pIp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0);
      check = pIp->setBound(pk, NdbIndexScanOperation::BoundEQ, &start_row);
      break;
    case 5:
      pOp = pSp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table);
      pIp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0);
      check = pIp->setBound(pk, NdbIndexScanOperation::BoundLE, &start_row);
      check = pIp->setBound(pk, NdbIndexScanOperation::BoundGT, &stop_row);
      start_row = stop_row;
      break;
    case 6:
      pOp = pSp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table);
      pIp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0, true);
      check = pIp->setBound(pk, NdbIndexScanOperation::BoundLE, &start_row);
      check = pIp->setBound(pk, NdbIndexScanOperation::BoundGT, &stop_row);
      start_row = stop_row;
      break;
    case 7:
      pOp = pSp = pTrans->getNdbScanOperation(g_table);
      pSp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0);
      NdbScanFilter filter(pOp) ;   
      filter.begin(NdbScanFilter::AND);
      filter.ge(pk, start_row);
      filter.lt(pk, stop_row);
      filter.end();
      start_row = stop_row;
      break;
    }
      
    assert(res);
    if(check != 0){
      ndbout << pOp->getNdbError() << endl;
      ndbout << pTrans->getNdbError() << endl;
    }
    assert(check == 0);

    for(int j = 0; j<g_tab->getNoOfColumns(); j++){
      res = pOp->getValue(j);
      assert(res);
    }
      
    check = pTrans->execute(NoCommit);
    if(check != 0){
      ndbout << pTrans->getNdbError() << endl;
    }
    assert(check == 0);
    if(g_paramters[P_OPER].value >= 4){
      while((check = pSp->nextResult(true)) == 0){
	cnt++;
      }
	
      if(check == -1){
	err(pTrans->getNdbError());
	return -1;
      }
      assert(check == 1);
      pSp->close();
    }
  }
  assert(g_paramters[P_OPER].value < 4 || (cnt == range));
  
  pTrans->close();
  
  stop = NdbTick_CurrentMillisecond();
  g_times[g_paramters[P_OPER].value] += (stop - start1);
  return 0;
}
int 
HugoTransactions::indexReadRecords(Ndb* pNdb, 
				   const char * idxName,
				   int records,
				   int batch){
  int                  reads = 0;
  int                  r = 0;
  int                  retryAttempt = 0;
  int                  check, a;
  NdbOperation *pOp;
  NdbIndexScanOperation *sOp;

  const NdbDictionary::Index* pIndex
    = pNdb->getDictionary()->getIndex(idxName, tab.getName());
  
  const bool ordered = (pIndex->getType()==NdbDictionary::Index::OrderedIndex);

  if (batch == 0) {
    g_info << "ERROR: Argument batch == 0 in indexReadRecords(). "
	   << "Not allowed." << endl;
    return NDBT_FAILED;
  }
  
  if (ordered) {
    batch = 1;
  }

  allocRows(batch);
  
  while (r < records){
    if (retryAttempt >= m_retryMax){
      g_info << "ERROR: has retried this operation " << retryAttempt 
	     << " times, failing!" << endl;
      return NDBT_FAILED;
    }

    pTrans = pNdb->startTransaction();
    if (pTrans == NULL) {
      const NdbError err = pNdb->getNdbError();
      
      if (err.status == NdbError::TemporaryError){
	ERR(err);
	NdbSleep_MilliSleep(50);
	retryAttempt++;
	continue;
      }
      ERR(err);
      return NDBT_FAILED;
    }
    
    for(int b=0; (b<batch) && (r+b < records); b++){
      if(!ordered){
	pOp = pTrans->getNdbIndexOperation(idxName, tab.getName());	
	if (pOp == NULL) {
	  ERR(pTrans->getNdbError());
	  closeTransaction(pNdb);
	  return NDBT_FAILED;
	}
	check = pOp->readTuple();
      } else {
	pOp = sOp = pTrans->getNdbIndexScanOperation(idxName, tab.getName());
	if (sOp == NULL) {
	  ERR(pTrans->getNdbError());
	  closeTransaction(pNdb);
	  return NDBT_FAILED;
	}
	check = sOp->readTuples();
      }
      
      if( check == -1 ) {
	ERR(pTrans->getNdbError());
	closeTransaction(pNdb);
	return NDBT_FAILED;
      }
      
      // Define primary keys
      if (equalForRow(pOp, r+b) != 0)
      {
        closeTransaction(pNdb);
        return NDBT_FAILED;
      }
      
      // Define attributes to read  
      for(a = 0; a<tab.getNoOfColumns(); a++){
	if((rows[b]->attributeStore(a) = 
	    pOp->getValue(tab.getColumn(a)->getName())) == 0) {
	  ERR(pTrans->getNdbError());
	  closeTransaction(pNdb);
	  return NDBT_FAILED;
	}
      }
    }

    check = pTrans->execute(Commit, AbortOnError);   
    check = (check == -1 ? -1 : !ordered ? check : sOp->nextResult(true));
    if( check == -1 ) {
      const NdbError err = pTrans->getNdbError();
      
      if (err.status == NdbError::TemporaryError){
	ERR(err);
	closeTransaction(pNdb);
	NdbSleep_MilliSleep(50);
	retryAttempt++;
	continue;
      }
      switch(err.code){
      case 626: // Tuple did not exist
	  g_info << r << ": " << err.code << " " << err.message << endl;
	  r++;
	  break;
	  
      default:
	ERR(err);
	closeTransaction(pNdb);
	return NDBT_FAILED;
      }
    } else{
      for (int b=0; (b<batch) && (r+b<records); b++){ 
	if (calc.verifyRowValues(rows[b]) != 0){
	  closeTransaction(pNdb);
	  return NDBT_FAILED;
	}
	reads++;
	r++;
      }
      if(ordered && sOp->nextResult(true) == 0){
	ndbout << "Error when comparing records "
	       << " - index op next_result to many" << endl;
	closeTransaction(pNdb);
	return NDBT_FAILED;
      }
    }
    closeTransaction(pNdb);
  }
  deallocRows();
  g_info << reads << " records read" << endl;
  return NDBT_OK;
}
/**
 * Transaction 5 - T5
 *
 * Delete session
 *
 * Input:
 *   SubscriberNumber
 *   ServerId
 *   ServerBit
 *   DoRollback
 * Output:
 *   ChangedBy
 *   ChangedTime
 *   Location
 *   BranchExecuted
 */
int
T5(void * obj,
   const SubscriberNumber   inNumber,
   const SubscriberSuffix   inSuffix,
   const ServerId           inServerId,
   const ServerBit          inServerBit,
   ChangedBy          outChangedBy,
   ChangedTime        outChangedTime,
   Location         * outLocation,
   DoRollback         inDoRollback,
   BranchExecuted   * outBranchExecuted,
   BenchmarkTime    * outTransactionTime) {

    Ndb           * pNDB = (Ndb *) obj;
    NdbConnection * MyTransaction = 0;
    NdbOperation  * MyOperation = 0;

    GroupId        groupId;
    ActiveSessions sessions;
    Permission     permission;

    BenchmarkTime start;
    get_time(&start);

    int check;
    NdbRecAttr * check2;

    MyTransaction = pNDB->startTransaction();
    if (MyTransaction == NULL)
        error_handler("T5-1: startTranscation", pNDB->getNdbErrorString(), 0);

    MyOperation= MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
    CHECK_NULL(MyOperation, "T5-1: getNdbOperation",
               MyTransaction);


    check = MyOperation->readTupleExclusive();
    CHECK_MINUS_ONE(check, "T5-1: readTuple",
                    MyTransaction);

    check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
                               inNumber);
    CHECK_MINUS_ONE(check, "T5-1: equal subscriber",
                    MyTransaction);

    check2 = MyOperation->getValue(IND_SUBSCRIBER_LOCATION,
                                   (char *)outLocation);
    CHECK_NULL(check2, "T5-1: getValue location",
               MyTransaction);

    check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_BY,
                                   outChangedBy);
    CHECK_NULL(check2, "T5-1: getValue changed_by",
               MyTransaction);

    check2 = MyOperation->getValue(IND_SUBSCRIBER_CHANGED_TIME,
                                   outChangedTime);
    CHECK_NULL(check2, "T5-1: getValue changed_time",
               MyTransaction);

    check2 = MyOperation->getValue(IND_SUBSCRIBER_GROUP,
                                   (char *)&groupId);
    CHECK_NULL(check2, "T5-1: getValue group",
               MyTransaction);

    check2 = MyOperation->getValue(IND_SUBSCRIBER_SESSIONS,
                                   (char *)&sessions);
    CHECK_NULL(check2, "T5-1: getValue sessions",
               MyTransaction);

    check = MyTransaction->execute( NoCommit );
    CHECK_MINUS_ONE(check, "T5-1: NoCommit",
                    MyTransaction);

    /* Operation 2 */

    MyOperation = MyTransaction->getNdbOperation(GROUP_TABLE);
    CHECK_NULL(MyOperation, "T5-2: getNdbOperation",
               MyTransaction);


    check = MyOperation->readTuple();
    CHECK_MINUS_ONE(check, "T5-2: readTuple",
                    MyTransaction);

    check = MyOperation->equal(IND_GROUP_ID,
                               (char*)&groupId);
    CHECK_MINUS_ONE(check, "T5-2: equal group",
                    MyTransaction);

    check2 = MyOperation->getValue(IND_GROUP_ALLOW_DELETE,
                                   (char *)&permission);
    CHECK_NULL(check2, "T5-2: getValue allow_delete",
               MyTransaction);

    check = MyTransaction->execute( NoCommit );
    CHECK_MINUS_ONE(check, "T5-2: NoCommit",
                    MyTransaction);

    DEBUG3("T5(%.*s, %.2d): ", SUBSCRIBER_NUMBER_LENGTH, inNumber, inServerId);

    if(((permission & inServerBit) == inServerBit) &&
            ((sessions   & inServerBit) == inServerBit)) {

        DEBUG("deleting - ");

        /* Operation 3 */
        MyOperation = MyTransaction->getNdbOperation(SESSION_TABLE);
        CHECK_NULL(MyOperation, "T5-3: getNdbOperation",
                   MyTransaction);

        check = MyOperation->deleteTuple();
        CHECK_MINUS_ONE(check, "T5-3: deleteTuple",
                        MyTransaction);

        check = MyOperation->equal(IND_SESSION_SUBSCRIBER,
                                   (char*)inNumber);
        CHECK_MINUS_ONE(check, "T5-3: equal number",
                        MyTransaction);

        check = MyOperation->equal(IND_SESSION_SERVER,
                                   (char*)&inServerId);
        CHECK_MINUS_ONE(check, "T5-3: equal server id",
                        MyTransaction);

        check = MyTransaction->execute( NoCommit );
        CHECK_MINUS_ONE(check, "T5-3: NoCommit",
                        MyTransaction);

        /* Operation 4 */
        MyOperation = MyTransaction->getNdbOperation(SUBSCRIBER_TABLE);
        CHECK_NULL(MyOperation, "T5-4: getNdbOperation",
                   MyTransaction);

        check = MyOperation->interpretedUpdateTuple();
        CHECK_MINUS_ONE(check, "T5-4: interpretedUpdateTuple",
                        MyTransaction);

        check = MyOperation->equal(IND_SUBSCRIBER_NUMBER,
                                   (char*)inNumber);
        CHECK_MINUS_ONE(check, "T5-4: equal number",
                        MyTransaction);

        check = MyOperation->subValue(IND_SUBSCRIBER_SESSIONS,
                                      (uint32)inServerBit);
        CHECK_MINUS_ONE(check, "T5-4: dec value",
                        MyTransaction);

        check = MyTransaction->execute( NoCommit );
        CHECK_MINUS_ONE(check, "T5-4: NoCommit",
                        MyTransaction);

        /* Operation 5 */
        MyOperation = MyTransaction->getNdbOperation(SERVER_TABLE);
        CHECK_NULL(MyOperation, "T5-5: getNdbOperation",
                   MyTransaction);


        check = MyOperation->interpretedUpdateTuple();
        CHECK_MINUS_ONE(check, "T5-5: interpretedUpdateTuple",
                        MyTransaction);

        check = MyOperation->equal(IND_SERVER_ID,
                                   (char*)&inServerId);
        CHECK_MINUS_ONE(check, "T5-5: equal serverId",
                        MyTransaction);

        check = MyOperation->equal(IND_SERVER_SUBSCRIBER_SUFFIX,
                                   (char*)inSuffix);
        CHECK_MINUS_ONE(check, "T5-5: equal suffix",
                        MyTransaction);

        check = MyOperation->incValue(IND_SERVER_DELETES, (uint32)1);
        CHECK_MINUS_ONE(check, "T5-5: inc value",
                        MyTransaction);

        check = MyTransaction->execute( NoCommit );
        CHECK_MINUS_ONE(check, "T5-5: NoCommit",
                        MyTransaction);

        (* outBranchExecuted) = 1;
    } else {
        DEBUG1("%s", ((permission & inServerBit) ? "permission - " : "no permission - "));
        DEBUG1("%s", ((sessions   & inServerBit) ? "in session - " : "no in session - "));
        (* outBranchExecuted) = 0;
    }

    if(!inDoRollback) {
        DEBUG("commit\n");
        check = MyTransaction->execute( Commit );
        CHECK_MINUS_ONE(check, "T5: Commit",
                        MyTransaction);
    } else {
        DEBUG("rollback\n");
        check = MyTransaction->execute(Rollback);
        CHECK_MINUS_ONE(check, "T5:Rollback",
                        MyTransaction);

    }

    pNDB->closeTransaction(MyTransaction);

    get_time(outTransactionTime);
    time_diff(outTransactionTime, &start);
    return 0;
}
int 
HugoTransactions::indexUpdateRecords(Ndb* pNdb, 
				     const char * idxName,
				     int records,
				     int batch){

  int updated = 0;
  int                  r = 0;
  int                  retryAttempt = 0;
  int                  check, a, b;
  NdbOperation *pOp;
  NdbScanOperation * sOp;

  const NdbDictionary::Index* pIndex
    = pNdb->getDictionary()->getIndex(idxName, tab.getName());
  
  const bool ordered = (pIndex->getType()==NdbDictionary::Index::OrderedIndex);
  if (ordered){
    batch = 1;
  }

  allocRows(batch);
  
  while (r < records){
    if (retryAttempt >= m_retryMax){
      g_info << "ERROR: has retried this operation " << retryAttempt 
	     << " times, failing!" << endl;
      return NDBT_FAILED;
    }
    
    pTrans = pNdb->startTransaction();
    if (pTrans == NULL) {
      const NdbError err = pNdb->getNdbError();
      
      if (err.status == NdbError::TemporaryError){
	ERR(err);
	NdbSleep_MilliSleep(50);
	retryAttempt++;
	continue;
      }
      ERR(err);
      return NDBT_FAILED;
    }

    for(b = 0; b<batch && (b+r)<records; b++){
      if(!ordered){
	pOp = pTrans->getNdbIndexOperation(idxName, tab.getName());	
	if (pOp == NULL) {
	  ERR(pTrans->getNdbError());
	  closeTransaction(pNdb);
	  return NDBT_FAILED;
	}
	
	check = pOp->readTupleExclusive();
	if( check == -1 ) {
	  ERR(pTrans->getNdbError());
	  closeTransaction(pNdb);
	  return NDBT_FAILED;
	}
      } else {
	pOp = sOp = pTrans->getNdbIndexScanOperation(idxName, tab.getName());
	if (pOp == NULL) {
	  ERR(pTrans->getNdbError());
	  closeTransaction(pNdb);
	  return NDBT_FAILED;
	}
	
	check = 0;
	sOp->readTuplesExclusive();
      }	
      
      // Define primary keys
      if (equalForRow(pOp, r+b) != 0)
      {
        closeTransaction(pNdb);
        return NDBT_FAILED;
      }
      
      // Define attributes to read  
      for(a = 0; a<tab.getNoOfColumns(); a++){
	if((rows[b]->attributeStore(a) = 
	    pOp->getValue(tab.getColumn(a)->getName())) == 0) {
	  ERR(pTrans->getNdbError());
	  closeTransaction(pNdb);
	  return NDBT_FAILED;
	}
      }
    }
     
    check = pTrans->execute(NoCommit, AbortOnError);   
    check = (check == -1 ? -1 : !ordered ? check : sOp->nextResult(true));
    if( check == -1 ) {
      const NdbError err = pTrans->getNdbError();
      ERR(err);
      closeTransaction(pNdb);
      
      if (err.status == NdbError::TemporaryError){
	NdbSleep_MilliSleep(50);
	retryAttempt++;
	continue;
      }
      return NDBT_FAILED;
    }

    if(ordered && check != 0){
      g_err << check << " - Row: " << r << " not found!!" << endl;
      closeTransaction(pNdb);
      return NDBT_FAILED;    
    }
    
    for(b = 0; b<batch && (b+r)<records; b++){
      if (calc.verifyRowValues(rows[b]) != 0){
	closeTransaction(pNdb);
	return NDBT_FAILED;
      }
      
      int updates = calc.getUpdatesValue(rows[b]) + 1;
      
      NdbOperation* pUpdOp;
      if(!ordered){
	pUpdOp = pTrans->getNdbIndexOperation(idxName, tab.getName());
	check = (pUpdOp == 0 ? -1 : pUpdOp->updateTuple());
      } else {
	pUpdOp = sOp->updateCurrentTuple();
      }

      if (pUpdOp == NULL) {
	ERR(pTrans->getNdbError());
	closeTransaction(pNdb);
	return NDBT_FAILED;
      }
      
      if( check == -1 ) {
	ERR(pTrans->getNdbError());
	closeTransaction(pNdb);
	return NDBT_FAILED;
      }
      
      if(!ordered)
      {
        if (equalForRow(pUpdOp, r+b) != 0)
        {
          closeTransaction(pNdb);
          return NDBT_FAILED;
        }
      }
      
      for(a = 0; a<tab.getNoOfColumns(); a++){
	if (tab.getColumn(a)->getPrimaryKey() == false){
	  if(setValueForAttr(pUpdOp, a, r+b, updates ) != 0){
	    ERR(pTrans->getNdbError());
	    closeTransaction(pNdb);
	    return NDBT_FAILED;
	  }
	}
      }
    }
    
    check = pTrans->execute(Commit, AbortOnError);   
    if( check == -1 ) {
      const NdbError err = pTrans->getNdbError();
      ERR(err);
      closeTransaction(pNdb);
      
      if (err.status == NdbError::TemporaryError){
	NdbSleep_MilliSleep(50);
	retryAttempt++;
	continue;
      }
      ndbout << "r = " << r << endl;
      return NDBT_FAILED;
    } else {
      updated += batch;
      m_latest_gci = pTrans->getGCI();
    }
    
    closeTransaction(pNdb);
    
    r+= batch; // Read next record
  }
  
  g_info << "|- " << updated << " records updated" << endl;
  return NDBT_OK;
}
/************************************************************************
 * populate()
 * 1. Prepare 'parallelism' number of insert transactions. 
 * 2. Send transactions to NDB and wait for callbacks to execute
 */
int populate(Ndb * myNdb, int data, async_callback_t * cbData)
{

  NdbOperation*   myNdbOperation;       // For operations
  const NdbDictionary::Dictionary* myDict= myNdb->getDictionary();
  const NdbDictionary::Table *myTable= myDict->getTable("api_async");
  if (myTable == NULL) 
    APIERROR(myDict->getNdbError());

  async_callback_t * cb;
  int retries = 0;
  int current = 0;
  for(int i=0; i<1024; i++)
  {
    if(transaction[i].used == 0)
    {
      current = i;
      if (cbData == 0) 
      {
       /**
        * We already have a callback
	* This is an absolutely new transaction
        */
	cb = new async_callback_t;
	cb->retries = 0;
      }
      else 
      { 
       /**
        * We already have a callback
        */
	cb =cbData;
	retries = cbData->retries;
      }
      /**
       * Set data used by the callback
       */
      cb->ndb = myNdb;  //handle to Ndb object so that we can close transaction
                        // in the callback (alt. make myNdb global).

      cb->data =  data; //this is the data we want to insert
      cb->transaction = current; //This is the number (id)  of this transaction
      transaction[current].used = 1 ; //Mark the transaction as used
      break;
    }
  }
  if(!current)
    return -1;

  while(retries < MAX_RETRIES) 
    {
      transaction[current].conn = myNdb->startTransaction();
      if (transaction[current].conn == NULL) {
	/**
	 * no transaction to close since conn == null
	 */
	milliSleep(10);
	retries++;
	continue;
      }
      myNdbOperation = transaction[current].conn->getNdbOperation(myTable);
      if (myNdbOperation == NULL) 
      {
	if (asynchErrorHandler(transaction[current].conn, myNdb)) 
	{
	  myNdb->closeTransaction(transaction[current].conn);
	  transaction[current].conn = 0;
	  milliSleep(10);
	  retries++;
	  continue;
	}
	asynchExitHandler(myNdb);
      } // if
      if(myNdbOperation->insertTuple() < 0  ||
	 myNdbOperation->equal("REG_NO", data) < 0 ||
	 myNdbOperation->setValue("BRAND", "Mercedes") <0 ||
	 myNdbOperation->setValue("COLOR", "Blue") < 0)
      {
	if (asynchErrorHandler(transaction[current].conn, myNdb)) 
	{
	  myNdb->closeTransaction(transaction[current].conn);
	  transaction[current].conn = 0;
	  retries++;
	  milliSleep(10);
	  continue;
	}
	asynchExitHandler(myNdb);
      }     

      /*Prepare transaction (the transaction is NOT yet sent to NDB)*/
      transaction[current].conn->executeAsynchPrepare(NdbTransaction::Commit, 
						       &callback,
						       cb);
      /**
       * When we have prepared parallelism number of transactions ->
       * send the transaction to ndb. 
       * Next time we will deal with the transactions are in the 
       * callback. There we will see which ones that were successful
       * and which ones to retry.
       */
      if (nPreparedTransactions == parallelism-1) 
      {
	// send-poll all transactions
	// close transaction is done in callback
	myNdb->sendPollNdb(3000, parallelism );
	nPreparedTransactions=0;
      } 
      else
	nPreparedTransactions++;
      return 1;
    }
    std::cout << "Unable to recover from errors. Exiting..." << std::endl;
    asynchExitHandler(myNdb);
    return -1;
}
Example #26
0
/* Test for correct behaviour using primary key operations
 * when an NDBD node's SegmentedSection pool is exhausted.
 */
int testSegmentedSectionPk(NDBT_Context* ctx, NDBT_Step* step){
  /*
   * Signal type       Exhausted @              How
   * -----------------------------------------------------
   * Long TCKEYREQ     Initial import           Consume + send
   * Long TCKEYREQ     Initial import, not first
   *                     TCKEYREQ in batch      Consume + send
   * Long TCKEYREQ     Initial import, not last
   *                     TCKEYREQ in batch      Consume + send
   * No testing of short TCKEYREQ variants as they cannot be
   * generated in mysql-5.1-telco-6.4+
   * TODO : Add short variant testing to testUpgrade.
   */

  /* We just run on one table */
  if (strcmp(ctx->getTab()->getName(), "WIDE_2COL") != 0)
    return NDBT_OK;

  const Uint32 maxRowBytes= NDB_MAX_TUPLE_SIZE_IN_WORDS * sizeof(Uint32);
  const Uint32 srcBuffBytes= NDBT_Tables::MaxVarTypeKeyBytes;
  const Uint32 maxAttrBytes= NDBT_Tables::MaxKeyMaxVarTypeAttrBytes;
  char smallKey[50];
  char srcBuff[srcBuffBytes];
  char smallRowBuf[maxRowBytes];
  char bigKeyRowBuf[maxRowBytes];
  char bigAttrRowBuf[maxRowBytes];

  /* Small key for hinting to same TC */
  Uint32 smallKeySize= setLongVarchar(&smallKey[0],
                                      "ShortKey",
                                      8);

  /* Large value source */
  memset(srcBuff, 'B', srcBuffBytes);

  const NdbRecord* record= ctx->getTab()->getDefaultRecord();

  /* Setup buffers
   * Small row buffer with small key and small data
   */ 
  setLongVarchar(NdbDictionary::getValuePtr(record,
                                            smallRowBuf,
                                            0),
                 "ShortKey",
                 8);
  NdbDictionary::setNull(record, smallRowBuf, 0, false);

  setLongVarchar(NdbDictionary::getValuePtr(record,
                                            smallRowBuf,
                                            1),
                 "ShortData",
                 9);
  NdbDictionary::setNull(record, smallRowBuf, 1, false);

  /* Big key buffer with big key and small data*/
  setLongVarchar(NdbDictionary::getValuePtr(record,
                                            bigKeyRowBuf,
                                            0),
                 &srcBuff[0],
                 srcBuffBytes);
  NdbDictionary::setNull(record, bigKeyRowBuf, 0, false);

  setLongVarchar(NdbDictionary::getValuePtr(record,
                                            bigKeyRowBuf,
                                            1),
                 "ShortData",
                 9);
  NdbDictionary::setNull(record, bigKeyRowBuf, 1, false);

  /* Big AttrInfo buffer with small key and big data */
  setLongVarchar(NdbDictionary::getValuePtr(record,
                                            bigAttrRowBuf,
                                            0),
                 "ShortKey", 
                 8);
  NdbDictionary::setNull(record, bigAttrRowBuf, 0, false);

  setLongVarchar(NdbDictionary::getValuePtr(record,
                                            bigAttrRowBuf,
                                            1),
                 &srcBuff[0],
                 maxAttrBytes);
  NdbDictionary::setNull(record, bigAttrRowBuf, 1, false);

  NdbRestarter restarter;
  Ndb* pNdb= GETNDB(step);

  /* Start a transaction on a specific node */
  NdbTransaction* trans= pNdb->startTransaction(ctx->getTab(),
                                                &smallKey[0],
                                                smallKeySize);
  CHECKNOTNULL(trans);

  /* Activate error insert 8065 in this transaction, limits
   * any single import/append to 1 section
   */
  CHECKEQUAL(NDBT_OK, activateErrorInsert(trans, 
                                          record, 
                                          ctx->getTab(),
                                          smallRowBuf, 
                                          &restarter, 
                                          8065));

  /* Ok, let's try an insert with a key bigger than 1 section.
   * Since it's part of the same transaction, it'll go via
   * the same TC.
   */
  const NdbOperation* bigInsert = trans->insertTuple(record, bigKeyRowBuf);

  CHECKNOTNULL(bigInsert);

  CHECKEQUAL(-1, trans->execute(NdbTransaction::NoCommit));

  /* ZGET_DATABUF_ERR expected */
  CHECKEQUAL(218, trans->getNdbError().code)

  trans->close();
  
  /* Ok, now a long TCKEYREQ to the same TC - this
   * has slightly different abort handling since no other
   * operations exist in this new transaction.
   * We also change it so that import overflow occurs 
   * on the AttrInfo section
   */
  /* Start transaction on the same node */
  CHECKNOTNULL(trans= pNdb->startTransaction(ctx->getTab(),
                                             &smallKey[0],
                                             smallKeySize));


  CHECKNOTNULL(bigInsert = trans->insertTuple(record, bigAttrRowBuf));

  CHECKEQUAL(-1,trans->execute(NdbTransaction::NoCommit));

  /* ZGET_DATABUF_ERR expected */
  CHECKEQUAL(218, trans->getNdbError().code);

  trans->close();

  /* Ok, now a long TCKEYREQ where we run out of SegmentedSections
   * on the first TCKEYREQ, but there are other TCKEYREQs following
   * in the same batch.  Check that abort handling is correct
   */
    /* Start transaction on the same node */
  CHECKNOTNULL(trans= pNdb->startTransaction(ctx->getTab(),
                                             &smallKey[0],
                                             smallKeySize));
  /* First op in batch, will cause overflow */
  CHECKNOTNULL(bigInsert = trans->insertTuple(record, bigAttrRowBuf));
  
  /* Second op in batch, what happens to it? */
  const NdbOperation* secondOp;
  CHECKNOTNULL(secondOp = trans->insertTuple(record, bigAttrRowBuf));


  CHECKEQUAL(-1,trans->execute(NdbTransaction::NoCommit));

  /* ZGET_DATABUF_ERR expected */
  CHECKEQUAL(218, trans->getNdbError().code);

  trans->close();

  /* Now try with a 'short' TCKEYREQ, generated using the old Api 
   * with a big key value
   */
  /* Start transaction on the same node */
  CHECKNOTNULL(trans= pNdb->startTransaction(ctx->getTab(),
                                             &smallKey[0],
                                             smallKeySize));
  
  NdbOperation* bigInsertOldApi;
  CHECKNOTNULL(bigInsertOldApi= trans->getNdbOperation(ctx->getTab()));

  CHECKEQUAL(0, bigInsertOldApi->insertTuple());
  CHECKEQUAL(0, bigInsertOldApi->equal((Uint32)0, 
                                       NdbDictionary::getValuePtr
                                       (record,
                                        bigKeyRowBuf,
                                        0)));
  CHECKEQUAL(0, bigInsertOldApi->setValue(1, 
                                          NdbDictionary::getValuePtr
                                          (record,
                                           bigKeyRowBuf,
                                           1)));

  CHECKEQUAL(-1, trans->execute(NdbTransaction::NoCommit));

  /* ZGET_DATABUF_ERR expected */
  CHECKEQUAL(218, trans->getNdbError().code)

  trans->close();

  /* Now try with a 'short' TCKEYREQ, generated using the old Api 
   * with a big data value
   */
  CHECKNOTNULL(trans= pNdb->startTransaction(ctx->getTab(),
                                             &smallKey[0],
                                             smallKeySize));
  
  CHECKNOTNULL(bigInsertOldApi= trans->getNdbOperation(ctx->getTab()));

  CHECKEQUAL(0, bigInsertOldApi->insertTuple());
  CHECKEQUAL(0, bigInsertOldApi->equal((Uint32)0, 
                                       NdbDictionary::getValuePtr
                                       (record,
                                        bigAttrRowBuf,
                                        0)));
  CHECKEQUAL(0, bigInsertOldApi->setValue(1, 
                                          NdbDictionary::getValuePtr
                                          (record,
                                           bigAttrRowBuf,
                                           1)));

  CHECKEQUAL(-1, trans->execute(NdbTransaction::NoCommit));

  /* ZGET_DATABUF_ERR expected */
  CHECKEQUAL(218, trans->getNdbError().code)

  trans->close();

  // TODO : Add code to testUpgrade
#if 0
  /*
   * Short TCKEYREQ    KeyInfo accumulate       Consume + send long
   *                     (TCKEYREQ + KEYINFO)
   * Short TCKEYREQ    AttrInfo accumulate      Consume + send short key
   *                                             + long AI
   *                      (TCKEYREQ + ATTRINFO)
   */
  /* Change error insert so that next TCKEYREQ will grab
   * all but one SegmentedSection so that we can then test SegmentedSection
   * exhaustion when importing the Key/AttrInfo words from the
   * TCKEYREQ signal itself.
   */
  restarter.insertErrorInAllNodes(8066);


  /* Now a 'short' TCKEYREQ, there will be space to import the
   * short key, but not the AttrInfo
   */
  /* Start transaction on same node */
  CHECKNOTNULL(trans= pNdb->startTransaction(ctx->getTab(),
                                             &smallKey[0],
                                             smallKeySize));
  
  CHECKNOTNULL(bigInsertOldApi= trans->getNdbOperation(ctx->getTab()));
  
  CHECKEQUAL(0, bigInsertOldApi->insertTuple());
  CHECKEQUAL(0, bigInsertOldApi->equal((Uint32)0, 
                                       NdbDictionary::getValuePtr
                                       (record,
                                        smallRowBuf,
                                        0)));
  CHECKEQUAL(0, bigInsertOldApi->setValue(1, NdbDictionary::getValuePtr
                                          (record,
                                           smallRowBuf,
                                           1)));

  CHECKEQUAL(-1, trans->execute(NdbTransaction::NoCommit));

  /* ZGET_DATABUF_ERR expected */
  CHECKEQUAL(218, trans->getNdbError().code)

  trans->close();

  /* Change error insert so that there are no SectionSegments 
   * This will cause failure when attempting to import the
   * KeyInfo from the TCKEYREQ
   */
  restarter.insertErrorInAllNodes(8067);

  /* Now a 'short' TCKEYREQ - there will be no space to import the key */
  CHECKNOTNULL(trans= pNdb->startTransaction(ctx->getTab(),
                                             &smallKey[0],
                                             smallKeySize));
  
  CHECKNOTNULL(bigInsertOldApi= trans->getNdbOperation(ctx->getTab()));
  
  CHECKEQUAL(0, bigInsertOldApi->insertTuple());
  CHECKEQUAL(0, bigInsertOldApi->equal((Uint32)0, 
                                       NdbDictionary::getValuePtr
                                       (record,
                                        smallRowBuf,
                                        0)));
  CHECKEQUAL(0, bigInsertOldApi->setValue(1, 
                                          NdbDictionary::getValuePtr
                                          (record,
                                           smallRowBuf,
                                           1)));

  CHECKEQUAL(-1, trans->execute(NdbTransaction::NoCommit));

  /* ZGET_DATABUF_ERR expected */
  CHECKEQUAL(218, trans->getNdbError().code)

  trans->close();  
#endif

  /* Finished with error insert, cleanup the error insertion
   * Error insert 8068 will free the hoarded segments
   */
  CHECKNOTNULL(trans= pNdb->startTransaction(ctx->getTab(),
                                             &smallKey[0],
                                             smallKeySize));

  CHECKEQUAL(NDBT_OK, activateErrorInsert(trans, 
                                          record, 
                                          ctx->getTab(),
                                          smallRowBuf, 
                                          &restarter, 
                                          8068));

  trans->execute(NdbTransaction::Rollback);
  
  CHECKEQUAL(0, trans->getNdbError().code);

  trans->close();

  return NDBT_OK;
}
Example #27
0
void BackupRestore::tuple_a(restore_callback_t *cb)
{
  while (cb->retries < 10) 
  {
    /**
     * start transactions
     */
    cb->connection = m_ndb->startTransaction();
    if (cb->connection == NULL) 
    {
      /*
	if (asynchErrorHandler(cb->connection, m_ndb)) 
	{
	cb->retries++;
	continue;
	}
      */
      asynchExitHandler();
    } // if
    
    const TupleS &tup = *(cb->tup);
    const TableS * table = tup.getTable();
    NdbOperation * op = cb->connection->getNdbOperation(table->getTableName());
    
    if (op == NULL) 
    {
      if (asynchErrorHandler(cb->connection, m_ndb)) 
      {
	cb->retries++;
	continue;
      }
      asynchExitHandler();
    } // if
    
    if (op->writeTuple() == -1) 
    {
      if (asynchErrorHandler(cb->connection, m_ndb))
      {
	cb->retries++;
	continue;
      }
      asynchExitHandler();
    } // if
    
    Uint32 ret = 0;
    for (int i = 0; i < tup.getNoOfAttributes(); i++) 
    {
      const AttributeS * attr = tup[i];
      int size = attr->Desc->size;
      int arraySize = attr->Desc->arraySize;
      char * dataPtr = attr->Data.string_value;
      Uint32 length = (size * arraySize) / 8;
      if (attr->Desc->m_column->getPrimaryKey()) 
      {
	ret = op->equal(i, dataPtr, length);
      }
      else
      {
	if (attr->Data.null) 
	  ret = op->setValue(i, NULL, 0);
	else
	  ret = op->setValue(i, dataPtr, length);
      }

      if (ret<0) 
	{
	  ndbout_c("Column: %d type %d",i,
		   tup.getTable()->m_dictTable->getColumn(i)->getType());
	  if (asynchErrorHandler(cb->connection, m_ndb)) 
	    {
	      cb->retries++;
	      break;
	    }
	  asynchExitHandler();
	}
    }
    if (ret < 0)
      continue;

    // Prepare transaction (the transaction is NOT yet sent to NDB)
    cb->connection->executeAsynchPrepare(Commit, &callback, cb);
    m_transactions++;
  }
  ndbout_c("Unable to recover from errors. Exiting...");
  asynchExitHandler();
}
Example #28
0
inline
int 
ScanInterpretTest::addRowToCheckTrans(Ndb* pNdb, 
				      NdbConnection* pCheckTrans){

  NdbOperation* pOp = 
    pCheckTrans->getNdbOperation(restab.getName());	
  if (pOp == NULL) {
    ERR(pNdb->getNdbError());
    return NDBT_FAILED;
  }
  
  if(pOp->readTuple() != 0) {
    ERR(pNdb->getNdbError());
    return NDBT_FAILED;
  }
  
  // Copy pk attribute's to the new operation
  for (int a = 0; a<restab.getNoOfColumns(); a++){
    const NdbDictionary::Column* attr = restab.getColumn(a); 
    if (attr->getPrimaryKey() == true){
      NdbRecAttr* reca = row.attributeStore(a);
      int check = -1;
      switch (attr->getType()){
      case NdbDictionary::Column::Char:
      case NdbDictionary::Column::Varchar:
      case NdbDictionary::Column::Binary:
      case NdbDictionary::Column::Varbinary:{
	check = pOp->equal( attr->getName(), 
			       reca->aRef());
	break;
      }
      case NdbDictionary::Column::Int:{
	check = pOp->equal( attr->getName(), 
			       reca->int32_value());      
      }
	break;
      case NdbDictionary::Column::Bigint:{
	check = pOp->equal( attr->getName(), 
			       reca->int64_value());
      }
	break;
      case NdbDictionary::Column::Unsigned:{
	check = pOp->equal( attr->getName(), 
			       reca->u_32_value());
      }
	break;
      case NdbDictionary::Column::Bigunsigned:{
	check = pOp->equal( attr->getName(), 
			       reca->u_64_value());
      }
	break;
      default:
	check = -1;
	break;
      }
      if(check != 0){
	ERR(pNdb->getNdbError());
	return NDBT_FAILED;
      }
    }
  }

  return NDBT_OK;
}
Example #29
0
void
BackupRestore::logEntry(const LogEntry & tup)
{
  if (!m_restore)
    return;

  NdbTransaction * trans = m_ndb->startTransaction();
  if (trans == NULL) 
  {
    // TODO: handle the error
    ndbout << "Cannot start transaction" << endl;
    exit(-1);
  } // if
  
  const TableS * table = tup.m_table;
  NdbOperation * op = trans->getNdbOperation(table->getTableName());
  if (op == NULL) 
  {
    ndbout << "Cannot get operation: ";
    ndbout << trans->getNdbError() << endl;
    exit(-1);
  } // if
  
  int check = 0;
  switch(tup.m_type)
  {
  case LogEntry::LE_INSERT:
    check = op->insertTuple();
    break;
  case LogEntry::LE_UPDATE:
    check = op->updateTuple();
    break;
  case LogEntry::LE_DELETE:
    check = op->deleteTuple();
    break;
  default:
    ndbout << "Log entry has wrong operation type."
	   << " Exiting...";
    exit(-1);
  }
  
  for (int i = 0; i < tup.m_values.size(); i++) 
  {
    const AttributeS * attr = tup.m_values[i];
    int size = attr->Desc->size;
    int arraySize = attr->Desc->arraySize;
    const char * dataPtr = attr->Data.string_value;
    
    const Uint32 length = (size / 8) * arraySize;
    if (attr->Desc->m_column->getPrimaryKey()) 
      op->equal(attr->Desc->attrId, dataPtr, length);
    else
      op->setValue(attr->Desc->attrId, dataPtr, length);
  }
  
#if 1
  trans->execute(Commit);
#else
  const int ret = trans->execute(Commit);
  // Both insert update and delete can fail during log running
  // and it's ok
  
  if (ret != 0)
  {
    ndbout << "execute failed: ";
    ndbout << trans->getNdbError() << endl;
    exit(-1);
  }
#endif
  
  m_ndb->closeTransaction(trans);
  m_logCount++;
}
Example #30
0
int 
HugoAsynchTransactions::pkUpdateRecordsAsynch(Ndb* pNdb, 
					int records,
					int batch,
					int trans,
					int operations) {

  g_info << "|- Updating records asynchronous..." << endl;

  int             check = 0;
  int             cTrans = 0;
  int             cReadRecords = 0;
  int             cReadIndex = 0;
  int             cRecords = 0;
  int             cIndex = 0;

  transactionsCompleted = 0;

  allocRows(trans*operations);
  allocTransactions(trans);
  int a, t, r;

  for (int i = 0; i < batch; i++) { // For each batch
    while (cRecords < records*batch) {
      cTrans = 0;
      cReadIndex = 0;
      for (t = 0; t < trans; t++) { // For each transaction
	transactions[t] = pNdb->startTransaction();
	if (transactions[t] == NULL) {
	  ERR(pNdb->getNdbError());
	  return NDBT_FAILED;
	}	
	for (int k = 0; k < operations; k++) { // For each operation
	  NdbOperation* pOp = transactions[t]->getNdbOperation(tab.getName());
	  if (pOp == NULL) { 
	    ERR(transactions[t]->getNdbError());
	    pNdb->closeTransaction(transactions[t]);
	    return NDBT_FAILED;
	  }
	  
	  // Read
	  // Define primary keys
	  check = pOp->readTupleExclusive();
	  for (a = 0; a < tab.getNoOfColumns(); a++) {
	    if (tab.getColumn(a)->getPrimaryKey() == true) {
	      if (equalForAttr(pOp, a, cReadRecords) != 0){
		ERR(transactions[t]->getNdbError());
		pNdb->closeTransaction(transactions[t]);
		return NDBT_FAILED;
	      }
	    }
	  }	    
	  // Define attributes to read  
	  for (a = 0; a < tab.getNoOfColumns(); a++) {
	    if ((rows[cReadIndex]->attributeStore(a) = 
		 pOp->getValue(tab.getColumn(a)->getName())) == 0) {
	      ERR(transactions[t]->getNdbError());
	      pNdb->closeTransaction(transactions[t]);
	      return NDBT_FAILED;
	    }
	  }	    	  
	  cReadIndex++;
	  cReadRecords++;
	  
	} // For each operation
	
	// Let's prepare...
	transactions[t]->executeAsynchPrepare(NoCommit, &asynchCallback, 
					this);
	cTrans++;

	if (cReadRecords >= records) {
	  // No more transactions needed
	  break;
	}      
      } // For each transaction

      // Wait for all outstanding transactions
      pNdb->sendPollNdb(3000, 0, 0);

      // Verify the data!
      for (r = 0; r < trans*operations; r++) {
	if (calc.verifyRowValues(rows[r]) != 0) {
	  g_info << "|- Verify failed..." << endl;
	  // Close all transactions
	  for (int t = 0; t < cTrans; t++) {
	    pNdb->closeTransaction(transactions[t]);
	  }
	  return NDBT_FAILED;
	}
      }	

      // Update
      cTrans = 0;
      cIndex = 0;
      for (t = 0; t < trans; t++) { // For each transaction
	for (int k = 0; k < operations; k++) { // For each operation
	  NdbOperation* pOp = transactions[t]->getNdbOperation(tab.getName());
	  if (pOp == NULL) { 
	    ERR(transactions[t]->getNdbError());
	    pNdb->closeTransaction(transactions[t]);
	    return NDBT_FAILED;
	  }
	  
	  int updates = calc.getUpdatesValue(rows[cIndex]) + 1;

	  check = pOp->updateTuple();
	  if (check == -1) {
	    ERR(transactions[t]->getNdbError());
	    pNdb->closeTransaction(transactions[t]);
	      return NDBT_FAILED;
	  }

	  // Set search condition for the record
	  for (a = 0; a < tab.getNoOfColumns(); a++) {
	    if (tab.getColumn(a)->getPrimaryKey() == true) {
	      if (equalForAttr(pOp, a, cRecords) != 0) {
		ERR(transactions[t]->getNdbError());
		pNdb->closeTransaction(transactions[t]);
		return NDBT_FAILED;
	      }
	    }
	  }

	  // Update the record
	  for (a = 0; a < tab.getNoOfColumns(); a++) {
	    if (tab.getColumn(a)->getPrimaryKey() == false) {
	      if (setValueForAttr(pOp, a, cRecords, updates) != 0) {
		ERR(transactions[t]->getNdbError());
		pNdb->closeTransaction(transactions[t]);
		return NDBT_FAILED;
	      }
	    }
	  }	  
	  cIndex++;
	  cRecords++;
	  
	} // For each operation
	
	// Let's prepare...
	transactions[t]->executeAsynchPrepare(Commit, &asynchCallback, 
					this);
	cTrans++;

	if (cRecords >= records) {
	  // No more transactions needed
	  break;
	}      
      } // For each transaction

      // Wait for all outstanding transactions
      pNdb->sendPollNdb(3000, 0, 0);

      // Close all transactions
      for (t = 0; t < cTrans; t++) {
	pNdb->closeTransaction(transactions[t]);
      }

    } // while (cRecords < records*batch)

  } // For each batch

  deallocTransactions();
  deallocRows();
  
  g_info << "|- " << ((unsigned int)transactionsCompleted * operations)/2 
	 << " updated..." << endl;
  return NDBT_OK;
}