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-2016 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  /** Reserved type for uses other than protocol messages. */
031  public static final byte MSG_TYPE_DISK_ENCODING = -1;
032
033  // PDU type values kept for compatibility with replication protocol version 1
034  static final byte MSG_TYPE_MODIFY_V1 = 1;
035  static final byte MSG_TYPE_ADD_V1 = 2;
036  static final byte MSG_TYPE_DELETE_V1 = 3;
037  static final byte MSG_TYPE_MODIFYDN_V1 = 4;
038  static final byte MSG_TYPE_SERVER_START_V1 = 6;
039  static final byte MSG_TYPE_REPL_SERVER_START_V1 = 7;
040  static final byte MSG_TYPE_REPL_SERVER_INFO_V1 = 16;
041
042  // PDU type values for current protocol version (see ProtocolVersion)
043  static final byte MSG_TYPE_ACK = 5;
044  static final byte MSG_TYPE_WINDOW = 8;
045  static final byte MSG_TYPE_HEARTBEAT = 9;
046  static final byte MSG_TYPE_INITIALIZE_REQUEST = 10;
047  static final byte MSG_TYPE_INITIALIZE_TARGET = 11;
048  static final byte MSG_TYPE_ENTRY = 12;
049  static final byte MSG_TYPE_DONE = 13;
050  static final byte MSG_TYPE_ERROR = 14;
051  static final byte MSG_TYPE_WINDOW_PROBE = 15;
052  static final byte MSG_TYPE_RESET_GENERATION_ID = 17;
053  static final byte MSG_TYPE_REPL_SERVER_MONITOR_REQUEST = 18;
054  static final byte MSG_TYPE_REPL_SERVER_MONITOR = 19;
055  static final byte MSG_TYPE_SERVER_START = 20;
056  static final byte MSG_TYPE_REPL_SERVER_START = 21;
057  static final byte MSG_TYPE_MODIFY = 22;
058  static final byte MSG_TYPE_ADD = 23;
059  static final byte MSG_TYPE_DELETE = 24;
060  static final byte MSG_TYPE_MODIFYDN = 25;
061  static final byte MSG_TYPE_TOPOLOGY = 26;
062  static final byte MSG_TYPE_START_SESSION = 27;
063  static final byte MSG_TYPE_CHANGE_STATUS = 28;
064  static final byte MSG_TYPE_GENERIC_UPDATE = 29;
065
066  // Added for protocol version 3
067  @Deprecated
068  static final byte MSG_TYPE_START_ECL = 30;
069  @Deprecated
070  static final byte MSG_TYPE_START_ECL_SESSION = 31;
071  @Deprecated
072  static final byte MSG_TYPE_ECL_UPDATE = 32;
073  static final byte MSG_TYPE_CT_HEARTBEAT = 33;
074
075  // Added for protocol version 4
076  // - New msgs types
077  static final byte MSG_TYPE_REPL_SERVER_START_DS = 34;
078  static final byte MSG_TYPE_STOP = 35;
079  static final byte MSG_TYPE_INITIALIZE_RCV_ACK = 36;
080  // - Modified msgs types
081  //   EntryMsg, InitializeRequestMsg, InitializeTargetMsg, ErrorMsg
082  //   TopologyMsg
083
084  /** @since {@link ProtocolVersion#REPLICATION_PROTOCOL_V8} */
085  static final byte MSG_TYPE_REPLICA_OFFLINE = 37;
086
087  // Adding a new type of message here probably requires to
088  // change accordingly generateMsg method below
089
090  /**
091   * Protected constructor.
092   */
093  protected ReplicationMsg()
094  {
095    // Nothing to do.
096  }
097
098  /**
099   * Serializes the PDU using the provided replication protocol version.
100   * WARNING: should be overwritten by a PDU (sub class) we want to support
101   * older protocol version serialization for.
102   *
103   * @param protocolVersion
104   *          The protocol version to use for serialization. The version should
105   *          normally be older than the current one.
106   * @return The encoded PDU, or <code>null</code> if the message isn't supported
107   *          in that protocol version.
108   */
109  public abstract byte[] getBytes(short protocolVersion);
110
111  /**
112   * Generates a ReplicationMsg from its encoded form. This un-serialization is
113   * done taking into account the various supported replication protocol
114   * versions.
115   *
116   * @param buffer
117   *          The encode form of the ReplicationMsg.
118   * @param protocolVersion
119   *          The version to use to decode the msg.
120   * @return The generated SynchronizationMessage.
121   * @throws DataFormatException
122   *           If the encoded form was not a valid msg.
123   * @throws NotSupportedOldVersionPDUException
124   *           If the PDU is part of an old protocol version and we do not
125   *           support it.
126   */
127  public static ReplicationMsg generateMsg(byte[] buffer, short protocolVersion)
128      throws DataFormatException, NotSupportedOldVersionPDUException
129  {
130    switch (buffer[0])
131    {
132    case MSG_TYPE_SERVER_START_V1:
133      throw new NotSupportedOldVersionPDUException("Server Start",
134          ProtocolVersion.REPLICATION_PROTOCOL_V1, buffer[0]);
135    case MSG_TYPE_REPL_SERVER_INFO_V1:
136      throw new NotSupportedOldVersionPDUException("Replication Server Info",
137          ProtocolVersion.REPLICATION_PROTOCOL_V1, buffer[0]);
138    case MSG_TYPE_MODIFY:
139      return new ModifyMsg(buffer);
140    case MSG_TYPE_MODIFY_V1:
141      return ModifyMsg.createV1(buffer);
142    case MSG_TYPE_ADD:
143    case MSG_TYPE_ADD_V1:
144      return new AddMsg(buffer);
145    case MSG_TYPE_DELETE:
146    case MSG_TYPE_DELETE_V1:
147      return new DeleteMsg(buffer);
148    case MSG_TYPE_MODIFYDN:
149    case MSG_TYPE_MODIFYDN_V1:
150      return new ModifyDNMsg(buffer);
151    case MSG_TYPE_ACK:
152      return new AckMsg(buffer);
153    case MSG_TYPE_SERVER_START:
154      return new ServerStartMsg(buffer);
155    case MSG_TYPE_REPL_SERVER_START:
156    case MSG_TYPE_REPL_SERVER_START_V1:
157      return new ReplServerStartMsg(buffer);
158    case MSG_TYPE_WINDOW:
159      return new WindowMsg(buffer);
160    case MSG_TYPE_HEARTBEAT:
161      return new HeartbeatMsg(buffer);
162    case MSG_TYPE_INITIALIZE_REQUEST:
163      return new InitializeRequestMsg(buffer, protocolVersion);
164    case MSG_TYPE_INITIALIZE_TARGET:
165      return new InitializeTargetMsg(buffer, protocolVersion);
166    case MSG_TYPE_ENTRY:
167      return new EntryMsg(buffer, protocolVersion);
168    case MSG_TYPE_DONE:
169      return new DoneMsg(buffer);
170    case MSG_TYPE_ERROR:
171      return new ErrorMsg(buffer, protocolVersion);
172    case MSG_TYPE_RESET_GENERATION_ID:
173      return new ResetGenerationIdMsg(buffer);
174    case MSG_TYPE_WINDOW_PROBE:
175      return new WindowProbeMsg(buffer);
176    case MSG_TYPE_TOPOLOGY:
177      return new TopologyMsg(buffer, protocolVersion);
178    case MSG_TYPE_REPL_SERVER_MONITOR_REQUEST:
179      return new MonitorRequestMsg(buffer);
180    case MSG_TYPE_REPL_SERVER_MONITOR:
181      return new MonitorMsg(buffer, protocolVersion);
182    case MSG_TYPE_START_SESSION:
183      return new StartSessionMsg(buffer, protocolVersion);
184    case MSG_TYPE_CHANGE_STATUS:
185      return new ChangeStatusMsg(buffer);
186    case MSG_TYPE_GENERIC_UPDATE:
187      return new UpdateMsg(buffer);
188    case MSG_TYPE_START_ECL:
189    case MSG_TYPE_START_ECL_SESSION:
190    case MSG_TYPE_ECL_UPDATE:
191      // Legacy versions never sent such messages to other instances (other JVMs).
192      // They were only used in the combined DS-RS case.
193      // It is safe to totally ignore these values since code now uses the ChangelogBackend.
194      return null;
195    case MSG_TYPE_CT_HEARTBEAT:
196      return new ChangeTimeHeartbeatMsg(buffer, protocolVersion);
197    case MSG_TYPE_REPL_SERVER_START_DS:
198      return new ReplServerStartDSMsg(buffer);
199    case MSG_TYPE_STOP:
200      return new StopMsg(buffer);
201    case MSG_TYPE_INITIALIZE_RCV_ACK:
202      return new InitializeRcvAckMsg(buffer);
203    case MSG_TYPE_REPLICA_OFFLINE:
204      return new ReplicaOfflineMsg(buffer);
205    default:
206      throw new DataFormatException("received message with unknown type");
207    }
208  }
209}