1 | package de.uka.ipd.sdq.sensorframework.storage.lists; |
2 | |
3 | import java.io.IOException; |
4 | import java.io.RandomAccessFile; |
5 | |
6 | /** |
7 | * @author Steffen Becker |
8 | * |
9 | * @param <T> |
10 | */ |
11 | public class Chunk<T> { |
12 | private long myFilePos; |
13 | private T[] data = null; |
14 | private int nextFreeElement = 0; |
15 | private RandomAccessFile raf; |
16 | private ISerialiser<T> serialiser; |
17 | private boolean changed; |
18 | private long fromElement; |
19 | |
20 | @SuppressWarnings("unchecked") |
21 | public Chunk(RandomAccessFile raf, ISerialiser<T> serialiser) throws IOException { |
22 | this.myFilePos = raf.length(); |
23 | this.raf = raf; |
24 | this.serialiser = serialiser; |
25 | data = (T[])(new Object[BackgroundMemoryList.MEMORY_CHUNKS_SIZE]); |
26 | changed = false; |
27 | fromElement = myFilePos / serialiser.getElementLength(); |
28 | } |
29 | |
30 | public Chunk(RandomAccessFile raf, ISerialiser<T> serialiser, int chunkNo) throws IOException { |
31 | this.raf = raf; |
32 | this.serialiser = serialiser; |
33 | raf.seek(chunkNo * BackgroundMemoryList.MEMORY_CHUNKS_SIZE * serialiser.getElementLength()); |
34 | this.myFilePos = raf.getFilePointer(); |
35 | loadChunk(); |
36 | changed = false; |
37 | fromElement = myFilePos / serialiser.getElementLength(); |
38 | } |
39 | |
40 | public void add(T d){ |
41 | if (d == null) |
42 | throw new IllegalArgumentException("Background memory list does not support null values."); |
43 | data[nextFreeElement++] = d; |
44 | changed = true; |
45 | } |
46 | |
47 | public long fromElement() { |
48 | return fromElement; |
49 | } |
50 | |
51 | @SuppressWarnings("unchecked") |
52 | public T get(int index) { |
53 | return (T)data[index]; |
54 | } |
55 | |
56 | public boolean isFull() { |
57 | return nextFreeElement >= data.length; |
58 | } |
59 | |
60 | @SuppressWarnings("unchecked") |
61 | private void loadChunk() throws IOException { |
62 | int count = (int)(BackgroundMemoryList.MEMORY_CHUNKS_SIZE * serialiser.getElementLength()); |
63 | if (raf.length() < raf.getFilePointer() + count) { |
64 | count = (int)( raf.length() - raf.getFilePointer() ); |
65 | } |
66 | byte[] b = new byte[count]; |
67 | raf.read(b, 0, count); |
68 | T[] newData = serialiser.deserialise(b); |
69 | if (newData.length == BackgroundMemoryList.MEMORY_CHUNKS_SIZE) { |
70 | data = newData; |
71 | } else { |
72 | data = (T[])(new Object[BackgroundMemoryList.MEMORY_CHUNKS_SIZE]); |
73 | for (int i = 0; i < newData.length; i++) |
74 | data[i] = newData[i]; |
75 | } |
76 | nextFreeElement = newData.length; |
77 | } |
78 | |
79 | public void persist() throws IOException { |
80 | if (changed) { |
81 | raf.seek(myFilePos); |
82 | raf.write(serialiser.serialise(data,nextFreeElement)); |
83 | } |
84 | } |
85 | |
86 | public int size() { |
87 | return nextFreeElement; |
88 | } |
89 | |
90 | public long toElement() { |
91 | return fromElement() + nextFreeElement - 1; |
92 | } |
93 | |
94 | public boolean accepts(int index) { |
95 | if (fromElement <= index) { |
96 | if (toElement() > index) { |
97 | return true; |
98 | } |
99 | if (nextFreeElement + fromElement == index) { |
100 | return !isFull(); |
101 | } |
102 | return false; |
103 | } else { |
104 | return false; |
105 | } |
106 | } |
107 | } |