Search in sources :

Example 1 with BorrowTaskMessage

use of org.voltdb.messaging.BorrowTaskMessage in project voltdb by VoltDB.

the class MpTransactionState method recursableRun.

@Override
public Map<Integer, List<VoltTable>> recursableRun(SiteProcedureConnection siteConnection) {
    final VoltTrace.TraceEventBatch traceLog = VoltTrace.log(VoltTrace.Category.MPSITE);
    // if we're restarting this transaction, and we only have local work, add some dummy
    // remote work so that we can avoid injecting a borrow task into the local buddy site
    // before the CompleteTransactionMessage with the restart flag reaches it.
    // Right now, any read on a replicated table which has no distributed work will
    // generate these null fragments in the restarted transaction.
    boolean usedNullFragment = false;
    if (m_isRestart && m_remoteWork == null) {
        usedNullFragment = true;
        m_remoteWork = new FragmentTaskMessage(m_localWork.getInitiatorHSId(), m_localWork.getCoordinatorHSId(), m_localWork.getTxnId(), m_localWork.getUniqueId(), m_localWork.isReadOnly(), false, false);
        m_remoteWork.setEmptyForRestart(getNextDependencyId());
        if (!m_haveDistributedInitTask && !isForReplay() && !isReadOnly()) {
            m_haveDistributedInitTask = true;
            m_remoteWork.setStateForDurability((Iv2InitiateTaskMessage) getNotice(), m_masterHSIds.keySet());
        }
        // Distribute fragments to remote destinations.
        long[] non_local_hsids = new long[m_useHSIds.size()];
        for (int i = 0; i < m_useHSIds.size(); i++) {
            non_local_hsids[i] = m_useHSIds.get(i);
        }
        // send to all non-local sites
        if (non_local_hsids.length > 0) {
            m_mbox.send(non_local_hsids, m_remoteWork);
        }
    }
    // Do distributed fragments, if any
    if (m_remoteWork != null) {
        // Create some record of expected dependencies for tracking
        m_remoteDeps = createTrackedDependenciesFromTask(m_remoteWork, m_useHSIds);
        // cause ProcedureRunner to do the right thing and cause rollback.
        while (!checkDoneReceivingFragResponses()) {
            FragmentResponseMessage msg = pollForResponses();
            if (traceLog != null) {
                final int batchIdx = m_remoteWork.getCurrentBatchIndex();
                traceLog.add(() -> VoltTrace.endAsync("sendfragment", MiscUtils.hsIdPairTxnIdToString(m_mbox.getHSId(), msg.m_sourceHSId, txnId, batchIdx), "status", Byte.toString(msg.getStatusCode())));
            }
            boolean expectedMsg = handleReceivedFragResponse(msg);
            if (expectedMsg) {
                // Will roll-back and throw if this message has an exception
                checkForException(msg);
            }
        }
    }
    // satisified. Clear this defensively. Procedure runner is sloppy with
    // cleaning up if it decides new work is necessary that is local-only.
    m_remoteWork = null;
    BorrowTaskMessage borrowmsg = new BorrowTaskMessage(m_localWork);
    m_localWork.setCoordinatorTask(true);
    m_localWork.m_sourceHSId = m_mbox.getHSId();
    // don't include the empty dependencies we got back in the borrow fragment.
    if (!usedNullFragment) {
        borrowmsg.addInputDepMap(m_remoteDepTables);
    }
    if (traceLog != null) {
        final int batchIdx = m_localWork.getCurrentBatchIndex();
        traceLog.add(() -> VoltTrace.beginAsync("sendborrow", MiscUtils.hsIdPairTxnIdToString(m_mbox.getHSId(), m_buddyHSId, txnId, batchIdx), "txnId", TxnEgo.txnIdToString(txnId), "dest", CoreUtils.hsIdToString(m_buddyHSId)));
    }
    m_mbox.send(m_buddyHSId, borrowmsg);
    FragmentResponseMessage msg;
    while (true) {
        msg = pollForResponses();
        final FragmentResponseMessage finalMsg = msg;
        if (traceLog != null) {
            final int batchIdx = m_localWork.getCurrentBatchIndex();
            traceLog.add(() -> VoltTrace.endAsync("sendborrow", MiscUtils.hsIdPairTxnIdToString(m_mbox.getHSId(), m_buddyHSId, txnId, batchIdx), "status", Byte.toString(finalMsg.getStatusCode())));
        }
        assert (msg.getTableCount() > 0);
        // If this is a restarted TXN, verify that this is not a stale message from a different Dependency
        if (!m_isRestart || (msg.m_sourceHSId == m_buddyHSId && msg.getTableDependencyIdAtIndex(0) == m_localWork.getOutputDepId(0))) {
            // Will roll-back and throw if this message has an exception
            checkForException(msg);
            break;
        } else {
            // ignore those
            assert m_isRestart;
        }
    }
    m_localWork = null;
    // Build results from the FragmentResponseMessage
    // This is similar to dependency tracking...maybe some
    // sane way to merge it
    Map<Integer, List<VoltTable>> results = new HashMap<Integer, List<VoltTable>>();
    for (int i = 0; i < msg.getTableCount(); i++) {
        int this_depId = msg.getTableDependencyIdAtIndex(i);
        VoltTable this_dep = msg.getTableAtIndex(i);
        List<VoltTable> tables = results.get(this_depId);
        if (tables == null) {
            tables = new ArrayList<VoltTable>();
            results.put(this_depId, tables);
        }
        tables.add(this_dep);
    }
    // Need some sanity check that we got all of the expected output dependencies?
    return results;
}
Also used : VoltTrace(org.voltdb.utils.VoltTrace) FragmentTaskMessage(org.voltdb.messaging.FragmentTaskMessage) HashMap(java.util.HashMap) BorrowTaskMessage(org.voltdb.messaging.BorrowTaskMessage) VoltTable(org.voltdb.VoltTable) FragmentResponseMessage(org.voltdb.messaging.FragmentResponseMessage) ArrayList(java.util.ArrayList) List(java.util.List)

