/adei/trunk

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

« back to all changes in this revision

Viewing changes to classes/cache/cachedb.php

  • Committer: Suren A. Chilingaryan
  • Date: 2020-02-25 03:16:18 UTC
  • Revision ID: csa@suren.me-20200225031618-57d452egb2mpodhh
Optimize Cache Administrator (inroduces new REQUEST flags and significant changes to CACHEDB)

Show diffs side-by-side

added added

removed removed

Lines of Context:
6
6
 var $default_postfix;
7
7
 
8
8
 var $md5_postfix;
9
 
 var $use_subseconds;
 
9
 var $use_subseconds = NULL;
10
10
 
11
11
 var $base_mask;        // Limits available channels, used in conjuction with VIRTUALReader
12
12
 
13
13
 var $transaction_operations;
14
14
 var $transaction_active;
15
15
 
 
16
 var $db_list_cache = array();
16
17
 
17
18
 const TYPE_AUTO = 0;
18
19
 const TYPE_MINMAX = 1;
20
21
 const TYPE_ALL = 3;
21
22
 
22
23
 const TABLE_INFO = 0x00010000;         // Information about cache tables
23
 
 const NEED_REQUESTS = 0x00020000;      // Create appropriate requests on listing
24
 
 const FIND_BROKEN = 0x00040000;        // Find incomplete caches
 
24
 const LEVEL_INFO = 0x00020000;         // Return information about the cache levels
 
25
 const NEED_REQUESTS = 0x00040000;      // Create appropriate requests on listing
 
26
 const FIND_BROKEN = 0x00080000;        // Find incomplete caches
 
27
 const SKIP_OK = 0x00100000;            // Don't report info on fully cached groups
 
28
 const SKIP_MISSING = 0x00200000;       // Don't report info on fully cached groups
25
29
 
26
30
 const INSERT_CALL = 1; 
27
31
 const DESTRUCTOR_CALL = 2;
87
91
*/
88
92
 }
89
93
 
90
 
 
91
94
 static function FindAggregator($aggregator) {
92
 
    $name = "CACHEDB::TYPE_" . strtoupper($aggregator);
93
 
    if (defined($name)) return constant($name);
94
 
    else if ((!$aggregator)||(($aggregator>0)&&($aggregator<=CACHEDB::TYPE_ALL))) return $aggregator;
 
95
    if ($aggregator) {
 
96
        $name = "CACHEDB::TYPE_" . strtoupper($aggregator);
 
97
        if (defined($name)) return constant($name);
 
98
        else if ((!$aggregator)||(($aggregator>0)&&($aggregator<=CACHEDB::TYPE_ALL))) return $aggregator;
95
99
    
96
 
    throw new ADEIException(translate("Unknown aggregation mode (%s) is specified", $aggregator));
 
100
        throw new ADEIException(translate("Unknown aggregation mode (%s) is specified", $aggregator));
 
101
    }
 
102
 
 
103
    return CACHE::TYPE_AUTO;
97
104
 }
98
105
 
