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