Exemple #1
0
static void deleteIndex(Ndb &myNdb, unsigned int noOfTuples, unsigned int noOfOperations, bool includePrimary, bool oneTrans, bool longKey)
{
  Uint64 tbefore, tafter, before, after;
  NdbConnection  *myTrans;  
  NdbIndexOperation   *myOp;   
  char indexName[] = "PNUMINDEX0000";
  char name[] = "Kalle0000000";
  
  tbefore = NdbTick_CurrentMillisecond();
  if (oneTrans) myTrans = myNdb.startTransaction();
  for (unsigned int i = 0; i<noOfTuples; i++) {
    for(unsigned int j = 1; 
	((j<=noOfOperations)&&(i<noOfTuples)); 
	(++j<=noOfOperations)?i++:i) { 
      if (!oneTrans) myTrans = myNdb.startTransaction();
      if (myTrans == NULL) 
        error_handler4(__LINE__, myNdb.getNdbError());
      
      myOp = myTrans->getNdbIndexOperation(indexName, "PERSON"); 
      if (myOp == NULL) 
        error_handler4(__LINE__, myTrans->getNdbError());
      
      myOp->deleteTuple();
      if (includePrimary) {
        sprintf(name, "Kalle%.7i", i);
        if (longKey)
          memcpy(longName, name, strlen(name)); 
        if (myOp->equal("NAME", (longKey)?longName:name) == -1) {
          error_handler4(__LINE__, myTrans->getNdbError());
          myNdb.closeTransaction(myTrans);
          break;
        }         
      } 
      if (myOp->equal("PNUM1", 17) == -1) {
        error_handler4(__LINE__, myTrans->getNdbError());
      myNdb.closeTransaction(myTrans);
      break;
      }          
      if (myOp->equal("PNUM3", 19) == -1) {
        error_handler4(__LINE__, myTrans->getNdbError());
        myNdb.closeTransaction(myTrans);
        break;
      }       
    }
    if (noOfOperations == 1)
      printf("Trying to delete person %s\n", name);
    else
      printf("Trying to delete %u persons\n", noOfOperations);
    before = NdbTick_CurrentMillisecond();
    if (myTrans->execute( (oneTrans) ? NoCommit : Commit ) == -1)
      {
        error_handler4(__LINE__, myTrans->getNdbError());
        myNdb.closeTransaction(myTrans);
        break;
      }
    after = NdbTick_CurrentMillisecond();
    if (noOfOperations == 1)
      printf("Deleted person %s, %u msec\n", name, (Uint32) after - before);
    else
      printf("Deleted %u persons, %u msec\n", noOfOperations, (Uint32) after - before);
    if (!oneTrans) myNdb.closeTransaction(myTrans);
  }
  if (oneTrans) {
    if (myTrans->execute( Commit ) == -1) {
      error_handler4(__LINE__, myTrans->getNdbError());
    }
    myNdb.closeTransaction(myTrans);
  }
  tafter = NdbTick_CurrentMillisecond();

  ndbout << "Deleted "<< noOfTuples << " tuples in " << ((oneTrans) ? 1 : noOfTuples) << " transaction(s), " << tafter - tbefore << " msec" << endl;        
}
Exemple #2
0
/* Test for correct behaviour using unique key operations
 * when an NDBD node's SegmentedSection pool is exhausted.
 */