Example 2 with BorrowTaskMessage

use of org.voltdb.messaging.BorrowTaskMessage in project voltdb by VoltDB.

the class TestMpTransactionState method testMPReadWithDummyResponse.

@Test
public void testMPReadWithDummyResponse() throws IOException {
    long txnId = 1234l;
    int batch_size = 3;
    Iv2InitiateTaskMessage taskmsg = new Iv2InitiateTaskMessage(0, -1, (txnId - 1), txnId, System.currentTimeMillis(), true, false, new StoredProcedureInvocation(), 0, 0, false);
    int hsids = 6;
    buddyHSId = 0;
    long[] non_local = configureHSIds(hsids);
    MpTestPlan plan = createTestPlan(batch_size, true, false, false, non_local);
    // replace the last remote fragment response with a dummy
    for (FragmentResponseMessage dummy : plan.generatedResponses) {
        if (dummy.getExecutorSiteId() == non_local[non_local.length - 1]) {
            dummy.setRecovering(true);
            for (int i = 0; i < dummy.getTableCount(); i++) {
                VoltTable depTable = dummy.getTableAtIndex(i);
                depTable.setStatusCode(VoltTableUtil.NULL_DEPENDENCY_STATUS);
                depTable.clearRowData();
            }
        }
    }
    Mailbox mailbox = mock(Mailbox.class);
    SiteProcedureConnection siteConnection = mock(SiteProcedureConnection.class);
    MpTransactionState dut = new MpTransactionState(mailbox, taskmsg, allHsids, partMasters, buddyHSId, false);
    // emulate ProcedureRunner's use for a single local fragment
    dut.setupProcedureResume(true, plan.depsToResume);
    dut.createLocalFragmentWork(plan.localWork, false);
    // This will be passed a FragmentTaskMessage with no deps
    dut.createAllParticipatingFragmentWork(plan.remoteWork);
    // we should send 6 messages
    verify(mailbox).send(eq(non_local), (VoltMessage) any());
    // offer all the necessary fragment responses to satisfy deps
    for (FragmentResponseMessage msg : plan.generatedResponses) {
        dut.offerReceivedFragmentResponse(msg);
    }
    // if we've satisfied everything, this should run to completion
    Map<Integer, List<VoltTable>> results = dut.recursableRun(siteConnection);
    ArgumentCaptor<BorrowTaskMessage> borrowCaptor = ArgumentCaptor.forClass(BorrowTaskMessage.class);
    verify(mailbox).send(eq(buddyHSId), borrowCaptor.capture());
    // make sure that the borrow task message doesn't have any dummy dependency tables as input
    BorrowTaskMessage borrowMsg = borrowCaptor.getValue();
    Map<Integer, List<VoltTable>> inputDepMap = borrowMsg.getInputDepMap();
    for (List<VoltTable> tables : inputDepMap.values()) {
        for (VoltTable table : tables) {
            assertNotSame(VoltTableUtil.NULL_DEPENDENCY_STATUS, table.getStatusCode());
        }
    }
    // verify returned deps/tables
    assertEquals(batch_size, results.size());
    System.out.println(results);
}
Also used : StoredProcedureInvocation(org.voltdb.StoredProcedureInvocation) Iv2InitiateTaskMessage(org.voltdb.messaging.Iv2InitiateTaskMessage) BorrowTaskMessage(org.voltdb.messaging.BorrowTaskMessage) VoltTable(org.voltdb.VoltTable) Mailbox(org.voltcore.messaging.Mailbox) SiteProcedureConnection(org.voltdb.SiteProcedureConnection) FragmentResponseMessage(org.voltdb.messaging.FragmentResponseMessage) ArrayList(java.util.ArrayList) List(java.util.List) Test(org.junit.Test)

Aggregations

ArrayList (java.util.ArrayList)2 List (java.util.List)2 VoltTable (org.voltdb.VoltTable)2 BorrowTaskMessage (org.voltdb.messaging.BorrowTaskMessage)2 FragmentResponseMessage (org.voltdb.messaging.FragmentResponseMessage)2 HashMap (java.util.HashMap)1 Test (org.junit.Test)1 Mailbox (org.voltcore.messaging.Mailbox)1 SiteProcedureConnection (org.voltdb.SiteProcedureConnection)1 StoredProcedureInvocation (org.voltdb.StoredProcedureInvocation)1 FragmentTaskMessage (org.voltdb.messaging.FragmentTaskMessage)1 Iv2InitiateTaskMessage (org.voltdb.messaging.Iv2InitiateTaskMessage)1 VoltTrace (org.voltdb.utils.VoltTrace)1