5
amount - is used for resolution calculation
6
limit - limits maximal number of points
9
class DATAInterval implements Iterator {
13
var $amount, $limit, $resolution;
16
var $row, $next, $lastrow;
28
function __construct(CACHEDB &$cache, MASK &$mask, INTERVAL &$ivl, $amount, $limit, $resolution, $flags = 0) {
29
$this->cache = &$cache;
30
$this->ids = &$mask->ids;
33
$this->amount = $amount;
34
$this->limit = $limit;
35
$this->resolution = $resolution;
37
$this->use_subseconds = $this->cache->use_subseconds;
39
$this->operation_info = array();
40
$this->postfix = false;
42
$this->flags = $flags;
45
function SetOption($option, $value) {
46
$this->$option = $value;
49
function SetOptions($options) {
50
foreach ($options as $opt => &$value) {
55
function combine(&$row, &$add, $ratio) {
56
// We ignoring edges for missing calculation
58
for ($i=0;isset($row['mean' . $i]);$i++) {
59
if ($add['min' . $i] < $row['min' . $i])
60
$row['min' . $i] = $add['min' . $i];
61
if ($add['max' . $i] > $row['max' . $i])
62
$row['max' . $i] = $add['max' . $i];
64
// $row['mean' . $i] = ($row['mean' . $i] + $ratio*$add['mean' . $i]) / (1 + $ratio);
66
$row['mean' . $i] = ($row['items']*$row['mean' . $i] + $add['items']*$add['mean' . $i]) / ($row['items'] + $add['items']);
70
$row['items'] += $add['items'];
71
$row['width'] += $add['width'];
75
global $CACHE_PRECISE_GAPS;
77
if ($this->resolution === false) {
78
$res = $this->cache->resolution->Get($this->ivl, $this->amount);
80
$res = $this->resolution;
83
$resolution = $this->cache->resolution->GetWindowSize($res);
85
$table = $this->cache->GetTableName($resolution, $this->postfix);
87
$this->operation_info["resolution"] = $resolution;
89
$from = $this->ivl->window_start;
90
$to = $from + $this->ivl->window_size;
92
$combine_ends = false;
94
if ($resolution > 0) {
96
$rem = $ifrom % $resolution;
97
if ($rem) $curfrom = $ifrom + ($resolution - $rem);
98
else $curfrom = $ifrom;
101
$rem = $ito % $resolution;
102
if ($rem) $curto = $ito - ($rem);
105
if ($this->ivl->flexibility) {
106
if ($this->ivl->flexibility == INTERVAL::FLAG_REDUCIBLE) {
110
if ($from != $curfrom) {
111
$curfrom -= $resolution;
115
$curto += $resolution;
121
$sqlfrom = $this->cache->SQLTime((int)$curfrom);
122
$sqlto = $this->cache->SQLTime((int)$curto);
124
if (($from != $curfrom)||($to != $curto)) {
126
foreach ($this->ids as $id) {
127
$list = "MIN(v$id) AS min$i, MAX(v$id) AS max$i, AVG(v$id) AS mean$i";
130
$rawtable = $this->cache->GetTableName(0, $this->postfix);
133
$points = ($curto - $curfrom) / $resolution;
134
$additional_points = 0;
136
if ($from != $curfrom) {
137
$sqltime = $this->cache->SQLTime($from);
139
$width = $curfrom - $from;
141
// $res = mysql_query("SELECT UNIX_TIMESTAMP(MIN(time)) AS timestamp $list FROM `$rawtable` WHERE `time` BETWEEN $sqltime AND $sqlfrom", $this->cache->dbh);
142
$res = mysql_query("SELECT UNIX_TIMESTAMP(MIN(time)) AS timestamp, COUNT(*) AS items, $width AS width $list FROM `$rawtable` WHERE (`time` >= $sqltime) AND (`time` < $sqlfrom)", $this->cache->dbh);
144
$firstrow = mysql_fetch_assoc($res);
145
if (($firstrow)&&($firstrow['time'])) $additional_points++;
146
else $firstrow = false;
148
mysql_free_result($res);
149
} else $firstrow = false;
150
} else $firstrow = false;
153
$sqltime = $this->cache->SQLTime($to);
155
$width = $to - $curto;
157
// $res = mysql_query("SELECT UNIX_TIMESTAMP(MIN(time)) AS timestamp $list FROM `$rawtable` WHERE `time` BETWEEN $sqlto AND $sqltime", $this->cache->dbh);
158
$res = mysql_query("SELECT UNIX_TIMESTAMP(MIN(time)) AS timestamp, COUNT(*) AS items, $width AS width $list FROM `$rawtable` WHERE (`time` >= $sqlto) AND (`time` < $sqltime)", $this->cache->dbh);
160
$this->lastrow = mysql_fetch_assoc($res);
161
if (($this->lastrow)&&($this->lastrow['time'])) $additional_points++;
162
else $this->lastrow = false;
164
mysql_free_result($res);
165
} else $this->lastrow = false;
166
} else $this->lastrow = false;
168
if (($this->limit)&&(($points + $aditional_points) > $this->limit)) {
169
if ($additional_points) {
170
if ($this->limit > 9) {
171
$limit = $this->limit - $aditional_points;
173
$limit = $this->limit;
174
$this->combine_ends = true;
177
$limit = $this->limit;
180
for ($grouping = $resolution; $points > $limit; $points /= 2) {
183
} else $grouping = 0;
186
$this->set_minmax = 0;
190
$grouping = "GROUP BY FLOOR((UNIX_TIMESTAMP(`time`) - " . ((int)$curfrom) . " )/$grouping)";
191
$list = "UNIX_TIMESTAMP(MIN(time)) AS timestamp, SUM(n) AS items, COUNT(*)*$resolution AS width";
192
if ($this->flags&CACHE::MISSING_INFO) {
193
if ($CACHE_PRECISE_GAPS) {
194
throw new ADEIException(translate("CACHE_PRECISE_GAPS is not supported yet"));
196
$val = "FLOOR(COUNT(*) / (1 + COUNT(*) - SUM(n = 0)))*$resolution";
197
$list .= ", IF($val > MAX(missing), $val, MAX(missing)) AS maxgap";
201
if ($this->flags&CACHE::TRUNCATE_INTERVALS) {
202
foreach ($this->ids as $id) {
203
$list .= ", MIN(min$id) AS min$i, MAX(max$id) AS max$i, AVG(mean$id) AS mean$i";
207
if ($this->flags&CACHE::REPORT_EMPTY) {
208
$grouping .= ", n=0";
209
$cond = "WHERE ((`time` >= $sqlfrom) AND (`time` < $sqlto))";
211
$cond = "WHERE ((`time` >= $sqlfrom) AND (`time` < $sqlto) AND (`n` > 0))";
214
if (!($this->flags&CACHE::REPORT_EMPTY)) $grouping .= " HAVING(`items` > 0)";
216
foreach ($this->ids as $id) {
217
$list .= ", MIN(IF(n,min$id,NULL)) AS min$i, MAX(IF(n,max$id,NULL)) AS max$i, AVG(IF(n,mean$id,NULL)) AS mean$i";
221
$cond = "WHERE ((`time` >= $sqlfrom) AND (`time` < $sqlto))";
225
$list = "UNIX_TIMESTAMP(time) AS timestamp, n AS items, $resolution AS width";
226
if ($this->flags&CACHE::MISSING_INFO) {
227
$list .= ", missing AS maxgap";
229
foreach ($this->ids as $id) {
230
$list .= ", min$id AS min$i, max$id AS max$i, mean$id AS mean$i";
234
if ($this->flags&CACHE::REPORT_EMPTY)
235
$cond = "WHERE ((`time` >= $sqlfrom) AND (`time` < $sqlto))";
237
$cond = "WHERE ((`time` >= $sqlfrom) AND (`time` < $sqlto) AND (`n` > 0))";
241
// $cond = "WHERE `time` BETWEEN $sqlfrom AND $sqlto";
242
// $cond = "WHERE ((`time` >= $sqlfrom) AND (`time` < $sqlto))";
243
// $cond = "WHERE ((`time` >= $sqlfrom) AND (`time` < $sqlto) AND (`n` > 0))";
244
$sort = "ORDER BY `time` ASC";
246
$use_subseconds = false;
247
$list = false; $i = 0;
248
$this->nextrow = false;
251
$limit = $this->limit;
252
$grouping = ($to - $from) / $limit;
256
$ifrom = floor($from);
259
$list = "UNIX_TIMESTAMP(MIN(time)) AS timestamp";
260
$groupval = "FLOOR((UNIX_TIMESTAMP(`time`) - " . ((int)$ifrom) . " )/$grouping)";
261
$grouping = "GROUP BY $groupval";
263
if (($grouping < 1)&&($this->use_subseconds)) {
264
$grouping *= 1000000000; /* in nanoseconds */
266
$use_subseconds = true;
267
$rfrom = ($from - $ifrom)*1000000000;
269
/* There is should not be MIN arround ns (otherwise problems
270
when on the edge of the seconds. Should it be on time?*/
271
$list = "UNIX_TIMESTAMP(MIN(time)) AS timestamp, ns";
272
$groupval = "FLOOR(((UNIX_TIMESTAMP(`time`) - $ifrom) * 1000000000 + (`ns` - $rfrom))/$grouping)";
273
$grouping = "GROUP BY $groupval";
274
} else $grouping = false;
275
} else $grouping = false;
280
$this->set_minmax = 0;
282
$list .= ", COUNT(*) AS items, (UNIX_TIMESTAMP(MAX(time)) - UNIX_TIMESTAMP(MIN(time))) AS width";
283
if ($this->flags&CACHE::MISSING_INFO) {
284
if ($CACHE_PRECISE_GAPS) {
285
/* Unfortunately, this is working from mysql client, but not from php. We should implement it with
286
stored functions, actually:
287
// $list .= ", MAX(IF(@tmpvar_pos=$groupval, UNIX_TIMESTAMP(time)-@tmpvar_width, 0)) AS maxgap, @tmpvar_pos:=$groupval AS tmpcol1, @tmpvar_width:=UNIX_TIMESTAMP(time) AS tmpcol2";
289
throw new ADEIException(translate("CACHE_PRECISE_GAPS is not supported yet"));
291
$list .= ", IF(COUNT(*)>1, (UNIX_TIMESTAMP(MAX(time)) - UNIX_TIMESTAMP(MIN(time))) / (COUNT(*) - 1), 0) AS maxgap";
295
foreach ($this->ids as $id) {
296
$list .= ", MIN(v$id) AS min$i, MAX(v$id) AS max$i, AVG(v$id) AS mean$i";
300
$cond = "WHERE `time` BETWEEN $sqlfrom AND $sqlto";
302
$this->set_minmax = 1;
304
if ($this->use_subseconds) {
305
$use_subseconds = true;
306
$list = "UNIX_TIMESTAMP(time) AS timestamp, ns";
308
$list = "UNIX_TIMESTAMP(time) AS timestamp";
311
$list .= ", 1 AS items, 0 AS width";
312
if ($this->flags&CACHE::MISSING_INFO) $list .= ", 0 AS maxgap";
314
foreach ($this->ids as $id) {
315
$list .= ", v$id AS mean$i";
320
$ifrom = (int)floor($from);
321
$ito = (int)floor($to);
323
// print_r($this->ivl);
324
// echo "$ifrom - $ito ($from - $to)\n";
325
if (($use_subseconds)&&(($ifrom != $from)||($ito != $to))) {
326
if ($ifrom == $ito) {
327
$sqlfrom = $this->cache->SQLTime($ifrom);
328
$nfrom = ($from - $ifrom)*1000000000;
329
$nto = ($to - $ito)*1000000000;
330
// $cond = "WHERE ((`time` = $sqlfrom) AND (`ns` BETWEEN $nfrom AND $nto))";
331
$cond = "WHERE ((`time` = $sqlfrom) AND (`ns` >= $nfrom) AND (`ns` < $nto))";
334
if ($ifrom != $from) {
335
$nfrom = ($from - $ifrom)*1000000000;
336
$sqlfrom = $this->cache->SQLTime($ifrom);
337
$cond = "((`time` = $sqlfrom) AND (`ns` >= $nfrom))";
341
if ($ifrom != $ito) {
342
if ($cond) $cond .= " OR ";
344
$sqlfrom = $this->cache->SQLTime($ifrom);
345
$sqlto = $this->cache->SQLTime($ito);
346
// $cond .= "(`time` BETWEEN $sqlfrom AND $sqlto)";
347
$cond .= "((`time` >= $sqlfrom) AND (`time` < $sqlto))";
348
} else $sqlto = false;
351
if ($cond) $cond .= " OR ";
352
if (!$sqlto) $sqlto = $this->cache->SQLTime($ito);
354
$nto = ($to - $ito)*1000000000;
355
$cond .= "((`time` = $sqlto) AND (`ns` < $nto))";
357
$cond = "WHERE ($cond)";
359
$sort = "ORDER BY `time` ASC, `ns` ASC";
361
$sqlfrom = $this->cache->SQLTime($ifrom);
362
$sqlto = $this->cache->SQLTime($ito);
363
// $cond = "WHERE `time` BETWEEN $sqlfrom AND $sqlto";
364
$cond = "WHERE ((`time`>= $sqlfrom) AND (`time` < $sqlto))";
365
$sort = "ORDER BY `time` ASC";
366
if ($use_subseconds) $sort .= ", `ns` ASC ";
373
/* $f=fopen("/tmp/xxx.9", "w");
374
fwrite ($f, "SELECT $list FROM `$table` $cond $grouping $sort LIMIT $limit\n");
376
// echo "SELECT $list FROM `$table` $cond $grouping $sort LIMIT $limit\n";
377
// echo "SELECT $list FROM `$table` $cond $grouping $sort LIMIT $limit\n";
378
$this->res = mysql_unbuffered_query("SELECT $list FROM `$table` $cond $grouping $sort LIMIT $limit", $this->cache->dbh);
380
$this->res = mysql_unbuffered_query("SELECT $list FROM `$table` $cond $sort", $this->cache->dbh);
383
if ($this->combine_ends) {
384
$this->nextrow = false;
388
$this->combine($this->nextrow, $firstrow, ($curfrom - $from)/$grouping);
389
$this->nextrow['time'] = $firstrow['time'];
392
if ($this->lastrow) {
394
$this->combine_ends = ($to - $curto)/$grouping;
396
$this->combine_ends = ($to - $curto)/($grouping + ($curfrom - $from));
398
} else $this->combine_ends = 0;
401
$this->nextrow = &$firstrow;
403
$this->nextrow = false;
416
if (isset($this->row['ns'])) {
417
$l = strlen($this->row['ns']);
418
if ($l < 9) return $this->row['timestamp'] . "." . str_repeat('0', 9 - $l) . $this->row['ns'];
419
return $this->row['timestamp'] . "." . $this->row['ns'];
421
return $this->row['timestamp'];
424
/* FIXME: provide min-max if only mean, provide interval ends */
426
$this->row = $this->nextrow; // FIXME. We can't reference here, howto optimize (php by itself?)
427
if (($this->row)&&(!isset($this->row['min0']))) {
428
for ($i=0;isset($this->row['mean' . $i]);$i++) {
429
$this->row['min' . $i] = $this->row['mean' . $i];
430
$this->row['max' . $i] = $this->row['mean' . $i];
435
$this->nextrow = mysql_fetch_assoc($this->res);
437
if (!$this->nextrow) {
438
mysql_free_result($this->res);
441
if ($this->combine_ends) {
442
$this->combine($this->row, $this->lastrow, $this->combine_ends);
443
$this->nextrow = false;
445
$this->nextrow = $this->lastrow;
448
} else $this->nextrow = false;
452
return $this->row?true:false;
455
function GetOperationInfo() {
456
return $this->operation_info;
b'\\ No newline at end of file'