bool DeleteExecutor::p_execute(const NValueArray ¶ms, ReadWriteTracker *tracker) { assert(m_targetTable); if (m_truncate) { VOLT_TRACE("truncating table %s...", m_targetTable->name().c_str()); // count the truncated tuples as deleted m_engine->m_tuplesModified += m_inputTable->activeTupleCount(); #ifdef ARIES if(m_engine->isARIESEnabled()){ // no need of persistency check, m_targetTable is // always persistent for deletes LogRecord *logrecord = new LogRecord(computeTimeStamp(), LogRecord::T_TRUNCATE,// this is a truncate record LogRecord::T_FORWARD,// the system is running normally -1,// XXX: prevLSN must be fetched from table! m_engine->getExecutorContext()->currentTxnId() ,// txn id m_engine->getSiteId(),// which execution site m_targetTable->name(),// the table affected NULL,// primary key irrelevant -1,// irrelevant numCols NULL,// list of modified cols irrelevant NULL,// before image irrelevant NULL// after image irrelevant ); size_t logrecordLength = logrecord->getEstimatedLength(); char *logrecordBuffer = new char[logrecordLength]; FallbackSerializeOutput output; output.initializeWithPosition(logrecordBuffer, logrecordLength, 0); logrecord->serializeTo(output); LogManager* m_logManager = this->m_engine->getLogManager(); Logger m_ariesLogger = m_logManager->getAriesLogger(); //VOLT_WARN("m_logManager : %p AriesLogger : %p",&m_logManager, &m_ariesLogger); const Logger *logger = m_logManager->getThreadLogger(LOGGERID_MM_ARIES); logger->log(LOGLEVEL_INFO, output.data(), output.position()); delete[] logrecordBuffer; logrecordBuffer = NULL; delete logrecord; logrecord = NULL; } #endif //m_engine->context().incrementTuples(m_targetTable->activeTupleCount()); // actually delete all the tuples m_targetTable->deleteAllTuples(true); return true; } // XXX : ARIES : Not sure if else is needed ? assert(m_inputTable); assert(m_inputTuple.sizeInValues() == m_inputTable->columnCount()); assert(m_targetTuple.sizeInValues() == m_targetTable->columnCount()); TableIterator inputIterator(m_inputTable); while (inputIterator.next(m_inputTuple)) { // // OPTIMIZATION: Single-Sited Query Plans // If our beloved DeletePlanNode is apart of a single-site query plan, // then the first column in the input table will be the address of a // tuple on the target table that we will want to blow away. This saves // us the trouble of having to do an index lookup // void *targetAddress = m_inputTuple.getNValue(0).castAsAddress(); m_targetTuple.move(targetAddress); // Read/Write Set Tracking if (tracker != NULL) { tracker->markTupleWritten(m_targetTable, &m_targetTuple); } #ifdef ARIES if(m_engine->isARIESEnabled()){ // no need of persistency check, m_targetTable is // always persistent for deletes // before image -- target is tuple to be deleted. TableTuple *beforeImage = &m_targetTuple; TableTuple *keyTuple = NULL; char *keydata = NULL; // See if we use an index instead TableIndex *index = m_targetTable->primaryKeyIndex(); if (index != NULL) { // First construct tuple for primary key keydata = new char[index->getKeySchema()->tupleLength()]; keyTuple = new TableTuple(keydata, index->getKeySchema()); for (int i = 0; i < index->getKeySchema()->columnCount(); i++) { keyTuple->setNValue(i, beforeImage->getNValue(index->getColumnIndices()[i])); } // no before image need be recorded, just the primary key beforeImage = NULL; } LogRecord *logrecord = new LogRecord(computeTimeStamp(), LogRecord::T_DELETE,// this is a delete record LogRecord::T_FORWARD,// the system is running normally -1,// XXX: prevLSN must be fetched from table! m_engine->getExecutorContext()->currentTxnId() ,// txn id m_engine->getSiteId(),// which execution site m_targetTable->name(),// the table affected keyTuple,// primary key -1,// must delete all columns NULL,// no list of modified cols beforeImage, NULL// no after image ); size_t logrecordLength = logrecord->getEstimatedLength(); char *logrecordBuffer = new char[logrecordLength]; FallbackSerializeOutput output; output.initializeWithPosition(logrecordBuffer, logrecordLength, 0); logrecord->serializeTo(output); LogManager* m_logManager = this->m_engine->getLogManager(); Logger m_ariesLogger = m_logManager->getAriesLogger(); //VOLT_WARN("m_logManager : %p AriesLogger : %p",&m_logManager, &m_ariesLogger); const Logger *logger = m_logManager->getThreadLogger(LOGGERID_MM_ARIES); logger->log(LOGLEVEL_INFO, output.data(), output.position()); delete[] logrecordBuffer; logrecordBuffer = NULL; delete logrecord; logrecord = NULL; if (keydata != NULL) { delete[] keydata; keydata = NULL; } if (keyTuple != NULL) { delete keyTuple; keyTuple = NULL; } } #endif // Delete from target table if (!m_targetTable->deleteTuple(m_targetTuple, true)) { VOLT_ERROR("Failed to delete tuple from table '%s'", m_targetTable->name().c_str()); return false; } } // add to the planfragments count of modified tuples m_engine->m_tuplesModified += m_inputTable->activeTupleCount(); //m_engine->context().incrementTuples(m_inputTable->activeTupleCount()); return true; }
bool UpdateExecutor::p_execute(const NValueArray ¶ms, ReadWriteTracker *tracker) { assert(m_inputTable); assert(m_targetTable); VOLT_TRACE("INPUT TABLE: %s\n", m_inputTable->debug().c_str()); VOLT_TRACE("TARGET TABLE - BEFORE: %s\n", m_targetTable->debug().c_str()); assert(m_inputTuple.sizeInValues() == m_inputTable->columnCount()); assert(m_targetTuple.sizeInValues() == m_targetTable->columnCount()); TableIterator input_iterator(m_inputTable); while (input_iterator.next(m_inputTuple)) { // // OPTIMIZATION: Single-Sited Query Plans // If our beloved UpdatePlanNode is apart of a single-site query plan, // then the first column in the input table will be the address of a // tuple on the target table that we will want to update. This saves us // the trouble of having to do an index lookup // void *target_address = m_inputTuple.getNValue(0).castAsAddress(); m_targetTuple.move(target_address); // Read/Write Set Tracking if (tracker != NULL) { tracker->markTupleWritten(m_targetTable, &m_targetTuple); } // Loop through INPUT_COL_IDX->TARGET_COL_IDX mapping and only update // the values that we need to. The key thing to note here is that we // grab a temp tuple that is a copy of the target tuple (i.e., the tuple // we want to update). This insures that if the input tuple is somehow // bringing garbage with it, we're only going to copy what we really // need to into the target tuple. // TableTuple &tempTuple = m_targetTable->getTempTupleInlined(m_targetTuple); for (int map_ctr = 0; map_ctr < m_inputTargetMapSize; map_ctr++) { tempTuple.setNValue(m_inputTargetMap[map_ctr].second, m_inputTuple.getNValue(m_inputTargetMap[map_ctr].first)); } // if there is a partition column for the target table if (m_partitionColumn != -1) { // check for partition problems // get the value for the partition column NValue value = tempTuple.getNValue(m_partitionColumn); bool isLocal = m_engine->isLocalSite(value); // if it doesn't map to this site if (!isLocal) { VOLT_ERROR("Mispartitioned tuple in single-partition plan for" " table '%s'", m_targetTable->name().c_str()); return false; } } #ifdef ARIES if(m_engine->isARIESEnabled()){ // add persistency check: PersistentTable* table = dynamic_cast<PersistentTable*>(m_targetTable); // only log if we are writing to a persistent table. if (table != NULL) { // before image -- target is old val with no updates // XXX: what about uninlined fields? // should we not be doing // m_targetTable->getTempTupleInlined(m_targetTuple); instead? TableTuple *beforeImage = &m_targetTuple; // after image -- temp is NEW, created using target and input TableTuple *afterImage = &tempTuple; TableTuple *keyTuple = NULL; char *keydata = NULL; std::vector<int32_t> modifiedCols; int32_t numCols = -1; // See if we can do better by using an index instead TableIndex *index = table->primaryKeyIndex(); if (index != NULL) { // First construct tuple for primary key keydata = new char[index->getKeySchema()->tupleLength()]; keyTuple = new TableTuple(keydata, index->getKeySchema()); for (int i = 0; i < index->getKeySchema()->columnCount(); i++) { keyTuple->setNValue(i, beforeImage->getNValue(index->getColumnIndices()[i])); } // no before image need be recorded, just the primary key beforeImage = NULL; } // Set the modified column list numCols = m_inputTargetMapSize; modifiedCols.resize(m_inputTargetMapSize, -1); for (int map_ctr = 0; map_ctr < m_inputTargetMapSize; map_ctr++) { // can't use column-id directly, otherwise we would go over vector bounds int pos = m_inputTargetMap[map_ctr].first - 1; modifiedCols.at(pos) = m_inputTargetMap[map_ctr].second; } // Next, let the input tuple be the diff after image afterImage = &m_inputTuple; LogRecord *logrecord = new LogRecord(computeTimeStamp(), LogRecord::T_UPDATE,// this is an update record LogRecord::T_FORWARD,// the system is running normally -1,// XXX: prevLSN must be fetched from table! m_engine->getExecutorContext()->currentTxnId() ,// txn id m_engine->getSiteId(),// which execution site m_targetTable->name(),// the table affected keyTuple,// primary key numCols, (numCols > 0) ? &modifiedCols : NULL, beforeImage, afterImage ); size_t logrecordLength = logrecord->getEstimatedLength(); char *logrecordBuffer = new char[logrecordLength]; FallbackSerializeOutput output; output.initializeWithPosition(logrecordBuffer, logrecordLength, 0); logrecord->serializeTo(output); LogManager* m_logManager = this->m_engine->getLogManager(); Logger m_ariesLogger = m_logManager->getAriesLogger(); //VOLT_WARN("m_logManager : %p AriesLogger : %p",&m_logManager, &m_ariesLogger); const Logger *logger = m_logManager->getThreadLogger(LOGGERID_MM_ARIES); logger->log(LOGLEVEL_INFO, output.data(), output.position()); delete[] logrecordBuffer; logrecordBuffer = NULL; delete logrecord; logrecord = NULL; if (keydata != NULL) { delete[] keydata; keydata = NULL; } if (keyTuple != NULL) { delete keyTuple; keyTuple = NULL; } } } #endif if (!m_targetTable->updateTuple(tempTuple, m_targetTuple, m_updatesIndexes)) { VOLT_INFO("Failed to update tuple from table '%s'", m_targetTable->name().c_str()); return false; } } VOLT_TRACE("TARGET TABLE - AFTER: %s\n", m_targetTable->debug().c_str()); // TODO lets output result table here, not in result executor. same thing in // delete/insert // add to the planfragments count of modified tuples m_engine->m_tuplesModified += m_inputTable->activeTupleCount(); return true; }
void METH(run_not_inplace)() { OMX_BUFFERHEADERTYPE * pInputBuf; OMX_BUFFERHEADERTYPE * pOutputBuf; ARMNMF_DBC_PRECONDITION((m_effect_caps.proc_type == EFFECT_PROCESS_TYPE_INPLACE) || (m_effect_caps.proc_type == EFFECT_PROCESS_TYPE_NOT_INPLACE)); // If not buffers on both ports then return... if( !mPorts[INPUT_PORT_IDX].queuedBufferCount() || !mPorts[OUTPUT_PORT_IDX].queuedBufferCount()) { return; } // Point to in- and out-buffers (do not de-queue until processed)... pInputBuf = mPorts[INPUT_PORT_IDX].getBuffer(0); pOutputBuf = mPorts[OUTPUT_PORT_IDX].getBuffer(0); initTimeStampComputation(pInputBuf, pOutputBuf); bool inBufEmptied = false; bool outBufFilled = false; //Check that output buffer contains enough space //ARMNMF_DBC_ASSERT(pInputBuf->nFilledLen <= pOutputBuf->nAllocLen); // Process... if (m_effect_caps.proc_type == EFFECT_PROCESS_TYPE_INPLACE) { // If effect has implemented in-place processing... // Copy in- to out-buffer... ARMNMF_DBC_ASSERT(pInputBuf->nOffset == 0); memcpy(pOutputBuf->pBuffer, pInputBuf->pBuffer, pInputBuf->nFilledLen); // Forward applicable parts of buffer header... pOutputBuf->nFilledLen = pInputBuf->nFilledLen; pOutputBuf->nOffset = pInputBuf->nOffset; pOutputBuf->nTimeStamp = pInputBuf->nTimeStamp; pOutputBuf->nFlags = pInputBuf->nFlags; // Process out-buffer in-place...Open t_effect_process_inplace_params params; params.base.size = sizeof(t_effect_process_inplace_params); params.base.proc_type = m_effect_caps.proc_type; params.buf_hdr = pOutputBuf; effect.process((t_effect_process_params*)¶ms); // Buffers always completely processed in case of in-place processing... inBufEmptied = true; outBufFilled = true; } else { // Else effect has implemented not in-place processing, ask it to process... t_effect_process_not_inplace_params params; params.base.size = sizeof(t_effect_process_not_inplace_params); params.base.proc_type = m_effect_caps.proc_type; params.inbuf_hdr = pInputBuf; params.inbuf_emptied = false; params.outbuf_hdr = pOutputBuf; params.outbuf_filled = false; effect.process((t_effect_process_params*)¶ms); // Check if buffers are processed... inBufEmptied = params.inbuf_emptied; outBufFilled = params.outbuf_filled; } OMX_U32 outFlags = pOutputBuf->nFlags; bool outEos = (outFlags & OMX_BUFFERFLAG_EOS); // outBufFilled indicates that out buffer is filled and shall be returned on output port // Effect MAY update pOutputBuf->nFilledLen incrementally // outEos indicates that out buffer is LAST. It implies that the buffer is filled! // outBufFilled=0 AND outEos=0 : the buffer is not filled and is kept on output port // outBufFilled=1 AND outEos=0 : the buffer is filled and is returned on output port // outBufFilled=X AND outEos=1 : the buffer is filled AND last and is returned on output port if (outBufFilled || outEos) { if (bPropagateTS) { pOutputBuf->nTimeStamp = computeTimeStamp(((pOutputBuf->nFilledLen*8)/mEffectConfig.outfmt.nof_bits_per_sample)); } mPorts[OUTPUT_PORT_IDX].dequeueAndReturnBuffer(); } // inBufEmptied indicates that in buf is emptied and shall be returned on input port // Effect MUST NOT update pInputBuf->nFilledLen // inEos indicates that in buffer is LAST. // The last in buffer may produce several out buffers (e.g. because of internal effect delay) => // If inEos then effect shall set inBufEmptied only when last out buffer is filled // ((Keep last in buffer while outBufHdr.eos=0)) // inBufEmptied=0 AND inEos=X : the buffer is not emptied and is kept on input port // inBufEmptied=1 AND inEos=X : the buffer is emptied and is returned on input port if (inBufEmptied) { mPorts[INPUT_PORT_IDX].dequeueAndReturnBuffer(); } // Fire buffer flag event if EOS... if (outEos) { proxy.eventHandler(OMX_EventBufferFlag, 1, outFlags); effect.reset(EFFECT_RESET_REASON_EOS); } }