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-2009 Sun Microsystems, Inc.
025 *      Portions Copyright 2013-2015 ForgeRock AS.
026 */
027package org.opends.server.replication.protocol;
028
029import java.util.zip.DataFormatException;
030
031import org.opends.server.replication.common.ServerState;
032import org.opends.server.types.DN;
033
034/**
035 * Message sent by a replication server to another replication server
036 * at Startup.
037 */
038public class ReplServerStartMsg extends StartMsg
039{
040  private final int serverId;
041  private final String serverURL;
042  private final DN baseDN;
043  private final int windowSize;
044  private final ServerState serverState;
045
046  /**
047   * Whether to continue using SSL to encrypt messages after the start
048   * messages have been exchanged.
049   */
050  private final boolean sslEncryption;
051
052  /**
053   * NOTE: Starting from protocol V4, we introduce a dedicated PDU for answering
054   * to the DS ServerStartMsg. This is the ReplServerStartDSMsg. So the
055   * degradedStatusThreshold value being used only by a DS, it could be removed
056   * from the ReplServerStartMsg PDU. However for a smoothly transition to V4
057   * protocol, we prefer to let this variable also in this PDU but the one
058   * really used is in the ReplServerStartDSMsg PDU. This prevents from having
059   * only RSv3 able to connect to RSv4 as connection initiator.
060   *
061   * Threshold value used by the RS to determine if a DS must be put in
062   * degraded status because the number of pending changes for him has crossed
063   * this value. This field is only used by a DS.
064   */
065  private int degradedStatusThreshold = -1;
066
067  /**
068   * Create a ReplServerStartMsg.
069   *
070   * @param serverId replication server id
071   * @param serverURL replication server URL
072   * @param baseDN base DN for which the ReplServerStartMsg is created.
073   * @param windowSize The window size.
074   * @param serverState our ServerState for this baseDN.
075   * @param generationId The generationId for this server.
076   * @param sslEncryption Whether to continue using SSL to encrypt messages
077   *                      after the start messages have been exchanged.
078   * @param groupId The group id of the RS
079   * @param degradedStatusThreshold The degraded status threshold
080   */
081  public ReplServerStartMsg(int serverId, String serverURL, DN baseDN,
082                               int windowSize,
083                               ServerState serverState,
084                               long generationId,
085                               boolean sslEncryption,
086                               byte groupId,
087                               int degradedStatusThreshold)
088  {
089    super((short) -1 /* version set when sending */, generationId);
090    this.serverId = serverId;
091    this.serverURL = serverURL;
092    this.baseDN = baseDN;
093    this.windowSize = windowSize;
094    this.serverState = serverState;
095    this.sslEncryption = sslEncryption;
096    this.groupId = groupId;
097    this.degradedStatusThreshold = degradedStatusThreshold;
098  }
099
100  /**
101   * Creates a new ReplServerStartMsg by decoding the provided byte array.
102   * @param in A byte array containing the encoded information for the
103   *             ReplServerStartMsg
104   * @throws DataFormatException If the in does not contain a properly
105   *                             encoded ReplServerStartMsg.
106   */
107  ReplServerStartMsg(byte[] in) throws DataFormatException
108  {
109    final ByteArrayScanner scanner = new ByteArrayScanner(in);
110    decodeHeader(scanner,
111        MSG_TYPE_REPL_SERVER_START, MSG_TYPE_REPL_SERVER_START_V1);
112
113    /* The ReplServerStartMsg payload is stored in the form :
114     * <baseDN><serverId><serverURL><windowSize><sslEncryption>
115     * <degradedStatusThreshold><serverState>
116     */
117    baseDN = scanner.nextDN();
118    serverId = scanner.nextIntUTF8();
119    serverURL = scanner.nextString();
120    windowSize = scanner.nextIntUTF8();
121    sslEncryption = Boolean.valueOf(scanner.nextString());
122
123    if (protocolVersion > ProtocolVersion.REPLICATION_PROTOCOL_V1)
124    {
125      degradedStatusThreshold = scanner.nextIntUTF8();
126    }
127
128    serverState = scanner.nextServerStateMustComeLast();
129  }
130
131  /**
132   * Get the Server Id.
133   * @return the server id
134   */
135  public int getServerId()
136  {
137    return this.serverId;
138  }
139
140  /**
141   * Get the server URL.
142   * @return the server URL
143   */
144  public String getServerURL()
145  {
146    return this.serverURL;
147  }
148
149  /**
150   * Get the base DN from this ReplServerStartMsg.
151   *
152   * @return the base DN from this ReplServerStartMsg.
153   */
154  public DN getBaseDN()
155  {
156    return baseDN;
157  }
158
159  /**
160   * Get the serverState.
161   * @return Returns the serverState.
162   */
163  public ServerState getServerState()
164  {
165    return this.serverState;
166  }
167
168  /** {@inheritDoc} */
169  @Override
170  public byte[] getBytes(short protocolVersion)
171  {
172    final ByteArrayBuilder builder = new ByteArrayBuilder();
173    if (protocolVersion == ProtocolVersion.REPLICATION_PROTOCOL_V1)
174    {
175      /*
176       * The ReplServerStartMessage is stored in the form :
177       * <operation type><basedn><serverid><serverURL><windowsize><serverState>
178       */
179      encodeHeader_V1(MSG_TYPE_REPL_SERVER_START_V1, builder);
180      builder.appendDN(baseDN);
181      builder.appendIntUTF8(serverId);
182      builder.appendString(serverURL);
183      builder.appendIntUTF8(windowSize);
184      builder.appendString(Boolean.toString(sslEncryption));
185      builder.appendServerStateMustComeLast(serverState);
186    }
187    else
188    {
189      /* The ReplServerStartMsg is stored in the form :
190       * <operation type><baseDN><serverId><serverURL><windowSize><sslEncryption>
191       * <degradedStatusThreshold><serverState>
192       */
193      encodeHeader(MSG_TYPE_REPL_SERVER_START, builder, protocolVersion);
194      builder.appendDN(baseDN);
195      builder.appendIntUTF8(serverId);
196      builder.appendString(serverURL);
197      builder.appendIntUTF8(windowSize);
198      builder.appendString(Boolean.toString(sslEncryption));
199      builder.appendIntUTF8(degradedStatusThreshold);
200      builder.appendServerStateMustComeLast(serverState);
201    }
202    return builder.toByteArray();
203  }
204
205  /**
206   * Get the window size for the server that created this message.
207   *
208   * @return The window size for the server that created this message.
209   */
210  public int getWindowSize()
211  {
212    return windowSize;
213  }
214
215  /**
216   * Get the SSL encryption value for the server that created the
217   * message.
218   *
219   * @return The SSL encryption value for the server that created the
220   *         message.
221   */
222  public boolean getSSLEncryption()
223  {
224    return sslEncryption;
225  }
226
227  /**
228   * Get the degraded status threshold value.
229   * @return The degraded status threshold value.
230   */
231  public int getDegradedStatusThreshold()
232  {
233    return degradedStatusThreshold;
234  }
235
236  /**
237   * Set the degraded status threshold (For test purpose).
238   * @param degradedStatusThreshold The degraded status threshold to set.
239   */
240  public void setDegradedStatusThreshold(int degradedStatusThreshold)
241  {
242    this.degradedStatusThreshold = degradedStatusThreshold;
243  }
244
245  /** {@inheritDoc} */
246  @Override
247  public String toString()
248  {
249    return "ReplServerStartMsg content: " +
250      "\nprotocolVersion: " + protocolVersion +
251      "\ngenerationId: " + generationId +
252      "\nbaseDN: " + baseDN +
253      "\ngroupId: " + groupId +
254      "\nserverId: " + serverId +
255      "\nserverState: " + serverState +
256      "\nserverURL: " + serverURL +
257      "\nsslEncryption: " + sslEncryption +
258      "\ndegradedStatusThreshold: " + degradedStatusThreshold +
259      "\nwindowSize: " + windowSize;
260  }
261}