1 package org.lcsim.util.loop;
2
3 import java.io.EOFException;
4 import java.io.File;
5 import java.io.FileNotFoundException;
6 import java.io.IOException;
7 import java.util.Arrays;
8 import java.util.Collections;
9 import java.util.List;
10
11 import org.freehep.record.source.AbstractRecordSource;
12 import org.freehep.record.source.NoSuchRecordException;
13 import org.lcsim.event.EventHeader;
14 import org.lcsim.lcio.*;
15
16
17
18
19
20
21 public class LCIOEventSource extends AbstractRecordSource {
22
23 private List<File> files;
24 private boolean atEnd = false;
25 private boolean atStart = true;
26 private LCIOReader reader;
27 private EventHeader currentEvent;
28 private int currentFile = 0;
29
30 private long _index = -1L;
31 private long[] _size;
32
33
34
35
36
37
38 public LCIOEventSource(File file) throws IOException {
39 super(file.getName());
40 this.reader = new LCIOReader(file);
41 this.files = Collections.singletonList(file);
42 _size = new long[1]; _size[0] = -1L;
43 }
44
45
46
47
48
49
50
51 public LCIOEventSource(String name, List<File> files) throws IOException {
52 super(name);
53 if (files.isEmpty()) throw new IOException("File list is empty");
54 this.reader = new LCIOReader(files.get(0));
55 this.files = files;
56 _size = new long[files.size()]; Arrays.fill(_size, -1L);
57 }
58
59
60
61
62
63
64 public LCIOEventSource(FileList list) throws FileNotFoundException, IOException {
65 super(list.getTitle());
66 this.files = list.getFileList();
67 if (files.isEmpty()) throw new IOException("File list is empty");
68 this.reader = new LCIOReader(files.get(0));
69 _size = new long[files.size()]; Arrays.fill(_size, -1L);
70 }
71
72
73 public Object getCurrentRecord() throws IOException {
74 if (_index == -1L) throw new IllegalStateException();
75 if (currentEvent == null) throw new IOException();
76 return currentEvent;
77 }
78
79 public long getCurrentIndex() {
80 return _index;
81 }
82
83 public Class<?> getRecordClass() {
84 return EventHeader.class;
85 }
86
87 public boolean supportsCurrent() {return true;}
88
89 public boolean supportsNext() {return true;}
90
91 public boolean supportsPrevious() {return true;}
92
93 public boolean supportsIndex() {return true;}
94
95 public boolean supportsShift() {return true;}
96
97 public boolean supportsRewind() {return true;}
98
99 public boolean hasCurrent() {
100 return _index != -1L;
101 }
102
103 public boolean hasNext() {
104 return !atEnd;
105 }
106 public boolean hasPrevious() {
107 return _index > 0L;
108 }
109
110 public boolean hasIndex(long index) {
111 return index >= 0L;
112 }
113
114 public boolean hasShift(long numberOfRecords) {
115 return hasIndex(_index + numberOfRecords);
116 }
117
118 public boolean hasRewind() {
119 return _index != -1L;
120 }
121
122 public void current() throws IOException, NoSuchRecordException {
123 jump(_index);
124 }
125
126 public void next() throws IOException, NoSuchRecordException {
127 for (;;) {
128 try {
129 currentEvent = reader.read();
130
131 _index++;
132 } catch (EOFException x) {
133 _size[currentFile] = _index;
134 if (currentFile + 1 >= files.size()) {
135 atEnd = true;
136 throw new NoSuchRecordException();
137 } else {
138 currentFile++;
139 reader.close();
140 reader = new LCIOReader(files.get(currentFile));
141 continue;
142 }
143 }
144 return;
145 }
146 }
147
148 public void previous() throws IOException, NoSuchRecordException {
149 jump(_index-1);
150 }
151
152 public void jump(long index) throws IOException, NoSuchRecordException {
153 if (index < 0L) throw new NoSuchRecordException();
154 long i = _index;
155 int f = -1;
156 while (++f < files.size() && _size[f] != -1L && _size[f] < index);
157 if (f >= files.size()) throw new NoSuchRecordException();
158 atEnd = false;
159 long recoveryTarget = _index;
160 if (f != currentFile || index <= _index) {
161 reader.close();
162 reader = new LCIOReader(files.get(f));
163 i = (f == 0) ? -1L : _size[f-1];
164 }
165 int skipMax = Integer.MAX_VALUE - 10;
166 for (long skip = index - i - 1L; skip > 0L; ) {
167 int skipNow = skip > skipMax ? skipMax : (int)skip ;
168 skip -= skipNow;
169 while (true) {
170 int skipped = reader.skipEventsChecked(skipNow);
171 i += skipped;
172 if (skipped == skipNow) {
173 break;
174 } else {
175 skipNow -= skipped;
176 reader.close();
177 _size[f++] = i;
178 if (f < files.size()) {
179 reader = new LCIOReader(files.get(f));
180 } else {
181 reader = new LCIOReader(files.get(0));
182 if (_index != -1L) {
183 currentFile = 0;
184 atEnd = false;
185 _index = -1L;
186 try {
187 jump(recoveryTarget);
188 } catch (NoSuchRecordException x) {
189 throw new IOException(x);
190 }
191 }
192 throw new NoSuchRecordException();
193 }
194 }
195 }
196 }
197 _index = i;
198 currentFile = f;
199 try {
200 next();
201 } catch (NoSuchRecordException x) {
202 try {
203 jump(recoveryTarget);
204 } catch (NoSuchRecordException xx) {
205 throw new IOException(x);
206 }
207 }
208 }
209
210 public void shift(long numberOfRecords) throws IOException, NoSuchRecordException {
211 jump(_index + numberOfRecords);
212 }
213
214 public void rewind() throws IOException {
215 currentFile = 0;
216 reader.close();
217 reader = new LCIOReader(files.get(currentFile));
218 atEnd = false;
219 _index = -1L;
220 currentEvent = null;
221 }
222
223 public void close() throws IOException {
224 if (reader != null) {
225 reader.close();
226 reader = null;
227 }
228 currentEvent = null;
229 }
230
231 public void releaseRecord(Object obj) {
232 currentEvent = null;
233 }
234
235 public void finalize() {
236 try {
237 close();
238 } catch (IOException x) {
239 }
240 }
241 }