/adei/ui

To get this branch, use:
bzr branch http://darksoft.org/webbzr/adei/ui

« back to all changes in this revision

Viewing changes to classes/cache/cachedb.php

  • Committer: Suren A. Chilingaryan
  • Date: 2008-04-02 10:23:22 UTC
  • Revision ID: csa@dside.dyndns.org-20080402102322-okib92sicg2dx3o3
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
class CACHEDB {
 
3
 var $req;
 
4
 var $dbh;
 
5
 
 
6
 var $default_db_server, $default_db_name, $default_db_group;
 
7
 var $default_postfix;
 
8
 
 
9
 var $md5_postfix;
 
10
 var $use_subseconds;
 
11
 
 
12
 const MYSQL_ER_BAD_DB_ERROR = 1049;
 
13
 const MYSQL_ER_NO_SUCH_TABLE = 1146;
 
14
 const MYSQL_ER_DUP_ENTRY = 1062;
 
15
 
 
16
 const TYPE_AUTO = 0;
 
17
 const TYPE_MINMAX = 1;
 
18
 const TYPE_MEAN = 2;
 
19
 const TYPE_ALL = 3;
 
20
 
 
21
 const NEED_COUNT = 1;          // Element count
 
22
 const TABLE_INFO = 2;          // Information about cache tables
 
23
 
 
24
 function __construct(SOURCERequest &$props) {
 
25
    global $ADEI_DB;
 
26
 
 
27
    $this->req = &$props;
 
28
 
 
29
    $this->dbh = mysql_connect($ADEI_DB['host'] . ($ADEI_DB['port']?(":" . $ADEI_DB['port']):""), $ADEI_DB['user'], $ADEI_DB['password']);
 
30
    if (!$this->dbh) throw new ADEIException(translate("Connection to the Caching MySQL Server is failed"));
 
31
    
 
32
    mysql_query("SET time_zone = '+0:00'");
 
33
 
 
34
    if (!@mysql_select_db($ADEI_DB['database'], $this->dbh)) {
 
35
                // ER_NO_DB_ERROR
 
36
        if (mysql_errno($this->dbh) == CACHEDB::MYSQL_ER_BAD_DB_ERROR) { 
 
37
            if (mysql_query("CREATE DATABASE " . $ADEI_DB['database'], $this->dbh)) {
 
38
                if (!mysql_select_db($ADEI_DB['database'], $this->dbh))
 
39
                    throw new ADEIException(translate("Connection to the Caching MySQL Database is failed") . " (" . mysql_error($this->dbh) . ")");
 
40
            } else 
 
41
                throw new ADEIException(translate("Creation of the caching MySQL database is failed") . " (" . mysql_error($this->dbh) . ")");
 
42
            
 
43
            
 
44
        } else 
 
45
            throw new ADEIException(translate("Connection to the Caching MySQL Database is failed") . " (" . mysql_error($this->dbh) . ")");
 
46
    }
 
47
 
 
48
    if (isset($this->req->props['db_server']))
 
49
        $this->default_db_server = $this->req->props['db_server'];
 
50
    else 
 
51
        $this->default_db_server = false;
 
52
    if (isset($this->req->props['db_name']))
 
53
        $this->default_db_name =  $this->req->props['db_name'];
 
54
    else 
 
55
        $this->default_db_name = false;
 
56
    if (isset($this->req->props['db_group']))
 
57
        $this->default_db_group = $this->req->props['db_group'];
 
58
    else 
 
59
        $this->default_db_group = false;
 
60
    
 
61
    if (($this->default_db_server !== false)&&($this->default_db_name !== false)&&($this->default_db_group !== false)) {
 
62
        $this->default_postfix = $this->GetCachePostfix();      
 
63
    }
 
64
 
 
65
    $this->default_postfix = false;
 
66
 }
 
67
 
 
68
 function ListCachedGroups($db_name = false, $db_server = false) {
 
69
        // DS, only listing databases having level0 CACHE
 
70
    if ((!$db_server)||(!$db_name)) {
 
71
        if (!$db_server) $db_server = $this->default_db_server;
 
72
        if (!$db_name) $db_name = $this->default_db_name;
 
73
 
 
74
        if ((!$db_server)||(!$db_name))
 
75
            throw new ADEIException(translate("Server name and database should be specified to list available groups"));
 
76
    }
 
77
 
 
78
    $groups = array();
 
79
    
 
80
    $prefix = "cache0__" . $db_server . "__" . $db_name . "__";
 
81
    $prefix_length = strlen($prefix);
 
82
    
 
83
    $res = @mysql_query("SHOW TABLES LIKE 'cache0__${db_server}__${db_name}%'", $this->dbh);
 
84
    if (!$res)
 
85
        throw new ADEIException(translate("SHOW TABLES request is failed on CACHE database, error: %s", mysql_error($this->dbh)));
 
86
        
 
87
    while ($row = mysql_fetch_row($res))
 
88
        array_push($groups, substr($row[0], $prefix_length));
 
89
    
 
90
    
 
91
    $md5 = array();
 
92
    $res = mysql_query("SHOW TABLES LIKE 'cache0__md5_%'", $this->dbh);
 
93
    while ($row = mysql_fetch_row($res))
 
94
        array_push($md5, substr($row[0], 6));
 
95
    
 
96
    if (sizeof($md5) > 0) {
 
97
        $prefix = "__" . $db_server . "__" . $db_name . "__";
 
98
        $prefix_length = strlen($prefix);
 
99
 
 
100
        $res = mysql_query("SELECT `hash`, `postfix` FROM md5 WHERE postfix LIKE '__${db_server}__${db_name}__%'", $this->dbh);
 
101
        if (!$res) 
 
102
            throw new ADEIException(translate("SELECT request on MD5 table is failed, error: %s", mysql_error($this->dbh)));
 
103
 
 
104
        while ($row = mysql_fetch_row($res)) {
 
105
            if (in_array($row[0], $md5))
 
106
                array_push($groups, substr($row[1], $postfix_length));
 
107
        }
 
108
 
 
109
        return array_unique($groups);
 
110
    }
 
111
    
 
112
    return $groups;    
 
113
 }
 
114
 
 
115
 function GetGroupPostfix($db_group = false, $db_name = false, $db_server = false) {
 
116
    if ((!$db_server)||(!$db_name)||(!$db_group)) {
 
117
        if ($db_server === false) $db_server = $this->default_db_server;
 
118
        if ($db_name === false) $db_name = $this->default_db_name;
 
119
        if ($db_group === false) $db_group = $this->default_db_group;
 
120
        if (($db_server === false)||($db_name === false)||($db_group === false))
 
121
            throw new ADEIException(translate("Server name, database and group is required to construct CACHE postfix"));
 
122
    }
 
123
 
 
124
    $db_group = preg_replace("/[^\w\d_]/","",$db_group);
 
125
    
 
126
    return "__${db_server}__${db_name}__${db_group}";
 
127
 }    
 
128
 
 
129
 function MD5CreateTable() {
 
130
    if (!@mysql_query("CREATE TABLE `md5` (`hash` CHAR(64) PRIMARY KEY,  `postfix` VARCHAR(4096) NOT NULL, UNIQUE INDEX(postfix(64)))", $this->dbh)) {
 
131
        throw new ADEIException(translate("Creation of system tables (md5) within CACHE database is failed") . " (" . mysql_error($this->dbh) . ")");
 
132
    }
 
133
 }
 
134
 
 
135
 function MD5CreateEntry($postfix) {
 
136
    $query = "INSERT INTO `md5` VALUES('" . $this->default_postfix . "' , '" . mysql_real_escape_string($postfix) . "')";
 
137
    if (!@mysql_query($query, $this->dbh)) 
 
138
        throw new ADEIException(translate("Can not insert entry into the MD5 caching table, error") . ": " . mysql_error($this->dbh));
 
139
 }
 
140
 
 
141
 function MD5Check() {
 
142
    $res = @mysql_query("SELECT `postfix` from `md5` WHERE `hash` = '" . $this->default_postfix . "'", $this->dbh);
 
143
    if (!$res) {
 
144
        switch (mysql_errno($this->dbh)) {
 
145
            case CACHE::MYSQL_ER_NO_SUCH_TABLE:
 
146
                $this->MD5CreateTable();
 
147
                $row = false;
 
148
            break;
 
149
            default:
 
150
                throw new ADEIException(translate("Can not query CACHE md5 table, error") . ": " . mysql_error($this->dbh));
 
151
        }
 
152
        
 
153
    } else {
 
154
        $row = mysql_fetch_row($res);
 
155
    }
 
156
    
 
157
    $postfix = $this->GetGroupPostfix();
 
158
 
 
159
    if ($row === false) 
 
160
        $this->MD5CreateEntry($postfix);
 
161
    elseif (strcmp($row[0], $postfix))
 
162
        throw new ADEIException(translate("Unlucky, the MD5 checksums of two groups (\"%s\" and \"%s\") are coinciding. This is not handled automaticaly yet. Please, add/alter md5 suffix to the newly added group.", $row[0], $postfix));
 
163
 }
 
164
 
 
165
 
 
166
 function GetCachePostfix($db_group = false, $db_name = false, $db_server = false) {
 
167
    $postfix = $this->GetGroupPostfix($db_group, $db_name, $db_server);
 
168
 
 
169
    if (isset($this->md5_postfix)) $md5 = $this->md5_postfix;
 
170
    else $md5 = $this->req->GetCustomOption('use_md5_postfix', $db_server, $db_name, $db_group);
 
171
    
 
172
    if ($md5) {
 
173
        return "__md5_" . (is_string($md5)?$md5:"") .  md5($postfix);
 
174
    } else return $postfix;
 
175
 }
 
176
 
 
177
 function SetDefaultPostfix($postfix = false) {
 
178
    if ($postfix) $this->default_postfix = $postfix;
 
179
    else {
 
180
        $this->default_postfix = $this->GetCachePostfix();
 
181
    }
 
182
 }
 
183
 
 
184
 function GetTableName($resolution = 0, $postfix = false) {
 
185
    return "cache" . $resolution . ($postfix?$postfix:$this->default_postfix);
 
186
 }
 
187
 
 
188
 function DetectSubseconds($postfix = false) {
 
189
    $table = $this->GetTableName(0, $postfix);
 
190
    $res = mysql_query("SHOW COLUMNS FROM $table", $this->dbh);
 
191
    if (!$res)
 
192
        throw new ADEIException("There is problem executing 'SHOW COLUMNS' request on CACHE table '$table'");
 
193
    
 
194
    mysql_fetch_array($res);            // skipping time column
 
195
    $row = mysql_fetch_array($res);     // possibly ns column
 
196
    if (!strcmp($row[0],"ns")) {
 
197
        if (!$postfix) $this->use_subseconds = true;
 
198
        return true;
 
199
    }
 
200
 
 
201
    if (!$postfix) $this->use_subseconds = false;
 
202
    return false;
 
203
 }
 
204
 
 
205
 function GetCacheWidth($postfix = false) {
 
206
    $table = $this->GetTableName(0, $postfix);
 
207
 
 
208
    $res = mysql_query("SHOW COLUMNS FROM $table", $this->dbh);
 
209
    if (!$res)
 
210
        throw new ADEIException("There is problem executing 'SHOW COLUMNS' request on CACHE table '$table'");
 
211
 
 
212
    while ($col = mysql_fetch_array($res)) $lastcol = &$col['Field'];
 
213
 
 
214
    if (!preg_match("/(\d+)/", $lastcol, $m)) 
 
215
        throw new ADEIException("There is problem finding out the number of channels. Last cache column is '$lastcol'");
 
216
        
 
217
    return ($m[1] + 1);
 
218
 }
 
219
 
 
220
 function GetCacheIDs($postfix = false) {
 
221
        // DS, check if we do not have a level0 CACHE
 
222
        $size = $this->GetCacheWidth($postfix);
 
223
        
 
224
        $ids = array();
 
225
        for ($i=0;$i<$size;$i++) array_push($ids, $i);
 
226
 
 
227
        return $ids;
 
228
 }
 
229
 
 
230
 function CreateCacheInterval($postfix = false, array &$iinfo = NULL, $flags = 0) {
 
231
    if (!$iinfo) {
 
232
        if ($this->req instanceof DATARequest)
 
233
            $iinfo = $this->req->GetIntervalInfo();
 
234
    }
 
235
 
 
236
    $ivl = new INTERVAL($iinfo, NULL, NULL, $flags);
 
237
    $ivl->ApplyCache($this);
 
238
 
 
239
    return $ivl;
 
240
 }
 
241
 
 
242
 function CreateInterval(array &$iinfo = NULL, $flags = 0) {
 
243
    return $this->CreateCacheInterval(false, $iinfo, $flags);
 
244
 }
 
245
 
 
246
 function CreateCacheMask($postfix = false, array &$minfo = NULL, $flags = 0) {
 
247
    if (!$minfo) {
 
248
        if ($this->req instanceof GROUPRequest)
 
249
            $minfo = $this->req->GetMaskInfo();
 
250
    }
 
251
    
 
252
    $mask = new MASK($minfo);
 
253
    if (!$mask->ids) $mask->ids = $this->GetCacheIDs($postfix);
 
254
    return $mask;
 
255
 }
 
256
 
 
257
 function CreateMask(array &$minfo = NULL, $flags = 0) {
 
258
    return $this->CreateCacheMask(false, $minfo, $flags);
 
259
 }
 
260
 
 
261
 function GetTableInfo($resolution = 0, $postfix = false, $flags = 0) {
 
262
    $table = $this->GetTableName($resolution, $postfix);
 
263
    
 
264
    $req = "UNIX_TIMESTAMP(MIN(time)) AS first, UNIX_TIMESTAMP(MAX(time)) AS last";
 
265
    if ($flags&CACHEDB::NEED_COUNT) $req .= ", COUNT(time) AS records";
 
266
 
 
267
    $res = mysql_query("SELECT $req FROM `$table`", $this->dbh);
 
268
    if (!$res) {
 
269
        switch (mysql_errno($this->dbh)) {
 
270
            case CACHE::MYSQL_ER_NO_SUCH_TABLE:
 
271
                return false;
 
272
            break;
 
273
            default:
 
274
                throw new ADEIException("SELECT request '$req' on CACHE table '$table' is failed...");
 
275
        }
 
276
    }
 
277
    return mysql_fetch_assoc($res);
 
278
 }
 
279
 
 
280
 function GetCacheInfo($postfix = false, $flags = 0) {
 
281
        // DS, check if we do not have a level0 CACHE
 
282
    return $this->GetTableInfo(0, $postfix, $flags);
 
283
 }
 
284
 
 
285
 function GetInfo($flags = 0) {
 
286
    return $this->GetCacheInfo(false, $flags);
 
287
 } 
 
288
 
 
289
 function GetCacheItemList($postfix = false, MASK &$mask = NULL, $flags = 0) {
 
290
    $items = array();
 
291
    
 
292
    if (($mask)&&($mask->ids)) {
 
293
        foreach ($mask->ids as $i => $id) {
 
294
            $items[$i] = array(
 
295
                "id" => $id,
 
296
                "name" =>  "Channel" . ($id+1),
 
297
            );
 
298
        }
 
299
    } else {
 
300
        $size = $this->GetCacheWidth($postfix);
 
301
 
 
302
        for ($i=0;$i<$size;$i++) {
 
303
            $items[$i] = array(
 
304
                "id" => $i,
 
305
                "name" =>  "Channel" . ($i+1),
 
306
            );
 
307
        }
 
308
    }
 
309
    
 
310
    return $items;
 
311
 }
 
312
 
 
313
 function GetItemList(MASK &$mask = NULL, $flags = 0) {
 
314
    return $this->GetCacheItemList(false, $mask, $flags);
 
315
 }
 
316
 
 
317
 function SQLTime($time) {
 
318
    return strftime("%Y%m%d%H%M%S", floor($time));
 
319
 
 
320
/* 
 
321
    Subseconds are not supported by MySQL Datetime type
 
322
    if (is_int($time))
 
323
        return strftime("%Y%m%d%H%M%S", $time);
 
324
    else {
 
325
        return strftime("%Y%m%d%H%M%S", floor($time)) . substr(sprintf("%.6F", $time - floor($time)), 1);
 
326
    }
 
327
*/
 
328
 }
 
329
 
 
330
 function CreateTable($resolution, $items, $postfix = false) {
 
331
    if (($this instanceof CACHE) == false)
 
332
        throw new ADEIException(translate("CreateTable calls are only allowed on CACHE object"));
 
333
 
 
334
    $name = $this->GetTableName($resolution, $postfix);
 
335
    
 
336
    if ($resolution > 0) {
 
337
        for ($i = 0; $i < $items; $i++)
 
338
            $query .= ", `min" . $i . "` DOUBLE, `max" . $i . "` DOUBLE, `mean" . $i . "` DOUBLE";
 
339
 
 
340
        /*, `duration` INT, `complete` BOOL,*/
 
341
        if (!mysql_query("CREATE TABLE `$name` (`time` DATETIME PRIMARY KEY, `n` BIGINT, `missing` INT" .  $query . ")", $this->dbh)) {
 
342
            throw new ADEIException(translate("Unable to create cache table, error") . ": " . mysql_error($this->dbh));
 
343
        }
 
344
    } else {    
 
345
        for ($i = 0; $i < $items; $i++)
 
346
            $query .= ", `v" . $i . "` DOUBLE";
 
347
 
 
348
        if ($this->use_subseconds) {
 
349
            $time = "`time` DATETIME, `ns` INT, `subcache` INT";
 
350
            $index = ", PRIMARY KEY (`time`, `ns`, `subcache`)";
 
351
        } else {
 
352
            $time = "`time` DATETIME PRIMARY KEY";
 
353
            $index = "";
 
354
        }
 
355
        
 
356
        if (!mysql_query("CREATE TABLE `$name` ($time"  .  $query . "$index)", $this->dbh)) {
 
357
            throw new ADEIException(translate("Unable to create cache table, error") . ": " . mysql_error($this->dbh) . " [" . "CREATE TABLE `$name` ($time"  .  $query . ",$index)" . "]");
 
358
        }
 
359
    }
 
360
 }
 
361
 
 
362
 function CreateQuery($table, $time, &$d) {
 
363
    if (($this instanceof CACHE) == false)
 
364
        throw new ADEIException(translate("CreateTable calls are only allowed on CACHE object"));
 
365
 
 
366
    if (is_object($d)) {
 
367
        $sqltime = $this->SQLTime((int)$time);
 
368
#       echo "Time: $time -> $sqltime\n";
 
369
        
 
370
        $query = "INSERT INTO `$table` VALUES ($sqltime, " . $d->n . ", " . $d->missing;
 
371
        if ($d->n > 0) {
 
372
            for ($j = 0; $j < $this->items; $j++) {
 
373
                $query .= ", " . $d->min[$j] . ", " . $d->max[$j] . ", " . $d->mean[$j];
 
374
            }
 
375
        } else {
 
376
            for ($j = 0; $j < $this->items; $j++) {
 
377
                $query .= ", 0, 0, 0";
 
378
            }
 
379
        }
 
380
        $query .= ")";
 
381
    } else {
 
382
        $sqltime = $this->SQLTime($time);
 
383
 
 
384
        if ($this->use_subseconds) {
 
385
            $point = strstr($time, ".");
 
386
            if ($point) {
 
387
                $subs = substr($point, 1);
 
388
                $chars = strlen($subs);
 
389
                if ($chars<9) $subs .= str_repeat("0", 9 - $chars);
 
390
                $ns = ", $subs";
 
391
            } else $ns = ", 0";
 
392
                // Subcache Information
 
393
            $ns .= ", 0";
 
394
        } else $ns="";
 
395
            
 
396
        $query = "INSERT INTO `$table` VALUES ($sqltime" . $ns;
 
397
        foreach ($d as $val) {
 
398
            $query .= ", $val";
 
399
        }
 
400
        $query .= ")";
 
401
    }
 
402
 
 
403
    return $query;
 
404
 }
 
405
 
 
406
 function Insert($resolution, &$query) {
 
407
    if (($this instanceof CACHE) == false)
 
408
        throw new ADEIException(translate("CreateTable calls are only allowed on CACHE object"));
 
409
 
 
410
    if (!@mysql_query($query, $this->dbh)) {
 
411
        switch (mysql_errno($this->dbh)) {
 
412
             case CACHE::MYSQL_ER_NO_SUCH_TABLE:
 
413
                $this->CreateTable($resolution, $this->items);
 
414
                if (!@mysql_query($query, $this->dbh)) {
 
415
                    throw new ADEIException(translate("Can not query caching table (Resolution: $resolution), error") . ": " . mysql_error($this->dbh));
 
416
                }
 
417
             break;
 
418
             case CACHE::MYSQL_ER_DUP_ENTRY:
 
419
                if (!strstr($query, "cache0"))
 
420
                    throw new ADEIException(translate("Internal error. Trying to insert the block wich is already in the cache (Resolution: $resolution)."));
 
421
                return CACHE::MYSQL_ER_DUP_ENTRY;
 
422
             break;
 
423
             default:
 
424
                throw new ADEIException(translate("Can not query caching table (Resolution: $resolution), error") . ": " . mysql_error($this->dbh));
 
425
        }
 
426
    }
 
427
 
 
428
    return 0;
 
429
 }
 
430
 
 
431
 function GetReady($table, $from, $to) {
 
432
    return new CACHEData($this, $table, $from, $to);
 
433
 }
 
434
 
 
435
 
 
436
 function GetCachePoints($postfix = false, MASK &$mask = NULL, INTERVAL &$ivl = NULL, $type = CACHEDB::TYPE_AUTO, $limit = 0, $amount = 0, $resolution = false) {
 
437
    if (!$mask) $mask = $this->CreateCacheMask();
 
438
    if (!$ivl) $ivl = $this->CreateCacheInterval();
 
439
 
 
440
    if ($type == CACHEDB::TYPE_ALL)
 
441
        $res = new RAWPoint($this, $mask, $ivl, $limit);
 
442
    else {
 
443
        $res = new DATAPoint($this, $mask, $ivl, $type, is_int($amount)?$amount:0, is_int($limit)?$limit:0, $resolution);
 
444
    }
 
445
 
 
446
    if (($postfix)||(!isset($this->use_subseconds))) {
 
447
        // we should find subsecond precision
 
448
        $use_subseconds = $this->DetectSubseconds($postfix);
 
449
        $res->SetOption("use_subseconds", $use_subseconds);
 
450
 
 
451
        if ($postfix) $res->SetOption("postfix", $postfix);
 
452
    }
 
453
    return $res;    
 
454
 }
 
455
}
 
456
 
 
457
?>
 
 
b'\\ No newline at end of file'