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