1 package org.csc.phynixx.loggersystem.logger.channellogger;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 import org.csc.phynixx.common.logger.IPhynixxLogger;
25 import org.csc.phynixx.common.logger.PhynixxLogManager;
26
27 import java.io.IOException;
28 import java.io.RandomAccessFile;
29 import java.nio.channels.FileLock;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 class TAEnabledRandomAccessFile {
58
59
60
61
62
63 public static final int HEADER_LENGTH = (Long.SIZE / Byte.SIZE);
64
65
66
67
68 public static final int BYTE_BYTES = 1;
69
70
71
72
73 public static final int MAX_BYTE_VALUE = (int) Byte.MAX_VALUE;
74
75 private static final IPhynixxLogger LOG = PhynixxLogManager.getLogger(TAEnabledRandomAccessFile.class);
76
77
78
79 private RandomAccessFile raf = null;
80
81
82 private FileLock fileLock = null;
83
84
85
86
87
88 private long committedSize=0;
89
90
91
92
93
94
95
96
97 TAEnabledRandomAccessFile(RandomAccessFile raf) throws IOException {
98 this.raf = raf;
99 fileLock = acquireFileLock(raf);
100 this.restoreCommittedSize();
101 check();
102 }
103
104 private FileLock acquireFileLock(RandomAccessFile raf) throws IOException {
105 return raf.getChannel().lock(0,HEADER_LENGTH, false);
106 }
107
108
109
110
111
112
113 public static int getHeaderLength() {
114 return HEADER_LENGTH;
115 }
116
117
118
119
120
121
122 RandomAccessFile getRandomAccessFile() {
123 check();
124 return this.raf;
125 }
126
127
128
129
130
131
132
133
134
135 private void checkPosition(long pos) {
136 if (pos < 0) {
137 throw new IllegalArgumentException("Uebergebene Position (=" + pos + ") darf nicht kleiner als 0 sein");
138 }
139 }
140
141
142
143
144
145
146 public long available() throws IOException {
147 check();
148 return this.getCommittedSize() - this.position();
149 }
150
151
152
153
154
155
156
157 long position() throws IOException {
158 check();
159 return this.raf.getFilePointer() - getHeaderLength();
160 }
161
162 private void check() {
163 if (isClose()) {
164 throw new IllegalStateException("TAEnabledRandomAccessFile is closed");
165 }
166
167 if( this.fileLock==null || !fileLock.isValid()) {
168 throw new IllegalStateException("Filelock is not valid");
169 }
170 }
171
172
173
174
175
176
177
178
179
180
181 private void position(long newPosition) throws IOException {
182
183 check();
184 checkPosition(newPosition);
185 this.getRandomAccessFile().seek(newPosition + getHeaderLength());
186 }
187
188
189
190
191
192
193 public void close() throws IOException {
194 if (raf != null) {
195
196 try {
197 if (this.fileLock != null) {
198 if( fileLock.isValid()) {
199 this.fileLock.release();
200 } else {
201 LOG.error("Filelock not valid");
202 }
203 } else {
204 LOG.error("Kein Filelock gesetzt");
205 }
206 } finally {
207
208 this.fileLock = null;
209 raf.close();
210 raf = null;
211 }
212 }
213 }
214
215
216
217
218
219
220 public boolean isClose() {
221 return (this.raf == null);
222 }
223
224
225
226
227
228
229
230
231
232
233
234 public long getCommittedSize() throws IOException {
235 check();
236
237 return this.committedSize;
238
239 }
240
241
242
243
244
245
246
247
248
249
250
251 public int readInt() throws IOException {
252 check();
253 checkRead(4);
254 return raf.readInt();
255 }
256
257
258
259
260
261
262
263
264
265
266 public short readShort() throws IOException {
267 check();
268 checkRead(2);
269 return raf.readShort();
270 }
271
272
273
274
275
276
277
278
279
280
281 public long readLong() throws IOException {
282 check();
283 checkRead(8);
284 return raf.readLong();
285 }
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303 public byte[] read(int length) throws IOException {
304 check();
305
306 checkRead(length);
307
308 if (length >= Integer.MAX_VALUE) {
309 throw new IOException("Length of read area may not exceed " + Integer.MAX_VALUE);
310 }
311
312 if (this.position()+length > this.getCommittedSize()) {
313 throw new IOException("Length of read area may not exceed the committed size of " + this.getCommittedSize());
314 }
315
316 int intLength = Long.valueOf(length).intValue();
317
318 byte[] buffer = new byte[intLength];
319
320 if (isClose()) {
321 throw new IOException("TAEnabledChanneList ist closed");
322 }
323
324 long retVal = this.getRandomAccessFile().read(buffer, 0, intLength);
325
326 if (retVal < 0) {
327 throw new IOException("Channel cannot read " + (position() + intLength) );
328 }
329 return buffer;
330 }
331
332 private void checkRead(int length) throws IOException {
333 if( this.available() < length) {
334 throw new IOException("Cannot read "+length +" byte. Starting from current position "+position()+" there are only "+this.available()+" bytes available");
335 }
336 }
337
338
339
340
341
342
343
344
345
346
347
348
349 public void write(byte[] buffer) throws IOException {
350 check();
351
352
353 if (isClose()) {
354 throw new IOException("TAEnabledChanneList is closed");
355 }
356 long currentPosition = this.position();
357 this.raf.write(buffer);
358
359
360 assert this.position() - currentPosition == buffer.length : "Expected new position : " + currentPosition + buffer.length + " actual position " + this.position();
361
362
363 }
364
365
366
367
368
369
370
371 public void writeShort(short value) throws IOException {
372 check();
373
374 getRandomAccessFile().writeShort(value);
375 }
376
377
378
379
380
381
382
383 public void writeInt(int value) throws IOException {
384 check();
385
386 getRandomAccessFile().writeInt(value);
387
388 }
389
390
391
392
393
394
395
396
397 public void writeLong(long value) throws IOException {
398 check();
399
400 getRandomAccessFile().writeLong(value);
401
402 }
403
404
405
406
407
408 public void rewind() throws IOException {
409 check();
410 this.position(0);
411
412 }
413
414
415
416
417
418 public void forwardWind() throws IOException {
419 check();
420 this.position(this.getCommittedSize());
421
422 }
423
424
425
426
427
428
429
430 public void reset() throws IOException {
431 check();
432
433 this.position(0);
434
435 this.commit();
436
437
438 this.getRandomAccessFile().getChannel().truncate(TAEnabledRandomAccessFile.HEADER_LENGTH);
439
440 }
441
442
443
444
445
446
447
448
449 public void commit() throws IOException {
450 check();
451 long currentPosition = this.position();
452
453
454 this.getRandomAccessFile().seek(0);
455
456
457 getRandomAccessFile().writeLong(currentPosition);
458
459
460
461 this.position(currentPosition);
462
463
464 this.getRandomAccessFile().getChannel().force(false);
465
466 this.committedSize= currentPosition;
467
468 }
469
470
471
472
473
474
475
476
477
478
479 private void restoreCommittedSize() throws IOException {
480
481 check();
482 long privCommittedSize=-1;
483 this.getRandomAccessFile().seek(0);
484 if (this.raf.length() < HEADER_LENGTH) {
485 this.getRandomAccessFile().writeLong(0);
486 privCommittedSize=0;
487 } else {
488 privCommittedSize = this.getRandomAccessFile().readLong();
489 }
490 this.position(privCommittedSize);
491 this.committedSize=privCommittedSize;
492 }
493
494
495
496
497 }