Exemple #1
0
void
SimpleSignal::set(class SignalSender& ss,
                  Uint8  trace, Uint16 recBlock, Uint16 gsn, Uint32 len)
{
    header.set(trace, recBlock, gsn, len);
    header.theSendersBlockRef      = refToBlock(ss.getOwnRef());
}
Exemple #2
0
bool Dbinfo::find_next(Ndbinfo::ScanCursor* cursor) const
{
  Uint32 node = refToNode(cursor->currRef);
  Uint32 block = refToBlock(cursor->currRef);
  const Uint32 instance = refToInstance(cursor->currRef);
  ndbrequire(instance == 0);

  if (node == 0)
  {
    jam();
    // First 'find_next'
    ndbrequire(block == 0);
    cursor->currRef = switchRef(dbinfo_blocks[0], getOwnNodeId());
    return true;
  }

  if (block)
  {
    jam();
    // Find next block
    ndbrequire(node == getOwnNodeId());
    block = find_next_block(block);
    if (block)
    {
      jam();
      cursor->currRef = switchRef(block, node);
      return true;
    }
  }

  // Nothing more to scan
  cursor->currRef = 0;
  return false;
}
SignalSender::SignalSender(TransporterFacade *facade, int blockNo)
{
  theFacade = facade;
  Uint32 res = open(theFacade, blockNo);
  assert(res != 0);
  m_blockNo = refToBlock(res);
}
Exemple #4
0
bool
printPREPFAILREQREF(FILE * output, 
		    const Uint32 * theData, 
		    Uint32 len, 
		    Uint16 receiverBlockNo){
  
  PrepFailReqRef * cc = (PrepFailReqRef*)theData;

  fprintf(output, " xxxBlockRef = (%d, %d) failNo = %d noOfNodes = %d\n",
	  refToBlock(cc->xxxBlockRef), refToNode(cc->xxxBlockRef),
	  cc->failNo, cc->noOfNodes);
  
  int hits = 0;
  fprintf(output, " Nodes: ");
  for(int i = 0; i<MAX_NODES; i++){
    if(NodeBitmask::get(cc->theNodes, i)){
      hits++;
      fprintf(output, " %d", i);
    }
    if(hits == 16){
      fprintf(output, "\n Nodes: ");
      hits = 0;
    }
  }
  if(hits != 0)
    fprintf(output, "\n");

  return true;
}
void
Dbtup::checkImmediateTriggersAfterUpdate(KeyReqStruct *req_struct,
                                         Operationrec* regOperPtr, 
                                         Tablerec* regTablePtr,
                                         bool disk)
{
  if(refToBlock(req_struct->TC_ref) != DBTC) {
    return;
  }

  if ((regOperPtr->op_struct.primary_replica) &&
      (!(regTablePtr->afterUpdateTriggers.isEmpty()))) {
    jam();
    fireImmediateTriggers(req_struct,
                          regTablePtr->afterUpdateTriggers,
                          regOperPtr,
                          disk);
  }
  if ((regOperPtr->op_struct.primary_replica) &&
      (!(regTablePtr->constraintUpdateTriggers.isEmpty()))) {
    jam();
    fireImmediateTriggers(req_struct,
                          regTablePtr->constraintUpdateTriggers,
                          regOperPtr,
                          disk);
  }
}
Exemple #6
0
void Ndb::connected(Uint32 ref)
{
// cluster connect, a_node == own reference
  theMyRef= ref;
  Uint32 tmpTheNode= refToNode(ref);
  Uint64 tBlockNo= refToBlock(ref);
  if (theNdbBlockNumber >= 0){
    assert(theMyRef == numberToRef(theNdbBlockNumber, tmpTheNode));
  }
  
  Uint32 cnt =
    theImpl->m_ndb_cluster_connection.get_db_nodes(theImpl->theDBnodes);
  theImpl->theNoOfDBnodes = cnt;
  
  theFirstTransId += ((Uint64)tBlockNo << 52)+
    ((Uint64)tmpTheNode << 40);
  //      assert(0);
  DBUG_PRINT("info",("connected with ref=%x, id=%d, no_db_nodes=%d, first_trans_id: 0x%lx",
		     theMyRef,
		     tmpTheNode,
		     theImpl->theNoOfDBnodes,
		     (long) theFirstTransId));
  theCommitAckSignal = new NdbApiSignal(theMyRef);

  theDictionary->m_receiver.m_reference= theMyRef;
  theNode= tmpTheNode; // flag that Ndb object is initialized
}
SignalSender::SignalSender(Ndb_cluster_connection* connection)
{
  theFacade = connection->m_impl.m_transporter_facade;
  Uint32 res = open(theFacade, -1);
  assert(res != 0);
  m_blockNo = refToBlock(res);
}
void
PgmanProxy::execEND_LCP_REQ(Signal* signal)
{
  const EndLcpReq* req = (const EndLcpReq*)signal->getDataPtr();
  Uint32 ssId = getSsId(req);
  Ss_END_LCP_REQ& ss = ssSeize<Ss_END_LCP_REQ>(ssId);
  ss.m_req = *req;

  const Uint32 sb = refToBlock(ss.m_req.senderRef);
  ndbrequire(sb == DBLQH || sb == LGMAN);

  if (sb == LGMAN) {
    jam();
    /*
     * At end of UNDO execution.  Extra PGMAN worker was used to
     * read up TUP pages.  Release these pages now.
     */
    ReleasePagesReq* req = (ReleasePagesReq*)signal->getDataPtrSend();
    req->senderData = ssId;
    req->senderRef = reference();
    req->requestType = ReleasePagesReq::RT_RELEASE_UNLOCKED;
    req->requestData = 0;
    sendSignal(extraWorkerRef(), GSN_RELEASE_PAGES_REQ,
               signal, ReleasePagesReq::SignalLength, JBB);
    return;
  }
  sendREQ(signal, ss);
}
Exemple #9
0
inline
NodeReceiverGroup& 
NodeReceiverGroup::operator=(BlockReference blockRef){
  m_nodes.clear();
  m_block = refToBlock(blockRef);
  m_nodes.set(refToNode(blockRef));
  return * this;
}
/*
 * Set index online.  Currently at system restart this arrives before
 * build and is therefore not correct.
 */
