Search in sources :

Example 11 with CompleteTransactionMessage

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

the class InitiatorMailbox method repairReplicasWithInternal.

private void repairReplicasWithInternal(List<Long> needsRepair, VoltMessage repairWork) {
    assert (lockingVows());
    if (repairWork instanceof Iv2InitiateTaskMessage) {
        Iv2InitiateTaskMessage m = (Iv2InitiateTaskMessage) repairWork;
        Iv2InitiateTaskMessage work = new Iv2InitiateTaskMessage(m.getInitiatorHSId(), getHSId(), m);
        m_scheduler.handleMessageRepair(needsRepair, work);
    } else if (repairWork instanceof FragmentTaskMessage) {
        // We need to get this into the repair log in case we've never seen it before.  Adding fragment
        // tasks to the repair log is safe; we'll never overwrite the first fragment if we've already seen it.
        m_repairLog.deliver(repairWork);
        m_scheduler.handleMessageRepair(needsRepair, repairWork);
    } else if (repairWork instanceof CompleteTransactionMessage) {
        // CompleteTransactionMessages should always be safe to handle.  Either the work was done, and we'll
        // ignore it, or we need to clean up, or we'll be restarting and it doesn't matter.  Make sure they
        // get into the repair log and then let them run their course.
        m_repairLog.deliver(repairWork);
        m_scheduler.handleMessageRepair(needsRepair, repairWork);
    } else {
        throw new RuntimeException("Invalid repair message type: " + repairWork);
    }
}
Also used : FragmentTaskMessage(org.voltdb.messaging.FragmentTaskMessage) Iv2InitiateTaskMessage(org.voltdb.messaging.Iv2InitiateTaskMessage) CompleteTransactionMessage(org.voltdb.messaging.CompleteTransactionMessage)

Example 12 with CompleteTransactionMessage

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

the class MpProcedureTask method completeInitiateTask.

@Override
void completeInitiateTask(SiteProcedureConnection siteConnection) {
    final VoltTrace.TraceEventBatch traceLog = VoltTrace.log(VoltTrace.Category.MPSITE);
    if (traceLog != null) {
        traceLog.add(() -> VoltTrace.instant("sendcomplete", "txnId", TxnEgo.txnIdToString(getTxnId()), "commit", Boolean.toString(!m_txnState.needsRollback()), "dest", CoreUtils.hsIdCollectionToString(m_initiatorHSIds)));
    }
    CompleteTransactionMessage complete = new CompleteTransactionMessage(// who is the "initiator" now??
    m_initiator.getHSId(), m_initiator.getHSId(), m_txnState.txnId, m_txnState.isReadOnly(), m_txnState.getHash(), m_txnState.needsRollback(), // really don't want to have ack the ack.
    false, false, m_msg.isForReplay());
    complete.setTruncationHandle(m_msg.getTruncationHandle());
    m_initiator.send(com.google_voltpatches.common.primitives.Longs.toArray(m_initiatorHSIds), complete);
    m_txnState.setDone();
    m_queue.flush(getTxnId());
}
Also used : VoltTrace(org.voltdb.utils.VoltTrace) CompleteTransactionMessage(org.voltdb.messaging.CompleteTransactionMessage)

Example 13 with CompleteTransactionMessage

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

the class SpScheduler method handleCompleteTransactionMessage.