99
106
 function GetSize() {
225
232
 
226
233
 function GetExtendedCacheInfo(&$postfix_or_row, $flags = 0) {
227
234
    global $READER_DB;
 
235
    global $ADEI_CACHE_LATENCY_THRESHOLD;
228
236
    
229
237
    if (is_array($postfix_or_row)) {
230
238
        $prefix = "cache0";
241
249
    $postfix = $info['postfix'];
242
250
    $srv = $info['db_server'];
243
251
    $db = $info['db_name'];
 
252
    $source = "${srv}__${db}";
244
253
    $group = $info['db_group'];
245
254
    $supported = $info['supported'];
246
 
    
 
255
 
 
256
    $cache_info = array();
 
257
    if (($flags&CACHEDB::TABLE_INFO)&&($supported)) {
 
258
        $cache_info = $this->GetCacheInfo($postfix);
 
259
 
 
260
        if ($flags&CACHEDB::SKIP_OK) {
 
261
            $now = time();
 
262
            if ((isset($cache_info['last']))&&(abs($now - $cache_info['last']) < $ADEI_CACHE_LATENCY_THRESHOLD))
 
263
                return array();
 
264
        }
 
265
    }
 
266
 
247
267
    if ($flags&CACHE::NEED_REQUESTS) {
248
268
            if ($supported) {
249
269
                try {
263
283
                    if ($reader->server['disconnected'])
264
284
                        $info['disconnected'] = true;
265
285
 
266
 
                    $db_list = $reader->GetDatabaseList(REQUEST::LIST_WILDCARDED);
267
 
                    if (isset($db_list[$db])) {
 
286
                    if (!in_array($srv, $this->db_list_cache))
 
287
                        $this->db_list_cache[$srv] = $reader->GetDatabaseList($flags&REQUEST::LIST_WILDCARDED);
 
288
                    $db_list = $this->db_list_cache[$srv];
 
289
                    
 
290
                    if (isset($db_list[$db])) {
268
291
                        $info['database'] = $db_list[$db]['name'];
269
292
                        if ((is_array($req->srv['database']))&&(!in_array($db, $req->srv['database'])))
270
293
                            $info['wildcarded'] = true;
271
294
                        
272
295
                        if ($req) {
 
296
                            $grp = $reader->CreateGroup($req->props);
273
297
                                    // Slows down considerably on big installations
274
298
                            if ($flags&REQUEST::NEED_READERINFO)
275
 
                                $group_list = $reader->GetGroupInfo(NULL, REQUEST::NEED_INFO|REQUEST::NEED_COUNT);
 
299
                                $group_list = $reader->GetGroupInfo($grp, REQUEST::NEED_INFO|REQUEST::NEED_COUNT|REQUEST::PREFER_EXACTINFO);
276
300
                            else
277
 
                                $group_list = $reader->GetGroupInfo();
278
 
                                
 
301
                                $group_list = $reader->GetGroupInfo($grp);
 
302
                            
279
303
                            if (isset($group_list[$group])) {
280
 
                                $ginfo = &$group_list[$group];
 
304
                                $ginfo = $group_list[$group];
 
305
                            } elseif (is_array($group_list)) {
 
306
                                $ginfo = $group_list;
 
307
                            } else {
 
308
                                $ginfo = false;
 
309
                                $req = false;
 
310
                            }
 
311
 
 
312
                            if ($ginfo) {
281
313
                                $info['group'] = $ginfo['name'];
 
314
                                foreach ($ginfo as $gkey => $gval) {
 
315
                                    $info[$gkey] = $gval;
 
316
                                }
 
317
 
 
318
/*
282
319
                                if (isset($ginfo['first'])) $info['first'] = $ginfo['first'];
283
320
                                if (isset($ginfo['last'])) $info['last'] = $ginfo['last'];
284
321
                                if (isset($ginfo['records'])) $info['last'] = $ginfo['records'];
285
 
                            } else {
286
 
                                $req = false;
 
322
                                if (isset($ginfo['query_time'])) $info['last'] = $ginfo['query_time'];
 
323
*/
287
324
                            }
288
325
                        }
289
326
                    } else {
290
 
                        $req = false;
 
327
                        if ($flags&CACHEDB::SKIP_MISSING)
 
328
                            return array();
 
329
                        $req = false;
291
330
                    }
292
 
                    
293
331
                } catch (ADEIException $ae) {
294
 
                    if ($info['server']) $info['disconnected'] = true;
 
332
                    if ($info['server']) {
 
333
                        $info['disconnected'] = true;
 
334
                        $info['error'] = $ae->getMessage();
 
335
                    }
295
336
                    $req = false;
296
337
                }
297
338
            } else $req = false;
298
 
            
 
339
    
299
340
            $info['req'] = $req;
300
341
    }
 
342
    
301
343
 
302
 
    if (($flags&CACHEDB::TABLE_INFO)&&($supported)&&($cache_info=$this->GetCacheInfo($postfix))) {
 
344
        // Fast variant of REQUEST:::NEED_COUNT is as precise as TABLE INFO (i.e. not)
 
345
    if (($flags&CACHEDB::TABLE_INFO)&&($supported)&&($cache_info)) {
303
346
            $info['info'] = $cache_info;
304
 
            
 
347
 
305
348
            if (is_array($postfix_or_row)) {
306
349
                $info['info']['records'] = $postfix_or_row[4];
307
350
                $info['info']['dbsize'] = $postfix_or_row[6] + $postfix_or_row[8];
309
352
            
310
353
            $tables = array();
311
354
 
312
 
            $mres = @mysql_query("SHOW TABLE STATUS LIKE 'cache%$postfix'", $this->dbh);
 
355
            if ($flags&CACHEDB::LEVEL_INFO) $mres = @mysql_query("SHOW TABLE STATUS LIKE 'cache%$postfix'", $this->dbh);
 
356
            else if ((!is_array($postfix_or_row))||(sizeof($postfix_or_row)<9)) $mres = @mysql_query("SHOW TABLE STATUS LIKE 'cache%$postfix'", $this->dbh);
 
357
            else $mres = array($postfix_or_row);
 
358
 
313
359
            if ($mres) {
314
360
                $size = 0;
315
 
                while ($mrow = mysql_fetch_row($mres)) {
 
361
                while ($mrow = (is_array($mres)?array_pop($mres):mysql_fetch_row($mres))) {
316
362
                    $size += $mrow[6] + $mrow[8];
317
363
                    if (preg_match("/^cache(\d+)$postfix$/", $mrow[0], $m)) {
318
364
                        $id = $m[1];
319
365
                        
320
366
                        if (!$id) $info['info']['records'] = $mrow[4];
321
367
 
322
 
                        $tables[$id] = $this->GetTableInfo($id, $postfix);
 
368
                        $tables[$id] = ($id > 0)?$this->GetTableInfo($id, $postfix):$cache_info;
323
369
                        if (!is_array($tables[$id])) $tables[$id] = array();
324
370
 
325
371
                        $tables[$id]['resolution'] = $id;
391
437
                $info['info']['items'] = $reader->GetItemList();
392
438
            }
393
439
    }
394
 
        
395
440
    return $info;
396
441
 }
397
 
 
398
 
 function GetCacheList($flags = 0) {
 
442
 
 
443
 function GetCacheList($filter = false, $flags = 0) {
 
444
    $query="\\_\\_";
 
445
    if ($filter) $query .= preg_replace("/_/", "\\_", $filter) . "\\_\\_";
 
446
    $query .= "%";
 
447
 
 
448
    $list = $this->GetCacheListSimple($query, $flags);
 
449
    
 
450
    if ($filter) {
 
451
        $res = @mysql_query("SELECT hash FROM md5 WHERE postfix LIKE '${query}'", $this->dbh);
 
452
        if ($res) {
 
453
            while ($row = mysql_fetch_row($res)) {
 
454
                $md5_list = $this->GetCacheListSimple($row[0], $flags);
 
455
                $list = array_merge($list, $md5_list);
 
456
            }
 
457
        }
 
458
    }
 
459
    
 
460
    return $list;
 
461
 }
 
462
   
 
463
 function GetCacheListSimple($query = false, $flags = 0) {
399
464
    $list = array();
400
465
 
401
 
 
 
466
        // This is inaccurate with InnoDB.
402
467
    if ($flags&CACHEDB::TABLE_INFO)
403
 
        $res = @mysql_query("SHOW TABLE STATUS LIKE 'cache0\\_\\_%'", $this->dbh);
 
468
        $res = @mysql_query("SHOW TABLE STATUS LIKE 'cache0${query}'", $this->dbh);
404
469
    else
405
 
        $res = @mysql_query("SHOW TABLES LIKE 'cache0\\_\\_%'", $this->dbh);
406
 
 
407
 
/*
408
 
    $res = @mysql_query("SHOW TABLES LIKE 'cache0\\_\\_aircoils%'", $this->dbh);
409
 
    $flags = $flags&~CACHE::FIND_BROKEN;
410
 
*/
 
470
        $res = @mysql_query("SHOW TABLES LIKE 'cache0${query}'", $this->dbh);
411
471
 
412
472
    $postfixes = array();
413
 
    
414
473
    while ($row = mysql_fetch_row($res)) {
415
474
        try {
 
475
            $t_start =  microtime(true);
416
476
            $info = $this->GetExtendedCacheInfo($row, $flags);
417
 
            array_push($list, $info);
 
477
            $t_end = microtime(true);
 
478
            $t = $t_end - $t_start;
 
479
            //echo ">  " . date('h:i:s', floor($t_start))  . substr($t_start - floor($t_start), 1) . "  ($t)   " . "${row[0]}  util " .  date('h:i:s', floor($t_end))  . substr($t_end - floor($t_end), 1) ."\n";
418
480
 
419
 
            array_push($postfixes, $info['postfix']);
 
481
            if ($info) {
 
482
                $info['get_extended_cache_info_time'] = $t;
 
483
                $list[$info['postfix']] = $info;
 
484
                array_push($postfixes, $info['postfix']);
 
485
            }
420
486
        } catch (ADEIException $ae) {
421
487
            // DS: what to do? Do we need to pass the error or we relly or FIND_BROKEN?
422
488
        }
423
489
    }
424
490
 
425
491
    if ($flags&CACHE::FIND_BROKEN) {
426
 
        $res = @mysql_query("SHOW TABLES LIKE 'cache%\\_\\_%'", $this->dbh);
 
492
        $res = @mysql_query("SHOW TABLES LIKE 'cache%${query}%'", $this->dbh);
427
493
        if ($res) {
428
494
            $all_postfixes = array();
429
495
            while ($row = mysql_fetch_row($res)) {
433
499
            }
434
500
 
435
501
            $incomplete = array_diff(array_unique($all_postfixes), $postfixes);
436
 
            
437
502
            foreach ($incomplete as $postfix) {
438
503
                try {
439
504
                    $info = $this->GetExtendedCacheInfo($postfix, $flags);
442
507
                    $info = $this->ParsePostfix($postfix, "", true);
443
508
                }
444
509
                $info['incomplete'] = true;
445
 
                array_push($list, $info);
 
510
//              array_push($list, $info);
 
511
                $list[$postfix] = $info;
446
512
            }
447
513
        }
448
514
    }
1019
1085
 
1020
1086
 function GetTableInfo($resolution = 0, $postfix = false, $flags = 0) {
1021
1087
    $table = $this->GetTableName($resolution, $postfix);
1022
 
    
1023
 
    $req = "EXTENDED_UNIX_TIMESTAMP(MIN(time)) AS first, EXTENDED_UNIX_TIMESTAMP(MAX(time)) AS last";
1024
 
    if ($flags&REQUEST::NEED_COUNT) $req .= ", COUNT(time) AS records";
1025
 
 
1026
 
    $res = mysql_query("SELECT $req FROM `$table`", $this->dbh);
 
1088
 
 
1089
    $extra = "";
 
1090
/*
 
1091
    if ($flags&REQUEST::NEED_COUNT) {
 
1092
            // This could be extremely slow on InnoDB (it will make a full scan of the index at minimum)
 
1093
        $extra .= ", COUNT(time) AS records";
 
1094
    }
 
1095
*/
 
1096
 
 
1097
    if (($resolution)||(!$this->DetectSubseconds($postfix)))
 
1098
        $req = "SELECT EXTENDED_UNIX_TIMESTAMP(MIN(time)) AS first, EXTENDED_UNIX_TIMESTAMP(MAX(time)) AS last${extra} FROM `$table`";
 
1099
    else {
 
1100
            // Querying 'ns' like this would be significantly slower
 
1101
        //$req = "ADEI_TIMESTAMP(EXTENDED_UNIX_TIMESTAMP(MIN(time)),ns) AS first, ADEI_TIMESTAMP(EXTENDED_UNIX_TIMESTAMP(MAX(time)),ns) AS last";
 
1102
        $req = "SELECT (SELECT ADEI_TIMESTAMP(EXTENDED_UNIX_TIMESTAMP(time),ns)/1000000000 FROM `$table` ORDER BY id LIMIT 1) as first, (SELECT ADEI_TIMESTAMP(EXTENDED_UNIX_TIMESTAMP(time),ns)/1000000000 FROM `$table` ORDER BY id DESC LIMIT 1) as last${extra}";
 
1103
    }
 
1104
        
 
1105
    $res = mysql_query($req, $this->dbh);
1027
1106
    if (!$res) {
1028
1107
        switch (mysql_errno($this->dbh)) {
1029
1108
            case CACHE::MYSQL_ER_NO_SUCH_TABLE:
1033
1112
                throw new ADEIException(translate("SELECT request '%s' on CACHE table '%s' is failed. MySQL error: %s", $req, $table, mysql_error($this->dbh)));
1034
1113
        }
1035
1114
    }
1036
 
    return mysql_fetch_assoc($res);
 
1115
 
 
1116
    $info = mysql_fetch_assoc($res);
 
1117
 
 
1118
    if ($flags&REQUEST::NEED_COUNT) {
 
1119
            // This could be inprecise, but other method is extremely slow on InnoDB (and very imprecise if done on the MySQL/Slave)
 
1120
        $res = mysql_query("EXPLAIN SELECT COUNT(time) AS records FROM `$table`", $this->dbh);
 
1121
        if ($res) {
 
1122
            $vals = mysql_fetch_assoc($res);
 
1123
            if ($vals) $info['records'] = $vals['rows'];
 
1124
        } 
 
1125
    }
 
1126
 
 
1127
    return $info;
1037
1128
 }
1038
1129
 
1039
1130
 function GetCacheInfo($postfix = false, $flags = 0) {