/* ---------------------------------------------------------------- */ void Dbtup::execSTORED_PROCREQ(Signal* signal) { OperationrecPtr regOperPtr; TablerecPtr regTabPtr; jamEntry(); regOperPtr.i = signal->theData[0]; c_operation_pool.getPtr(regOperPtr); regTabPtr.i = signal->theData[1]; ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec); Uint32 requestInfo = signal->theData[3]; TransState trans_state= get_trans_state(regOperPtr.p); ndbrequire(trans_state == TRANS_IDLE || ((trans_state == TRANS_ERROR_WAIT_STORED_PROCREQ) && (requestInfo == ZSTORED_PROCEDURE_DELETE))); ndbrequire(regTabPtr.p->tableStatus == DEFINED); switch (requestInfo) { case ZSCAN_PROCEDURE: jam(); scanProcedure(signal, regOperPtr.p, signal->theData[4]); break; case ZCOPY_PROCEDURE: jam(); copyProcedure(signal, regTabPtr, regOperPtr.p); break; case ZSTORED_PROCEDURE_DELETE: jam(); deleteScanProcedure(signal, regOperPtr.p); break; default: ndbrequire(false); }//switch }//Dbtup::execSTORED_PROCREQ()
void Dbtup::execTUP_WRITELOG_REQ(Signal* signal) { jamEntry(); OperationrecPtr loopOpPtr; loopOpPtr.i= signal->theData[0]; Uint32 gci_hi = signal->theData[1]; Uint32 gci_lo = signal->theData[2]; c_operation_pool.getPtr(loopOpPtr); while (loopOpPtr.p->prevActiveOp != RNIL) { jam(); loopOpPtr.i= loopOpPtr.p->prevActiveOp; c_operation_pool.getPtr(loopOpPtr); } do { ndbrequire(get_trans_state(loopOpPtr.p) == TRANS_STARTED); signal->theData[0] = loopOpPtr.p->userpointer; signal->theData[1] = gci_hi; signal->theData[2] = gci_lo; if (loopOpPtr.p->nextActiveOp == RNIL) { jam(); EXECUTE_DIRECT(DBLQH, GSN_LQH_WRITELOG_REQ, signal, 3); return; } jam(); EXECUTE_DIRECT(DBLQH, GSN_LQH_WRITELOG_REQ, signal, 3); jamEntry(); loopOpPtr.i= loopOpPtr.p->nextActiveOp; c_operation_pool.getPtr(loopOpPtr); } while (true); }
/* ---------------------------------------------------------------- */ void Dbtup::execSTORED_PROCREQ(Signal* signal) { OperationrecPtr regOperPtr; TablerecPtr regTabPtr; jamEntry(); regOperPtr.i = signal->theData[0]; c_operation_pool.getPtr(regOperPtr); regTabPtr.i = signal->theData[1]; ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec); Uint32 requestInfo = signal->theData[3]; TransState trans_state= get_trans_state(regOperPtr.p); ndbrequire(trans_state == TRANS_IDLE || ((trans_state == TRANS_ERROR_WAIT_STORED_PROCREQ) && (requestInfo == ZSTORED_PROCEDURE_DELETE))); ndbrequire(regTabPtr.p->tableStatus == DEFINED); /* * Also store count of procs called from non-API scans. * It can be done here since seize/release always succeeds. * The count is only used under -DERROR_INSERT via DUMP. */ BlockReference apiBlockref = signal->theData[5]; switch (requestInfo) { case ZSCAN_PROCEDURE: { jam(); #if defined VM_TRACE || defined ERROR_INSERT storedProcCountNonAPI(apiBlockref, +1); #endif SectionHandle handle(this, signal); ndbrequire(handle.m_cnt == 1); scanProcedure(signal, regOperPtr.p, &handle, false); // Not copy break; } case ZCOPY_PROCEDURE: jam(); #if defined VM_TRACE || defined ERROR_INSERT storedProcCountNonAPI(apiBlockref, +1); #endif copyProcedure(signal, regTabPtr, regOperPtr.p); break; case ZSTORED_PROCEDURE_DELETE: jam(); #if defined VM_TRACE || defined ERROR_INSERT storedProcCountNonAPI(apiBlockref, -1); #endif deleteScanProcedure(signal, regOperPtr.p); break; default: ndbrequire(false); }//switch }//Dbtup::execSTORED_PROCREQ()
/* ----------------------------------------------------------------- */ void Dbtup::execTUP_COMMITREQ(Signal* signal) { FragrecordPtr regFragPtr; OperationrecPtr regOperPtr; TablerecPtr regTabPtr; KeyReqStruct req_struct(this, KRS_COMMIT); TransState trans_state; Uint32 no_of_fragrec, no_of_tablerec; TupCommitReq * const tupCommitReq= (TupCommitReq *)signal->getDataPtr(); regOperPtr.i= tupCommitReq->opPtr; Uint32 hash_value= tupCommitReq->hashValue; Uint32 gci_hi = tupCommitReq->gci_hi; Uint32 gci_lo = tupCommitReq->gci_lo; Uint32 transId1 = tupCommitReq->transId1; Uint32 transId2 = tupCommitReq->transId2; jamEntry(); c_operation_pool.getPtr(regOperPtr); regFragPtr.i= regOperPtr.p->fragmentPtr; trans_state= get_trans_state(regOperPtr.p); no_of_fragrec= cnoOfFragrec; ndbrequire(trans_state == TRANS_STARTED); ptrCheckGuard(regFragPtr, no_of_fragrec, fragrecord); no_of_tablerec= cnoOfTablerec; regTabPtr.i= regFragPtr.p->fragTableId; req_struct.signal= signal; req_struct.hash_value= hash_value; req_struct.gci_hi = gci_hi; req_struct.gci_lo = gci_lo; /* Put transid in req_struct, so detached triggers can access it */ req_struct.trans_id1 = transId1; req_struct.trans_id2 = transId2; req_struct.m_reorg = regOperPtr.p->op_struct.bit_field.m_reorg; regOperPtr.p->m_commit_disk_callback_page = tupCommitReq->diskpage; #ifdef VM_TRACE if (tupCommitReq->diskpage == RNIL) { m_pgman_ptr.i = RNIL; m_pgman_ptr.p = 0; req_struct.m_disk_page_ptr.i = RNIL; req_struct.m_disk_page_ptr.p = 0; } #endif ptrCheckGuard(regTabPtr, no_of_tablerec, tablerec); PagePtr page; Tuple_header* tuple_ptr= (Tuple_header*) get_ptr(&page, ®OperPtr.p->m_tuple_location, regTabPtr.p); /** * NOTE: This has to be run before potential time-slice when * waiting for disk, as otherwise the "other-ops" in a multi-op * commit might run while we're waiting for disk * */ if (!regTabPtr.p->tuxCustomTriggers.isEmpty()) { if(get_tuple_state(regOperPtr.p) == TUPLE_PREPARED) { jam(); OperationrecPtr loopPtr = regOperPtr; if (unlikely(!regOperPtr.p->is_first_operation())) { findFirstOp(loopPtr); } /** * Execute all tux triggers at first commit * since previous tuple is otherwise removed... */ jam(); goto first; while(loopPtr.i != RNIL) { c_operation_pool.getPtr(loopPtr); first: executeTuxCommitTriggers(signal, loopPtr.p, regFragPtr.p, regTabPtr.p); set_tuple_state(loopPtr.p, TUPLE_TO_BE_COMMITTED); loopPtr.i = loopPtr.p->nextActiveOp; } } } bool get_page = false; if(regOperPtr.p->op_struct.bit_field.m_load_diskpage_on_commit) { jam(); Page_cache_client::Request req; /** * Only last op on tuple needs "real" commit, * hence only this one should have m_load_diskpage_on_commit */ ndbassert(tuple_ptr->m_operation_ptr_i == regOperPtr.i); /** * Check for page */ if(!regOperPtr.p->m_copy_tuple_location.isNull()) { jam(); Tuple_header* tmp= get_copy_tuple(®OperPtr.p->m_copy_tuple_location); memcpy(&req.m_page, tmp->get_disk_ref_ptr(regTabPtr.p), sizeof(Local_key)); if (unlikely(regOperPtr.p->op_type == ZDELETE && tmp->m_header_bits & Tuple_header::DISK_ALLOC)) { jam(); /** * Insert+Delete */ regOperPtr.p->op_struct.bit_field.m_load_diskpage_on_commit = 0; regOperPtr.p->op_struct.bit_field.m_wait_log_buffer = 0; disk_page_abort_prealloc(signal, regFragPtr.p, &req.m_page, req.m_page.m_page_idx); D("Logfile_client - execTUP_COMMITREQ"); Logfile_client lgman(this, c_lgman, regFragPtr.p->m_logfile_group_id); lgman.free_log_space(regOperPtr.p->m_undo_buffer_space); goto skip_disk; if (0) ndbout_c("insert+delete"); jamEntry(); goto skip_disk; } } else { jam(); // initial delete ndbassert(regOperPtr.p->op_type == ZDELETE); memcpy(&req.m_page, tuple_ptr->get_disk_ref_ptr(regTabPtr.p), sizeof(Local_key)); ndbassert(tuple_ptr->m_header_bits & Tuple_header::DISK_PART); } if (retrieve_data_page(signal, req, regOperPtr) == 0) { return; // Data page has not been retrieved yet. } get_page = true; } if(regOperPtr.p->op_struct.bit_field.m_wait_log_buffer) { jam(); /** * Only last op on tuple needs "real" commit, * hence only this one should have m_wait_log_buffer */ ndbassert(tuple_ptr->m_operation_ptr_i == regOperPtr.i); if (retrieve_log_page(signal, regFragPtr, regOperPtr) == 0) { return; // Log page has not been retrieved yet. } } assert(tuple_ptr); skip_disk: req_struct.m_tuple_ptr = tuple_ptr; Uint32 nextOp = regOperPtr.p->nextActiveOp; Uint32 prevOp = regOperPtr.p->prevActiveOp; /** * The trigger code (which is shared between detached/imediate) * check op-list to check were to read before values from * detached triggers should always read from original tuple value * from before transaction start, not from any intermediate update * * Setting the op-list has this effect */ regOperPtr.p->nextActiveOp = RNIL; regOperPtr.p->prevActiveOp = RNIL; if(tuple_ptr->m_operation_ptr_i == regOperPtr.i) { jam(); /** * Perform "real" commit */ Uint32 disk = regOperPtr.p->m_commit_disk_callback_page; set_commit_change_mask_info(regTabPtr.p, &req_struct, regOperPtr.p); checkDetachedTriggers(&req_struct, regOperPtr.p, regTabPtr.p, disk != RNIL); tuple_ptr->m_operation_ptr_i = RNIL; if (regOperPtr.p->op_type == ZDELETE) { jam(); if (get_page) { ndbassert(tuple_ptr->m_header_bits & Tuple_header::DISK_PART); } dealloc_tuple(signal, gci_hi, gci_lo, page.p, tuple_ptr, &req_struct, regOperPtr.p, regFragPtr.p, regTabPtr.p); } else if(regOperPtr.p->op_type != ZREFRESH) { jam(); commit_operation(signal, gci_hi, gci_lo, tuple_ptr, page, regOperPtr.p, regFragPtr.p, regTabPtr.p); } else { jam(); commit_refresh(signal, gci_hi, gci_lo, tuple_ptr, page, &req_struct, regOperPtr.p, regFragPtr.p, regTabPtr.p); } } if (nextOp != RNIL) { c_operation_pool.getPtr(nextOp)->prevActiveOp = prevOp; } if (prevOp != RNIL) { c_operation_pool.getPtr(prevOp)->nextActiveOp = nextOp; } if(!regOperPtr.p->m_copy_tuple_location.isNull()) { jam(); c_undo_buffer.free_copy_tuple(®OperPtr.p->m_copy_tuple_location); } initOpConnection(regOperPtr.p); signal->theData[0] = 0; }