/* This file is part of VoltDB.
 * Copyright (C) 2008-2013 VoltDB Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with VoltDB.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.voltdb.messaging;

import java.io.IOException;
import java.nio.ByteBuffer;
import org.voltcore.messaging.Subject;
import org.voltcore.messaging.VoltMessage;

/**
 * Rejoin message used to drive the whole rejoin process. It could be sent from
 * the rejoin coordinator to a local site, or it could be sent from a rejoining
 * site to an existing site.
 */
public class RejoinMessage extends VoltMessage {
    public static enum Type {
        INITIATION,           // start live rejoin or join.
        INITIATION_COMMUNITY, // start community rejoin.
        INITIATION_RESPONSE,  // For IV2, the site must return the HSId of
                              // the SnapshotDataSink mailbox

        // The following are response types
        REQUEST_RESPONSE, // sent from the rejoining site to itself
        SNAPSHOT_FINISHED, // sent from a local site to the coordinator
        REPLAY_FINISHED, // sent from a local site to the coordinator

        // Join specific message types
        FIRST_FRAGMENT_RECEIVED, // sent from a local site to the coordinator
    }

    private Type m_type;
    private long m_snapshotTxnId = -1; // snapshot txnId
    private long m_snapshotSinkHSId = -1;
    private long m_masterHSId = -1;
    private String m_snapshotNonce = null;

    /** Empty constructor for de-serialization */
    public RejoinMessage() {
        m_subject = Subject.DEFAULT.getId();
    }

    public RejoinMessage(long snapshotTxnId) {
        m_subject = Subject.DEFAULT.getId();
        m_type = Type.REQUEST_RESPONSE;
        m_snapshotTxnId = snapshotTxnId;
    }

    public RejoinMessage(long sourceHSId, Type type) {
        m_sourceHSId = sourceHSId;
        m_subject = Subject.DEFAULT.getId();
        m_type = type;
    }

    /**
     * For IV2, INITIATION and INITIATION_COMMUNITY pass the nonce used by the
     * Iv2RejoinCoordinator to the site.
     */
    public RejoinMessage(long sourceHSId, Type type, String snapshotNonce)
    {
        this(sourceHSId, type);
        assert(type == Type.INITIATION || type == Type.INITIATION_COMMUNITY);
        m_snapshotNonce = snapshotNonce;
    }

    /**
     * For IV2, INITIATION_RESPONSE is used by the local site to inform the
     * Iv2RejoinCoordinator of the HSId of the SnapshotDataSink is has created
     */
    public RejoinMessage(long sourceHSId, long masterHSId, long sinkHSId)
    {
        this(sourceHSId, Type.INITIATION_RESPONSE);
        m_masterHSId = masterHSId;
        m_snapshotSinkHSId = sinkHSId;
    }

    public Type getType() {
        return m_type;
    }

    public long getSnapshotTxnId() {
        return m_snapshotTxnId;
    }

    public String getSnapshotNonce() {
        return m_snapshotNonce;
    }

    public long getMasterHSId() {
        return m_masterHSId;
    }

    public long getSnapshotSinkHSId() {
        return m_snapshotSinkHSId;
    }

    @Override
    public int getSerializedSize() {
        int msgsize = super.getSerializedSize();
        msgsize +=
            8 + // m_sourceHSId
            1 + // m_type
            8; // m_snapshotTxnId
        return msgsize;
    }

    @Override
    protected void initFromBuffer(ByteBuffer buf) throws IOException {
        throw new RuntimeException("RejoinMessage: Attempted to deserialize a message which should never need it.");
    }

    @Override
    public void flattenToBuffer(ByteBuffer buf) throws IOException {
        throw new RuntimeException("RejoinMessage: Attempted to serialize a message which should never need it.");
    }
}

@@ -1720,32 +1720,99 @@
 c message types%0A
+        SNAPSHOT_DATA, // sent from the coordinator to local sites%0A
         FIRST_FR
@@ -2082,16 +2082,92 @@
  = null;
+%0A    private int m_tableId = -1;%0A    private ByteBuffer m_tableBlock = null;
 %0A%0A    /*
@@ -3387,32 +3387,338 @@
 inkHSId;%0A    %7D%0A%0A
+    /**%0A     * For IV2, tee replicated table blocks from the coordinator to each site's producer%0A     */%0A    public RejoinMessage(long sourceHSId, int tableId, ByteBuffer tableBlock)%0A    %7B%0A        this(sourceHSId, Type.SNAPSHOT_DATA);%0A        m_tableId = tableId;%0A        m_tableBlock = tableBlock;%0A    %7D%0A%0A
     public Type 
@@ -4057,32 +4057,183 @@
 inkHSId;%0A    %7D%0A%0A
+    public int getTableId() %7B%0A        return m_tableId;%0A    %7D%0A%0A    public ByteBuffer getTableBlock() %7B%0A        return m_tableBlock.duplicate();%0A    %7D%0A%0A
     @Override%0A  

Add a new type to RejoinMessage for table block data transfer.