aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/js/rrdFile.js
diff options
context:
space:
mode:
authorPim van den Berg2013-05-10 21:36:54 +0200
committerPim van den Berg2013-05-10 21:36:54 +0200
commit0163faefef02207ad0ea3330af688103633293ff (patch)
treec407fca93a3418af59c4c7133327f5bc1630fba5 /js/rrdFile.js
parentMerge pull request #5 from mce35/nut (diff)
downloadapt-panopticon_cgp-0163faefef02207ad0ea3330af688103633293ff.zip
apt-panopticon_cgp-0163faefef02207ad0ea3330af688103633293ff.tar.gz
apt-panopticon_cgp-0163faefef02207ad0ea3330af688103633293ff.tar.bz2
apt-panopticon_cgp-0163faefef02207ad0ea3330af688103633293ff.tar.xz
import js directory from jsrrdgraph for client side graph rendering
Source: https://github.com/manuelluis/jsrrdgraph@276b880
Diffstat (limited to 'js/rrdFile.js')
-rw-r--r--js/rrdFile.js408
1 files changed, 408 insertions, 0 deletions
diff --git a/js/rrdFile.js b/js/rrdFile.js
new file mode 100644
index 0000000..870c88e
--- /dev/null
+++ b/js/rrdFile.js
@@ -0,0 +1,408 @@
1/*
2 * Client library for access to RRD archive files
3 * Part of the javascriptRRD package
4 * Copyright (c) 2009-2010 Frank Wuerthwein, fkw@ucsd.edu
5 * Igor Sfiligoi, isfiligoi@ucsd.edu
6 *
7 * Original repository: http://javascriptrrd.sourceforge.net/
8 *
9 * MIT License [http://www.opensource.org/licenses/mit-license.php]
10 *
11 */
12
13/*
14 *
15 * RRDTool has been developed and is maintained by
16 * Tobias Oether [http://oss.oetiker.ch/rrdtool/]
17 *
18 * This software can be used to read files produced by the RRDTool
19 * but has been developed independently.
20 *
21 * Limitations:
22 *
23 * This version of the module assumes RRD files created on linux
24 * with intel architecture and supports both 32 and 64 bit CPUs.
25 * All integers in RRD files are suppoes to fit in 32bit values.
26 *
27 * Only versions 3 and 4 of the RRD archive are supported.
28 *
29 * Only AVERAGE,MAXIMUM,MINIMUM and LAST consolidation functions are
30 * supported. For all others, the behaviour is at the moment undefined.
31 *
32 */
33
34/*
35 * Dependencies:
36 *
37 * The data provided to this module require an object of a class
38 * that implements the following methods:
39 * getByteAt(idx) - Return a 8 bit unsigned integer at offset idx
40 * getLongAt(idx) - Return a 32 bit unsigned integer at offset idx
41 * getDoubleAt(idx) - Return a double float at offset idx
42 * getFastDoubleAt(idx) - Similar to getDoubleAt but with less precision
43 * getCStringAt(idx,maxsize) - Return a string of at most maxsize characters
44 * that was 0-terminated in the source
45 *
46 * The BinaryFile from binaryXHR.js implements this interface.
47 *
48 */
49
50
51// ============================================================
52// Exception class
53function InvalidRRD(msg) {
54 this.message=msg;
55 this.name="Invalid RRD";
56}
57
58// pretty print
59InvalidRRD.prototype.toString = function() {
60 return this.name + ': "' + this.message + '"';
61}
62
63
64// ============================================================
65// RRD DS Info class
66function RRDDS(rrd_data,rrd_data_idx,my_idx) {
67 this.rrd_data=rrd_data;
68 this.rrd_data_idx=rrd_data_idx;
69 this.my_idx=my_idx;
70}
71
72RRDDS.prototype.getIdx = function() {
73 return this.my_idx;
74}
75RRDDS.prototype.getName = function() {
76 return this.rrd_data.getCStringAt(this.rrd_data_idx,20);
77}
78RRDDS.prototype.getType = function() {
79 return this.rrd_data.getCStringAt(this.rrd_data_idx+20,20);
80}
81RRDDS.prototype.getMin = function() {
82 return this.rrd_data.getDoubleAt(this.rrd_data_idx+48);
83}
84RRDDS.prototype.getMax = function() {
85 return this.rrd_data.getDoubleAt(this.rrd_data_idx+56);
86}
87
88
89// ============================================================
90// RRD RRA Info class
91function RRDRRAInfo(rrd_data,rra_def_idx,
92 rrd_align,row_cnt,pdp_step,my_idx) {
93 this.rrd_data=rrd_data;
94 this.rra_def_idx=rra_def_idx;
95 this.rrd_align=rrd_align;
96 this.row_cnt=row_cnt;
97 this.pdp_step=pdp_step;
98 this.my_idx=my_idx;
99}
100
101RRDRRAInfo.prototype.getIdx = function() {
102 return this.my_idx;
103}
104
105// Get number of rows
106RRDRRAInfo.prototype.getNrRows = function() {
107 return this.row_cnt;
108}
109
110// Get number of slots used for consolidation
111// Mostly for internal use
112RRDRRAInfo.prototype.getPdpPerRow = function() {
113 if (this.rrd_align==32)
114 return this.rrd_data.getLongAt(this.rra_def_idx+24,20);
115 else
116 return this.rrd_data.getLongAt(this.rra_def_idx+32,20);
117}
118
119// Get RRA step (expressed in seconds)
120RRDRRAInfo.prototype.getStep = function() {
121 return this.pdp_step*this.getPdpPerRow();
122}
123
124// Get consolidation function name
125RRDRRAInfo.prototype.getCFName = function() {
126 return this.rrd_data.getCStringAt(this.rra_def_idx,20);
127}
128
129
130// ============================================================
131// RRD RRA handling class
132function RRDRRA(rrd_data,rra_ptr_idx,
133 rra_info,
134 header_size,prev_row_cnts,ds_cnt) {
135 this.rrd_data=rrd_data;
136 this.rra_info=rra_info;
137 this.row_cnt=rra_info.row_cnt;
138 this.ds_cnt=ds_cnt;
139
140 var row_size=ds_cnt*8;
141
142 this.base_rrd_db_idx=header_size+prev_row_cnts*row_size;
143
144 // get imediately, since it will be needed often
145 this.cur_row=rrd_data.getLongAt(rra_ptr_idx);
146
147 // calculate idx relative to base_rrd_db_idx
148 // mostly used internally
149 this.calc_idx = function(row_idx,ds_idx) {
150 if ((row_idx>=0) && (row_idx<this.row_cnt)) {
151 if ((ds_idx>=0) && (ds_idx<ds_cnt)){
152 // it is round robin, starting from cur_row+1
153 var real_row_idx=row_idx+this.cur_row+1;
154 if (real_row_idx>=this.row_cnt) real_row_idx-=this.row_cnt;
155 return row_size*real_row_idx+ds_idx*8;
156 } else {
157 throw RangeError("DS idx ("+ row_idx +") out of range [0-" + ds_cnt +").");
158 }
159 } else {
160 throw RangeError("Row idx ("+ row_idx +") out of range [0-" + this.row_cnt +").");
161 }
162 }
163}
164
165RRDRRA.prototype.getIdx = function() {
166 return this.rra_info.getIdx();
167}
168
169// Get number of rows/columns
170RRDRRA.prototype.getNrRows = function() {
171 return this.row_cnt;
172}
173RRDRRA.prototype.getNrDSs = function() {
174 return this.ds_cnt;
175}
176
177// Get RRA step (expressed in seconds)
178RRDRRA.prototype.getStep = function() {
179 return this.rra_info.getStep();
180}
181
182// Get consolidation function name
183RRDRRA.prototype.getCFName = function() {
184 return this.rra_info.getCFName();
185}
186
187RRDRRA.prototype.getEl = function(row_idx,ds_idx) {
188 return this.rrd_data.getDoubleAt(this.base_rrd_db_idx+this.calc_idx(row_idx,ds_idx));
189}
190
191// Low precision version of getEl
192// Uses getFastDoubleAt
193RRDRRA.prototype.getElFast = function(row_idx,ds_idx) {
194 return this.rrd_data.getFastDoubleAt(this.base_rrd_db_idx+this.calc_idx(row_idx,ds_idx));
195}
196
197// ============================================================
198// RRD Header handling class
199function RRDHeader(rrd_data) {
200 this.rrd_data=rrd_data;
201 this.validate_rrd();
202 this.load_header();
203 this.calc_idxs();
204}
205
206// Internal, used for initialization
207RRDHeader.prototype.validate_rrd = function() {
208 if (this.rrd_data.getCStringAt(0,4)!=="RRD") throw new InvalidRRD("Wrong magic id.");
209
210 this.rrd_version=this.rrd_data.getCStringAt(4,5);
211 if ((this.rrd_version!=="0003")&&(this.rrd_version!=="0004")) {
212 throw new InvalidRRD("Unsupported RRD version "+this.rrd_version+".");
213 }
214
215 if (this.rrd_data.getDoubleAt(12)==8.642135e+130) {
216 this.rrd_align=32;
217 } else if (this.rrd_data.getDoubleAt(16)==8.642135e+130) {
218 this.rrd_align=64;
219 } else {
220 throw new InvalidRRD("Unsupported platform.");
221 }
222}
223
224// Internal, used for initialization
225RRDHeader.prototype.load_header = function() {
226 if (this.rrd_align==32) {
227 this.ds_cnt=this.rrd_data.getLongAt(20,false);
228 this.rra_cnt=this.rrd_data.getLongAt(24,false);
229 this.pdp_step=this.rrd_data.getLongAt(28,false);
230 // 8*10 unused values follow
231 this.top_header_size=112;
232 } else {
233 //get only the low 32 bits, the high 32 should always be 0
234 this.ds_cnt=this.rrd_data.getLongAt(24,false);
235 this.rra_cnt=this.rrd_data.getLongAt(32,false);
236 this.pdp_step=this.rrd_data.getLongAt(40,false);
237 // 8*10 unused values follow
238 this.top_header_size=128;
239 }
240}
241
242// Internal, used for initialization
243RRDHeader.prototype.calc_idxs = function() {
244 this.ds_def_idx=this.top_header_size;
245 // char ds_nam[20], char dst[20], unival par[10]
246 this.ds_el_size=120;
247
248 this.rra_def_idx=this.ds_def_idx+this.ds_el_size*this.ds_cnt;
249 // char cf_nam[20], uint row_cnt, uint pdp_cnt, unival par[10]
250 this.row_cnt_idx;
251 if (this.rrd_align==32) {
252 this.rra_def_el_size=108;
253 this.row_cnt_idx=20;
254 } else {
255 this.rra_def_el_size=120;
256 this.row_cnt_idx=24;
257 }
258
259 this.live_head_idx=this.rra_def_idx+this.rra_def_el_size*this.rra_cnt;
260 // time_t last_up, int last_up_usec
261 if (this.rrd_align==32) {
262 this.live_head_size=8;
263 } else {
264 this.live_head_size=16;
265 }
266
267 this.pdp_prep_idx=this.live_head_idx+this.live_head_size;
268 // char last_ds[30], unival scratch[10]
269 this.pdp_prep_el_size=112;
270
271 this.cdp_prep_idx=this.pdp_prep_idx+this.pdp_prep_el_size*this.ds_cnt;
272 // unival scratch[10]
273 this.cdp_prep_el_size=80;
274
275 this.rra_ptr_idx=this.cdp_prep_idx+this.cdp_prep_el_size*this.ds_cnt*this.rra_cnt;
276 // uint cur_row
277 if (this.rrd_align==32) {
278 this.rra_ptr_el_size=4;
279 } else {
280 this.rra_ptr_el_size=8;
281 }
282
283 this.header_size=this.rra_ptr_idx+this.rra_ptr_el_size*this.rra_cnt;
284}
285
286// Optional initialization
287// Read and calculate row counts
288RRDHeader.prototype.load_row_cnts = function() {
289 this.rra_def_row_cnts=[];
290 this.rra_def_row_cnt_sums=[]; // how many rows before me
291 for (var i=0; i<this.rra_cnt; i++) {
292 this.rra_def_row_cnts[i]=this.rrd_data.getLongAt(this.rra_def_idx+i*this.rra_def_el_size+this.row_cnt_idx,false);
293 if (i==0) {
294 this.rra_def_row_cnt_sums[i]=0;
295 } else {
296 this.rra_def_row_cnt_sums[i]=this.rra_def_row_cnt_sums[i-1]+this.rra_def_row_cnts[i-1];
297 }
298 }
299}
300
301// ---------------------------
302// Start of user functions
303
304RRDHeader.prototype.getMinStep = function() {
305 return this.pdp_step;
306}
307RRDHeader.prototype.getLastUpdate = function() {
308 return this.rrd_data.getLongAt(this.live_head_idx,false);
309}
310
311RRDHeader.prototype.getNrDSs = function() {
312 return this.ds_cnt;
313}
314RRDHeader.prototype.getDSNames = function() {
315 var ds_names=[]
316 for (var idx=0; idx<this.ds_cnt; idx++) {
317 var ds=this.getDSbyIdx(idx);
318 var ds_name=ds.getName()
319 ds_names.push(ds_name);
320 }
321 return ds_names;
322}
323RRDHeader.prototype.getDSbyIdx = function(idx) {
324 if ((idx>=0) && (idx<this.ds_cnt)) {
325 return new RRDDS(this.rrd_data,this.ds_def_idx+this.ds_el_size*idx,idx);
326 } else {
327 throw RangeError("DS idx ("+ idx +") out of range [0-" + this.ds_cnt +").");
328 }
329}
330RRDHeader.prototype.getDSbyName = function(name) {
331 for (var idx=0; idx<this.ds_cnt; idx++) {
332 var ds=this.getDSbyIdx(idx);
333 var ds_name=ds.getName()
334 if (ds_name==name)
335 return ds;
336 }
337 throw RangeError("DS name "+ name +" unknown.");
338}
339
340RRDHeader.prototype.getNrRRAs = function() {
341 return this.rra_cnt;
342}
343RRDHeader.prototype.getRRAInfo = function(idx) {
344 if ((idx>=0) && (idx<this.rra_cnt)) {
345 return new RRDRRAInfo(this.rrd_data,
346 this.rra_def_idx+idx*this.rra_def_el_size,
347 this.rrd_align,this.rra_def_row_cnts[idx],this.pdp_step,
348 idx);
349 } else {
350 throw RangeError("RRA idx ("+ idx +") out of range [0-" + this.rra_cnt +").");
351 }
352}
353
354// ============================================================
355// RRDFile class
356// Given a BinaryFile, gives access to the RRD archive fields
357//
358// Arguments:
359// bf must be an object compatible with the BinaryFile interface
360function RRDFile(bf) {
361 var rrd_data=bf
362
363 this.rrd_header=new RRDHeader(rrd_data);
364 this.rrd_header.load_row_cnts();
365
366 // ===================================
367 // Start of user functions
368
369 this.getMinStep = function() {
370 return this.rrd_header.getMinStep();
371 }
372 this.getLastUpdate = function() {
373 return this.rrd_header.getLastUpdate();
374 }
375
376 this.getNrDSs = function() {
377 return this.rrd_header.getNrDSs();
378 }
379 this.getDSNames = function() {
380 return this.rrd_header.getDSNames();
381 }
382 this.getDS = function(id) {
383 if (typeof id == "number") {
384 return this.rrd_header.getDSbyIdx(id);
385 } else {
386 return this.rrd_header.getDSbyName(id);
387 }
388 }
389
390 this.getNrRRAs = function() {
391 return this.rrd_header.getNrRRAs();
392 }
393
394 this.getRRAInfo = function(idx) {
395 return this.rrd_header.getRRAInfo(idx);
396 }
397
398 this.getRRA = function(idx) {
399 var rra_info=this.rrd_header.getRRAInfo(idx);
400 return new RRDRRA(rrd_data,
401 this.rrd_header.rra_ptr_idx+idx*this.rrd_header.rra_ptr_el_size,
402 rra_info,
403 this.rrd_header.header_size,
404 this.rrd_header.rra_def_row_cnt_sums[idx],
405 this.rrd_header.ds_cnt);
406 }
407
408}