1
2
3
4
5
6
7
8
9 package org.jrobin.core.jrrd;
10
11 import java.io.IOException;
12 import java.io.PrintStream;
13 import java.text.DecimalFormat;
14 import java.text.NumberFormat;
15 import java.text.SimpleDateFormat;
16 import java.util.ArrayList;
17 import java.util.Calendar;
18 import java.util.Date;
19 import java.util.Iterator;
20
21
22
23
24
25
26
27 public class Archive {
28
29 RRDatabase db;
30 long offset;
31 long dataOffset;
32 long size;
33 ConsolidationFunctionType type;
34 int rowCount;
35 int pdpCount;
36 double xff;
37 ArrayList<CDPStatusBlock> cdpStatusBlocks;
38 int currentRow;
39
40 private double[][] values;
41
42 Archive(RRDatabase db) throws IOException {
43
44 this.db = db;
45
46 RRDFile file = db.rrdFile;
47
48 offset = file.getFilePointer();
49 type =
50 ConsolidationFunctionType.get(file.readString(Constants.CF_NAM_SIZE));
51 rowCount = file.readInt();
52 pdpCount = file.readInt();
53
54 file.align();
55
56 xff = file.readDouble();
57
58
59 file.align();
60 file.skipBytes(72);
61
62 size = file.getFilePointer() - offset;
63 }
64
65
66
67
68
69
70 public ConsolidationFunctionType getType() {
71 return type;
72 }
73
74 void loadCDPStatusBlocks(RRDFile file, int numBlocks) throws IOException {
75
76 cdpStatusBlocks = new ArrayList<CDPStatusBlock>();
77
78 for (int i = 0; i < numBlocks; i++) {
79 cdpStatusBlocks.add(new CDPStatusBlock(file));
80 }
81 }
82
83
84
85
86
87
88
89 public CDPStatusBlock getCDPStatusBlock(int index) {
90 return cdpStatusBlocks.get(index);
91 }
92
93
94
95
96
97
98
99 public Iterator<CDPStatusBlock> getCDPStatusBlocks() {
100 return cdpStatusBlocks.iterator();
101 }
102
103 void loadCurrentRow(RRDFile file) throws IOException {
104 currentRow = file.readInt();
105 }
106
107 void loadData(RRDFile file, int dsCount) throws IOException {
108
109 dataOffset = file.getFilePointer();
110
111
112 file.skipBytes(8 * rowCount * dsCount);
113 }
114
115 DataChunk loadData(DataChunk chunk) throws IOException {
116
117 Calendar end = Calendar.getInstance();
118 Calendar start = (Calendar) end.clone();
119
120 start.add(Calendar.DATE, -1);
121
122 loadData(chunk, start.getTime().getTime() / 1000,
123 end.getTime().getTime() / 1000);
124 return chunk;
125 }
126
127 void loadData(DataChunk chunk, long startTime, long endTime)
128 throws IOException {
129
130 long pointer;
131
132 if (chunk.start < 0) {
133 pointer = currentRow + 1;
134 }
135 else {
136 pointer = currentRow + chunk.start + 1;
137 }
138
139 db.rrdFile.ras.seek(dataOffset + (pointer * 8));
140
141
142
143
144 double[][] data = chunk.data;
145
146
147
148
149 int row = 0;
150 for (int i = chunk.start; i < rowCount - chunk.end; i++, row++) {
151 if (i < 0) {
152 for (int ii = 0; ii < chunk.dsCount; ii++) {
153 data[row][ii] = Double.NaN;
154 }
155 }
156 else if (i >= rowCount) {
157 for (int ii = 0; ii < chunk.dsCount; ii++) {
158 data[row][ii] = Double.NaN;
159 }
160 }
161 else {
162 if (pointer >= rowCount) {
163 pointer -= rowCount;
164
165 db.rrdFile.ras.seek(dataOffset + (pointer * 8));
166 }
167
168 for (int ii = 0; ii < chunk.dsCount; ii++) {
169 data[row][ii] = db.rrdFile.readDouble();
170 }
171
172 pointer++;
173 }
174 }
175 }
176
177 void printInfo(PrintStream s, NumberFormat numberFormat, int index) {
178
179 StringBuffer sb = new StringBuffer("rra[");
180
181 sb.append(index);
182 s.print(sb);
183 s.print("].cf = \"");
184 s.print(type);
185 s.println("\"");
186 s.print(sb);
187 s.print("].rows = ");
188 s.println(rowCount);
189 s.print(sb);
190 s.print("].pdp_per_row = ");
191 s.println(pdpCount);
192 s.print(sb);
193 s.print("].xff = ");
194 s.println(xff);
195 sb.append("].cdp_prep[");
196
197 int cdpIndex = 0;
198
199 for (Iterator<CDPStatusBlock> i = cdpStatusBlocks.iterator(); i.hasNext();) {
200 CDPStatusBlock cdp = i.next();
201
202 s.print(sb);
203 s.print(cdpIndex);
204 s.print("].value = ");
205
206 double value = cdp.value;
207
208 s.println(Double.isNaN(value)
209 ? "NaN"
210 : numberFormat.format(value));
211 s.print(sb);
212 s.print(cdpIndex++);
213 s.print("].unknown_datapoints = ");
214 s.println(cdp.unknownDatapoints);
215 }
216 }
217
218 void toXml(PrintStream s) {
219
220 try {
221 s.println("\t<rra>");
222 s.print("\t\t<cf> ");
223 s.print(type);
224 s.println(" </cf>");
225 s.print("\t\t<pdp_per_row> ");
226 s.print(pdpCount);
227 s.print(" </pdp_per_row> <!-- ");
228 s.print(db.header.pdpStep * pdpCount);
229 s.println(" seconds -->");
230 s.print("\t\t<xff> ");
231 s.print(xff);
232 s.println(" </xff>");
233 s.println();
234 s.println("\t\t<cdp_prep>");
235
236 for (int i = 0; i < cdpStatusBlocks.size(); i++) {
237 cdpStatusBlocks.get(i).toXml(s);
238 }
239
240 s.println("\t\t</cdp_prep>");
241 s.println("\t\t<database>");
242
243 long timer = -(rowCount - 1);
244 int counter = 0;
245 int row = currentRow;
246
247 db.rrdFile.ras.seek(dataOffset + (row + 1) * 16);
248
249 long lastUpdate = db.lastUpdate.getTime() / 1000;
250 int pdpStep = db.header.pdpStep;
251 NumberFormat numberFormat = new DecimalFormat("0.0000000000E0");
252 SimpleDateFormat dateFormat =
253 new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
254
255 while (counter++ < rowCount) {
256 row++;
257
258 if (row == rowCount) {
259 row = 0;
260
261 db.rrdFile.ras.seek(dataOffset);
262 }
263
264 long now = (lastUpdate - lastUpdate % (pdpCount * pdpStep))
265 + (timer * pdpCount * pdpStep);
266
267 timer++;
268
269 s.print("\t\t\t<!-- ");
270 s.print(dateFormat.format(new Date(now * 1000)));
271 s.print(" / ");
272 s.print(now);
273 s.print(" --> ");
274
275 for (int col = 0; col < db.header.dsCount; col++) {
276 s.print("<v> ");
277
278 double value = db.rrdFile.readDouble();
279
280
281 if (Double.isNaN(value)) {
282 s.print("NaN");
283 }
284 else {
285 s.print(numberFormat.format(value));
286 }
287
288 s.print(" </v>");
289 }
290
291 s.println("</row>");
292 }
293
294 s.println("\t\t</database>");
295 s.println("\t</rra>");
296 }
297 catch (IOException e) {
298 throw new RuntimeException(e.getMessage());
299 }
300 }
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328 public double[][] getValues() throws IOException {
329
330 if (values != null) {
331 return values;
332 }
333 values = new double[db.header.dsCount][rowCount];
334 int row = currentRow;
335
336 db.rrdFile.ras.seek(dataOffset + (row + 1) * db.header.dsCount * 8);
337
338 for (int counter = 0; counter < rowCount; counter++) {
339 row++;
340 if (row == rowCount) {
341 row = 0;
342 db.rrdFile.ras.seek(dataOffset);
343 }
344 for (int col = 0; col < db.header.dsCount; col++) {
345 double value = db.rrdFile.readDouble();
346 values[col][counter] = value;
347 }
348 }
349 return values;
350 }
351
352
353
354
355
356
357
358
359 public int getPdpCount() {
360 return pdpCount;
361 }
362
363
364
365
366
367
368 public int getRowCount() {
369 return rowCount;
370 }
371
372
373
374
375
376
377 public double getXff() {
378 return xff;
379 }
380
381
382
383
384
385
386 public String toString() {
387
388 StringBuffer sb = new StringBuffer("[Archive: OFFSET=0x");
389
390 sb.append(Long.toHexString(offset));
391 sb.append(", SIZE=0x");
392 sb.append(Long.toHexString(size));
393 sb.append(", type=");
394 sb.append(type);
395 sb.append(", rowCount=");
396 sb.append(rowCount);
397 sb.append(", pdpCount=");
398 sb.append(pdpCount);
399 sb.append(", xff=");
400 sb.append(xff);
401 sb.append(", currentRow=");
402 sb.append(currentRow);
403 sb.append("]");
404
405 for (Iterator<CDPStatusBlock> i = cdpStatusBlocks.iterator(); i.hasNext();) {
406 CDPStatusBlock cdp = i.next();
407
408 sb.append("\n\t\t");
409 sb.append(cdp.toString());
410 }
411
412 return sb.toString();
413 }
414 }