Search in sources :

Example 26 with TransactionInfoBaseMessage

use of org.voltcore.messaging.TransactionInfoBaseMessage in project voltdb by VoltDB.

the class TestMpPromoteAlgo method testFuzz.

@Test
public void testFuzz() throws Exception {
    System.out.println("Running testFuzz");
    InitiatorMailbox mbox = mock(InitiatorMailbox.class);
    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 uig = 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;
    }
    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());
        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);
    MpPromoteAlgo dut = new MpPromoteAlgo(survivors, mbox, "bleh ");
    Future<RepairResult> result = dut.start();
    for (int i = 0; i < 3; i++) {
        List<Iv2RepairLogResponseMessage> stuff = logs[i].contents(dut.getRequestId(), true);
        System.out.println("Repair log size from: " + i + ": " + stuff.size());
        for (Iv2RepairLogResponseMessage msg : stuff) {
            msg.m_sourceHSId = (long) i;
            dut.deliver(msg);
        }
    }
    result.get();
    assertFalse(result.isCancelled());
    assertTrue(result.isDone());
    // Unfortunately, it's painful to try to stub things to make repairSurvivors() work, so we'll
    // go and inspect the guts of SpPromoteAlgo instead.  This iteration is largely a copy of the inner loop
    // of repairSurvivors()
    List<TransactionInfoBaseMessage> finalStream = new ArrayList<TransactionInfoBaseMessage>();
    for (Iv2RepairLogResponseMessage li : dut.m_repairLogUnion) {
        VoltMessage msg = dut.createRepairMessage(li);
        finalStream.add((TransactionInfoBaseMessage) msg);
    }
    // Check the sanity of the repair stream generated by the MPI.
    long lastTxnId = Long.MIN_VALUE;
    boolean seenFrag = false;
    for (TransactionInfoBaseMessage msg : finalStream) {
        if (lastTxnId == Long.MIN_VALUE) {
            lastTxnId = msg.getTxnId();
        } else {
            assertTrue(msg.getTxnId() > lastTxnId);
            lastTxnId = msg.getTxnId();
        }
        if (msg instanceof FragmentTaskMessage) {
            assertFalse(seenFrag);
            seenFrag = true;
        }
    }
}
Also used : Iv2RepairLogResponseMessage(org.voltdb.messaging.Iv2RepairLogResponseMessage) FragmentTaskMessage(org.voltdb.messaging.FragmentTaskMessage) ArrayList(java.util.ArrayList) RepairResult(org.voltdb.iv2.RepairAlgo.RepairResult) VoltMessage(org.voltcore.messaging.VoltMessage) Random(java.util.Random) CompleteTransactionMessage(org.voltdb.messaging.CompleteTransactionMessage) TransactionInfoBaseMessage(org.voltcore.messaging.TransactionInfoBaseMessage) Test(org.junit.Test)

Example 27 with TransactionInfoBaseMessage

use of org.voltcore.messaging.TransactionInfoBaseMessage in project voltdb by VoltDB.

the class AgreementSite method processMessage.

