Search in sources :

Example 11 with FragmentResponseMessage

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

the class MpTransactionState method pollForResponses.

private FragmentResponseMessage pollForResponses() {
    FragmentResponseMessage msg = null;
    try {
        final String snapShotRestoreProcName = "@SnapshotRestore";
        while (msg == null) {
            msg = m_newDeps.poll(60L * 5, TimeUnit.SECONDS);
            if (msg == null && !snapShotRestoreProcName.equals(m_initiationMsg.getStoredProcedureName())) {
                tmLog.warn("Possible multipartition transaction deadlock detected for: " + m_initiationMsg);
                if (m_remoteWork == null) {
                    tmLog.warn("Waiting on local BorrowTask response from site: " + CoreUtils.hsIdToString(m_buddyHSId));
                } else {
                    tmLog.warn("Waiting on remote dependencies: ");
                    for (Entry<Integer, Set<Long>> e : m_remoteDeps.entrySet()) {
                        tmLog.warn("Dep ID: " + e.getKey() + " waiting on: " + CoreUtils.hsIdCollectionToString(e.getValue()));
                    }
                }
                m_mbox.send(com.google_voltpatches.common.primitives.Longs.toArray(m_useHSIds), new DumpMessage());
            }
        }
    } catch (InterruptedException e) {
        // could retry; but this is unexpected. Crash.
        throw new RuntimeException(e);
    }
    SerializableException se = msg.getException();
    if (se != null && se instanceof TransactionRestartException) {
        // If this is a restart exception, we don't need to match up the DependencyId
        setNeedsRollback(true);
        throw se;
    }
    return msg;
}
Also used : HashSet(java.util.HashSet) Set(java.util.Set) DumpMessage(org.voltdb.messaging.DumpMessage) FragmentResponseMessage(org.voltdb.messaging.FragmentResponseMessage) TransactionRestartException(org.voltdb.exceptions.TransactionRestartException) SerializableException(org.voltdb.exceptions.SerializableException)

Example 12 with FragmentResponseMessage

use of org.voltdb.messaging.FragmentResponseMessage 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 13 with FragmentResponseMessage

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

the class SpScheduler method handleFragmentResponseMessage.

// Eventually, the master for a partition set will need to be able to dedupe
// FragmentResponses from its replicas.
private void handleFragmentResponseMessage(FragmentResponseMessage message) {
    final TransactionState txnState = m_outstandingTxns.get(message.getTxnId());
    final VoltTrace.TraceEventBatch traceLog = VoltTrace.log(VoltTrace.Category.SPI);
    // Send the message to the duplicate counter, if any
    DuplicateCounter counter = m_duplicateCounters.get(new DuplicateCounterKey(message.getTxnId(), message.getSpHandle()));
    final TransactionState txn = m_outstandingTxns.get(message.getTxnId());
    if (counter != null) {
        String traceName = "recvfragment";
        if (message.m_sourceHSId != m_mailbox.getHSId()) {
            traceName = "replicatefragment";
        }
        String finalTraceName = traceName;
        if (traceLog != null) {
            traceLog.add(() -> VoltTrace.endAsync(finalTraceName, MiscUtils.hsIdPairTxnIdToString(m_mailbox.getHSId(), message.m_sourceHSId, message.getSpHandle(), message.getTxnId()), "status", message.getStatusCode()));
        }
        int result = counter.offer(message);
        if (result == DuplicateCounter.DONE) {
            if (txn != null && txn.isDone()) {
                setRepairLogTruncationHandle(txn.m_spHandle);
            }
            m_duplicateCounters.remove(new DuplicateCounterKey(message.getTxnId(), message.getSpHandle()));
            FragmentResponseMessage resp = (FragmentResponseMessage) counter.getLastResponse();
            // MPI is tracking deps per partition HSID.  We need to make
            // sure we write ours into the message getting sent to the MPI
            resp.setExecutorSiteId(m_mailbox.getHSId());
            m_mailbox.send(counter.m_destinationId, resp);
        } else if (result == DuplicateCounter.MISMATCH) {
            VoltDB.crashGlobalVoltDB("HASH MISMATCH running multi-part procedure.", true, null);
        } else if (result == DuplicateCounter.ABORT) {
            VoltDB.crashGlobalVoltDB("PARTIAL ROLLBACK/ABORT running multi-part procedure.", true, null);
        }
        // doing duplicate suppression: all done.
        return;
    }
    // K-safety: read-only queries (on master) or write queries (on replica).
    if (m_defaultConsistencyReadLevel == ReadLevel.SAFE && m_isLeader && m_sendToHSIds.length > 0 && message.getRespBufferable() && (txn == null || txn.isReadOnly())) {
        // on k-safety leader with safe reads configuration: one shot reads + normal multi-fragments MP reads
        // we will have to buffer these reads until previous writes acked in the cluster.
        long readTxnId = txn == null ? message.getSpHandle() : txn.m_spHandle;
        m_bufferedReadLog.offer(m_mailbox, message, readTxnId, m_repairLogTruncationHandle);
        return;
    }
    // for complete writes txn, we will advance the transaction point
    if (txn != null && !txn.isReadOnly() && txn.isDone()) {
        setRepairLogTruncationHandle(txn.m_spHandle);
    }
    if (traceLog != null) {
        traceLog.add(() -> VoltTrace.endAsync("recvfragment", MiscUtils.hsIdPairTxnIdToString(m_mailbox.getHSId(), message.m_sourceHSId, message.getSpHandle(), message.getTxnId()), "status", message.getStatusCode()));
    }
    m_mailbox.send(message.getDestinationSiteId(), message);
}
Also used : TransactionState(org.voltdb.dtxn.TransactionState) VoltTrace(org.voltdb.utils.VoltTrace) FragmentResponseMessage(org.voltdb.messaging.FragmentResponseMessage)

