001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2006-2010 Sun Microsystems, Inc.
015 * Portions copyright 2013-2014 ForgeRock AS.
016 */
017package org.opends.server.replication.protocol;
018
019import java.util.zip.DataFormatException;
020
021/**
022 * Abstract class that must be used when defining messages that can
023 * be sent for replication purpose between servers.
024 *
025 * When extending this class one should also create a new MSG_TYPE
026 * and should update the generateMsg() method.
027 */
028public abstract class ReplicationMsg
029{
030  // PDU type values kept for compatibility with replication protocol version 1
031  static final byte MSG_TYPE_MODIFY_V1 = 1;
032  static final byte MSG_TYPE_ADD_V1 = 2;
033  static final byte MSG_TYPE_DELETE_V1 = 3;
034  static final byte MSG_TYPE_MODIFYDN_V1 = 4;
035  static final byte MSG_TYPE_SERVER_START_V1 = 6;
036  static final byte MSG_TYPE_REPL_SERVER_START_V1 = 7;
037  static final byte MSG_TYPE_REPL_SERVER_INFO_V1 = 16;
038
039  // PDU type values for current protocol version (see ProtocolVersion)
040  static final byte MSG_TYPE_ACK = 5;
041  static final byte MSG_TYPE_WINDOW = 8;
042  static final byte MSG_TYPE_HEARTBEAT = 9;
043  static final byte MSG_TYPE_INITIALIZE_REQUEST = 10;
044  static final byte MSG_TYPE_INITIALIZE_TARGET = 11;
045  static final byte MSG_TYPE_ENTRY = 12;
046  static final byte MSG_TYPE_DONE = 13;
047  static final byte MSG_TYPE_ERROR = 14;
048  static final byte MSG_TYPE_WINDOW_PROBE = 15;
049  static final byte MSG_TYPE_RESET_GENERATION_ID = 17;
050  static final byte MSG_TYPE_REPL_SERVER_MONITOR_REQUEST = 18;
051  static final byte MSG_TYPE_REPL_SERVER_MONITOR = 19;
052  static final byte MSG_TYPE_SERVER_START = 20;
053  static final byte MSG_TYPE_REPL_SERVER_START = 21;
054  static final byte MSG_TYPE_MODIFY = 22;
055  static final byte MSG_TYPE_ADD = 23;
056  static final byte MSG_TYPE_DELETE = 24;
057  static final byte MSG_TYPE_MODIFYDN = 25;
058  static final byte MSG_TYPE_TOPOLOGY = 26;
059  static final byte MSG_TYPE_START_SESSION = 27;
060  static final byte MSG_TYPE_CHANGE_STATUS = 28;
061  static final byte MSG_TYPE_GENERIC_UPDATE = 29;
062
063  // Added for protocol version 3
064  @Deprecated
065  static final byte MSG_TYPE_START_ECL = 30;
066  @Deprecated
067  static final byte MSG_TYPE_START_ECL_SESSION = 31;
068  @Deprecated
069  static final byte MSG_TYPE_ECL_UPDATE = 32;
070  static final byte MSG_TYPE_CT_HEARTBEAT = 33;
071
072  // Added for protocol version 4
073  // - New msgs types
074  static final byte MSG_TYPE_REPL_SERVER_START_DS = 34;
075  static final byte MSG_TYPE_STOP = 35;
076  static final byte MSG_TYPE_INITIALIZE_RCV_ACK = 36;
077  // - Modified msgs types
078  //   EntryMsg, InitializeRequestMsg, InitializeTargetMsg, ErrorMsg
079  //   TopologyMsg
080
081  /** @since {@link ProtocolVersion#REPLICATION_PROTOCOL_V8} */
082  static final byte MSG_TYPE_REPLICA_OFFLINE = 37;
083
084  // Adding a new type of message here probably requires to
085  // change accordingly generateMsg method below
086
087  /**
088   * Protected constructor.
089   */
090  protected ReplicationMsg()
091  {
092    // Nothing to do.
093  }
094
095  /**
096   * Serializes the PDU using the provided replication protocol version.
097   * WARNING: should be overwritten by a PDU (sub class) we want to support
098   * older protocol version serialization for.
099   *
100   * @param protocolVersion
101   *          The protocol version to use for serialization. The version should
102   *          normally be older than the current one.
103   * @return The encoded PDU, or <code>null</code> if the message isn't supported
104   *          in that protocol version.
105   */
106  public abstract byte[] getBytes(short protocolVersion);
107
108  /**
109   * Generates a ReplicationMsg from its encoded form. This un-serialization is
110   * done taking into account the various supported replication protocol
111   * versions.
112   *
113   * @param buffer
114   *          The encode form of the ReplicationMsg.
115   * @param protocolVersion
116   *          The version to use to decode the msg.
117   * @return The generated SynchronizationMessage.
118   * @throws DataFormatException
119   *           If the encoded form was not a valid msg.
120   * @throws NotSupportedOldVersionPDUException
121   *           If the PDU is part of an old protocol version and we do not
122   *           support it.
123   */
124  public static ReplicationMsg generateMsg(byte[] buffer, short protocolVersion)
125      throws DataFormatException, NotSupportedOldVersionPDUException
126  {
127    switch (buffer[0])
128    {
129    case MSG_TYPE_SERVER_START_V1:
130      throw new NotSupportedOldVersionPDUException("Server Start",
131          ProtocolVersion.REPLICATION_PROTOCOL_V1, buffer[0]);
132    case MSG_TYPE_REPL_SERVER_INFO_V1:
133      throw new NotSupportedOldVersionPDUException("Replication Server Info",
134          ProtocolVersion.REPLICATION_PROTOCOL_V1, buffer[0]);
135    case MSG_TYPE_MODIFY:
136      return new ModifyMsg(buffer);
137    case MSG_TYPE_MODIFY_V1:
138      return ModifyMsg.createV1(buffer);
139    case MSG_TYPE_ADD:
140    case MSG_TYPE_ADD_V1:
141      return new AddMsg(buffer);
142    case MSG_TYPE_DELETE:
143    case MSG_TYPE_DELETE_V1:
144      return new DeleteMsg(buffer);
145    case MSG_TYPE_MODIFYDN:
146    case MSG_TYPE_MODIFYDN_V1:
147      return new ModifyDNMsg(buffer);
148    case MSG_TYPE_ACK:
149      return new AckMsg(buffer);
150    case MSG_TYPE_SERVER_START:
151      return new ServerStartMsg(buffer);
152    case MSG_TYPE_REPL_SERVER_START:
153    case MSG_TYPE_REPL_SERVER_START_V1:
154      return new ReplServerStartMsg(buffer);
155    case MSG_TYPE_WINDOW:
156      return new WindowMsg(buffer);
157    case MSG_TYPE_HEARTBEAT:
158      return new HeartbeatMsg(buffer);
159    case MSG_TYPE_INITIALIZE_REQUEST:
160      return new InitializeRequestMsg(buffer, protocolVersion);
161    case MSG_TYPE_INITIALIZE_TARGET:
162      return new InitializeTargetMsg(buffer, protocolVersion);
163    case MSG_TYPE_ENTRY:
164      return new EntryMsg(buffer, protocolVersion);
165    case MSG_TYPE_DONE:
166      return new DoneMsg(buffer);
167    case MSG_TYPE_ERROR:
168      return new ErrorMsg(buffer, protocolVersion);
169    case MSG_TYPE_RESET_GENERATION_ID:
170      return new ResetGenerationIdMsg(buffer);
171    case MSG_TYPE_WINDOW_PROBE:
172      return new WindowProbeMsg(buffer);
173    case MSG_TYPE_TOPOLOGY:
174      return new TopologyMsg(buffer, protocolVersion);
175    case MSG_TYPE_REPL_SERVER_MONITOR_REQUEST:
176      return new MonitorRequestMsg(buffer);
177    case MSG_TYPE_REPL_SERVER_MONITOR:
178      return new MonitorMsg(buffer, protocolVersion);
179    case MSG_TYPE_START_SESSION:
180      return new StartSessionMsg(buffer, protocolVersion);
181    case MSG_TYPE_CHANGE_STATUS:
182      return new ChangeStatusMsg(buffer);
183    case MSG_TYPE_GENERIC_UPDATE:
184      return new UpdateMsg(buffer);
185    case MSG_TYPE_START_ECL:
186    case MSG_TYPE_START_ECL_SESSION:
187    case MSG_TYPE_ECL_UPDATE:
188      // Legacy versions never sent such messages to other instances (other JVMs).
189      // They were only used in the combined DS-RS case.
190      // It is safe to totally ignore these values since code now uses the ChangelogBackend.
191      return null;
192    case MSG_TYPE_CT_HEARTBEAT:
193      return new ChangeTimeHeartbeatMsg(buffer, protocolVersion);
194    case MSG_TYPE_REPL_SERVER_START_DS:
195      return new ReplServerStartDSMsg(buffer);
196    case MSG_TYPE_STOP:
197      return new StopMsg(buffer);
198    case MSG_TYPE_INITIALIZE_RCV_ACK:
199      return new InitializeRcvAckMsg(buffer);
200    case MSG_TYPE_REPLICA_OFFLINE:
201      return new ReplicaOfflineMsg(buffer);
202    default:
203      throw new DataFormatException("received message with unknown type");
204    }
205  }
206}