private void handleCompleteTransactionMessage(CompleteTransactionMessage message) {
    CompleteTransactionMessage msg = message;
    if (m_isLeader) {
        msg = new CompleteTransactionMessage(m_mailbox.getHSId(), m_mailbox.getHSId(), message);
        // Set the spHandle so that on repair the new master will set the max seen spHandle
        // correctly
        advanceTxnEgo();
        msg.setSpHandle(getCurrentTxnId());
        if (m_sendToHSIds.length > 0 && !msg.isReadOnly()) {
            m_mailbox.send(m_sendToHSIds, msg);
        }
    } else {
        setMaxSeenTxnId(msg.getSpHandle());
    }
    logRepair(msg);
    TransactionState txn = m_outstandingTxns.get(msg.getTxnId());
    // now, fix that later.
    if (txn != null) {
        CompleteTransactionMessage finalMsg = msg;
        final VoltTrace.TraceEventBatch traceLog = VoltTrace.log(VoltTrace.Category.SPI);
        if (traceLog != null) {
            traceLog.add(() -> VoltTrace.instant("recvCompleteTxn", "txnId", TxnEgo.txnIdToString(finalMsg.getTxnId()), "partition", Integer.toString(m_partitionId), "hsId", CoreUtils.hsIdToString(m_mailbox.getHSId())));
        }
        final boolean isSysproc = ((FragmentTaskMessage) txn.getNotice()).isSysProcTask();
        if (m_sendToHSIds.length > 0 && !msg.isRestart() && (!msg.isReadOnly() || isSysproc)) {
            DuplicateCounter counter;
            counter = new DuplicateCounter(msg.getCoordinatorHSId(), msg.getTxnId(), m_replicaHSIds, msg);
            safeAddToDuplicateCounterMap(new DuplicateCounterKey(msg.getTxnId(), msg.getSpHandle()), counter);
        }
        Iv2Trace.logCompleteTransactionMessage(msg, m_mailbox.getHSId());
        final CompleteTransactionTask task = new CompleteTransactionTask(m_mailbox, txn, m_pendingTasks, msg);
        queueOrOfferMPTask(task);
    } else {
        // Generate a dummy response message when this site has not seen previous FragmentTaskMessage,
        // the leader may have started to wait for replicas' response messages.
        // This can happen in the early phase of site rejoin before replica receiving the snapshot initiation,
        // it also means this CompleteTransactionMessage message will be dropped because it's after snapshot.
        final CompleteTransactionResponseMessage resp = new CompleteTransactionResponseMessage(msg);
        resp.m_sourceHSId = m_mailbox.getHSId();
        handleCompleteTransactionResponseMessage(resp);
    }
}
Also used : TransactionState(org.voltdb.dtxn.TransactionState) CompleteTransactionResponseMessage(org.voltdb.messaging.CompleteTransactionResponseMessage) VoltTrace(org.voltdb.utils.VoltTrace) FragmentTaskMessage(org.voltdb.messaging.FragmentTaskMessage) CompleteTransactionMessage(org.voltdb.messaging.CompleteTransactionMessage)

Example 14 with CompleteTransactionMessage

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

the class MpScheduler method handleInitiateResponseMessage.

// The MpScheduler will see InitiateResponseMessages from the Partition masters when
// performing an every-partition system procedure.  A consequence of this deduping
// is that the MpScheduler will also need to forward the final InitiateResponseMessage
// for a normal multipartition procedure back to the client interface since it must
// see all of these messages and control their transmission.
public void handleInitiateResponseMessage(InitiateResponseMessage message) {
    final VoltTrace.TraceEventBatch traceLog = VoltTrace.log(VoltTrace.Category.MPI);
    if (traceLog != null) {
        traceLog.add(() -> VoltTrace.endAsync("initmp", message.getTxnId()));
    }
    DuplicateCounter counter = m_duplicateCounters.get(message.getTxnId());
    if (counter != null) {
        int result = counter.offer(message);
        if (result == DuplicateCounter.DONE) {
            m_duplicateCounters.remove(message.getTxnId());
            // Only advance the truncation point on committed transactions.  See ENG-4211
            if (message.shouldCommit()) {
                m_repairLogTruncationHandle = m_repairLogAwaitingCommit;
                m_repairLogAwaitingCommit = message.getTxnId();
            }
            m_outstandingTxns.remove(message.getTxnId());
            m_mailbox.send(counter.m_destinationId, message);
        } else if (result == DuplicateCounter.MISMATCH) {
            VoltDB.crashLocalVoltDB("HASH MISMATCH running every-site system procedure.", true, null);
        } else if (result == DuplicateCounter.ABORT) {
            VoltDB.crashLocalVoltDB("PARTIAL ROLLBACK/ABORT running every-site system procedure.", true, null);
        }
    // doing duplicate suppresion: all done.
    } else {
        // Only advance the truncation point on committed transactions.
        if (message.shouldCommit()) {
            m_repairLogTruncationHandle = m_repairLogAwaitingCommit;
            m_repairLogAwaitingCommit = message.getTxnId();
        }
        m_outstandingTxns.remove(message.getTxnId());
        // the initiatorHSId is the ClientInterface mailbox. Yeah. I know.
        m_mailbox.send(message.getInitiatorHSId(), message);
        // We actually completed this MP transaction.  Create a fake CompleteTransactionMessage
        // to send to our local repair log so that the fate of this transaction is never forgotten
        // even if all the masters somehow die before forwarding Complete on to their replicas.
        CompleteTransactionMessage ctm = new CompleteTransactionMessage(m_mailbox.getHSId(), message.m_sourceHSId, message.getTxnId(), message.isReadOnly(), 0, !message.shouldCommit(), false, false, false);
        ctm.setTruncationHandle(m_repairLogTruncationHandle);
        // dump it in the repair log
        // hacky castage
        ((MpInitiatorMailbox) m_mailbox).deliverToRepairLog(ctm);
    }
}
Also used : VoltTrace(org.voltdb.utils.VoltTrace) CompleteTransactionMessage(org.voltdb.messaging.CompleteTransactionMessage)