void
Dbtux::execALTER_INDX_IMPL_REQ(Signal* signal)
{
  jamEntry();
  const AlterIndxImplReq reqCopy = *(const AlterIndxImplReq*)signal->getDataPtr();
  const AlterIndxImplReq* const req = &reqCopy;

  IndexPtr indexPtr;
  c_indexPool.getPtr(indexPtr, req->indexId);

  //Uint32 save = indexPtr.p->m_state;
  if (! (refToBlock(req->senderRef) == DBDICT) &&
      ! (isNdbMt() && refToMain(req->senderRef) == DBTUX && 
         refToInstance(req->senderRef) == 0))
  {
    /**
     * DICT has a really distorted view of the world...
     *   ignore it :(
     */
    jam();
    switch(req->requestType){
    case AlterIndxImplReq::AlterIndexOffline:
      jam();
      /*
       * This happens at failed index build, and before dropping an
       * Online index.  It causes scans to terminate.
       */
      indexPtr.p->m_state = Index::Dropping;
      break;
    case AlterIndxImplReq::AlterIndexBuilding:
      jam();
      indexPtr.p->m_state = Index::Building;
      break;
    default:
      jam(); // fall-through
    case AlterIndxImplReq::AlterIndexOnline:
      jam();
      indexPtr.p->m_state = Index::Online;
      break;
    }
  }
  
  // success
  AlterIndxImplConf* const conf = (AlterIndxImplConf*)signal->getDataPtrSend();
  conf->senderRef = reference();
  conf->senderData = req->senderData;
  if (req->senderRef != 0)
  {
    /**
     * TUP cheats and does execute direct
     *   setting UserRef to 0
     */
    jam();
    sendSignal(req->senderRef, GSN_ALTER_INDX_IMPL_CONF,
               signal, AlterIndxImplConf::SignalLength, JBB);
  }
}
void
checkData(SignalHeader * const header, Uint8 prio, Uint32 * const theData,
	  LinearSectionPtr ptr[3]){
  Uint32 expectedLength = 0;
  if(prio == 0)
    expectedLength = 17;
  else
    expectedLength = 19;

  if(header->theLength != expectedLength){
    ndbout << "Unexpected signal length: " << header->theLength 
	   << " expected: " << expectedLength << endl;
    abort();
  }

  if(header->theVerId_signalNumber != expectedLength + 1)
    abort();

  if(header->theReceiversBlockNumber != expectedLength + 2)
    abort();

  if(refToBlock(header->theSendersBlockRef) != expectedLength + 3)
    abort();

  if(header->theSendersSignalId != expectedLength + 5)
    abort();

  if(header->theTrace != expectedLength + 6)
    abort();

  if(header->m_noOfSections != (prio == 0 ? 0 : 1))
    abort();

  if(header->m_fragmentInfo != (prio + 1))
    abort();
  
  Uint32 dataWordStart = header->theLength ;
  for(unsigned i = 0; i<header->theLength; i++){
    if(theData[i] != i){ //dataWordStart){
      ndbout << "data corrupt!\n" << endl;
      abort();
    }
    dataWordStart ^= (~i*i);
  }

  if(prio != 0){
    ndbout_c("Found section");
    if(ptr[0].sz != header->theLength)
      abort();

    if(memcmp(ptr[0].p, theData, (ptr[0].sz * 4)) != 0)
      abort();
  }
}
bool
printAPI_VERSION_CONF(FILE * output,
                      const Uint32 * theData,
                      Uint32 len,
                      Uint16 recBlockNo){

  ApiVersionConf * sig = (ApiVersionConf *)&theData[0];

  fprintf(output,
          " senderRef: (node: %d, block: %d), nodeId: %d\n" \
          " version: %d, mysql_version: %d, inet_addr: %d\n",
	  refToNode(sig->senderRef), refToBlock(sig->senderRef),
	  sig->nodeId, sig->version, sig->mysql_version, sig->inet_addr);
  return true;
}
Exemple #13
0
/******************************************************************************
NdbApiSignal();

Return Value:   None
Remark:         Creates a NdbApiSignal object.
******************************************************************************/
NdbApiSignal::NdbApiSignal(BlockReference ref)
{
    theVerId_signalNumber   = 0;    // 4 bit ver id - 16 bit gsn
    theReceiversBlockNumber = 0;  // Only 16 bit blocknum
    theSendersBlockRef      = refToBlock(ref);
    theLength               = 0;
    theSendersSignalId      = 0;
    theSignalId             = 0;
    theTrace                = 0;
    m_noOfSections          = 0;
    m_fragmentInfo          = 0;
    for (int i = 0; i < 25; i++)
        theData[i] = 0x13579753;

    setDataPtr(&theData[0]);
    theNextSignal = 0;
}
bool
printSTART_REC_REQ(FILE * output, 
		  const Uint32 * theData, 
		  Uint32 len, 
		  Uint16 recBlockNo){
  StartRecReq * sig = (StartRecReq *) theData;

  fprintf(output, " receivingNodeId: %d senderRef: (%d, %d)\n",
	  sig->receivingNodeId, 
	  refToNode(sig->senderRef),
	  refToBlock(sig->senderRef));
  
  fprintf(output, " keepGci: %d lastCompletedGci: %d newestGci: %d\n",
	  sig->keepGci, 
	  sig->lastCompletedGci,
	  sig->newestGci);

  return true;
}
void
Dbtup::execDROP_TRIG_REQ(Signal* signal)
{
  jamEntry();
  BlockReference senderRef = signal->getSendersBlockRef();
  const DropTrigReq reqCopy = *(const DropTrigReq*)signal->getDataPtr();
  const DropTrigReq* const req = &reqCopy;

  // Find table
  TablerecPtr tabPtr;
  tabPtr.i = req->getTableId();
  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);

  // Drop trigger
  Uint32 r = dropTrigger(tabPtr.p, req, refToBlock(senderRef));
  if (r == 0){
    // Send conf
    DropTrigConf* const conf = (DropTrigConf*)signal->getDataPtrSend();
    conf->setUserRef(senderRef);
    conf->setConnectionPtr(req->getConnectionPtr());
    conf->setRequestType(req->getRequestType());
    conf->setTableId(req->getTableId());
    conf->setIndexId(req->getIndexId());
    conf->setTriggerId(req->getTriggerId());
    sendSignal(senderRef, GSN_DROP_TRIG_CONF, 
	       signal, DropTrigConf::SignalLength, JBB);
  } else {
    // Send ref
    DropTrigRef* const ref = (DropTrigRef*)signal->getDataPtrSend();
    ref->setUserRef(senderRef);
    ref->setConnectionPtr(req->getConnectionPtr());
    ref->setRequestType(req->getRequestType());
    ref->setTableId(req->getTableId());
    ref->setIndexId(req->getIndexId());
    ref->setTriggerId(req->getTriggerId());
    ref->setErrorCode((DropTrigRef::ErrorCode)r);
    ref->setErrorLine(__LINE__);
    ref->setErrorNode(refToNode(reference()));
    sendSignal(senderRef, GSN_DROP_TRIG_REF, 
	       signal, DropTrigRef::SignalLength, JBB);
  }
}//Dbtup::DROP_TRIG_REQ()
void Dbtup::storedProcCountNonAPI(BlockReference apiBlockref, int add_del)
{
  BlockNumber apiBlockno = refToBlock(apiBlockref);
  if (apiBlockno < MIN_API_BLOCK_NO) {
    ndbassert(blockToMain(apiBlockno) == BACKUP ||
              blockToMain(apiBlockno) == SUMA ||
              blockToMain(apiBlockno) == DBLQH ||
              blockToMain(apiBlockno) == DBSPJ);
    if (add_del == +1) {
      jam();
      c_storedProcCountNonAPI++;
    } else if (add_del == -1) {
      jam();
      ndbassert(c_storedProcCountNonAPI > 0);
      c_storedProcCountNonAPI--;
    } else {
      ndbassert(false);
    }
  }
}
Uint32
trp_client::open(TransporterFacade* tf, int blockNo)
{
  Uint32 res = 0;
  assert(m_facade == 0);
  if (m_facade == 0)
  {
    m_facade = tf;
    res = tf->open_clnt(this, blockNo);
    if (res != 0)
    {
      m_blockNo = refToBlock(res);
    }
    else
    {
      m_facade = 0;
    }
  }
  return res;
}
bool 
printFIRE_TRIG_ORD(FILE * output, const Uint32 * theData, Uint32 len, 
		   Uint16 receiverBlockNo)
{
  const FireTrigOrd * const sig = (FireTrigOrd *) theData;

  fprintf(output, " TriggerId: %d TriggerEvent: %s\n",
	  sig->getTriggerId(),
	  trigEvent(sig->getTriggerEvent()));
  fprintf(output, " UserRef: (%d, %d) User data: %x\n",
	  refToNode(sig->getUserRef()),
	  refToBlock(sig->getUserRef()),
	  sig->getConnectionPtr());
  fprintf(output, " Signal: PK=%d BEFORE=%d AFTER=%d\n",
	  sig->getNoOfPrimaryKeyWords(),
	  sig->getNoOfBeforeValueWords(),
	  sig->getNoOfAfterValueWords());
  
  return true;
}
Exemple #19
0
void Dbtup::bufferTRANSID_AI(Signal* signal, BlockReference aRef,
                             Uint32 Tlen)
{
  if (Tlen == 3)
    return;
  
  Uint32 hostId= refToNode(aRef);
  Uint32 Theader= ((refToBlock(aRef) << 16)+(Tlen-3));
  
  ndbrequire(hostId < MAX_NODES);
  Uint32 TpacketLen= hostBuffer[hostId].packetLenTA;
  Uint32 TnoOfPackets= hostBuffer[hostId].noOfPacketsTA;
  Uint32 sig0= signal->theData[0];
  Uint32 sig1= signal->theData[1];
  Uint32 sig2= signal->theData[2];

  BlockReference TBref= numberToRef(API_PACKED, hostId);

  if ((Tlen + TpacketLen + 1) <= 25) {
// ----------------------------------------------------------------
// There is still space in the buffer. We will copy it into the
// buffer.
// ----------------------------------------------------------------
    jam();
    updatePackedList(signal, hostId);
  } else if (false && TnoOfPackets == 1) {
// ----------------------------------------------------------------
// The buffer is full and there was only one packet buffered. We
// will send this as a normal signal.
// ----------------------------------------------------------------
    Uint32 TnewRef= numberToRef((hostBuffer[hostId].packetBufferTA[0] >> 16),
                                 hostId);
    MEMCOPY_NO_WORDS(&signal->theData[0],
                     &hostBuffer[hostId].packetBufferTA[1],
                     TpacketLen - 1);
    sendSignal(TnewRef, GSN_TRANSID_AI, signal, (TpacketLen - 1), JBB);
    TpacketLen= 0;
    TnoOfPackets= 0;
  } else {
Exemple #20
0
void AsyncFile::openReq(Request* request)
{  
  m_auto_sync_freq = 0;
  m_write_wo_sync = 0;
  m_open_flags = request->par.open.flags;

  // for open.flags, see signal FSOPENREQ
#ifdef NDB_WIN32
  DWORD dwCreationDisposition;
  DWORD dwDesiredAccess = 0;
  DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
  DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_NO_BUFFERING;
  Uint32 flags = request->par.open.flags;
    
    // Convert file open flags from Solaris to Windows
  if ((flags & FsOpenReq::OM_CREATE) && (flags & FsOpenReq::OM_TRUNCATE)){
    dwCreationDisposition = CREATE_ALWAYS;
  } else if (flags & FsOpenReq::OM_TRUNCATE){
    dwCreationDisposition = TRUNCATE_EXISTING;
  } else if (flags & FsOpenReq::OM_CREATE){
    dwCreationDisposition = CREATE_NEW;
  } else {
    dwCreationDisposition = OPEN_EXISTING;
  }
  
  switch(flags & 3){
  case FsOpenReq::OM_READONLY:
    dwDesiredAccess = GENERIC_READ;
    break;
  case FsOpenReq::OM_WRITEONLY:
    dwDesiredAccess = GENERIC_WRITE;
    break;
  case FsOpenReq::OM_READWRITE:
    dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
    break;
  default:
    request->error = 1000;
    break;
    return;
  }

  hFile = CreateFile(theFileName.c_str(), dwDesiredAccess, dwShareMode, 
                     0, dwCreationDisposition, dwFlagsAndAttributes, 0);
    
  if(INVALID_HANDLE_VALUE == hFile) {
    request->error = GetLastError();
    if(((ERROR_PATH_NOT_FOUND == request->error) || (ERROR_INVALID_NAME == request->error))
       && (flags & FsOpenReq::OM_CREATE)) {
      createDirectories();
      hFile = CreateFile(theFileName.c_str(), dwDesiredAccess, dwShareMode, 
                         0, dwCreationDisposition, dwFlagsAndAttributes, 0);
            
      if(INVALID_HANDLE_VALUE == hFile)
        request->error = GetLastError();
      else
        request->error = 0;
            
      return;
    }
  } 
  else {
    request->error = 0;
    return;
  }
#else
  Uint32 flags = request->par.open.flags;
  int new_flags = 0;

  // Convert file open flags from Solaris to Liux
  if (flags & FsOpenReq::OM_CREATE)
  {
    new_flags |= O_CREAT;
  }
  
  if (flags & FsOpenReq::OM_TRUNCATE){
#if 0
    if(Global_unlinkO_CREAT){
      unlink(theFileName.c_str());
    } else 
#endif
      new_flags |= O_TRUNC;
  }  

  if (flags & FsOpenReq::OM_AUTOSYNC)
  {
    m_auto_sync_freq = request->par.open.auto_sync_size;
  }

  if (flags & FsOpenReq::OM_APPEND){
    new_flags |= O_APPEND;
  }

  if (flags & FsOpenReq::OM_DIRECT) 
#ifdef O_DIRECT
  {
    new_flags |= O_DIRECT;
  }
#endif
  
  if ((flags & FsOpenReq::OM_SYNC) && ! (flags & FsOpenReq::OM_INIT))
  {
#ifdef O_SYNC
    new_flags |= O_SYNC;
#endif
  }

  const char * rw = "";
  switch(flags & 0x3){
  case FsOpenReq::OM_READONLY:
    rw = "r";
    new_flags |= O_RDONLY;
    break;
  case FsOpenReq::OM_WRITEONLY:
    rw = "w";
    new_flags |= O_WRONLY;
    break;
  case FsOpenReq::OM_READWRITE:
    rw = "rw";
    new_flags |= O_RDWR;
    break;
  default:
    request->error = 1000;
    break;
    return;
  }

  // allow for user to choose any permissionsa with umask
  const int mode = S_IRUSR | S_IWUSR |
	           S_IRGRP | S_IWGRP |
		   S_IROTH | S_IWOTH;
  if (flags & FsOpenReq::OM_CREATE_IF_NONE)
  {
    Uint32 tmp_flags = new_flags;
#ifdef O_DIRECT
    tmp_flags &= ~O_DIRECT;
#endif
    if ((theFd = ::open(theFileName.c_str(), tmp_flags, mode)) != -1) 
    {
      close(theFd);
      request->error = FsRef::fsErrFileExists;      
      return;
    }
    new_flags |= O_CREAT;
  }

no_odirect:
  if (-1 == (theFd = ::open(theFileName.c_str(), new_flags, mode))) 
  {
    PRINT_ERRORANDFLAGS(new_flags);
    if ((errno == ENOENT) && (new_flags & O_CREAT)) 
    {
      createDirectories();
      if (-1 == (theFd = ::open(theFileName.c_str(), new_flags, mode))) 
      {
#ifdef O_DIRECT
	if (new_flags & O_DIRECT)
	{
	  new_flags &= ~O_DIRECT;
	  goto no_odirect;
	}
#endif
        PRINT_ERRORANDFLAGS(new_flags);
        request->error = errno;
	return;
      }
    }
#ifdef O_DIRECT
    else if (new_flags & O_DIRECT)
    {
      new_flags &= ~O_DIRECT;
      goto no_odirect;
    }
#endif
    else
    {
      request->error = errno;
      return;
    }
  }
  
  if (flags & FsOpenReq::OM_CHECK_SIZE)
  {
    struct stat buf;
    if ((fstat(theFd, &buf) == -1))
    {
      request->error = errno;
    } 
    else if((Uint64)buf.st_size != request->par.open.file_size)
    {
      request->error = FsRef::fsErrInvalidFileSize;
    }
    if (request->error)
      return;
  }
  
  if (flags & FsOpenReq::OM_INIT)
  {
    off_t off = 0;
    const off_t sz = request->par.open.file_size;
    Uint32 tmp[sizeof(SignalHeader)+25];
    Signal * signal = (Signal*)(&tmp[0]);
    FsReadWriteReq* req = (FsReadWriteReq*)signal->getDataPtrSend();

    Uint32 index = 0;
    Uint32 block = refToBlock(request->theUserReference);

#ifdef HAVE_XFS_XFS_H
    if(platform_test_xfs_fd(theFd))
    {
      ndbout_c("Using xfsctl(XFS_IOC_RESVSP64) to allocate disk space");
      xfs_flock64_t fl;
      fl.l_whence= 0;
      fl.l_start= 0;
      fl.l_len= (off64_t)sz;
      if(xfsctl(NULL, theFd, XFS_IOC_RESVSP64, &fl) < 0)
        ndbout_c("failed to optimally allocate disk space");
    }
#endif
#ifdef HAVE_POSIX_FALLOCATE
    posix_fallocate(theFd, 0, sz);
#endif

    while(off < sz)
    {
      req->filePointer = 0;          // DATA 0
      req->userPointer = request->theUserPointer;          // DATA 2
      req->numberOfPages = 1;        // DATA 5  
      req->varIndex = index++;
      req->data.pageData[0] = m_page_ptr.i;

      m_fs.EXECUTE_DIRECT(block, GSN_FSWRITEREQ, signal, 
			  FsReadWriteReq::FixedLength + 1);
  retry:
      Uint32 size = request->par.open.page_size;
      char* buf = (char*)m_page_ptr.p;
      while(size > 0){
	const int n = write(theFd, buf, size);
	if(n == -1 && errno == EINTR)
	{
	  continue;
	}
	if(n == -1 || n == 0)
	{
	  break;
	}
	size -= n;
	buf += n;
      }
      if(size != 0)
      {
	int err = errno;
#ifdef O_DIRECT
	if ((new_flags & O_DIRECT) && off == 0)
	{
	  ndbout_c("error on first write(%d), disable O_DIRECT", err);
	  new_flags &= ~O_DIRECT;
	  close(theFd);
	  theFd = ::open(theFileName.c_str(), new_flags, mode);
	  if (theFd != -1)
	    goto retry;
	}
#endif
	close(theFd);
	unlink(theFileName.c_str());
	request->error = err;
	return;
      }
      off += request->par.open.page_size;
    }
    if(lseek(theFd, 0, SEEK_SET) != 0)
      request->error = errno;
  }
  else if (flags & FsOpenReq::OM_DIRECT)
  {
#ifdef O_DIRECT
    if (flags & (FsOpenReq::OM_TRUNCATE | FsOpenReq::OM_CREATE))
    {
      request->error = check_odirect_write(flags, new_flags, mode);
    }
    else
    {
      request->error = check_odirect_read(flags, new_flags, mode);
    }
    
    if (request->error)
      return;
#endif
  }
#ifdef VM_TRACE
  if (flags & FsOpenReq::OM_DIRECT)
  {
#ifdef O_DIRECT
    ndbout_c("%s %s O_DIRECT: %d",
             theFileName.c_str(), rw,
             !!(new_flags & O_DIRECT));
#else
    ndbout_c("%s %s O_DIRECT: 0",
             theFileName.c_str(), rw);
#endif
  }
#endif  
  if ((flags & FsOpenReq::OM_SYNC) && (flags & FsOpenReq::OM_INIT))
  {
#ifdef O_SYNC
    /**
     * reopen file with O_SYNC
     */
    close(theFd);
    new_flags &= ~(O_CREAT | O_TRUNC);
    new_flags |= O_SYNC;
    theFd = ::open(theFileName.c_str(), new_flags, mode);
    if (theFd == -1)
    {
      request->error = errno;
    }
#endif
  }
#endif
}
Exemple #21
0
/**
 * We're holding the trp_client lock while performing poll from
 * ClusterMgr. So we always execute all the execSIGNAL-methods in
 * ClusterMgr with protection other methods that use the trp_client
 * lock (reportDisconnect, reportConnect, is_cluster_completely_unavailable,
 * ArbitMgr (sendSignalToQmgr)).
 */
void
ClusterMgr::trp_deliver_signal(const NdbApiSignal* sig,
                               const LinearSectionPtr ptr[3])
{
    const Uint32 gsn = sig->theVerId_signalNumber;
    const Uint32 * theData = sig->getDataPtr();

    switch (gsn) {
    case GSN_API_REGREQ:
        execAPI_REGREQ(theData);
        break;

    case GSN_API_REGCONF:
        execAPI_REGCONF(sig, ptr);
        break;

    case GSN_API_REGREF:
        execAPI_REGREF(theData);
        break;

    case GSN_NODE_FAILREP:
        execNODE_FAILREP(sig, ptr);
        break;

    case GSN_NF_COMPLETEREP:
        execNF_COMPLETEREP(sig, ptr);
        break;
    case GSN_ARBIT_STARTREQ:
        if (theArbitMgr != NULL)
            theArbitMgr->doStart(theData);
        break;

    case GSN_ARBIT_CHOOSEREQ:
        if (theArbitMgr != NULL)
            theArbitMgr->doChoose(theData);
        break;

    case GSN_ARBIT_STOPORD:
        if(theArbitMgr != NULL)
            theArbitMgr->doStop(theData);
        break;

    case GSN_ALTER_TABLE_REP:
    {
        if (theFacade.m_globalDictCache == NULL)
            break;
        const AlterTableRep* rep = (const AlterTableRep*)theData;
        theFacade.m_globalDictCache->lock();
        theFacade.m_globalDictCache->
        alter_table_rep((const char*)ptr[0].p,
                        rep->tableId,
                        rep->tableVersion,
                        rep->changeType == AlterTableRep::CT_ALTERED);
        theFacade.m_globalDictCache->unlock();
        break;
    }
    case GSN_SUB_GCP_COMPLETE_REP:
    {
        /**
         * Report
         */
        theFacade.for_each(this, sig, ptr);

        /**
         * Reply
         */
        {
            BlockReference ownRef = numberToRef(API_CLUSTERMGR, theFacade.ownId());
            NdbApiSignal tSignal(* sig);
            Uint32* send= tSignal.getDataPtrSend();
            memcpy(send, theData, tSignal.getLength() << 2);
            CAST_PTR(SubGcpCompleteAck, send)->rep.senderRef = ownRef;
            Uint32 ref= sig->theSendersBlockRef;
            Uint32 aNodeId= refToNode(ref);
            tSignal.theReceiversBlockNumber= refToBlock(ref);
            tSignal.theVerId_signalNumber= GSN_SUB_GCP_COMPLETE_ACK;
            tSignal.theSendersBlockRef = API_CLUSTERMGR;
            safe_noflush_sendSignal(&tSignal, aNodeId);
        }
        break;
    }
    case GSN_TAKE_OVERTCCONF:
    {
        /**
         * Report
         */
        theFacade.for_each(this, sig, ptr);
        return;
    }
    case GSN_CONNECT_REP:
    {
        execCONNECT_REP(sig, ptr);
        return;
    }
    case GSN_DISCONNECT_REP:
    {
        execDISCONNECT_REP(sig, ptr);
        return;
    }
    case GSN_CLOSE_COMREQ:
    {
        theFacade.perform_close_clnt(this);
        return;
    }
    case GSN_EXPAND_CLNT:
    {
        theFacade.expand_clnt();
        return;
    }
    default:
        break;

    }
    return;
}
Exemple #22
0
void 
Ndbfs::execFSAPPENDREQ(Signal * signal)
{
  const FsAppendReq * const fsReq = (FsAppendReq *)&signal->theData[0];
  const Uint16 filePointer =  (Uint16)fsReq->filePointer;
  const UintR userPointer = fsReq->userPointer; 
  const BlockReference userRef = fsReq->userReference;
  const BlockNumber blockNumber = refToBlock(userRef);

  FsRef::NdbfsErrorCodeType errorCode;

  AsyncFile* openFile = theOpenFiles.find(filePointer);
  const NewVARIABLE *myBaseAddrRef = &getBat(blockNumber)[fsReq->varIndex];

  const Uint32* tWA   = (const Uint32*)myBaseAddrRef->WA;
  const Uint32  tSz   = myBaseAddrRef->nrr;
  const Uint32 offset = fsReq->offset;
  const Uint32 size   = fsReq->size;
  const Uint32 synch_flag = fsReq->synch_flag;
  Request *request = theRequestPool->get();

  if (openFile == NULL) {
    jam();
    errorCode = FsRef::fsErrFileDoesNotExist;
    goto error;
  }

  if (myBaseAddrRef == NULL) {
    jam(); // Ensure that a valid variable is used
    errorCode = FsRef::fsErrInvalidParameters;
    goto error;
  }
  
  if (fsReq->varIndex >= getBatSize(blockNumber)) {
    jam();// Ensure that a valid variable is used    
    errorCode = FsRef::fsErrInvalidParameters;
    goto error;
  }
  
  if(offset + size > tSz){
    jam(); // Ensure that a valid variable is used
    errorCode = FsRef::fsErrInvalidParameters;
    goto error;
  }

  request->error = 0;
  request->set(userRef, userPointer, filePointer);
  request->file = openFile;
  request->theTrace = signal->getTrace();
  
  request->par.append.buf = (const char *)(tWA + offset);
  request->par.append.size = size << 2;

  if (!synch_flag)
    request->action = Request::append;
  else
    request->action = Request::append_synch;
  ndbrequire(forward(openFile, request));
  return;
  
error:
  jam();
  theRequestPool->put(request);
  FsRef * const fsRef = (FsRef *)&signal->theData[0];
  fsRef->userPointer = userPointer;
  fsRef->setErrorCode(fsRef->errorCode, errorCode);
  fsRef->osErrorCode = ~0; // Indicate local error

  jam();
  sendSignal(userRef, GSN_FSAPPENDREF, signal, 3, JBB);
  return;
}
Exemple #23
0
void 
Filename::set(Filename::NameSpec& spec,
	      BlockReference blockReference, 
	      const Uint32 filenumber[4], bool dir) 
{
  char buf[PATH_MAX];

  const Uint32 type = FsOpenReq::getSuffix(filenumber);
  const Uint32 version = FsOpenReq::getVersion(filenumber);

  size_t sz;
  if (version == 2)
  {
    sz = BaseString::snprintf(theName, sizeof(theName), "%s", 
         spec.backup_path.c_str());
    m_base_name = theName + spec.backup_path.length();
  }
  else
  {
    sz = BaseString::snprintf(theName, sizeof(theName), "%s", 
         spec.fs_path.c_str());
    m_base_name = theName + spec.fs_path.length();
  }
  
  switch(version){
  case 1 :{
    const Uint32 diskNo = FsOpenReq::v1_getDisk(filenumber);
    const Uint32 table  = FsOpenReq::v1_getTable(filenumber);
    const Uint32 frag   = FsOpenReq::v1_getFragment(filenumber);
    const Uint32 S_val  = FsOpenReq::v1_getS(filenumber);
    const Uint32 P_val  = FsOpenReq::v1_getP(filenumber);

    if (diskNo < 0xff){	  
      BaseString::snprintf(buf, sizeof(buf), "D%d%s", diskNo, DIR_SEPARATOR);
      strcat(theName, buf);
    }
    
    {
      const char* blockName = getBlockName( refToBlock(blockReference) );
      if (blockName == NULL){
	ERROR_SET(ecError, NDBD_EXIT_AFS_PARAMETER,"","No Block Name");
	return;
      }
      BaseString::snprintf(buf, sizeof(buf), "%s%s", blockName, DIR_SEPARATOR);
      strcat(theName, buf);
    }
    
    if (table < 0xffffffff){
      BaseString::snprintf(buf, sizeof(buf), "T%d%s", table, DIR_SEPARATOR);
      strcat(theName, buf);
    }
    
    if (frag < 0xffffffff){
      BaseString::snprintf(buf, sizeof(buf), "F%d%s", frag, DIR_SEPARATOR);
      strcat(theName, buf);
    }
    
    
    if (S_val < 0xffffffff){
      BaseString::snprintf(buf, sizeof(buf), "S%d", S_val);
      strcat(theName, buf);
    }

    if (P_val < 0xff){
      BaseString::snprintf(buf, sizeof(buf), "P%d", P_val);
      strcat(theName, buf);
    }
    
  }
  break;
  case 2:{
    const Uint32 seq = FsOpenReq::v2_getSequence(filenumber);
    const Uint32 nodeId = FsOpenReq::v2_getNodeId(filenumber);
    const Uint32 count = FsOpenReq::v2_getCount(filenumber);
    
    BaseString::snprintf(buf, sizeof(buf), "BACKUP%sBACKUP-%d%s",
	     DIR_SEPARATOR, seq, DIR_SEPARATOR); 
    strcat(theName, buf);
    if(count == 0xffffffff) {
      BaseString::snprintf(buf, sizeof(buf), "BACKUP-%d.%d",
	       seq, nodeId); strcat(theName, buf);
    } else {
      BaseString::snprintf(buf, sizeof(buf), "BACKUP-%d-%d.%d",
	       seq, count, nodeId); strcat(theName, buf);
    }
    break;
  }
  break;
  case 3:{
    const Uint32 diskNo = FsOpenReq::v1_getDisk(filenumber);

    if(diskNo == 0xFF){
      ERROR_SET(ecError, NDBD_EXIT_AFS_PARAMETER,"","Invalid disk specification");
    }

    BaseString::snprintf(buf, sizeof(buf), "D%d%s", diskNo, DIR_SEPARATOR);
    strcat(theName, buf);
  }
    break;
  case 5:
  {
    Uint32 tableId = FsOpenReq::v5_getTableId(filenumber);
    Uint32 lcpNo = FsOpenReq::v5_getLcpNo(filenumber);
    Uint32 fragId = FsOpenReq::v5_getFragmentId(filenumber);
    BaseString::snprintf(buf, sizeof(buf), "LCP/%d/T%dF%d", lcpNo, tableId, fragId);
    strcat(theName, buf);
    break;
  }
  default:
    ERROR_SET(ecError, NDBD_EXIT_AFS_PARAMETER,"","Wrong version");
  }
  if (type >= noOfExtensions){
    ERROR_SET(ecError, NDBD_EXIT_AFS_PARAMETER,"","File Type doesn't exist");
    return;
  }
  strcat(theName, fileExtension[type]);
  
  if(dir == true){
    for(int l = strlen(theName) - 1; l >= 0; l--){
      if(theName[l] == DIR_SEPARATOR[0]){
	theName[l] = 0;
	break;
      }
    }
  }
}
Exemple #24
0
void 
Ndbfs::readWriteRequest(int action, Signal * signal)
{
  const FsReadWriteReq * const fsRWReq = (FsReadWriteReq *)&signal->theData[0];
  Uint16 filePointer =  (Uint16)fsRWReq->filePointer;
  const UintR userPointer = fsRWReq->userPointer; 
  const BlockReference userRef = fsRWReq->userReference;
  const BlockNumber blockNumber = refToBlock(userRef);

  AsyncFile* openFile = theOpenFiles.find(filePointer);

  const NewVARIABLE *myBaseAddrRef = &getBat(blockNumber)[fsRWReq->varIndex];
  UintPtr tPageSize;
  UintPtr tClusterSize;
  UintPtr tNRR;
  UintPtr tPageOffset;
  char*        tWA;
  FsRef::NdbfsErrorCodeType errorCode;

  Request *request = theRequestPool->get();
  request->error = 0;
  request->set(userRef, userPointer, filePointer);
  request->file = openFile;
  request->action = (Request::Action) action;
  request->theTrace = signal->getTrace();

  Uint32 format = fsRWReq->getFormatFlag(fsRWReq->operationFlag);

  if (fsRWReq->numberOfPages == 0) { //Zero pages not allowed
    jam();
    errorCode = FsRef::fsErrInvalidParameters;
    goto error;
  }

  if(format != FsReadWriteReq::fsFormatGlobalPage &&
     format != FsReadWriteReq::fsFormatSharedPage)
  {     
    if (fsRWReq->varIndex >= getBatSize(blockNumber)) {
      jam();// Ensure that a valid variable is used    
      errorCode = FsRef::fsErrInvalidParameters;
      goto error;
    }
    if (myBaseAddrRef == NULL) {
      jam(); // Ensure that a valid variable is used
      errorCode = FsRef::fsErrInvalidParameters;
      goto error;
    }
    if (openFile == NULL) {
      jam(); //file not open
      errorCode = FsRef::fsErrFileDoesNotExist;
      goto error;
    }
    tPageSize = pageSize(myBaseAddrRef);
    tClusterSize = myBaseAddrRef->ClusterSize;
    tNRR = myBaseAddrRef->nrr;
    tWA = (char*)myBaseAddrRef->WA;
    
    switch (format) {
      
      // List of memory and file pages pairs
    case FsReadWriteReq::fsFormatListOfPairs: { 
      jam();
      for (unsigned int i = 0; i < fsRWReq->numberOfPages; i++) {
	jam();
	const UintPtr varIndex = fsRWReq->data.listOfPair[i].varIndex;
	const UintPtr fileOffset = fsRWReq->data.listOfPair[i].fileOffset;
	if (varIndex >= tNRR) {
	  jam();
	  errorCode = FsRef::fsErrInvalidParameters;
	  goto error;
	}//if
	request->par.readWrite.pages[i].buf = &tWA[varIndex * tClusterSize];
	request->par.readWrite.pages[i].size = tPageSize;
	request->par.readWrite.pages[i].offset = fileOffset * tPageSize;
      }//for
      request->par.readWrite.numberOfPages = fsRWReq->numberOfPages;
      break;
    }//case
      
      // Range of memory page with one file page
    case FsReadWriteReq::fsFormatArrayOfPages: { 
      if ((fsRWReq->numberOfPages + fsRWReq->data.arrayOfPages.varIndex) > tNRR) {
        jam();
        errorCode = FsRef::fsErrInvalidParameters;
        goto error;
      }//if
      const UintPtr varIndex = fsRWReq->data.arrayOfPages.varIndex;
      const UintPtr fileOffset = fsRWReq->data.arrayOfPages.fileOffset;
      
      request->par.readWrite.pages[0].offset = fileOffset * tPageSize;
      request->par.readWrite.pages[0].size = tPageSize * fsRWReq->numberOfPages;
      request->par.readWrite.numberOfPages = 1;
      request->par.readWrite.pages[0].buf = &tWA[varIndex * tPageSize];
      break;
    }//case
      
      // List of memory pages followed by one file page
    case FsReadWriteReq::fsFormatListOfMemPages: { 
      
      tPageOffset = fsRWReq->data.listOfMemPages.varIndex[fsRWReq->numberOfPages];
      tPageOffset *= tPageSize;
      
      for (unsigned int i = 0; i < fsRWReq->numberOfPages; i++) {
	jam();
	UintPtr varIndex = fsRWReq->data.listOfMemPages.varIndex[i];
	
	if (varIndex >= tNRR) {
	  jam();
	  errorCode = FsRef::fsErrInvalidParameters;
	  goto error;
	}//if
	request->par.readWrite.pages[i].buf = &tWA[varIndex * tClusterSize];
	request->par.readWrite.pages[i].size = tPageSize;
	request->par.readWrite.pages[i].offset = tPageOffset + (i*tPageSize);
      }//for
      request->par.readWrite.numberOfPages = fsRWReq->numberOfPages;
      break;
      // make it a writev or readv
    }//case
      
    default: {
      jam();
      errorCode = FsRef::fsErrInvalidParameters;
      goto error;
    }//default
    }//switch
  } 
  else if (format == FsReadWriteReq::fsFormatGlobalPage)
  {
    Ptr<GlobalPage> ptr;
    m_global_page_pool.getPtr(ptr, fsRWReq->data.pageData[0]);
    request->par.readWrite.pages[0].buf = (char*)ptr.p;
    request->par.readWrite.pages[0].size = ((UintPtr)GLOBAL_PAGE_SIZE)*fsRWReq->numberOfPages;
    request->par.readWrite.pages[0].offset= ((UintPtr)GLOBAL_PAGE_SIZE)*fsRWReq->varIndex;
    request->par.readWrite.numberOfPages = 1;
  }
  else
  {
    ndbrequire(format == FsReadWriteReq::fsFormatSharedPage);
    Ptr<GlobalPage> ptr;
    m_shared_page_pool.getPtr(ptr, fsRWReq->data.pageData[0]);
    request->par.readWrite.pages[0].buf = (char*)ptr.p;
    request->par.readWrite.pages[0].size = ((UintPtr)GLOBAL_PAGE_SIZE)*fsRWReq->numberOfPages;
    request->par.readWrite.pages[0].offset= ((UintPtr)GLOBAL_PAGE_SIZE)*fsRWReq->varIndex;
    request->par.readWrite.numberOfPages = 1;
  }
  
  ndbrequire(forward(openFile, request));
  return;
  
error:
  theRequestPool->put(request);
  FsRef * const fsRef = (FsRef *)&signal->theData[0];
  fsRef->userPointer = userPointer;
  fsRef->setErrorCode(fsRef->errorCode, errorCode);
  fsRef->osErrorCode = ~0; // Indicate local error
  switch (action) {
  case Request:: write:
  case Request:: writeSync: {
    jam();
    sendSignal(userRef, GSN_FSWRITEREF, signal, 3, JBB);
    break;
  }//case
  case Request:: readPartial: 
  case Request:: read: {
    jam();
    sendSignal(userRef, GSN_FSREADREF, signal, 3, JBB);
  }//case
  }//switch
  return;
}
Exemple #25
0
int
main(void){

  srand(NdbTick_CurrentMillisecond());
#if 0
  for(int i = 0; i<100; i++)
    ndbout_c("randRange(0, 3) = %d", randRange(0, 3));
  return 0;
#endif
  SignalSender ss;
  
  ndbout << "Connecting...";
  if(!ss.connect(30)){
    ndbout << "failed" << endl << "Exiting" << endl;
    return 0;
  }
  ndbout << "done" << endl;
  ndbout_c("Connected as block=%d node=%d",
	   refToBlock(ss.getOwnRef()), refToNode(ss.getOwnRef()));
  
  Uint32 data[25];
  Uint32 sec0[70];
  Uint32 sec1[123];
  Uint32 sec2[10];
  
  data[0] = ss.getOwnRef();
  data[1] = 1;
  data[2] = 76; 
  data[3] = 1;
  data[4] = 1;
  data[5] = 70;
  data[6] = 123;
  data[7] = 10;
  const Uint32 theDataLen = 18;

  for(Uint32 i = 0; i<70; i++)
    sec0[i] = i;
  
  for(Uint32 i = 0; i<123; i++)
    sec1[i] = 70+i;

  for(Uint32 i = 0; i<10; i++)
    sec2[i] = (i + 1)*(i + 1);
  
  SimpleSignal signal1;
  signal1.set(ss, 0, CMVMI, GSN_TESTSIG, theDataLen + 2);  
  signal1.header.m_noOfSections = 1;
  signal1.header.m_fragmentInfo = 1;

  memcpy(&signal1.theData[0], data, 4 * theDataLen );
  signal1.theData[theDataLen + 0] = 0;
  signal1.theData[theDataLen + 1] = 7; // FragmentId
  
  signal1.ptr[0].sz = 60;
  signal1.ptr[0].p = &sec0[0];
  
  SimpleSignal signal2;
  
  Uint32 idx = 0;
  memcpy(&signal2.theData[0], data, 4 * theDataLen );
  signal2.theData[theDataLen + idx] = 0; idx++;
  signal2.theData[theDataLen + idx] = 1; idx++;
  //signal2.theData[theDataLen + idx] = 2; idx++;
  signal2.theData[theDataLen + idx] = 7; idx++; // FragmentId

  signal2.set(ss, 0, CMVMI, GSN_TESTSIG, theDataLen + idx);
  signal2.header.m_fragmentInfo = 3;
  signal2.header.m_noOfSections = idx - 1;
  
  signal2.ptr[0].sz = 10;
  signal2.ptr[0].p = &sec0[60];
  
  signal2.ptr[1].sz = 123;
  signal2.ptr[1].p = &sec1[0];
  
  signal2.ptr[2].sz = 10;
  signal2.ptr[2].p = &sec2[0];
  
  char * buf;
  while((buf = readline("Enter command: "))){
    add_history(buf);
    data[1] = atoi(buf);
    if(strcmp(buf, "r") == 0){
      SimpleSignal * ret1 = ss.waitFor();
      (* ret1).print();
      delete ret1;
      continue;
    }
    if(strcmp(buf, "a") == 0){
      runTest(ss, 10, true);
      print_help();
      continue;
    }
    if(strcmp(buf, "b") == 0){
      runTest(ss, 100, false);
      print_help();
      continue;
    }
    if(strcmp(buf, "c") == 0){
      runTest(ss, 1000000, false);
      print_help();
      continue;
    }
    
    if(data[1] >= 1 && data[1] <= 12){
      Uint32 nodeId = ss.getAliveNode();
      ndbout_c("Sending 2 fragmented to node %d", nodeId);
      ss.sendSignal(nodeId, &signal1);
      ss.sendSignal(nodeId, &signal2);

      if(data[1] >= 5){
	continue;
      }
      ndbout_c("Waiting for signal from %d", nodeId);
      
      SimpleSignal * ret1 = ss.waitFor((Uint16)nodeId);
      (* ret1).print();
      Uint32 count = ret1->theData[4] - 1;
      delete ret1;
      while(count > 0){
	ndbout << "Waiting for " << count << " signals... ";
	SimpleSignal * ret1 = ss.waitFor();
	ndbout_c("received from node %d", 
		 refToNode(ret1->header.theSendersBlockRef));
	(* ret1).print();
	delete ret1;
	count--;
      }
    } else if (data[1] == 13) {
      const Uint32 count = 3500;
      const Uint32 loop = 1000;

      signal1.set(ss, 0, CMVMI, GSN_TESTSIG, 25);
      signal1.header.m_fragmentInfo = 0;
      signal1.header.m_noOfSections = 0;
      signal1.theData[1] = 14; 
      signal1.theData[3] = 0;   // Print
      signal1.theData[8] = count;
      signal1.theData[9] = loop;
      Uint32 nodeId = ss.getAliveNode();
      ndbout_c("Sending 25 len signal to node %d", nodeId);
      ss.sendSignal(nodeId, &signal1);

      Uint32 total;
      {
	SimpleSignal * ret1 = ss.waitFor((Uint16)nodeId);
	ndbout_c("received from node %d", 
		 refToNode(ret1->header.theSendersBlockRef));
	total = ret1->theData[10] - 1;
	delete ret1;
      }

      do {
	ndbout << "Waiting for " << total << " signals... " << flush;
	SimpleSignal * ret1 = ss.waitFor((Uint16)nodeId);
	ndbout_c("received from node %d", 
		 refToNode(ret1->header.theSendersBlockRef));
	delete ret1;
	total --;
      } while(total > 0);
    } else {
      print_help();
    }
  }
  ndbout << "Exiting" << endl;
};
/* ---------------------------------------------------------------- */
bool
Dbtup::createTrigger(Tablerec* table, const CreateTrigReq* req)
{
  if (ERROR_INSERTED(4003)) {
    CLEAR_ERROR_INSERT_VALUE;
    return false;
  }
  TriggerType::Value ttype = req->getTriggerType();
  TriggerActionTime::Value ttime = req->getTriggerActionTime();
  TriggerEvent::Value tevent = req->getTriggerEvent();

  DLList<TupTriggerData>* tlist = findTriggerList(table, ttype, ttime, tevent);
  ndbrequire(tlist != NULL);

  TriggerPtr tptr;
  if (!tlist->seize(tptr))
    return false;

  // Set trigger id
  tptr.p->triggerId = req->getTriggerId();

  //  ndbout_c("Create TupTrigger %u = %u %u %u %u", tptr.p->triggerId, table, ttype, ttime, tevent);

  // Set index id
  tptr.p->indexId = req->getIndexId();

  // Set trigger type etc
  tptr.p->triggerType = ttype;
  tptr.p->triggerActionTime = ttime;
  tptr.p->triggerEvent = tevent;

  tptr.p->sendBeforeValues = true;
  if ((tptr.p->triggerType == TriggerType::SUBSCRIPTION) &&
      ((tptr.p->triggerEvent == TriggerEvent::TE_UPDATE) ||
       (tptr.p->triggerEvent == TriggerEvent::TE_DELETE))) {
    jam();
    tptr.p->sendBeforeValues = false;
  }
  /*
  tptr.p->sendOnlyChangedAttributes = false;
  if (((tptr.p->triggerType == TriggerType::SUBSCRIPTION) ||
      (tptr.p->triggerType == TriggerType::SUBSCRIPTION_BEFORE)) &&
      (tptr.p->triggerEvent == TriggerEvent::TE_UPDATE)) {
    jam();
    tptr.p->sendOnlyChangedAttributes = true;
  }
  */
  tptr.p->sendOnlyChangedAttributes = !req->getReportAllMonitoredAttributes();
  // Set monitor all
  tptr.p->monitorAllAttributes = req->getMonitorAllAttributes();
  tptr.p->monitorReplicas = req->getMonitorReplicas();
  tptr.p->m_receiverBlock = refToBlock(req->getReceiverRef());

  tptr.p->attributeMask.clear();
  if (tptr.p->monitorAllAttributes) {
    jam();
    for(Uint32 i = 0; i < table->m_no_of_attributes; i++) {
      if (!primaryKey(table, i)) {
        jam();
        tptr.p->attributeMask.set(i);
      }
    }
  } else {
    // Set attribute mask
    jam();
    tptr.p->attributeMask = req->getAttributeMask();
  }
  return true;
}//Dbtup::createTrigger()
Exemple #27
0
void
Dbtup::scanReply(Signal* signal, ScanOpPtr scanPtr)
{
  ScanOp& scan = *scanPtr.p;
  FragrecordPtr fragPtr;
  fragPtr.i = scan.m_fragPtrI;
  ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
  Fragrecord& frag = *fragPtr.p;
  // for reading tuple key in Current state
  Uint32* pkData = (Uint32*)c_dataBuffer;
  unsigned pkSize = 0;
  if (scan.m_state == ScanOp::Current) {
    // found an entry to return
    jam();
    ndbrequire(scan.m_accLockOp == RNIL);
    if (scan.m_bits & ScanOp::SCAN_LOCK) {
      jam();
      // read tuple key - use TUX routine
      const ScanPos& pos = scan.m_scanPos;
      const Local_key& key_mm = pos.m_key_mm;
      int ret = tuxReadPk(fragPtr.i, pos.m_realpid_mm, key_mm.m_page_idx,
			  pkData, true);
      ndbrequire(ret > 0);
      pkSize = ret;
      dbg((DBTUP, "PK size=%d data=%08x", pkSize, pkData[0]));
      // get read lock or exclusive lock
      AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
      lockReq->returnCode = RNIL;
      lockReq->requestInfo = (scan.m_bits & ScanOp::SCAN_LOCK_SH) ?
        AccLockReq::LockShared : AccLockReq::LockExclusive;
      lockReq->accOpPtr = RNIL;
      lockReq->userPtr = scanPtr.i;
      lockReq->userRef = reference();
      lockReq->tableId = scan.m_tableId;
      lockReq->fragId = frag.fragmentId;
      lockReq->fragPtrI = RNIL; // no cached frag ptr yet
      lockReq->hashValue = md5_hash((Uint64*)pkData, pkSize);
      lockReq->tupAddr = key_mm.ref();
      lockReq->transId1 = scan.m_transId1;
      lockReq->transId2 = scan.m_transId2;
      EXECUTE_DIRECT(DBACC, GSN_ACC_LOCKREQ,
          signal, AccLockReq::LockSignalLength);
      jamEntry();
      switch (lockReq->returnCode) {
      case AccLockReq::Success:
        jam();
        scan.m_state = ScanOp::Locked;
        scan.m_accLockOp = lockReq->accOpPtr;
        break;
      case AccLockReq::IsBlocked:
        jam();
        // normal lock wait
        scan.m_state = ScanOp::Blocked;
        scan.m_bits |= ScanOp::SCAN_LOCK_WAIT;
        scan.m_accLockOp = lockReq->accOpPtr;
        // LQH will wake us up
        signal->theData[0] = scan.m_userPtr;
        signal->theData[1] = true;
        EXECUTE_DIRECT(DBLQH, GSN_CHECK_LCP_STOP, signal, 2);
        jamEntry();
        return;
        break;
      case AccLockReq::Refused:
        jam();
        // we cannot see deleted tuple (assert only)
        ndbassert(false);
        // skip it
        scan.m_state = ScanOp::Next;
        signal->theData[0] = scan.m_userPtr;
        signal->theData[1] = true;
        EXECUTE_DIRECT(DBLQH, GSN_CHECK_LCP_STOP, signal, 2);
        jamEntry();
        return;
        break;
      case AccLockReq::NoFreeOp:
        jam();
        // max ops should depend on max scans (assert only)
        ndbassert(false);
        // stay in Current state
        scan.m_state = ScanOp::Current;
        signal->theData[0] = scan.m_userPtr;
        signal->theData[1] = true;
        EXECUTE_DIRECT(DBLQH, GSN_CHECK_LCP_STOP, signal, 2);
        jamEntry();
        return;
        break;
      default:
        ndbrequire(false);
        break;
      }
    } else {
      scan.m_state = ScanOp::Locked;
    }
  } 

  if (scan.m_state == ScanOp::Locked) {
    // we have lock or do not need one
    jam();
    // conf signal
    NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
    conf->scanPtr = scan.m_userPtr;
    // the lock is passed to LQH
    Uint32 accLockOp = scan.m_accLockOp;
    if (accLockOp != RNIL) {
      scan.m_accLockOp = RNIL;
      // remember it until LQH unlocks it
      addAccLockOp(scan, accLockOp);
    } else {
      ndbrequire(! (scan.m_bits & ScanOp::SCAN_LOCK));
      // operation RNIL in LQH would signal no tuple returned
      accLockOp = (Uint32)-1;
    }
    const ScanPos& pos = scan.m_scanPos;
    conf->accOperationPtr = accLockOp;
    conf->fragId = frag.fragmentId;
    conf->localKey[0] = pos.m_key_mm.ref();
    conf->localKey[1] = 0;
    conf->localKeyLength = 1;
    unsigned signalLength = 6;
    if (scan.m_bits & ScanOp::SCAN_LOCK) {
      sendSignal(scan.m_userRef, GSN_NEXT_SCANCONF,
          signal, signalLength, JBB);
    } else {
      Uint32 blockNo = refToBlock(scan.m_userRef);
      EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, signalLength);
      jamEntry();
    }
    // next time look for next entry
    scan.m_state = ScanOp::Next;
    return;
  }
  if (scan.m_state == ScanOp::Last ||
      scan.m_state == ScanOp::Invalid) {
    jam();
    NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
    conf->scanPtr = scan.m_userPtr;
    conf->accOperationPtr = RNIL;
    conf->fragId = RNIL;
    unsigned signalLength = 3;
    sendSignal(scanPtr.p->m_userRef, GSN_NEXT_SCANCONF,
        signal, signalLength, JBB);
    return;
  }
  ndbrequire(false);
}
Exemple #28
0
bool
Dbtup::scanNext(Signal* signal, ScanOpPtr scanPtr)
{
  ScanOp& scan = *scanPtr.p;
  ScanPos& pos = scan.m_scanPos;
  Local_key& key = pos.m_key;
  const Uint32 bits = scan.m_bits;
  // table
  TablerecPtr tablePtr;
  tablePtr.i = scan.m_tableId;
  ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
  Tablerec& table = *tablePtr.p;
  // fragment
  FragrecordPtr fragPtr;
  fragPtr.i = scan.m_fragPtrI;
  ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
  Fragrecord& frag = *fragPtr.p;
  // tuple found
  Tuple_header* th = 0;
  Uint32 thbits = 0;
  Uint32 loop_count = 0;
  Uint32 scanGCI = scanPtr.p->m_scanGCI;
  Uint32 foundGCI;
 
  const bool mm = (bits & ScanOp::SCAN_DD);
  const bool lcp = (bits & ScanOp::SCAN_LCP);
  
  Uint32 lcp_list = fragPtr.p->m_lcp_keep_list;
  Uint32 size = table.m_offsets[mm].m_fix_header_size;

  if (lcp && lcp_list != RNIL)
    goto found_lcp_keep;

  switch(pos.m_get){
  case ScanPos::Get_next_tuple:
  case ScanPos::Get_next_tuple_fs:
    jam();
    key.m_page_idx += size;
    // fall through
  case ScanPos::Get_tuple:
  case ScanPos::Get_tuple_fs:
    jam();
    /**
     * We need to refetch page after timeslice
     */
    pos.m_get = ScanPos::Get_page;
    break;
  default:
    break;
  }
  
  while (true) {
    switch (pos.m_get) {
    case ScanPos::Get_next_page:
      // move to next page
      jam();
      {
        if (! (bits & ScanOp::SCAN_DD))
          pos.m_get = ScanPos::Get_next_page_mm;
        else
          pos.m_get = ScanPos::Get_next_page_dd;
      }
      continue;
    case ScanPos::Get_page:
      // get real page
      jam();
      {
        if (! (bits & ScanOp::SCAN_DD))
          pos.m_get = ScanPos::Get_page_mm;
        else
          pos.m_get = ScanPos::Get_page_dd;
      }
      continue;
    case ScanPos::Get_next_page_mm:
      // move to next logical TUP page
      jam();
      {
        key.m_page_no++;
        if (key.m_page_no >= frag.noOfPages) {
          jam();

          if ((bits & ScanOp::SCAN_NR) && (scan.m_endPage != RNIL))
          {
            jam();
            if (key.m_page_no < scan.m_endPage)
            {
              jam();
              ndbout_c("scanning page %u", key.m_page_no);
              goto cont;
            }
          }
          // no more pages, scan ends
          pos.m_get = ScanPos::Get_undef;
          scan.m_state = ScanOp::Last;
          return true;
        }
    cont:
        key.m_page_idx = 0;
        pos.m_get = ScanPos::Get_page_mm;
        // clear cached value
        pos.m_realpid_mm = RNIL;
      }
      /*FALLTHRU*/
    case ScanPos::Get_page_mm:
      // get TUP real page
      jam();
      {
        if (pos.m_realpid_mm == RNIL) {
          jam();
          if (key.m_page_no < frag.noOfPages)
            pos.m_realpid_mm = getRealpid(fragPtr.p, key.m_page_no);
          else
          {
            ndbassert(bits & ScanOp::SCAN_NR);
            goto nopage;
          }
        }
        PagePtr pagePtr;
	c_page_pool.getPtr(pagePtr, pos.m_realpid_mm);

        if (pagePtr.p->page_state == ZEMPTY_MM) {
          // skip empty page
          jam();
          if (! (bits & ScanOp::SCAN_NR))
          {
            pos.m_get = ScanPos::Get_next_page_mm;
            break; // incr loop count
          }
          else
          {
            jam();
            pos.m_realpid_mm = RNIL;
          }
        }
    nopage:
        pos.m_page = pagePtr.p;
        pos.m_get = ScanPos::Get_tuple;
      }
      continue;
    case ScanPos::Get_next_page_dd:
      // move to next disk page
      jam();
      {
        Disk_alloc_info& alloc = frag.m_disk_alloc_info;
        Local_fragment_extent_list list(c_extent_pool, alloc.m_extent_list);
        Ptr<Extent_info> ext_ptr;
        c_extent_pool.getPtr(ext_ptr, pos.m_extent_info_ptr_i);
        Extent_info* ext = ext_ptr.p;
        key.m_page_no++;
        if (key.m_page_no >= ext->m_first_page_no + alloc.m_extent_size) {
          // no more pages in this extent
          jam();
          if (! list.next(ext_ptr)) {
            // no more extents, scan ends
            jam();
            pos.m_get = ScanPos::Get_undef;
            scan.m_state = ScanOp::Last;
            return true;
          } else {
            // move to next extent
            jam();
            pos.m_extent_info_ptr_i = ext_ptr.i;
            ext = c_extent_pool.getPtr(pos.m_extent_info_ptr_i);
            key.m_file_no = ext->m_key.m_file_no;
            key.m_page_no = ext->m_first_page_no;
          }
        }
        key.m_page_idx = 0;
        pos.m_get = ScanPos::Get_page_dd;
        /*
          read ahead for scan in disk order
          do read ahead every 8:th page
        */
        if ((bits & ScanOp::SCAN_DD) &&
            (((key.m_page_no - ext->m_first_page_no) & 7) == 0))
        {
          jam();
          // initialize PGMAN request
          Page_cache_client::Request preq;
          preq.m_page = pos.m_key;
          preq.m_callback = TheNULLCallback;

          // set maximum read ahead
          Uint32 read_ahead = m_max_page_read_ahead;

          while (true)
          {
            // prepare page read ahead in current extent
            Uint32 page_no = preq.m_page.m_page_no;
            Uint32 page_no_limit = page_no + read_ahead;
            Uint32 limit = ext->m_first_page_no + alloc.m_extent_size;
            if (page_no_limit > limit)
            {
              jam();
              // read ahead crosses extent, set limit for this extent
              read_ahead = page_no_limit - limit;
              page_no_limit = limit;
              // and make sure we only read one extra extent next time around
              if (read_ahead > alloc.m_extent_size)
                read_ahead = alloc.m_extent_size;
            }
            else
            {
              jam();
              read_ahead = 0; // no more to read ahead after this
            }
            // do read ahead pages for this extent
            while (page_no < page_no_limit)
            {
              // page request to PGMAN
              jam();
              preq.m_page.m_page_no = page_no;
              int flags = 0;
              // ignore result
              m_pgman.get_page(signal, preq, flags);
              jamEntry();
              page_no++;
            }
            if (!read_ahead || !list.next(ext_ptr))
            {
              // no more extents after this or read ahead done
              jam();
              break;
            }
            // move to next extent and initialize PGMAN request accordingly
            Extent_info* ext = c_extent_pool.getPtr(ext_ptr.i);
            preq.m_page.m_file_no = ext->m_key.m_file_no;
            preq.m_page.m_page_no = ext->m_first_page_no;
          }
        } // if ScanOp::SCAN_DD read ahead
      }
      /*FALLTHRU*/
    case ScanPos::Get_page_dd:
      // get global page in PGMAN cache
      jam();
      {
        // check if page is un-allocated or empty
	if (likely(! (bits & ScanOp::SCAN_NR)))
	{
	  Tablespace_client tsman(signal, c_tsman,
				  frag.fragTableId, 
				  frag.fragmentId, 
				  frag.m_tablespace_id);
	  unsigned uncommitted, committed;
	  uncommitted = committed = ~(unsigned)0;
	  int ret = tsman.get_page_free_bits(&key, &uncommitted, &committed);
	  ndbrequire(ret == 0);
	  if (committed == 0 && uncommitted == 0) {
	    // skip empty page
	    jam();
	    pos.m_get = ScanPos::Get_next_page_dd;
	    break; // incr loop count
	  }
	}
        // page request to PGMAN
        Page_cache_client::Request preq;
        preq.m_page = pos.m_key;
        preq.m_callback.m_callbackData = scanPtr.i;
        preq.m_callback.m_callbackFunction =
          safe_cast(&Dbtup::disk_page_tup_scan_callback);
        int flags = 0;
        int res = m_pgman.get_page(signal, preq, flags);
        jamEntry();
        if (res == 0) {
          jam();
          // request queued
          pos.m_get = ScanPos::Get_tuple;
          return false;
        }
        ndbrequire(res > 0);
        pos.m_page = (Page*)m_pgman.m_ptr.p;
      }
      pos.m_get = ScanPos::Get_tuple;
      continue;
      // get tuple
      // move to next tuple
    case ScanPos::Get_next_tuple:
    case ScanPos::Get_next_tuple_fs:
      // move to next fixed size tuple
      jam();
      {
        key.m_page_idx += size;
        pos.m_get = ScanPos::Get_tuple_fs;
      }
      /*FALLTHRU*/
    case ScanPos::Get_tuple:
    case ScanPos::Get_tuple_fs:
      // get fixed size tuple
      jam();
      {
        Fix_page* page = (Fix_page*)pos.m_page;
        if (key.m_page_idx + size <= Fix_page::DATA_WORDS) 
	{
	  pos.m_get = ScanPos::Get_next_tuple_fs;
          th = (Tuple_header*)&page->m_data[key.m_page_idx];
	  
	  if (likely(! (bits & ScanOp::SCAN_NR)))
	  {
	    jam();
            thbits = th->m_header_bits;
	    if (! (thbits & Tuple_header::FREE))
	    {
              goto found_tuple;
	    } 
	  }
	  else
	  {
            if (pos.m_realpid_mm == RNIL)
            {
              jam();
              foundGCI = 0;
              goto found_deleted_rowid;
            }
            thbits = th->m_header_bits;
	    if ((foundGCI = *th->get_mm_gci(tablePtr.p)) > scanGCI ||
                foundGCI == 0)
	    {
	      if (! (thbits & Tuple_header::FREE))
	      {
		jam();
		goto found_tuple;
	      }
	      else
	      {
		goto found_deleted_rowid;
	      }
	    }
	    else if (thbits != Fix_page::FREE_RECORD && 
		     th->m_operation_ptr_i != RNIL)
	    {
	      jam();
	      goto found_tuple; // Locked tuple...
	      // skip free tuple
	    }
	  }
        } else {
          jam();
          // no more tuples on this page
          pos.m_get = ScanPos::Get_next_page;
        }
      }
      break; // incr loop count
  found_tuple:
      // found possible tuple to return
      jam();
      {
        // caller has already set pos.m_get to next tuple
        if (! (bits & ScanOp::SCAN_LCP && thbits & Tuple_header::LCP_SKIP)) {
          Local_key& key_mm = pos.m_key_mm;
          if (! (bits & ScanOp::SCAN_DD)) {
            key_mm = pos.m_key;
            // real page id is already set
          } else {
	    key_mm.assref(th->m_base_record_ref);
            // recompute for each disk tuple
            pos.m_realpid_mm = getRealpid(fragPtr.p, key_mm.m_page_no);
          }
          // TUPKEYREQ handles savepoint stuff
          scan.m_state = ScanOp::Current;
          return true;
        } else {
          jam();
          // clear it so that it will show up in next LCP
          th->m_header_bits = thbits & ~(Uint32)Tuple_header::LCP_SKIP;
	  if (tablePtr.p->m_bits & Tablerec::TR_Checksum) {
	    jam();
	    setChecksum(th, tablePtr.p);
	  }
        }
      }
      break;
  found_deleted_rowid:
      jam();
      {
	ndbassert(bits & ScanOp::SCAN_NR);
	Local_key& key_mm = pos.m_key_mm;
	if (! (bits & ScanOp::SCAN_DD)) {
	  key_mm = pos.m_key;
	  // caller has already set pos.m_get to next tuple
	  // real page id is already set
	} else {
	  key_mm.assref(th->m_base_record_ref);
	  // recompute for each disk tuple
	  pos.m_realpid_mm = getRealpid(fragPtr.p, key_mm.m_page_no);
	  
	  Fix_page *mmpage = (Fix_page*)c_page_pool.getPtr(pos.m_realpid_mm);
	  th = (Tuple_header*)(mmpage->m_data + key_mm.m_page_idx);
	  if ((foundGCI = *th->get_mm_gci(tablePtr.p)) > scanGCI ||
              foundGCI == 0)
	  {
	    if (! (thbits & Tuple_header::FREE))
	      break;
	  }
	}
	
	NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
	conf->scanPtr = scan.m_userPtr;
	conf->accOperationPtr = RNIL;
	conf->fragId = frag.fragmentId;
	conf->localKey[0] = pos.m_key_mm.ref();
	conf->localKey[1] = 0;
	conf->localKeyLength = 1;
	conf->gci = foundGCI;
	Uint32 blockNo = refToBlock(scan.m_userRef);
	EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, 7);
	jamEntry();

	// TUPKEYREQ handles savepoint stuff
	loop_count = 32;
	scan.m_state = ScanOp::Next;
	return false;
      }
      break; // incr loop count
    default:
      ndbrequire(false);
      break;
    }
    if (++loop_count >= 32)
      break;
  }
  // TODO: at drop table we have to flush and terminate these
  jam();
  signal->theData[0] = ZTUP_SCAN;
  signal->theData[1] = scanPtr.i;
  sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
  return false;

found_lcp_keep:
  Local_key tmp;
  tmp.assref(lcp_list);
  tmp.m_page_no = getRealpid(fragPtr.p, tmp.m_page_no);
  
  Ptr<Page> pagePtr;
  c_page_pool.getPtr(pagePtr, tmp.m_page_no);
  Tuple_header* ptr = (Tuple_header*)
    ((Fix_page*)pagePtr.p)->get_ptr(tmp.m_page_idx, 0);
  Uint32 headerbits = ptr->m_header_bits;
  ndbrequire(headerbits & Tuple_header::LCP_KEEP);
  
  Uint32 next = ptr->m_operation_ptr_i;
  ptr->m_operation_ptr_i = RNIL;
  ptr->m_header_bits = headerbits & ~(Uint32)Tuple_header::FREE;
  
  if (tablePtr.p->m_bits & Tablerec::TR_Checksum) {
    jam();
    setChecksum(ptr, tablePtr.p);
  }
  
  NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
  conf->scanPtr = scan.m_userPtr;
  conf->accOperationPtr = (Uint32)-1;
  conf->fragId = frag.fragmentId;
  conf->localKey[0] = lcp_list;
  conf->localKey[1] = 0;
  conf->localKeyLength = 1;
  conf->gci = 0;
  Uint32 blockNo = refToBlock(scan.m_userRef);
  EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, 7);
  
  fragPtr.p->m_lcp_keep_list = next;
  ptr->m_header_bits |= Tuple_header::FREED; // RESTORE free flag
  if (headerbits & Tuple_header::FREED)
  {
    if (tablePtr.p->m_attributes[MM].m_no_of_varsize)
    {
      jam();
      free_var_rec(fragPtr.p, tablePtr.p, &tmp, pagePtr);
    } else {
      jam();
      free_fix_rec(fragPtr.p, tablePtr.p, &tmp, (Fix_page*)pagePtr.p);
    }
  }
  return false;
}
Exemple #29
0
inline
NodeReceiverGroup::NodeReceiverGroup(Uint32 blockRef){
  m_nodes.clear();
  m_block = refToBlock(blockRef);
  m_nodes.set(refToNode(blockRef));
}
void
execute(void * callbackObj, 
	SignalHeader * const header, 
	Uint8 prio, 
	Uint32 * const theData,
	LinearSectionPtr ptr[3]){

  const Uint32 secCount = header->m_noOfSections;
  const Uint32 length = header->theLength;

#ifdef TRACE_DISTRIBUTED
  ndbout_c("recv: %s(%d) from (%s, %d)",
	   getSignalName(header->theVerId_signalNumber), 
	   header->theVerId_signalNumber,
	   getBlockName(refToBlock(header->theSendersBlockRef)),
	   refToNode(header->theSendersBlockRef));
#endif
  
  bool ok = true;
  Ptr<SectionSegment> secPtr[3];
  switch(secCount){
  case 3:
    ok &= import(secPtr[2], ptr[2].p, ptr[2].sz);
  case 2:
    ok &= import(secPtr[1], ptr[1].p, ptr[1].sz);
  case 1:
    ok &= import(secPtr[0], ptr[0].p, ptr[0].sz);
  }

  /**
   * Check that we haven't received a too long signal
   */
  ok &= (length + secCount <= 25);
  
  Uint32 secPtrI[3];
  if(ok){
    /**
     * Normal path 
     */
    secPtrI[0] = secPtr[0].i;
    secPtrI[1] = secPtr[1].i;
    secPtrI[2] = secPtr[2].i;

    globalScheduler.execute(header, prio, theData, secPtrI);  
    return;
  }
  
  /**
   * Out of memory
   */
  for(Uint32 i = 0; i<secCount; i++){
    if(secPtr[i].p != 0){
      g_sectionSegmentPool.releaseList(relSz(ptr[i].sz), secPtr[i].i, 
				       secPtr[i].p->m_lastSegment);
    }
  }
  Uint32 gsn = header->theVerId_signalNumber;
  Uint32 len = header->theLength;
  Uint32 newLen= (len > 22 ? 22 : len);
  SignalDroppedRep * rep = (SignalDroppedRep*)theData;
  memmove(rep->originalData, theData, (4 * newLen));
  rep->originalGsn = gsn;
  rep->originalLength = len;
  rep->originalSectionCount = secCount;
  header->theVerId_signalNumber = GSN_SIGNAL_DROPPED_REP;
  header->theLength = newLen + 3;
  header->m_noOfSections = 0;
  globalScheduler.execute(header, prio, theData, secPtrI);    
}