private void processMessage(VoltMessage message) throws Exception {
    if (!m_hsIds.contains(message.m_sourceHSId)) {
        m_recoveryLog.info("Dropping message " + message + " because it is not from a known up site");
        return;
    }
    if (message instanceof TransactionInfoBaseMessage) {
        TransactionInfoBaseMessage info = (TransactionInfoBaseMessage) message;
        // Special case heartbeats which only update RPQ
        if (info instanceof HeartbeatMessage) {
            // use the heartbeat to unclog the priority queue if clogged
            long lastSeenTxnFromInitiator = m_txnQueue.noteTransactionRecievedAndReturnLastSeen(info.getInitiatorHSId(), info.getTxnId(), ((HeartbeatMessage) info).getLastSafeTxnId());
            // respond to the initiator with the last seen transaction
            HeartbeatResponseMessage response = new HeartbeatResponseMessage(m_hsId, lastSeenTxnFromInitiator, m_txnQueue.getQueueState() == RestrictedPriorityQueue.QueueState.BLOCKED_SAFETY);
            m_mailbox.send(info.getInitiatorHSId(), response);
            // we're done here (in the case of heartbeats)
            return;
        }
        assert (false);
    } else if (message instanceof HeartbeatResponseMessage) {
        HeartbeatResponseMessage hrm = (HeartbeatResponseMessage) message;
        m_safetyState.updateLastSeenTxnIdFromExecutorBySiteId(hrm.getExecHSId(), hrm.getLastReceivedTxnId());
    } else if (message instanceof LocalObjectMessage) {
        LocalObjectMessage lom = (LocalObjectMessage) message;
        if (lom.payload instanceof Runnable) {
            ((Runnable) lom.payload).run();
        } else if (lom.payload instanceof Request) {
            Request r = (Request) lom.payload;
            long txnId = 0;
            boolean isRead = false;
            switch(r.type) {
                case OpCode.createSession:
                    txnId = r.sessionId;
                    break;
                //For reads see if we can skip global agreement and just do the read
                case OpCode.exists:
                case OpCode.getChildren:
                case OpCode.getChildren2:
                case OpCode.getData:
                    //in this case because ordering of reads and writes matters
                    if (m_txnQueue.isEmpty()) {
                        r.setOwner(m_hsId);
                        m_server.prepRequest(new Request(r), m_lastUsedTxnId);
                        return;
                    }
                    isRead = true;
                //it in the global order
                default:
                    txnId = m_idManager.getNextUniqueTransactionId();
                    break;
            }
            /*
                 * Don't send the whole request if this is a read blocked on a write
                 * We may send a heartbeat instead of propagating a useless read transaction
                 * at the end of this block
                 */
            if (!isRead) {
                for (long initiatorHSId : m_hsIds) {
                    if (initiatorHSId == m_hsId)
                        continue;
                    AgreementTaskMessage atm = new AgreementTaskMessage(r, txnId, m_hsId, m_safetyState.getNewestGloballySafeTxnId());
                    m_mailbox.send(initiatorHSId, atm);
                }
            }
            //Process the ATM eagerly locally to aid
            //in having a complete set of stuff to ship
            //to a recovering agreement site
            AgreementTaskMessage atm = new AgreementTaskMessage(new Request(r), txnId, m_hsId, m_safetyState.getNewestGloballySafeTxnId());
            atm.m_sourceHSId = m_hsId;
            processMessage(atm);
            /*
                 * Don't send a heartbeat out for ever single blocked read that occurs
                 * Try and limit to 2000 a second which is a lot and should be pretty
                 * close to the previous behavior of propagating all reads. My measurements
                 * don't show the old behavior is better than none at all, but I fear
                 * change.
                 */
            if (isRead) {
                final long now = System.nanoTime();
                if (TimeUnit.NANOSECONDS.toMicros(now - m_lastHeartbeatTime) > 500) {
                    m_lastHeartbeatTime = now;
                    sendHeartbeats();
                }
            }
        }
    } else if (message instanceof AgreementTaskMessage) {
        AgreementTaskMessage atm = (AgreementTaskMessage) message;
        if (!m_transactionsById.containsKey(atm.m_txnId) && atm.m_txnId >= m_minTxnIdAfterRecovery) {
            m_txnQueue.noteTransactionRecievedAndReturnLastSeen(atm.m_initiatorHSId, atm.m_txnId, atm.m_lastSafeTxnId);
            AgreementTransactionState transactionState = new AgreementTransactionState(atm.m_txnId, atm.m_initiatorHSId, atm.m_request);
            if (m_txnQueue.add(transactionState)) {
                m_transactionsById.put(transactionState.txnId, transactionState);
            } else {
                m_agreementLog.info("Dropping txn " + transactionState.txnId + " data from failed initiatorSiteId: " + transactionState.initiatorHSId);
            }
        } else {
            m_recoveryLog.info("Agreement, discarding duplicate txn during recovery, txnid is " + atm.m_txnId + " this should only occur during recovery. minTxnIdAfterRecovery " + m_minTxnIdAfterRecovery + " and  dup is " + m_transactionsById.containsKey(atm.m_txnId));
        }
    } else if (message instanceof BinaryPayloadMessage) {
        BinaryPayloadMessage bpm = (BinaryPayloadMessage) message;
        ByteBuffer metadata = ByteBuffer.wrap(bpm.m_metadata);
        final byte type = metadata.get();
        if (type == BINARY_PAYLOAD_SNAPSHOT) {
            assert (m_recovering);
            assert (m_recoveryStage == RecoveryStage.SENT_PROPOSAL);
            if (m_recoveryStage != RecoveryStage.SENT_PROPOSAL) {
                org.voltdb.VoltDB.crashLocalVoltDB("Received a recovery snapshot in stage " + m_recoveryStage.toString(), true, null);
            }
            long selectedRecoverBeforeTxn = metadata.getLong();
            if (selectedRecoverBeforeTxn < m_recoverBeforeTxn) {
                org.voltdb.VoltDB.crashLocalVoltDB("Selected recover before txn was earlier than the  proposed recover before txn", true, null);
            }
            m_recoverBeforeTxn = selectedRecoverBeforeTxn;
            //anything before this precedes the snapshot
            m_minTxnIdAfterRecovery = m_recoverBeforeTxn;
            try {
                m_recoverySnapshot = org.xerial.snappy.Snappy.uncompress(bpm.m_payload);
            } catch (IOException e) {
                org.voltdb.VoltDB.crashLocalVoltDB("Unable to decompress ZK snapshot", true, e);
            }
            m_recoveryStage = RecoveryStage.RECEIVED_SNAPSHOT;
            /*
                 * Clean out all txns from before the snapshot
                 */
            Iterator<Map.Entry<Long, OrderableTransaction>> iter = m_transactionsById.entrySet().iterator();
            while (iter.hasNext()) {
                final Map.Entry<Long, OrderableTransaction> entry = iter.next();
                if (entry.getKey() < m_minTxnIdAfterRecovery) {
                    m_txnQueue.faultTransaction(entry.getValue());
                    iter.remove();
                }
            }
        } else if (type == BINARY_PAYLOAD_JOIN_REQUEST) {
            JSONObject jsObj = new JSONObject(new String(bpm.m_payload, "UTF-8"));
            final long initiatorHSId = jsObj.getLong("initiatorHSId");
            final long txnId = jsObj.getLong("txnId");
            final long lastSafeTxnId = jsObj.getLong("lastSafeTxnId");
            final long joiningHSId = jsObj.getLong("joiningHSId");
            if (m_recovering) {
                org.voltdb.VoltDB.crashLocalVoltDB("Received a join request during recovery for " + CoreUtils.hsIdToString(joiningHSId) + " from " + CoreUtils.hsIdToString(initiatorHSId), true, null);
            }
            m_txnQueue.noteTransactionRecievedAndReturnLastSeen(initiatorHSId, txnId, lastSafeTxnId);
            AgreementRejoinTransactionState transactionState = new AgreementRejoinTransactionState(txnId, initiatorHSId, joiningHSId, null);
            if (m_txnQueue.add(transactionState)) {
                m_transactionsById.put(transactionState.txnId, transactionState);
            } else {
                m_agreementLog.info("Dropping txn " + transactionState.txnId + " data from failed initiatorSiteId: " + transactionState.initiatorHSId);
            }
        }
    } else if (message instanceof FaultMessage) {
        FaultMessage fm = (FaultMessage) message;
        discoverGlobalFaultData(fm);
    } else if (message instanceof RecoveryMessage) {
        RecoveryMessage rm = (RecoveryMessage) message;
        assert (m_recoverBeforeTxn == null);
        assert (m_siteRequestingRecovery == null);
        assert (m_recovering == false);
        assert (m_recoveryStage == RecoveryStage.RECOVERED);
        m_recoverBeforeTxn = rm.txnId();
        m_siteRequestingRecovery = rm.sourceSite();
    }
}
Also used : HeartbeatResponseMessage(org.voltcore.messaging.HeartbeatResponseMessage) Request(org.apache.zookeeper_voltpatches.server.Request) IOException(java.io.IOException) BinaryPayloadMessage(org.voltcore.messaging.BinaryPayloadMessage) ByteBuffer(java.nio.ByteBuffer) LocalObjectMessage(org.voltcore.messaging.LocalObjectMessage) HeartbeatMessage(org.voltcore.messaging.HeartbeatMessage) FaultMessage(org.voltcore.messaging.FaultMessage) JSONObject(org.json_voltpatches.JSONObject) RecoveryMessage(org.voltcore.messaging.RecoveryMessage) TransactionInfoBaseMessage(org.voltcore.messaging.TransactionInfoBaseMessage) AgreementTaskMessage(org.voltcore.messaging.AgreementTaskMessage) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