int testSegmentedSectionIx(NDBT_Context* ctx, NDBT_Step* step){
  /* 
   * Signal type       Exhausted @              How
   * -----------------------------------------------------
   * Long TCINDXREQ    Initial import           Consume + send 
   * Long TCINDXREQ    Build second TCKEYREQ    Consume + send short
   *                                             w. long base key
   */
  /* We will generate : 
   *   10 SS left : 
   *     Long IndexReq with too long Key/AttrInfo
   *    1 SS left :
   *     Long IndexReq read with short Key + Attrinfo to long 
   *       base table Key
   */
  /* We just run on one table */
  if (strcmp(ctx->getTab()->getName(), "WIDE_2COL_IX") != 0)
    return NDBT_OK;

  const char* indexName= "WIDE_2COL_IX$NDBT_IDX0";
  const Uint32 maxRowBytes= NDB_MAX_TUPLE_SIZE_IN_WORDS * sizeof(Uint32);
  const Uint32 srcBuffBytes= NDBT_Tables::MaxVarTypeKeyBytes;
  const Uint32 maxIndexKeyBytes= NDBT_Tables::MaxKeyMaxVarTypeAttrBytesIndex;
  /* We want to use 6 Segmented Sections, each of 60 32-bit words, including
   * a 2 byte length overhead
   * (We don't want to use 10 Segmented Sections as in some scenarios TUP 
   *  uses Segmented Sections when sending results, and if we use TUP on
   *  the same node, the exhaustion will occur in TUP, which is not what
   *  we're testing)
   */
  const Uint32 mediumPrimaryKeyBytes= (6* 60 * 4) - 2;
  char smallKey[50];
  char srcBuff[srcBuffBytes];
  char smallRowBuf[maxRowBytes];
  char bigKeyIxBuf[maxRowBytes];
  char bigAttrIxBuf[maxRowBytes];
  char bigKeyRowBuf[maxRowBytes];
  char resultSpace[maxRowBytes];

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

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

  Ndb* pNdb= GETNDB(step);

  const NdbRecord* baseRecord= ctx->getTab()->getDefaultRecord();
  const NdbRecord* ixRecord= pNdb->
    getDictionary()->getIndex(indexName,
                              ctx->getTab()->getName())->getDefaultRecord();

  /* Setup buffers
   * Small row buffer with short key and data in base table record format
   */ 
  setLongVarchar(NdbDictionary::getValuePtr(baseRecord,
                                            smallRowBuf,
                                            0),
                 "ShortKey",
                 8);
  NdbDictionary::setNull(baseRecord, smallRowBuf, 0, false);

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

  /* Big index key buffer
   * Big index key (normal row attribute) in index record format
   * Index's key is attrid 1 from the base table
   * This could get confusing !
   */
  
  setLongVarchar(NdbDictionary::getValuePtr(ixRecord,
                                            bigKeyIxBuf,
                                            1),
                 &srcBuff[0],
                 maxIndexKeyBytes);
  NdbDictionary::setNull(ixRecord, bigKeyIxBuf, 1, false);

  /* Big AttrInfo buffer
   * Small key and large attrinfo in base table record format */
  setLongVarchar(NdbDictionary::getValuePtr(baseRecord,
                                            bigAttrIxBuf,
                                            0),
                 "ShortIXKey", 
                 10);

  NdbDictionary::setNull(baseRecord, bigAttrIxBuf, 0, false);

  setLongVarchar(NdbDictionary::getValuePtr(baseRecord,
                                            bigAttrIxBuf,
                                            1),
                 &srcBuff[0],
                 maxIndexKeyBytes);
  NdbDictionary::setNull(baseRecord, bigAttrIxBuf, 1, false);

  /* Big key row buffer 
   * Medium sized key and small attrinfo (index key) in
   * base table record format
   */
  setLongVarchar(NdbDictionary::getValuePtr(baseRecord,
                                            bigKeyRowBuf,
                                            0),
                 &srcBuff[0], 
                 mediumPrimaryKeyBytes);

  NdbDictionary::setNull(baseRecord, bigKeyRowBuf, 0, false);

  setLongVarchar(NdbDictionary::getValuePtr(baseRecord,
                                            bigKeyRowBuf,
                                            1),
                 "ShortIXKey",
                 10);
  NdbDictionary::setNull(baseRecord, bigKeyRowBuf, 1, false);


  /* Start a transaction on a specific node */
  NdbTransaction* trans= pNdb->startTransaction(ctx->getTab(),
                                                &smallKey[0],
                                                smallKeySize);
  /* Insert a row in the base table with a big PK, and
   * small data (Unique IX key).  This is used later to lookup
   * a big PK and cause overflow when reading TRANSID_AI in TC.
   */
  CHECKNOTNULL(trans->insertTuple(baseRecord,
                                  bigKeyRowBuf));

  CHECKEQUAL(0, trans->execute(NdbTransaction::Commit));

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

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

  /* Ok, let's try an index read with a big index key.
   * Since it's part of the same transaction, it'll go via
   * the same TC.
   */
  const NdbOperation* bigRead= trans->readTuple(ixRecord,
                                                bigKeyIxBuf,
                                                baseRecord,
                                                resultSpace);

  CHECKNOTNULL(bigRead);

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

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

  trans->close();

  
  /* Ok, now a long TCINDXREQ to the same TC - this
   * has slightly different abort handling since no other
   * operations exist in this new transaction.
   */
  /* Start a transaction on a specific node */
  CHECKNOTNULL(trans= pNdb->startTransaction(ctx->getTab(),
                                             &smallKey[0],
                                             smallKeySize));

  CHECKNOTNULL(trans->readTuple(ixRecord,
                                bigKeyIxBuf,
                                baseRecord,
                                resultSpace));
  
  CHECKEQUAL(-1, trans->execute(NdbTransaction::NoCommit));

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

  /* Now a TCINDXREQ that overflows, but is not the last in the
   * batch, what happens to the other TCINDXREQ in the batch?
   */
  CHECKNOTNULL(trans= pNdb->startTransaction(ctx->getTab(),
                                             &smallKey[0],
                                             smallKeySize));

  CHECKNOTNULL(trans->readTuple(ixRecord,
                                bigKeyIxBuf,
                                baseRecord,
                                resultSpace));
  /* Another read */
  CHECKNOTNULL(trans->readTuple(ixRecord,
                                bigKeyIxBuf,
                                baseRecord,
                                resultSpace));
  
  CHECKEQUAL(-1, trans->execute(NdbTransaction::NoCommit));

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


  /* Next we read a tuple with a large primary key via the unique
   * index.  The index read itself should be fine, but
   * pulling in the base table PK will cause abort due to overflow
   * handling TRANSID_AI
   */
  /* Start a transaction on a specific node */
  CHECKNOTNULL(trans= pNdb->startTransaction(ctx->getTab(),
                                             &smallKey[0],
                                             smallKeySize));

  /* Activate error insert 8066 in this transaction, limits a
   * single import/append to 1 section.
   * Note that the TRANSID_AI is received by TC as a short-signal
   * train, so no single append is large, but when the first
   * segment is used and append starts on the second, it will
   * fail.
   */
  CHECKEQUAL(NDBT_OK, activateErrorInsert(trans, 
                                          baseRecord, 
                                          ctx->getTab(),
                                          smallRowBuf, 
                                          &restarter, 
                                          8066));
  CHECKEQUAL(0, trans->execute(NdbTransaction::NoCommit));
  
  CHECKNOTNULL(bigRead= trans->readTuple(ixRecord,
                                         bigAttrIxBuf,
                                         baseRecord,
                                         resultSpace));

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

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

  trans->close();

  // TODO Move short signal testing to testUpgrade
#if 0
  /*
   * Short TCINDXREQ   KeyInfo accumulate       Consume + send long
   *                     (TCINDXREQ + KEYINFO)
   * Short TCINDXREQ   AttrInfo accumulate      Consume + send short key
   *                                             + long AI
   *                     (TCINDXREQ + ATTRINFO)
   */
  /* Now try with a 'short' TCINDXREQ, generated using the old Api 
   * with a big index key value
   */
  CHECKNOTNULL(trans= pNdb->startTransaction(ctx->getTab(),
                                             &smallKey[0],
                                             smallKeySize));
  
  const NdbDictionary::Index* index;
  CHECKNOTNULL(index= pNdb->getDictionary()->
               getIndex(indexName,
                        ctx->getTab()->getName()));

  NdbIndexOperation* bigReadOldApi;
  CHECKNOTNULL(bigReadOldApi= trans->getNdbIndexOperation(index));

  CHECKEQUAL(0, bigReadOldApi->readTuple());
  /* We use the attribute id of the index, not the base table here */
  CHECKEQUAL(0, bigReadOldApi->equal((Uint32)0, 
                                     NdbDictionary::getValuePtr
                                     (ixRecord,
                                      bigKeyIxBuf,
                                      1)));

  CHECKNOTNULL(bigReadOldApi->getValue((Uint32)1));

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

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

  trans->close();

  /* Now try with a 'short' TCINDXREQ, generated using the old Api 
   * with a big attrinfo value
   */
  CHECKNOTNULL(trans= pNdb->startTransaction(ctx->getTab(),
                                             &smallKey[0],
                                             smallKeySize));
  
  NdbIndexOperation* bigUpdateOldApi;
  CHECKNOTNULL(bigUpdateOldApi= trans->getNdbIndexOperation(index));

  CHECKEQUAL(0, bigUpdateOldApi->updateTuple());
  /* We use the attribute id of the index, not the base table here */
  CHECKEQUAL(0, bigUpdateOldApi->equal((Uint32)0, 
                                       NdbDictionary::getValuePtr
                                       (baseRecord,
                                        smallRowBuf,
                                        1)));

  CHECKEQUAL(0, bigUpdateOldApi->setValue((Uint32)1,
                                          NdbDictionary::getValuePtr
                                          (baseRecord,
                                           bigAttrIxBuf,
                                           1)));
  
  CHECKEQUAL(-1, trans->execute(NdbTransaction::NoCommit));

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

  trans->close();

  /* Change error insert so that next TCINDXREQ will grab
   * all but one SegmentedSection
   */
  restarter.insertErrorInAllNodes(8066);

  /* Now a short TCINDXREQ where the KeyInfo from the TCINDXREQ
   * can be imported, but the ATTRINFO can't
   */
  CHECKNOTNULL(trans= pNdb->startTransaction(ctx->getTab(),
                                             &smallKey[0],
                                             smallKeySize));
  
  CHECKNOTNULL(bigUpdateOldApi= trans->getNdbIndexOperation(index));

  CHECKEQUAL(0, bigUpdateOldApi->updateTuple());
  /* We use the attribute id of the index, not the base table here */
  CHECKEQUAL(0, bigUpdateOldApi->equal((Uint32)0, 
                                       NdbDictionary::getValuePtr
                                       (baseRecord,
                                        smallRowBuf,
                                        1)));

  CHECKEQUAL(0, bigUpdateOldApi->setValue((Uint32)1,
                                          NdbDictionary::getValuePtr
                                          (baseRecord,
                                           bigAttrIxBuf,
                                           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 */
  restarter.insertErrorInAllNodes(8067);

  /* Now a short TCINDXREQ where the KeyInfo from the TCINDXREQ
   * can't be imported
   */
  CHECKNOTNULL(trans= pNdb->startTransaction(ctx->getTab(),
                                             &smallKey[0],
                                             smallKeySize));

  CHECKNOTNULL(bigUpdateOldApi= trans->getNdbIndexOperation(index));

  CHECKEQUAL(0, bigUpdateOldApi->updateTuple());
  /* We use the attribute id of the index, not the base table here */
  CHECKEQUAL(0, bigUpdateOldApi->equal((Uint32)0, 
                                       NdbDictionary::getValuePtr
                                       (baseRecord,
                                        smallRowBuf,
                                        1)));

  CHECKEQUAL(0, bigUpdateOldApi->setValue((Uint32)1,
                                          NdbDictionary::getValuePtr
                                          (baseRecord,
                                           bigAttrIxBuf,
                                           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 */
  CHECKNOTNULL(trans= pNdb->startTransaction(ctx->getTab(),
                                             &smallKey[0],
                                             smallKeySize));

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

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

  trans->close();

  return NDBT_OK;
}
Exemple #3
0
/****************************************************************************
void handleReceivedSignal(NdbApiSignal* aSignal);

Parameters:     aSignal: The signal object.
Remark:         Send all operations belonging to this connection. 
*****************************************************************************/
void	
Ndb::handleReceivedSignal(const NdbApiSignal* aSignal,
			  const LinearSectionPtr ptr[3])
{
  NdbOperation* tOp;
  NdbIndexOperation* tIndexOp;
  NdbTransaction* tCon;
  int tReturnCode = -1;
  const Uint32* tDataPtr = aSignal->getDataPtr();
  const Uint32 tWaitState = theImpl->theWaiter.get_state();
  const Uint32 tSignalNumber = aSignal->readSignalNumber();
  const Uint32 tFirstData = *tDataPtr;
  const Uint32 tLen = aSignal->getLength();
  Uint32 tNewState = tWaitState;
  void * tFirstDataPtr;
  NdbWaiter *t_waiter = &theImpl->theWaiter;

  /* Update cached Min Db node version */
  theCachedMinDbNodeVersion = theImpl->m_transporter_facade->getMinDbNodeVersion();

  if (likely(NdbImpl::recordGSN(tSignalNumber)))
  {
    Uint32 secs = aSignal->m_noOfSections;
    theImpl->incClientStat(BytesRecvdCount,
                           ((aSignal->getLength() << 2) +
                            ((secs > 2)? ptr[2].sz << 2: 0) + 
                            ((secs > 1)? ptr[1].sz << 2: 0) +
                            ((secs > 0)? ptr[0].sz << 2: 0)));
  }
  
  /*
    In order to support 64 bit processes in the application we need to use
    id's rather than a direct pointer to the object used. It is also a good
    idea that one cannot corrupt the application code by sending a corrupt
    memory pointer.
    
    All signals received by the API requires the first data word to be such
    an id to the receiving object.
  */
  
  switch (tSignalNumber){
  case GSN_TCKEYCONF:
  case GSN_TCINDXCONF:
    {
      const TcKeyConf * const keyConf = (TcKeyConf *)tDataPtr;
      if (tFirstData != RNIL)
      {
        tFirstDataPtr = int2void(tFirstData);
        if (tFirstDataPtr == 0) goto InvalidSignal;
        tCon = void2con(tFirstDataPtr);
      }
      else
      {
        tCon = lookupTransactionFromOperation(keyConf);
        if (tCon == NULL) goto InvalidSignal;
      }
      const BlockReference aTCRef = aSignal->theSendersBlockRef;

      if ((tCon->checkMagicNumber() == 0) &&
          (tCon->theSendStatus == NdbTransaction::sendTC_OP)) {
        tReturnCode = tCon->receiveTCKEYCONF(keyConf, tLen);
        if (tReturnCode != -1) {
          completedTransaction(tCon);
        }//if

	if(TcKeyConf::getMarkerFlag(keyConf->confInfo)){
	  NdbTransaction::sendTC_COMMIT_ACK(theImpl,
                                            theCommitAckSignal,
                                            keyConf->transId1, 
                                            keyConf->transId2,
                                            aTCRef);
	}
      
	return;
      }//if
      goto InvalidSignal;
      
      return;
    }
  case GSN_TRANSID_AI:{
    tFirstDataPtr = int2void(tFirstData);
    if (tFirstDataPtr){
      NdbReceiver* const tRec = void2rec(tFirstDataPtr);
      if(!tRec->checkMagicNumber()){
	return;
      }
      tCon = tRec->getTransaction();
      if((tCon!=NULL) &&
	 tCon->checkState_TransId(((const TransIdAI*)tDataPtr)->transId)){
	Uint32 com;
	if(aSignal->m_noOfSections > 0){
	  if(tRec->getType()==NdbReceiver::NDB_QUERY_OPERATION){
	    com = ((NdbQueryOperationImpl*)(tRec->m_owner))
              ->execTRANSID_AI(ptr[0].p, ptr[0].sz);
	  }else{
	    com = tRec->execTRANSID_AI(ptr[0].p, ptr[0].sz);
	  }
	} else {
	  assert(tRec->getType()!=NdbReceiver::NDB_QUERY_OPERATION);
	  com = tRec->execTRANSID_AI(tDataPtr + TransIdAI::HeaderLength, 
				     tLen - TransIdAI::HeaderLength);
	}

        {
          tCon->theNdb->theImpl->incClientStat(Ndb::ReadRowCount, 1);
          if (refToNode(aSignal->theSendersBlockRef) == tCon->theDBnode)
            tCon->theNdb->theImpl->incClientStat(Ndb::TransLocalReadRowCount,1);
        }

	if(com == 0)
	  return;

	switch(tRec->getType()){
	case NdbReceiver::NDB_OPERATION:
	case NdbReceiver::NDB_INDEX_OPERATION:
	  if(tCon->OpCompleteSuccess() != -1){ //More completions pending?
	    completedTransaction(tCon);
	  }
	  return;
	case NdbReceiver::NDB_SCANRECEIVER:
	  tCon->theScanningOp->receiver_delivered(tRec);
          tNewState = (((WaitSignalType) tWaitState) == WAIT_SCAN ? 
                     (Uint32) NO_WAIT : tWaitState);
	  break;
        case NdbReceiver::NDB_QUERY_OPERATION:
        {
          // Handled differently whether it is a scan or lookup
          NdbQueryOperationImpl* tmp = (NdbQueryOperationImpl*)(tRec->m_owner);
          if (tmp->getQueryDef().isScanQuery()) {
            tNewState = (((WaitSignalType) tWaitState) == WAIT_SCAN ? 
                       (Uint32) NO_WAIT : tWaitState);
            break;
          } else {
            if (tCon->OpCompleteSuccess() != -1) { //More completions pending?
              completedTransaction(tCon);
            }
            return;
          }
        }
	default:
	  goto InvalidSignal;
	}
	break;
      } else {
	/**
	 * This is ok as transaction can have been aborted before TRANSID_AI
	 * arrives (if TUP on  other node than TC)
	 */
	return;
      }
    } else{ // if((tFirstDataPtr)
      return;
    }
  }
  case GSN_TCKEY_FAILCONF:
    {
      tFirstDataPtr = int2void(tFirstData);
      const TcKeyFailConf * failConf = (TcKeyFailConf *)tDataPtr;
      const BlockReference aTCRef = aSignal->theSendersBlockRef;
      if (tFirstDataPtr != 0){
	tOp = void2rec_op(tFirstDataPtr);
	
	if (tOp->checkMagicNumber(false) == 0) {
	  tCon = tOp->theNdbCon;
	  if (tCon != NULL) {
	    if ((tCon->theSendStatus == NdbTransaction::sendTC_OP) ||
		(tCon->theSendStatus == NdbTransaction::sendTC_COMMIT)) {
	      tReturnCode = tCon->receiveTCKEY_FAILCONF(failConf);
	      if (tReturnCode != -1) {
		completedTransaction(tCon);
	      }//if
	    }//if
	  }
	}
      } else {
#ifdef VM_TRACE
	ndbout_c("Recevied TCKEY_FAILCONF wo/ operation");
#endif
      }
      if(tFirstData & 1){
	NdbTransaction::sendTC_COMMIT_ACK(theImpl,
                                          theCommitAckSignal,
                                          failConf->transId1, 
                                          failConf->transId2,
                                          aTCRef);
      }
      return;
    }
  case GSN_TCKEY_FAILREF:
    {
      tFirstDataPtr = int2void(tFirstData);
      if(tFirstDataPtr != 0){
	tOp = void2rec_op(tFirstDataPtr);
	if (tOp->checkMagicNumber(false) == 0) {
	  tCon = tOp->theNdbCon;
	  if (tCon != NULL) {
	    if ((tCon->theSendStatus == NdbTransaction::sendTC_OP) ||
		(tCon->theSendStatus == NdbTransaction::sendTC_ROLLBACK)) {
	      tReturnCode = tCon->receiveTCKEY_FAILREF(aSignal);
	      if (tReturnCode != -1) {
		completedTransaction(tCon);
		return;
	      }//if
	    }//if
	  }//if
	}//if
      }
#ifdef VM_TRACE
      ndbout_c("Recevied TCKEY_FAILREF wo/ operation");
#endif
      return;
      return;
    }
  case GSN_TCKEYREF:
    {
      tFirstDataPtr = int2void(tFirstData);
      if (tFirstDataPtr == 0) goto InvalidSignal;

      const NdbReceiver* const receiver = void2rec(tFirstDataPtr);
      if(!receiver->checkMagicNumber()){
        goto InvalidSignal; 
      }
      tCon = receiver->getTransaction();
      if (tCon != NULL) {
        if (tCon->theSendStatus == NdbTransaction::sendTC_OP) {
          if (receiver->getType()==NdbReceiver::NDB_QUERY_OPERATION) {
            NdbQueryOperationImpl* tmp =
              (NdbQueryOperationImpl*)(receiver->m_owner);
            if (tmp->execTCKEYREF(aSignal) &&
               tCon->OpCompleteFailure() != -1) {
              completedTransaction(tCon);
              return;
            }
          } else {
            tOp = void2rec_op(tFirstDataPtr);
            /* NB! NdbOperation::checkMagicNumber() returns 0 if it *is* 
             * an NdbOperation.*/
            assert(tOp->checkMagicNumber()==0); 
            tReturnCode = tOp->receiveTCKEYREF(aSignal);
            if (tReturnCode != -1) {
              completedTransaction(tCon);
              return;
            }//if
          }//if
          break;
        }//if
      }//if (tCon != NULL)
      goto InvalidSignal;
      return;
    } 
  case GSN_TC_COMMITCONF:
    {
      tFirstDataPtr = int2void(tFirstData);
      if (tFirstDataPtr == 0) goto InvalidSignal;

      const TcCommitConf * const commitConf = (TcCommitConf *)tDataPtr;
      const BlockReference aTCRef = aSignal->theSendersBlockRef;
      
      tCon = void2con(tFirstDataPtr);
      if ((tCon->checkMagicNumber() == 0) &&
	  (tCon->theSendStatus == NdbTransaction::sendTC_COMMIT)) {
	tReturnCode = tCon->receiveTC_COMMITCONF(commitConf, tLen);
	if (tReturnCode != -1) {
	  completedTransaction(tCon);
	}//if

	if(tFirstData & 1){
	  NdbTransaction::sendTC_COMMIT_ACK(theImpl,
                                            theCommitAckSignal,
                                            commitConf->transId1, 
                                            commitConf->transId2,
                                            aTCRef);
	}
	return;
      }
      goto InvalidSignal;
      return;
    }

  case GSN_TC_COMMITREF:
    {
      tFirstDataPtr = int2void(tFirstData);
      if (tFirstDataPtr == 0) goto InvalidSignal;

      tCon = void2con(tFirstDataPtr);
      if ((tCon->checkMagicNumber() == 0) &&
	  (tCon->theSendStatus == NdbTransaction::sendTC_COMMIT)) {
	tReturnCode = tCon->receiveTC_COMMITREF(aSignal);
	if (tReturnCode != -1) {
	  completedTransaction(tCon);
	}//if
      }//if
      return;
    }
  case GSN_TCROLLBACKCONF:
    {
      tFirstDataPtr = int2void(tFirstData);
      if (tFirstDataPtr == 0) goto InvalidSignal;

      tCon = void2con(tFirstDataPtr);
      if ((tCon->checkMagicNumber() == 0) &&
	  (tCon->theSendStatus == NdbTransaction::sendTC_ROLLBACK)) {
	tReturnCode = tCon->receiveTCROLLBACKCONF(aSignal);
	if (tReturnCode != -1) {
	  completedTransaction(tCon);
	}//if
      }//if
      return;
    }
  case GSN_TCROLLBACKREF:
    {
      tFirstDataPtr = int2void(tFirstData);
      if (tFirstDataPtr == 0) goto InvalidSignal;

      tCon = void2con(tFirstDataPtr);
      if ((tCon->checkMagicNumber() == 0) &&
	  (tCon->theSendStatus == NdbTransaction::sendTC_ROLLBACK)) {
	tReturnCode = tCon->receiveTCROLLBACKREF(aSignal);
	if (tReturnCode != -1) {
	  completedTransaction(tCon);
	}//if
      }//if
      return;
    }
  case GSN_TCROLLBACKREP:
    {
      tFirstDataPtr = int2void(tFirstData);
      if (tFirstDataPtr == 0) goto InvalidSignal;

      tCon = void2con(tFirstDataPtr);
      if (tCon->checkMagicNumber() == 0) {
	tReturnCode = tCon->receiveTCROLLBACKREP(aSignal);
	if (tReturnCode != -1) {
	  completedTransaction(tCon);
	}//if
      }//if
      return;
    }
  case GSN_TCSEIZECONF:
    {
      tFirstDataPtr = int2void(tFirstData);
      if (tFirstDataPtr == 0) goto InvalidSignal;

      if (tWaitState != WAIT_TC_SEIZE) {
	goto InvalidSignal;
      }//if
      tCon = void2con(tFirstDataPtr);
      if (tCon->checkMagicNumber() != 0) {
	goto InvalidSignal;
      }//if
      tReturnCode = tCon->receiveTCSEIZECONF(aSignal);
      if (tReturnCode != -1) {
        tNewState = NO_WAIT;
      } else {
	goto InvalidSignal;
      }//if
      break;
    }
  case GSN_TCSEIZEREF:
    {
      tFirstDataPtr = int2void(tFirstData);
      if (tFirstDataPtr == 0) goto InvalidSignal;

      if (tWaitState != WAIT_TC_SEIZE) {
	return;
      }//if
      tCon = void2con(tFirstDataPtr);
      if (tCon->checkMagicNumber() != 0) {
	return;
      }//if
      tReturnCode = tCon->receiveTCSEIZEREF(aSignal);
      if (tReturnCode != -1) {
        tNewState = NO_WAIT;
      } else {
        return;
      }//if
      break;
    }
  case GSN_TCRELEASECONF:
    {
      tFirstDataPtr = int2void(tFirstData);
      if (tFirstDataPtr == 0) goto InvalidSignal;

      if (tWaitState != WAIT_TC_RELEASE) {
	goto InvalidSignal;
      }//if
      tCon = void2con(tFirstDataPtr);
      if (tCon->checkMagicNumber() != 0) {
	goto InvalidSignal;
      }//if
      tReturnCode = tCon->receiveTCRELEASECONF(aSignal);
      if (tReturnCode != -1) {
        tNewState = NO_WAIT;
      }//if
      break;
    } 
  case GSN_TCRELEASEREF:
    {
      tFirstDataPtr = int2void(tFirstData);
      if (tFirstDataPtr == 0) goto InvalidSignal;

      if (tWaitState != WAIT_TC_RELEASE) {
	goto InvalidSignal;
      }//if
      tCon = void2con(tFirstDataPtr);
      if (tCon->checkMagicNumber() != 0) {
	goto InvalidSignal;
      }//if
      tReturnCode = tCon->receiveTCRELEASEREF(aSignal);
      if (tReturnCode != -1) {
        tNewState = NO_WAIT;
      }//if
      break;
    }
      
  case GSN_GET_TABINFOREF:
  case GSN_GET_TABINFO_CONF:
  case GSN_CREATE_TABLE_REF:
  case GSN_CREATE_TABLE_CONF:
  case GSN_DROP_TABLE_CONF:
  case GSN_DROP_TABLE_REF:
  case GSN_ALTER_TABLE_CONF:
  case GSN_ALTER_TABLE_REF:
  case GSN_CREATE_INDX_CONF:
  case GSN_CREATE_INDX_REF:
  case GSN_DROP_INDX_CONF:
  case GSN_DROP_INDX_REF:
  case GSN_INDEX_STAT_CONF:
  case GSN_INDEX_STAT_REF:
  case GSN_CREATE_EVNT_CONF:
  case GSN_CREATE_EVNT_REF:
  case GSN_DROP_EVNT_CONF:
  case GSN_DROP_EVNT_REF:
  case GSN_LIST_TABLES_CONF:
  case GSN_CREATE_FILE_REF:
  case GSN_CREATE_FILE_CONF:
  case GSN_CREATE_FILEGROUP_REF:
  case GSN_CREATE_FILEGROUP_CONF:
  case GSN_DROP_FILE_REF:
  case GSN_DROP_FILE_CONF:
  case GSN_DROP_FILEGROUP_REF:
  case GSN_DROP_FILEGROUP_CONF:
  case GSN_SCHEMA_TRANS_BEGIN_CONF:
  case GSN_SCHEMA_TRANS_BEGIN_REF:
  case GSN_SCHEMA_TRANS_END_CONF:
  case GSN_SCHEMA_TRANS_END_REF:
  case GSN_SCHEMA_TRANS_END_REP:
  case GSN_WAIT_GCP_CONF:
  case GSN_WAIT_GCP_REF:
  case GSN_CREATE_HASH_MAP_REF:
  case GSN_CREATE_HASH_MAP_CONF:
    NdbDictInterface::execSignal(&theDictionary->m_receiver,
				 aSignal, ptr);
    return;
    
  case GSN_SUB_REMOVE_CONF:
  case GSN_SUB_REMOVE_REF:
    return; // ignore these signals
  case GSN_SUB_START_CONF:
  case GSN_SUB_START_REF:
  case GSN_SUB_STOP_CONF:
  case GSN_SUB_STOP_REF:
    NdbDictInterface::execSignal(&theDictionary->m_receiver,
				 aSignal, ptr);
    return;
  case GSN_SUB_GCP_COMPLETE_REP:
  {
    const SubGcpCompleteRep * const rep=
      CAST_CONSTPTR(SubGcpCompleteRep, aSignal->getDataPtr());
    theEventBuffer->execSUB_GCP_COMPLETE_REP(rep, tLen);
    return;
  }
  case GSN_SUB_TABLE_DATA:
  {
    const SubTableData * const sdata=
      CAST_CONSTPTR(SubTableData, aSignal->getDataPtr());
    const Uint32 oid = sdata->senderData;
    NdbEventOperationImpl *op= (NdbEventOperationImpl*)int2void(oid);

    if (unlikely(op == 0 || op->m_magic_number != NDB_EVENT_OP_MAGIC_NUMBER))
    {
      g_eventLogger->error("dropped GSN_SUB_TABLE_DATA due to wrong magic "
                           "number");
      return ;
    }

    // Accumulate DIC_TAB_INFO for TE_ALTER events
    if (SubTableData::getOperation(sdata->requestInfo) == 
	NdbDictionary::Event::_TE_ALTER &&
        !op->execSUB_TABLE_DATA(aSignal, ptr))
      return;
    
    LinearSectionPtr copy[3];
    for (int i = 0; i<aSignal->m_noOfSections; i++)
    {
      copy[i] = ptr[i];
    }
    for (int i = aSignal->m_noOfSections; i < 3; i++)
    {
      copy[i].p = NULL;
      copy[i].sz = 0;
    }
    DBUG_PRINT("info",("oid=senderData: %d, gci{hi/lo}: %d/%d, operation: %d, "
		       "tableId: %d",
		       sdata->senderData, sdata->gci_hi, sdata->gci_lo,
		       SubTableData::getOperation(sdata->requestInfo),
		       sdata->tableId));

    theEventBuffer->insertDataL(op, sdata, tLen, copy);
    return;
  }
  case GSN_SCAN_TABCONF:
    {
      tFirstDataPtr = int2void(tFirstData);
      assert(tFirstDataPtr);
      assert(void2con(tFirstDataPtr));
      assert(void2con(tFirstDataPtr)->checkMagicNumber() == 0);
      if(tFirstDataPtr && 
	 (tCon = void2con(tFirstDataPtr)) && (tCon->checkMagicNumber() == 0)){
	
	if(aSignal->m_noOfSections > 0){
	  tReturnCode = tCon->receiveSCAN_TABCONF(aSignal, 
						  ptr[0].p, ptr[0].sz);
	} else {
	  tReturnCode = 
	    tCon->receiveSCAN_TABCONF(aSignal, 
				      tDataPtr + ScanTabConf::SignalLength, 
				      tLen - ScanTabConf::SignalLength);
	}
	if (tReturnCode != -1 && tWaitState == WAIT_SCAN)
          tNewState = NO_WAIT;
	break;
      } else {
	goto InvalidSignal;
      }
    }
  case GSN_SCAN_TABREF:
    {
      tFirstDataPtr = int2void(tFirstData);
      if (tFirstDataPtr == 0) goto InvalidSignal;
      
      tCon = void2con(tFirstDataPtr);
      
      assert(tFirstDataPtr != 0 && 
	     void2con(tFirstDataPtr)->checkMagicNumber() == 0);
      
      if (tCon->checkMagicNumber() == 0){
	tReturnCode = tCon->receiveSCAN_TABREF(aSignal);
	if (tReturnCode != -1 && tWaitState == WAIT_SCAN){
          tNewState = NO_WAIT;
	}
	break;
      }
      goto InvalidSignal;
    }
  case GSN_KEYINFO20: {
    tFirstDataPtr = int2void(tFirstData);
    NdbReceiver* tRec;
    if (tFirstDataPtr && (tRec = void2rec(tFirstDataPtr)) &&
	tRec->checkMagicNumber() && (tCon = tRec->getTransaction()) &&
	tCon->checkState_TransId(&((const KeyInfo20*)tDataPtr)->transId1)){
      
      Uint32 len = ((const KeyInfo20*)tDataPtr)->keyLen;
      Uint32 info = ((const KeyInfo20*)tDataPtr)->scanInfo_Node;
      int com = -1;
      if(aSignal->m_noOfSections > 0 && len == ptr[0].sz){
	com = tRec->execKEYINFO20(info, ptr[0].p, len);
      } else if(len == tLen - KeyInfo20::HeaderLength){
	com = tRec->execKEYINFO20(info, tDataPtr+KeyInfo20::HeaderLength, len);
      }
      
      switch(com){
      case 1:
	tCon->theScanningOp->receiver_delivered(tRec);
        tNewState = (((WaitSignalType) tWaitState) == WAIT_SCAN ? 
                     (Uint32) NO_WAIT : tWaitState);
	break;
      case 0:
	break;
      case -1:
	goto InvalidSignal;
      }
      break;
    } else {
      /**
       * This is ok as transaction can have been aborted before KEYINFO20
       * arrives (if TUP on  other node than TC)
       */
      return;
    }
  }
  case GSN_TCINDXREF:{
    tFirstDataPtr = int2void(tFirstData);
    if (tFirstDataPtr == 0) goto InvalidSignal;

    tIndexOp = void2rec_iop(tFirstDataPtr);
    if (tIndexOp->checkMagicNumber() == 0) {
      tCon = tIndexOp->theNdbCon;
      if (tCon != NULL) {
	if (tCon->theSendStatus == NdbTransaction::sendTC_OP) {
	  tReturnCode = tIndexOp->receiveTCINDXREF(aSignal);
	  if (tReturnCode != -1) {
	    completedTransaction(tCon);
	  }//if
	  return;
	}//if
      }//if
    }//if
    goto InvalidSignal;
    return;
  } 
  case GSN_API_REGCONF:
  case GSN_CONNECT_REP:
    return; // Ignore
  case GSN_NODE_FAILREP:
  {
    const NodeFailRep *rep = CAST_CONSTPTR(NodeFailRep,
                                           aSignal->getDataPtr());
    for (Uint32 i = NdbNodeBitmask::find_first(rep->theNodes);
         i != NdbNodeBitmask::NotFound;
         i = NdbNodeBitmask::find_next(rep->theNodes, i + 1))
    {
      report_node_failure(i);
    }

    NdbDictInterface::execSignal(&theDictionary->m_receiver, aSignal, ptr);
    break;
  }
  case GSN_NF_COMPLETEREP:
  {
    const NFCompleteRep *rep = CAST_CONSTPTR(NFCompleteRep,
                                             aSignal->getDataPtr());
    report_node_failure_completed(rep->failedNodeId);
    break;
  }
  case GSN_TAKE_OVERTCCONF:
    abortTransactionsAfterNodeFailure(tFirstData); // theData[0]
    break;
  case GSN_ALLOC_NODEID_CONF:
  {
    const AllocNodeIdConf *rep = CAST_CONSTPTR(AllocNodeIdConf,
                                               aSignal->getDataPtr());
    Uint32 nodeId = rep->nodeId;
    connected(numberToRef(theNdbBlockNumber, nodeId));
    break;
  }
  default:
    tFirstDataPtr = NULL;
    goto InvalidSignal;
  }//swich

  if (tNewState != tWaitState)
  {
    /*
      If our waiter object is the owner of the "poll rights", then we
      can simply return, we will return from this routine to the
      place where external_poll was called. From there it will move
      the "poll ownership" to a new thread if available.

      If our waiter object doesn't own the "poll rights", then we must
      signal the thread from where this waiter object called
      its conditional wait. This will wake up this thread so that it
      can continue its work.
    */
    t_waiter->signal(tNewState);
  }

  return;


InvalidSignal:
#ifdef VM_TRACE
  ndbout_c("Ndbif: Error Ndb::handleReceivedSignal "
	   "(tFirstDataPtr=%p, GSN=%d, theImpl->theWaiter.m_state=%d)"
	   " sender = (Block: %d Node: %d)",
           tFirstDataPtr,
	   tSignalNumber,
	   tWaitState,
	   refToBlock(aSignal->theSendersBlockRef),
	   refToNode(aSignal->theSendersBlockRef));
#endif
#ifdef NDB_NO_DROPPED_SIGNAL
  abort();
#endif
  
  return;
}//Ndb::handleReceivedSignal()