Example 15 with CompleteTransactionMessage

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

the class TestSpPromoteAlgo method testFuzz.

@Test
public void testFuzz() throws Exception {
    InitiatorMailbox mbox = mock(InitiatorMailbox.class);
    Map<Long, List<TransactionInfoBaseMessage>> finalStreams = new HashMap<Long, List<TransactionInfoBaseMessage>>();
    Random rand = new Random(System.currentTimeMillis());
    // Generate a random message stream to several "replicas", interrupted
    // at random points to all but one.  Validate that promotion repair
    // results in identical, correct, repair streams to all replicas.
    TxnEgo sphandle = TxnEgo.makeZero(0);
    UniqueIdGenerator spbuig = new UniqueIdGenerator(0, 0);
    UniqueIdGenerator mpbuig = new UniqueIdGenerator(0, 0);
    sphandle = sphandle.makeNext();
    RandomMsgGenerator msgGen = new RandomMsgGenerator();
    boolean[] stops = new boolean[3];
    RepairLog[] logs = new RepairLog[3];
    for (int i = 0; i < 3; i++) {
        logs[i] = new RepairLog();
        stops[i] = false;
        finalStreams.put((long) i, new ArrayList<TransactionInfoBaseMessage>());
    }
    long maxBinaryLogSpUniqueId = Long.MIN_VALUE;
    for (int i = 0; i < 4000; i++) {
        // get next message, update the sphandle according to SpScheduler rules,
        // but only submit messages that would have been forwarded by the master
        // to the repair log.
        TransactionInfoBaseMessage msg = msgGen.generateRandomMessageInStream();
        msg.setSpHandle(sphandle.getTxnId());
        if (msg instanceof Iv2InitiateTaskMessage) {
            Pair<Long, Long> uids = TestRepairLog.setBinaryLogUniqueId(msg, spbuig, mpbuig);
            maxBinaryLogSpUniqueId = Math.max(maxBinaryLogSpUniqueId, uids.getFirst());
        }
        sphandle = sphandle.makeNext();
        if (!msg.isReadOnly() || msg instanceof CompleteTransactionMessage) {
            if (!stops[0]) {
                logs[0].deliver(msg);
            }
            if (!stops[1]) {
                logs[1].deliver(msg);
            }
            logs[2].deliver(msg);
            // be fed any transactions
            for (int j = 0; j < 2; j++) {
                // Hacky way to get spaced failures
                if (rand.nextDouble() < (.01 / ((j + 1) * 5))) {
                    stops[j] = true;
                }
            }
        }
    }
    List<Long> survivors = new ArrayList<Long>();
    survivors.add(0l);
    survivors.add(1l);
    survivors.add(2l);
    SpPromoteAlgo dut = new SpPromoteAlgo(survivors, mbox, "bleh ", 0);
    Future<RepairResult> result = dut.start();
    for (int i = 0; i < 3; i++) {
        List<Iv2RepairLogResponseMessage> stuff = logs[i].contents(dut.getRequestId(), false);
        System.out.println("Repair log size from: " + i + ": " + stuff.size());
        for (Iv2RepairLogResponseMessage msg : stuff) {
            msg.m_sourceHSId = i;
            dut.deliver(msg);
            // First message is metadata only, skip it in validation stream
            if (msg.getSequence() > 0) {
                //System.out.println("finalstreams: " + finalStreams);
                //System.out.println("get(i): " + i + ": " + finalStreams.get((long)i));
                //System.out.println("msg: " + msg);
                finalStreams.get((long) i).add((TransactionInfoBaseMessage) msg.getPayload());
            }
        }
    }
    assertFalse(result.isCancelled());
    assertTrue(result.isDone());
    // of repairSurvivors()
    for (Iv2RepairLogResponseMessage li : dut.m_repairLogUnion) {
        for (Entry<Long, SpPromoteAlgo.ReplicaRepairStruct> entry : dut.m_replicaRepairStructs.entrySet()) {
            if (entry.getValue().needs(li.getHandle())) {
                // append the missing message for this 'node' to the list of messages that node has seen
                finalStreams.get(entry.getKey()).add((TransactionInfoBaseMessage) li.getPayload());
            }
        }
    }
    // check that all the lists for all the nodes are identical after repair
    int longest = Integer.MIN_VALUE;
    for (Entry<Long, List<TransactionInfoBaseMessage>> entry : finalStreams.entrySet()) {
        System.out.println("SIZE: " + entry.getValue().size());
        if (entry.getValue().size() > longest) {
            if (longest == Integer.MIN_VALUE) {
                longest = entry.getValue().size();
            } else {
                fail("Mismatch in repair stream size!");
            }
        }
    }
    for (int i = 0; i < longest; i++) {
        TransactionInfoBaseMessage current = null;
        for (Entry<Long, List<TransactionInfoBaseMessage>> entry : finalStreams.entrySet()) {
            TransactionInfoBaseMessage msg = entry.getValue().get(i);
            if (current == null) {
                current = msg;
            } else {
                assertEquals(current.getSpHandle(), msg.getSpHandle());
                assertEquals(current.getClass(), msg.getClass());
            }
        }
    }
}
Also used : Iv2RepairLogResponseMessage(org.voltdb.messaging.Iv2RepairLogResponseMessage) HashMap(java.util.HashMap) Iv2InitiateTaskMessage(org.voltdb.messaging.Iv2InitiateTaskMessage) ArrayList(java.util.ArrayList) Random(java.util.Random) CompleteTransactionMessage(org.voltdb.messaging.CompleteTransactionMessage) TransactionInfoBaseMessage(org.voltcore.messaging.TransactionInfoBaseMessage) ArrayList(java.util.ArrayList) List(java.util.List) RepairResult(org.voltdb.iv2.RepairAlgo.RepairResult) Test(org.junit.Test)

