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()); }
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); }
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); } }
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); }
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; }
/****************************************************************************** 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; }
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 {
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 }
/** * 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; }
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; }
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; } } } }
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; }
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()
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); }
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; }
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); }