Exemple #1
0
bool DeleteExecutor::p_execute(const NValueArray &params, 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;
}
Exemple #2
0
bool UpdateExecutor::p_execute(const NValueArray &params, 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*)&params);

        // 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*)&params);

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