Aggregations

CompleteTransactionMessage (org.voltdb.messaging.CompleteTransactionMessage)19 FragmentTaskMessage (org.voltdb.messaging.FragmentTaskMessage)9 Iv2InitiateTaskMessage (org.voltdb.messaging.Iv2InitiateTaskMessage)7 Iv2RepairLogResponseMessage (org.voltdb.messaging.Iv2RepairLogResponseMessage)7 TransactionInfoBaseMessage (org.voltcore.messaging.TransactionInfoBaseMessage)4 VoltTrace (org.voltdb.utils.VoltTrace)4 Test (org.junit.Test)3 ArrayList (java.util.ArrayList)2 Random (java.util.Random)2 AtomicLong (java.util.concurrent.atomic.AtomicLong)2 RepairResult (org.voltdb.iv2.RepairAlgo.RepairResult)2 HashMap (java.util.HashMap)1 List (java.util.List)1 VoltMessage (org.voltcore.messaging.VoltMessage)1 ClientResponseImpl (org.voltdb.ClientResponseImpl)1 VoltTable (org.voltdb.VoltTable)1 TransactionState (org.voltdb.dtxn.TransactionState)1 CompleteTransactionResponseMessage (org.voltdb.messaging.CompleteTransactionResponseMessage)1 DumpMessage (org.voltdb.messaging.DumpMessage)1 InitiateResponseMessage (org.voltdb.messaging.InitiateResponseMessage)1