int Dbtup::accReadPk(Uint32 tableId, Uint32 fragId, Uint32 fragPageId, Uint32 pageIndex, Uint32* dataOut, bool xfrmFlag) { jamEntry(); // get table TablerecPtr tablePtr; tablePtr.i = tableId; ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec); // get fragment FragrecordPtr fragPtr; getFragmentrec(fragPtr, fragId, tablePtr.p); // get real page id and tuple offset Uint32 pageId = getRealpid(fragPtr.p, fragPageId); // use TUX routine - optimize later int ret = tuxReadPk(fragPtr.i, pageId, pageIndex, dataOut, xfrmFlag); return ret; }
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); }