Example 14 with FragmentResponseMessage

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

the class SysprocFragmentTask method respondWithDummy.

/**
     * Respond with a dummy fragment response.
     */
private void respondWithDummy() {
    final FragmentResponseMessage response = new FragmentResponseMessage(m_fragmentMsg, m_initiator.getHSId());
    response.m_sourceHSId = m_initiator.getHSId();
    response.setRecovering(true);
    response.setStatus(FragmentResponseMessage.SUCCESS, null);
    // on elastic join, so the fragment response message is actually going to the MPI.
    for (int frag = 0; frag < m_fragmentMsg.getFragmentCount(); frag++) {
        final int outputDepId = m_fragmentMsg.getOutputDepId(frag);
        response.addDependency(new DependencyPair.BufferDependencyPair(outputDepId, m_rawDummyResponse, 0, m_rawDummyResponse.length));
    }
    response.setRespBufferable(m_respBufferable);
    m_initiator.deliver(response);
}
Also used : FragmentResponseMessage(org.voltdb.messaging.FragmentResponseMessage) DependencyPair(org.voltdb.DependencyPair)

Example 15 with FragmentResponseMessage

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

the class TestMpTransactionState method testOneSitePartitionedReadWithRollback.

@Test
public void testOneSitePartitionedReadWithRollback() throws IOException {
    long txnId = 1234l;
    int batch_size = 3;
    Iv2InitiateTaskMessage taskmsg = new Iv2InitiateTaskMessage(0, 0, (txnId - 1), txnId, System.currentTimeMillis(), true, false, new StoredProcedureInvocation(), 0, 0, false);
    int hsids = 1;
    buddyHSId = 0;
    long[] non_local = configureHSIds(hsids);
    MpTestPlan plan = createTestPlan(batch_size, true, false, true, non_local);
    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 one message
    verify(mailbox).send(eq(new long[] { 0 }), (VoltMessage) any());
    // offer all the necessary fragment responses to satisfy deps
    for (FragmentResponseMessage msg : plan.generatedResponses) {
        System.out.println("Offering response: " + msg);
        dut.offerReceivedFragmentResponse(msg);
    }
    // We're getting an error, so this should throw something
    boolean threw = false;
    try {
        dut.recursableRun(siteConnection);
        fail();
    } catch (EEException eee) {
        if (eee.getErrorCode() == 1234) {
            threw = true;
        }
    }
    assertTrue(threw);
}
Also used : StoredProcedureInvocation(org.voltdb.StoredProcedureInvocation) Mailbox(org.voltcore.messaging.Mailbox) SiteProcedureConnection(org.voltdb.SiteProcedureConnection) Iv2InitiateTaskMessage(org.voltdb.messaging.Iv2InitiateTaskMessage) FragmentResponseMessage(org.voltdb.messaging.FragmentResponseMessage) EEException(org.voltdb.exceptions.EEException) Test(org.junit.Test)

Aggregations

FragmentResponseMessage (org.voltdb.messaging.FragmentResponseMessage)23 ArrayList (java.util.ArrayList)9 Test (org.junit.Test)9 List (java.util.List)6 Mailbox (org.voltcore.messaging.Mailbox)6 DependencyPair (org.voltdb.DependencyPair)6 SiteProcedureConnection (org.voltdb.SiteProcedureConnection)6 StoredProcedureInvocation (org.voltdb.StoredProcedureInvocation)6 Iv2InitiateTaskMessage (org.voltdb.messaging.Iv2InitiateTaskMessage)6 VoltTable (org.voltdb.VoltTable)5 EEException (org.voltdb.exceptions.EEException)5 FragmentTaskMessage (org.voltdb.messaging.FragmentTaskMessage)5 VoltTrace (org.voltdb.utils.VoltTrace)4 Matchers.anyLong (org.mockito.Matchers.anyLong)2 ParameterSet (org.voltdb.ParameterSet)2 TransactionState (org.voltdb.dtxn.TransactionState)2 SQLException (org.voltdb.exceptions.SQLException)2 SerializableException (org.voltdb.exceptions.SerializableException)2 TransactionRestartException (org.voltdb.exceptions.TransactionRestartException)2 BorrowTaskMessage (org.voltdb.messaging.BorrowTaskMessage)2