TransactionInfoBaseMessage (org.voltcore.messaging.TransactionInfoBaseMessage)27 Test (org.junit.Test)24 CompleteTransactionMessage (org.voltdb.messaging.CompleteTransactionMessage)4 ArrayList (java.util.ArrayList)3 FragmentTaskMessage (org.voltdb.messaging.FragmentTaskMessage)3 Iv2InitiateTaskMessage (org.voltdb.messaging.Iv2InitiateTaskMessage)3 Iv2RepairLogResponseMessage (org.voltdb.messaging.Iv2RepairLogResponseMessage)3 HashMap (java.util.HashMap)2 Random (java.util.Random)2 RepairResult (org.voltdb.iv2.RepairAlgo.RepairResult)2 IOException (java.io.IOException)1 ByteBuffer (java.nio.ByteBuffer)1 List (java.util.List)1 Map (java.util.Map)1 AtomicLong (java.util.concurrent.atomic.AtomicLong)1 Request (org.apache.zookeeper_voltpatches.server.Request)1 JSONObject (org.json_voltpatches.JSONObject)1 Matchers.anyLong (org.mockito.Matchers.anyLong)1 AgreementTaskMessage (org.voltcore.messaging.AgreementTaskMessage)1 BinaryPayloadMessage (org.voltcore.messaging.BinaryPayloadMessage)1