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-2014 ForgeRock AS. 016 */ 017package org.opends.server.replication.protocol; 018 019import java.util.zip.DataFormatException; 020 021import org.opends.server.replication.common.CSN; 022 023import static org.opends.server.replication.protocol.ByteArrayBuilder.*; 024import static org.opends.server.replication.protocol.ProtocolVersion.*; 025 026/** 027 * Class that define messages sent by a replication domain (DS) to the 028 * replication server to let the RS know the DS current change time. 029 */ 030public class ChangeTimeHeartbeatMsg extends ReplicationMsg 031{ 032 033 /** 034 * The CSN containing the change time. 035 */ 036 private final CSN csn; 037 038 /** 039 * Constructor of a Change Time Heartbeat message providing the change time 040 * value in a CSN. 041 * 042 * @param csn 043 * The provided CSN. 044 */ 045 public ChangeTimeHeartbeatMsg(CSN csn) 046 { 047 this.csn = csn; 048 } 049 050 /** 051 * Get a CSN with the transmitted change time. 052 * 053 * @return the CSN 054 */ 055 public CSN getCSN() 056 { 057 return csn; 058 } 059 060 /** 061 * Creates a message from a provided byte array. 062 * 063 * @param in 064 * The provided byte array. 065 * @param version 066 * The version of the protocol to use to decode the msg. 067 * @throws DataFormatException 068 * When an error occurs. 069 */ 070 public ChangeTimeHeartbeatMsg(byte[] in, short version) 071 throws DataFormatException 072 { 073 try 074 { 075 final ByteArrayScanner scanner = new ByteArrayScanner(in); 076 final byte msgType = scanner.nextByte(); 077 if (msgType != MSG_TYPE_CT_HEARTBEAT) 078 { 079 throw new DataFormatException("input is not a valid " 080 + getClass().getSimpleName() + " message: " + msgType); 081 } 082 083 csn = version >= REPLICATION_PROTOCOL_V7 084 ? scanner.nextCSN() 085 : scanner.nextCSNUTF8(); 086 087 if (!scanner.isEmpty()) 088 { 089 throw new DataFormatException( 090 "Did not expect to find more bytes to read for " 091 + getClass().getSimpleName() + " message."); 092 } 093 } 094 catch (RuntimeException e) 095 { 096 // Index out of bounds, bad format, etc. 097 throw new DataFormatException("byte[] is not a valid CT_HEARTBEAT msg"); 098 } 099 } 100 101 /** {@inheritDoc} */ 102 @Override 103 public byte[] getBytes(short protocolVersion) 104 { 105 if (protocolVersion < ProtocolVersion.REPLICATION_PROTOCOL_V7) 106 { 107 ByteArrayBuilder builder = new ByteArrayBuilder(bytes(1) + csnsUTF8(1)); 108 builder.appendByte(MSG_TYPE_CT_HEARTBEAT); 109 builder.appendCSNUTF8(csn); 110 return builder.toByteArray(); 111 } 112 113 final ByteArrayBuilder builder = new ByteArrayBuilder(bytes(1) + csns(1)); 114 builder.appendByte(MSG_TYPE_CT_HEARTBEAT); 115 builder.appendCSN(csn); 116 return builder.toByteArray(); 117 } 118 119 /** {@inheritDoc} */ 120 @Override 121 public String toString() 122 { 123 return getClass().getSimpleName() + ", csn=" + csn.toStringUI(); 124 } 125 126}