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