aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/js/RrdDataFile.js
blob: ae4dcff686c889ad88d8a6eda6ecf550b14b3bfa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/**
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.

 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA

 *
 * Manuel Sanmartin <manuel.luis at gmail.com>
 **/

"use strict";

/**
 * RrdDataFile
 * @constructor
 */
var RrdDataFile = function() {
  this.init.apply(this, arguments);
};

RrdDataFile.prototype = {
	rrdfiles: null,

	init: function()
	{
		this.rrdfiles = {};
	},
	fetch: function(gdp, ft_step)
	{
    var cal_start, cal_end;
    var best_full_rra = 0, best_part_rra = 0, chosen_rra = 0;
    var best_full_step_diff = 0, best_part_step_diff = 0, tmp_step_diff = 0, tmp_match = 0, best_match = 0;
    var full_match, rra_base;
    var first_full = 1;
    var first_part = 1;
    var rrd;
    var data_ptr;
    var rows;

		if (gdp.rrd in this.rrdfiles) {
			rrd = this.rrdfiles[gdp.rrd];
		} else {
			var bf = FetchBinaryURL(gdp.rrd);
			rrd = new RRDFile(bf);
			this.rrdfiles[gdp.rrd] = rrd;
		}

		var cf_idx = gdp.cf;
		var ds_cnt = rrd.getNrDSs();
		var rra_cnt = rrd.getNrRRAs();

    for (var i = 0; i < ds_cnt; i++)
			gdp.ds_namv[i] = rrd.rrd_header.getDSbyIdx(i).getName();

		for (var i = 0; i < rra_cnt; i++) {
			var rra = rrd.getRRAInfo(i);
			if (RrdGraphDesc.cf_conv(rra.getCFName()) === cf_idx) {
				cal_end = (rrd.getLastUpdate() - (rrd.getLastUpdate() % (rra.getPdpPerRow() * rra.pdp_step)));
				cal_start = (cal_end - (rra.getPdpPerRow() * rra.row_cnt * rra.pdp_step));
				full_match = gdp.end - gdp.start;

				tmp_step_diff = Math.abs(ft_step - (rrd.getMinStep() * rra.pdp_cnt));
				if (cal_start <= gdp.start) {
					if (first_full || (tmp_step_diff < best_full_step_diff)) {
						first_full = 0;
						best_full_step_diff = tmp_step_diff;
						best_full_rra = i;
					}
				} else {
					tmp_match = full_match;
					if (cal_start > gdp.start) tmp_match -= (cal_start - gdp.start);
					if (first_part || (best_match < tmp_match) || (best_match === tmp_match && tmp_step_diff < best_part_step_diff)) {
						first_part = 0;
						best_match = tmp_match;
						best_part_step_diff = tmp_step_diff;
						best_part_rra = i;
					}
				}
			}
		}

		if (first_full === 0) chosen_rra = best_full_rra;
		else if (first_part === 0) chosen_rra = best_part_rra;
		else throw "the RRD does not contain an RRA matching the chosen CF";

		var rra_info = rrd.getRRAInfo(chosen_rra);
		var rra = rrd.getRRA(chosen_rra);

		ft_step = rrd.rrd_header.pdp_step * rra_info.getPdpPerRow();
    gdp.start -= (gdp.start % ft_step);
    gdp.end += (ft_step - gdp.end % ft_step);
    rows = (gdp.end - gdp.start) / ft_step + 1;

		gdp.ds_cnt = ds_cnt;
    data_ptr = 0;

    var rra_end_time = (rrd.getLastUpdate() - (rrd.getLastUpdate() % ft_step));
    var rra_start_time = (rra_end_time - (ft_step * (rra_info.row_cnt - 1)));
    /* here's an error by one if we don't be careful */
    var start_offset = (gdp.start + ft_step - rra_start_time) / ft_step;
    var end_offset = (rra_end_time - gdp.end) / ft_step;

		gdp.data = [];

		for (i = start_offset; i < rra.row_cnt - end_offset; i++) {
			if (i < 0) {
				for (var ii = 0; ii < ds_cnt; ii++)
					gdp.data[data_ptr++] = Number.NaN;
			} else if (i >= rra.row_cnt) {
	    	for (var ii = 0; ii < ds_cnt; ii++)
					gdp.data[data_ptr++] = Number.NaN;
			} else {
				for (var ii = 0; ii < ds_cnt; ii++)
					gdp.data[data_ptr++] = rra.getEl(i, ii);
			}
		}
		return ft_step;
	}
};