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 *      Copyright 2014 ForgeRock AS
024 */
025package org.opends.server.replication.protocol;
026
027import java.util.zip.DataFormatException;
028
029import org.opends.server.replication.common.CSN;
030
031import static org.opends.server.replication.protocol.ByteArrayBuilder.*;
032
033/**
034 * Class that define messages sent by a replica (DS) to the replication server
035 * (RS) to let the RS know the date at which a replica went offline.
036 */
037public class ReplicaOfflineMsg extends UpdateMsg
038{
039
040  /**
041   * Constructor of a replica offline message providing the offline timestamp in
042   * a CSN.
043   *
044   * @param offlineCSN
045   *          the provided offline CSN
046   */
047  public ReplicaOfflineMsg(final CSN offlineCSN)
048  {
049    super(offlineCSN, new byte[0]);
050  }
051
052  /**
053   * Creates a message by deserializing it from the provided byte array.
054   *
055   * @param in
056   *          The provided byte array.
057   * @throws DataFormatException
058   *           When an error occurs during decoding .
059   */
060  public ReplicaOfflineMsg(byte[] in) throws DataFormatException
061  {
062    try
063    {
064      final ByteArrayScanner scanner = new ByteArrayScanner(in);
065      final byte msgType = scanner.nextByte();
066      if (msgType != MSG_TYPE_REPLICA_OFFLINE)
067      {
068        throw new DataFormatException("input is not a valid "
069            + getClass().getSimpleName() + " message: " + msgType);
070      }
071      protocolVersion = scanner.nextShort();
072      csn = scanner.nextCSN();
073
074      if (!scanner.isEmpty())
075      {
076        throw new DataFormatException(
077            "Did not expect to find more bytes to read for "
078                + getClass().getSimpleName());
079      }
080    }
081    catch (RuntimeException e)
082    {
083      // Index out of bounds, bad format, etc.
084      throw new DataFormatException("byte[] is not a valid "
085          + getClass().getSimpleName());
086    }
087  }
088
089  /** {@inheritDoc} */
090  @Override
091  public byte[] getBytes(short protocolVersion)
092  {
093    if (protocolVersion < ProtocolVersion.REPLICATION_PROTOCOL_V8)
094    {
095      return null;
096    }
097    final ByteArrayBuilder builder = new ByteArrayBuilder(size());
098    builder.appendByte(MSG_TYPE_REPLICA_OFFLINE);
099    builder.appendShort(protocolVersion);
100    builder.appendCSN(csn);
101    return builder.toByteArray();
102  }
103
104  /** {@inheritDoc} */
105  @Override
106  public int size()
107  {
108    return bytes(1) + shorts(1) + csns(1);
109  }
110
111  /** {@inheritDoc} */
112  @Override
113  public boolean contributesToDomainState()
114  {
115    return false; // replica offline msg MUST NOT update the ds-sync-state
116  }
117
118  /** {@inheritDoc} */
119  @Override
120  public String toString()
121  {
122    return getClass().getSimpleName() + " offlineCSN=" + csn;
123  }
124}