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 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2006-2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.replication.common; 028 029 /** 030 * Class used to represent Change Numbers. 031 */ 032 public class ChangeNumber implements java.io.Serializable, 033 java.lang.Comparable<ChangeNumber> 034 { 035 private static final long serialVersionUID = -8802722277749190740L; 036 private long timeStamp; 037 private int seqnum; 038 private short serverId; 039 040 /** 041 * Create a new ChangeNumber from a String. 042 * 043 * @param str the string from which to create a ChangeNumber 044 */ 045 public ChangeNumber(String str) 046 { 047 String temp = str.substring(0, 16); 048 timeStamp = Long.parseLong(temp, 16); 049 050 temp = str.substring(16, 20); 051 serverId = Short.parseShort(temp, 16); 052 053 temp = str.substring(20, 28); 054 seqnum = Integer.parseInt(temp, 16); 055 } 056 057 /** 058 * Create a new ChangeNumber. 059 * 060 * @param time time for the ChangeNumber 061 * @param seq sequence number 062 * @param id identity of server 063 */ 064 public ChangeNumber(long time, int seq, short id) 065 { 066 serverId = id; 067 timeStamp = time; 068 seqnum = seq; 069 } 070 071 /** 072 * Getter for the time. 073 * @return the time 074 */ 075 public long getTime() 076 { 077 return timeStamp; 078 } 079 080 /** 081 * Get the timestamp associated to this ChangeNumber in seconds. 082 * @return timestamp associated to this ChangeNumber in seconds 083 */ 084 public long getTimeSec() 085 { 086 return timeStamp/1000; 087 } 088 089 /** 090 * Getter for the sequence number. 091 * @return the sequence number 092 */ 093 public int getSeqnum() 094 { 095 return seqnum; 096 } 097 098 /** 099 * Getter for the server ID. 100 * @return the server ID 101 */ 102 public short getServerId() 103 { 104 return serverId; 105 } 106 107 108 /** 109 * {@inheritDoc} 110 */ 111 public boolean equals(Object obj) 112 { 113 if (obj instanceof ChangeNumber) 114 { 115 ChangeNumber cn = (ChangeNumber) obj; 116 if ((this.seqnum == cn.seqnum) && 117 (this.serverId == cn.serverId) && 118 (this.timeStamp == cn.timeStamp) ) 119 return true; 120 else 121 return false; 122 } 123 else 124 return false; 125 } 126 127 /** 128 * {@inheritDoc} 129 */ 130 @Override 131 public int hashCode() 132 { 133 return this.seqnum + this.serverId + Long.valueOf(timeStamp).hashCode(); 134 } 135 136 /** 137 * Convert the ChangeNumber to a printable String. 138 * @return the string 139 */ 140 public String toString() 141 { 142 return String.format("%016x%04x%08x", timeStamp, serverId, seqnum); 143 } 144 145 /** 146 * Compares 2 ChangeNumber. 147 * @param CN1 the first ChangeNumber to compare 148 * @param CN2 the second ChangeNumber to compare 149 * @return value 0 if changeNumber matches, negative if first 150 * changeNumber is smaller, positive otherwise 151 */ 152 public static int compare(ChangeNumber CN1, ChangeNumber CN2) 153 { 154 if (CN1 == null) 155 { 156 if (CN2 == null) 157 return 0; 158 else 159 return -1; 160 } 161 else if (CN2 == null) 162 return 1; 163 else if (CN1.timeStamp < CN2.timeStamp) 164 return -1; 165 else if (CN2.timeStamp < CN1.timeStamp) 166 return 1; 167 else 168 { 169 // timestamps are equals compare seqnums 170 if (CN1.seqnum < CN2.seqnum) 171 return -1; 172 else if (CN2.seqnum < CN1.seqnum) 173 return 1; 174 else 175 { 176 // timestamp and seqnum are equals compare serverIds 177 if (CN1.serverId < CN2.serverId) 178 return -1; 179 else if (CN2.serverId < CN1.serverId) 180 return 1; 181 182 // if we get here ChangeNumber are equals 183 return 0; 184 } 185 186 } 187 } 188 189 /** 190 * Computes the difference in number of changes between 2 191 * change numbers. 192 * @param op1 the first ChangeNumber 193 * @param op2 the second ChangeNumber 194 * @return the difference 195 */ 196 public static int diffSeqNum(ChangeNumber op1, ChangeNumber op2) 197 { 198 int totalCount = 0; 199 int max = op1.getSeqnum(); 200 if (op2 != null) 201 { 202 int current = op2.getSeqnum(); 203 if (current == max) 204 { 205 } 206 else if (current < max) 207 { 208 totalCount += max - current; 209 } 210 else 211 { 212 totalCount += Integer.MAX_VALUE - (current - max) + 1; 213 } 214 } 215 else 216 { 217 totalCount += max; 218 } 219 return totalCount; 220 } 221 222 /** 223 * check if the current Object is strictly older than ChangeNumber 224 * given in parameter. 225 * @param CN the Changenumber to compare with 226 * @return true if strictly older, false if younger or same 227 */ 228 public Boolean older(ChangeNumber CN) 229 { 230 if (compare(this, CN) < 0) 231 return true; 232 233 return false; 234 } 235 236 /** 237 * check if the current Object is older than ChangeNumber 238 * given in parameter. 239 * @param CN the Changenumber to compare with 240 * @return true if older or equal, false if younger 241 */ 242 public Boolean olderOrEqual(ChangeNumber CN) 243 { 244 if (compare(this, CN) <= 0) 245 return true; 246 247 return false; 248 } 249 250 /** 251 * Check if the current Object is newer than ChangeNumber. 252 * @param CN the Changenumber to compare with 253 * @return true if newer 254 */ 255 public boolean newerOrEquals(ChangeNumber CN) 256 { 257 if (compare(this, CN) >= 0) 258 return true; 259 260 return false; 261 } 262 263 /** 264 * Check if the current Object is strictly newer than ChangeNumber. 265 * @param CN the Changenumber to compare with 266 * @return true if strictly newer 267 */ 268 public boolean newer(ChangeNumber CN) 269 { 270 if (compare(this, CN) > 0) 271 return true; 272 273 return false; 274 } 275 276 /** 277 * Compares this object with the specified object for order. 278 * @param cn the ChangeNumber to compare with. 279 * @return a negative integer, zero, or a positive integer as this object 280 * is less than, equal to, or greater than the specified object. 281 */ 282 public int compareTo(ChangeNumber cn) 283 { 284 return compare(this, cn); 285 } 286 }