1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.mitosis.common;
21
22
23 import java.io.Serializable;
24
25
26
27
28
29
30
31 public class DefaultCSN implements CSN, Serializable, Comparable<CSN>
32 {
33
34
35
36
37
38
39
40 private static final long serialVersionUID = 1L;
41
42
43 private final long timestamp;
44
45
46 private final String replicaId;
47
48
49 private final int operationSequence;
50
51
52 private transient String csnStr;
53
54
55 private transient byte[] bytes;
56
57
58
59
60
61
62
63
64
65 public DefaultCSN( long timestamp, String replicaId, int operationSequence )
66 {
67 this.timestamp = timestamp;
68 this.replicaId = replicaId;
69 this.operationSequence = operationSequence;
70 }
71
72
73
74
75
76
77
78
79
80
81 public DefaultCSN( String value ) throws InvalidCSNException
82 {
83 assert value != null;
84
85 int sepTS = value.indexOf( ':' );
86
87 assert sepTS > 0;
88
89 int sepID = value.lastIndexOf( ':' );
90
91 if ( ( sepID == -1 ) || ( sepID == sepTS ) | ( sepID - sepTS < 2 ) )
92 {
93 throw new InvalidCSNException();
94 }
95
96 try
97 {
98 timestamp = Long.parseLong( value.substring( 0, sepTS ), 16 );
99 }
100 catch ( NumberFormatException ife )
101 {
102 throw new InvalidCSNException();
103 }
104
105 try
106 {
107 replicaId = value.substring( sepTS + 1, sepID );
108 }
109 catch ( IllegalArgumentException iae )
110 {
111 throw new InvalidCSNException();
112 }
113
114 try
115 {
116 operationSequence = Integer.parseInt( value.substring( sepID + 1 ), 16 );
117 }
118 catch ( NumberFormatException ife )
119 {
120 throw new InvalidCSNException();
121 }
122 }
123
124
125
126
127
128
129
130 public DefaultCSN( byte[] value )
131 {
132 timestamp = ( ( long ) ( value[0] & 0x00FF ) << 56 ) | ( ( long ) ( value[1] & 0x00FF ) << 48 )
133 | ( ( long ) ( value[2] & 0x00FF ) << 40 ) | ( ( long ) ( value[3] & 0x00FF ) << 32 )
134 | ( ( value[4] << 24 ) & 0x00000000FF000000L ) | ( ( value[5] << 16 ) & 0x0000000000FF0000L )
135 | ( ( value[6] << 8 ) & 0x000000000000FF00L ) | ( value[7] & 0x00000000000000FFL );
136
137 operationSequence = ( ( value[8] & 0x00FF ) << 24 ) + ( ( value[9] & 0x00FF ) << 16 )
138 + ( ( value[10] & 0x00FF ) << 8 ) + ( value[11] & 0x00FF );
139
140 char[] chars = new char[value.length - 12];
141
142 for ( int i = 12; i < value.length; i++ )
143 {
144 chars[i - 12] = ( char ) ( value[i] & 0x00FF );
145 }
146
147 replicaId = new String( chars );
148 bytes = value;
149 }
150
151
152
153
154
155
156
157
158 public String toOctetString()
159 {
160 if ( csnStr == null )
161 {
162 StringBuilder buf = new StringBuilder( 40 );
163 buf.append( timestamp );
164 buf.append( ':' );
165 buf.append( replicaId );
166 buf.append( ':' );
167 buf.append( operationSequence );
168 csnStr = buf.toString();
169 }
170
171 return csnStr;
172 }
173
174
175
176
177
178
179
180
181
182
183 public byte[] toBytes()
184 {
185 if ( bytes == null )
186 {
187 String id = replicaId;
188 byte[] bb = new byte[8 + id.length() + 4];
189
190 bb[0] = ( byte ) ( timestamp >> 56 );
191 bb[1] = ( byte ) ( timestamp >> 48 );
192 bb[2] = ( byte ) ( timestamp >> 40 );
193 bb[3] = ( byte ) ( timestamp >> 32 );
194 bb[4] = ( byte ) ( timestamp >> 24 );
195 bb[5] = ( byte ) ( timestamp >> 16 );
196 bb[6] = ( byte ) ( timestamp >> 8 );
197 bb[7] = ( byte ) timestamp;
198 bb[8] = ( byte ) ( ( operationSequence >> 24 ) );
199 bb[9] = ( byte ) ( ( operationSequence >> 16 ) );
200 bb[10] = ( byte ) ( ( operationSequence >> 8 ) );
201 bb[11] = ( byte ) ( operationSequence );
202
203 for ( int i = 0; i < id.length(); i++ )
204 {
205 bb[12 + i] = ( byte ) id.charAt( i );
206 }
207
208 bytes = bb;
209 }
210
211 return bytes;
212 }
213
214
215
216
217
218 public long getTimestamp()
219 {
220 return timestamp;
221 }
222
223
224
225
226
227 public String getReplicaId()
228 {
229 return replicaId;
230 }
231
232
233
234
235
236 public int getOperationSequence()
237 {
238 return operationSequence;
239 }
240
241
242
243
244
245 public String toString()
246 {
247 return toOctetString();
248 }
249
250
251
252
253
254
255
256 public int hashCode()
257 {
258 return replicaId.hashCode() ^ ( int ) timestamp ^ operationSequence;
259 }
260
261
262
263
264
265
266
267
268
269 public boolean equals( Object o )
270 {
271 if ( o == null )
272 {
273 return false;
274 }
275
276 if ( this == o )
277 {
278 return true;
279 }
280
281 if ( !( o instanceof CSN ) )
282 {
283 return false;
284 }
285
286 CSN that = ( CSN ) o;
287
288 return timestamp == that.getTimestamp() && replicaId.equals( that.getReplicaId() )
289 && operationSequence == that.getOperationSequence();
290 }
291
292
293
294
295
296
297
298
299
300
301
302 public int compareTo( CSN csn )
303 {
304 if ( csn == null )
305 {
306 return 1;
307 }
308
309 long thatTimestamp = csn.getTimestamp();
310
311 if ( this.timestamp < thatTimestamp )
312 {
313 return -1;
314 }
315 else if ( this.timestamp > thatTimestamp )
316 {
317 return 1;
318 }
319
320 int replicaIdCompareResult = this.replicaId.compareTo( csn.getReplicaId() );
321
322 if ( replicaIdCompareResult != 0 )
323 {
324 return replicaIdCompareResult;
325 }
326
327 int thatSequence = csn.getOperationSequence();
328
329 if ( this.operationSequence < thatSequence )
330 {
331 return -1;
332 }
333 else if ( this.operationSequence > thatSequence )
334 {
335 return 1;
336 }
337 else
338 {
339 return 0;
340 }
341 }
342 }