[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/lib/adodb/ -> adodb-perf.inc.php (source)

   1  <?php
   2  /*
   3  V5.19  23-Apr-2014  (c) 2000-2014 John Lim (jlim#natsoft.com). All rights reserved.
   4    Released under both BSD license and Lesser GPL library license.
   5    Whenever there is any discrepancy between the two licenses,
   6    the BSD license will take precedence. See License.txt.
   7    Set tabs to 4 for best viewing.
   8  
   9    Latest version is available at http://adodb.sourceforge.net
  10  
  11    Library for basic performance monitoring and tuning.
  12  
  13    My apologies if you see code mixed with presentation. The presentation suits
  14    my needs. If you want to separate code from presentation, be my guest. Patches
  15    are welcome.
  16  
  17  */
  18  
  19  if (!defined('ADODB_DIR')) include_once(dirname(__FILE__).'/adodb.inc.php');
  20  include_once (ADODB_DIR.'/tohtml.inc.php');
  21  
  22  define( 'ADODB_OPT_HIGH', 2);
  23  define( 'ADODB_OPT_LOW', 1);
  24  
  25  global $ADODB_PERF_MIN;
  26  $ADODB_PERF_MIN = 0.05; // log only if >= minimum number of secs to run
  27  
  28  
  29  // returns in K the memory of current process, or 0 if not known
  30  function adodb_getmem()
  31  {
  32      if (function_exists('memory_get_usage'))
  33          return (integer) ((memory_get_usage()+512)/1024);
  34  
  35      $pid = getmypid();
  36  
  37      if ( strncmp(strtoupper(PHP_OS),'WIN',3)==0) {
  38          $output = array();
  39  
  40          exec('tasklist /FI "PID eq ' . $pid. '" /FO LIST', $output);
  41          return substr($output[5], strpos($output[5], ':') + 1);
  42      }
  43  
  44      /* Hopefully UNIX */
  45      exec("ps --pid $pid --no-headers -o%mem,size", $output);
  46      if (sizeof($output) == 0) return 0;
  47  
  48      $memarr = explode(' ',$output[0]);
  49      if (sizeof($memarr)>=2) return (integer) $memarr[1];
  50  
  51      return 0;
  52  }
  53  
  54  // avoids localization problems where , is used instead of .
  55  function adodb_round($n,$prec)
  56  {
  57      return number_format($n, $prec, '.', '');
  58  }
  59  
  60  /* obsolete: return microtime value as a float. Retained for backward compat */
  61  function adodb_microtime()
  62  {
  63      return microtime(true);
  64  }
  65  
  66  /* sql code timing */
  67  function adodb_log_sql(&$connx,$sql,$inputarr)
  68  {
  69      $perf_table = adodb_perf::table();
  70      $connx->fnExecute = false;
  71      $a0 = microtime(true);
  72      $rs = $connx->Execute($sql,$inputarr);
  73      $a1 = microtime(true);
  74  
  75      if (!empty($connx->_logsql) && (empty($connx->_logsqlErrors) || !$rs)) {
  76      global $ADODB_LOG_CONN;
  77  
  78          if (!empty($ADODB_LOG_CONN)) {
  79              $conn = $ADODB_LOG_CONN;
  80              if ($conn->databaseType != $connx->databaseType)
  81                  $prefix = '/*dbx='.$connx->databaseType .'*/ ';
  82              else
  83                  $prefix = '';
  84          } else {
  85              $conn = $connx;
  86              $prefix = '';
  87          }
  88  
  89          $conn->_logsql = false; // disable logsql error simulation
  90          $dbT = $conn->databaseType;
  91  
  92          $time = $a1 - $a0;
  93  
  94          if (!$rs) {
  95              $errM = $connx->ErrorMsg();
  96              $errN = $connx->ErrorNo();
  97              $conn->lastInsID = 0;
  98              $tracer = substr('ERROR: '.htmlspecialchars($errM),0,250);
  99          } else {
 100              $tracer = '';
 101              $errM = '';
 102              $errN = 0;
 103              $dbg = $conn->debug;
 104              $conn->debug = false;
 105              if (!is_object($rs) || $rs->dataProvider == 'empty')
 106                  $conn->_affected = $conn->affected_rows(true);
 107              $conn->lastInsID = @$conn->Insert_ID();
 108              $conn->debug = $dbg;
 109          }
 110          if (isset($_SERVER['HTTP_HOST'])) {
 111              $tracer .= '<br>'.$_SERVER['HTTP_HOST'];
 112              if (isset($_SERVER['PHP_SELF'])) $tracer .= htmlspecialchars($_SERVER['PHP_SELF']);
 113          } else
 114              if (isset($_SERVER['PHP_SELF'])) $tracer .= '<br>'.htmlspecialchars($_SERVER['PHP_SELF']);
 115          //$tracer .= (string) adodb_backtrace(false);
 116  
 117          $tracer = (string) substr($tracer,0,500);
 118  
 119          if (is_array($inputarr)) {
 120              if (is_array(reset($inputarr))) $params = 'Array sizeof='.sizeof($inputarr);
 121              else {
 122                  // Quote string parameters so we can see them in the
 123                  // performance stats. This helps spot disabled indexes.
 124                  $xar_params = $inputarr;
 125                  foreach ($xar_params as $xar_param_key => $xar_param) {
 126                      if (gettype($xar_param) == 'string')
 127                      $xar_params[$xar_param_key] = '"' . $xar_param . '"';
 128                  }
 129                  $params = implode(', ', $xar_params);
 130                  if (strlen($params) >= 3000) $params = substr($params, 0, 3000);
 131              }
 132          } else {
 133              $params = '';
 134          }
 135  
 136          if (is_array($sql)) $sql = $sql[0];
 137          if ($prefix) $sql = $prefix.$sql;
 138          $arr = array('b'=>strlen($sql).'.'.crc32($sql),
 139                      'c'=>substr($sql,0,3900), 'd'=>$params,'e'=>$tracer,'f'=>adodb_round($time,6));
 140          //var_dump($arr);
 141          $saved = $conn->debug;
 142          $conn->debug = 0;
 143  
 144          $d = $conn->sysTimeStamp;
 145          if (empty($d)) $d = date("'Y-m-d H:i:s'");
 146          if ($conn->dataProvider == 'oci8' && $dbT != 'oci8po') {
 147              $isql = "insert into $perf_table values($d,:b,:c,:d,:e,:f)";
 148          } else if ($dbT == 'odbc_mssql' || $dbT == 'informix' || strncmp($dbT,'odbtp',4)==0) {
 149              $timer = $arr['f'];
 150              if ($dbT == 'informix') $sql2 = substr($sql2,0,230);
 151  
 152              $sql1 = $conn->qstr($arr['b']);
 153              $sql2 = $conn->qstr($arr['c']);
 154              $params = $conn->qstr($arr['d']);
 155              $tracer = $conn->qstr($arr['e']);
 156  
 157              $isql = "insert into $perf_table (created,sql0,sql1,params,tracer,timer) values($d,$sql1,$sql2,$params,$tracer,$timer)";
 158              if ($dbT == 'informix') $isql = str_replace(chr(10),' ',$isql);
 159              $arr = false;
 160          } else {
 161              if ($dbT == 'db2') $arr['f'] = (float) $arr['f'];
 162              $isql = "insert into $perf_table (created,sql0,sql1,params,tracer,timer) values( $d,?,?,?,?,?)";
 163          }
 164  
 165          global $ADODB_PERF_MIN;
 166          if ($errN != 0 || $time >= $ADODB_PERF_MIN) {
 167              $ok = $conn->Execute($isql,$arr);
 168          } else
 169              $ok = true;
 170  
 171          $conn->debug = $saved;
 172  
 173          if ($ok) {
 174              $conn->_logsql = true;
 175          } else {
 176              $err2 = $conn->ErrorMsg();
 177              $conn->_logsql = true; // enable logsql error simulation
 178              $perf = NewPerfMonitor($conn);
 179              if ($perf) {
 180                  if ($perf->CreateLogTable()) $ok = $conn->Execute($isql,$arr);
 181              } else {
 182                  $ok = $conn->Execute("create table $perf_table (
 183                  created varchar(50),
 184                  sql0 varchar(250),
 185                  sql1 varchar(4000),
 186                  params varchar(3000),
 187                  tracer varchar(500),
 188                  timer decimal(16,6))");
 189              }
 190              if (!$ok) {
 191                  ADOConnection::outp( "<p><b>LOGSQL Insert Failed</b>: $isql<br>$err2</p>");
 192                  $conn->_logsql = false;
 193              }
 194          }
 195          $connx->_errorMsg = $errM;
 196          $connx->_errorCode = $errN;
 197      }
 198      $connx->fnExecute = 'adodb_log_sql';
 199      return $rs;
 200  }
 201  
 202  
 203  /*
 204  The settings data structure is an associative array that database parameter per element.
 205  
 206  Each database parameter element in the array is itself an array consisting of:
 207  
 208  0: category code, used to group related db parameters
 209  1: either
 210      a. sql string to retrieve value, eg. "select value from v\$parameter where name='db_block_size'",
 211      b. array holding sql string and field to look for, e.g. array('show variables','table_cache'),
 212      c. a string prefixed by =, then a PHP method of the class is invoked,
 213          e.g. to invoke $this->GetIndexValue(), set this array element to '=GetIndexValue',
 214  2: description of the database parameter
 215  */
 216  
 217  class adodb_perf {
 218      var $conn;
 219      var $color = '#F0F0F0';
 220      var $table = '<table border=1 bgcolor=white>';
 221      var $titles = '<tr><td><b>Parameter</b></td><td><b>Value</b></td><td><b>Description</b></td></tr>';
 222      var $warnRatio = 90;
 223      var $tablesSQL = false;
 224      var $cliFormat = "%32s => %s \r\n";
 225      var $sql1 = 'sql1';  // used for casting sql1 to text for mssql
 226      var $explain = true;
 227      var $helpurl = "<a href=http://phplens.com/adodb/reference.functions.fnexecute.and.fncacheexecute.properties.html#logsql>LogSQL help</a>";
 228      var $createTableSQL = false;
 229      var $maxLength = 2000;
 230  
 231      // Sets the tablename to be used
 232      static function table($newtable = false)
 233      {
 234          static $_table;
 235  
 236          if (!empty($newtable))  $_table = $newtable;
 237          if (empty($_table)) $_table = 'adodb_logsql';
 238          return $_table;
 239      }
 240  
 241      // returns array with info to calculate CPU Load
 242  	function _CPULoad()
 243      {
 244  /*
 245  
 246  cpu  524152 2662 2515228 336057010
 247  cpu0 264339 1408 1257951 168025827
 248  cpu1 259813 1254 1257277 168031181
 249  page 622307 25475680
 250  swap 24 1891
 251  intr 890153570 868093576 6 0 4 4 0 6 1 2 0 0 0 124 0 8098760 2 13961053 0 0 0 0 0 0 0 0 0 0 0 0 0 16 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 252  disk_io: (3,0):(3144904,54369,610378,3090535,50936192) (3,1):(3630212,54097,633016,3576115,50951320)
 253  ctxt 66155838
 254  btime 1062315585
 255  processes 69293
 256  
 257  */
 258          // Algorithm is taken from
 259          // http://social.technet.microsoft.com/Forums/en-US/winservergen/thread/414b0e1b-499c-411e-8a02-6a12e339c0f1/
 260          if (strncmp(PHP_OS,'WIN',3)==0) {
 261              if (PHP_VERSION == '5.0.0') return false;
 262              if (PHP_VERSION == '5.0.1') return false;
 263              if (PHP_VERSION == '5.0.2') return false;
 264              if (PHP_VERSION == '5.0.3') return false;
 265              if (PHP_VERSION == '4.3.10') return false; # see http://bugs.php.net/bug.php?id=31737
 266  
 267              static $FAIL = false;
 268              if ($FAIL) return false;
 269  
 270              $objName = "winmgmts:{impersonationLevel=impersonate}!\\\\.\\root\\CIMV2";
 271              $myQuery = "SELECT * FROM Win32_PerfFormattedData_PerfOS_Processor WHERE Name = '_Total'";
 272  
 273              try {
 274                  @$objWMIService = new COM($objName);
 275                  if (!$objWMIService) {
 276                      $FAIL = true;
 277                      return false;
 278                  }
 279  
 280                  $info[0] = -1;
 281                  $info[1] = 0;
 282                  $info[2] = 0;
 283                  $info[3] = 0;
 284                  foreach($objWMIService->ExecQuery($myQuery) as $objItem)  {
 285                          $info[0] = $objItem->PercentProcessorTime();
 286                  }
 287  
 288              } catch(Exception $e) {
 289                  $FAIL = true;
 290                  echo $e->getMessage();
 291                  return false;
 292              }
 293  
 294              return $info;
 295          }
 296  
 297          // Algorithm - Steve Blinch (BlitzAffe Online, http://www.blitzaffe.com)
 298          $statfile = '/proc/stat';
 299          if (!file_exists($statfile)) return false;
 300  
 301          $fd = fopen($statfile,"r");
 302          if (!$fd) return false;
 303  
 304          $statinfo = explode("\n",fgets($fd, 1024));
 305          fclose($fd);
 306          foreach($statinfo as $line) {
 307              $info = explode(" ",$line);
 308              if($info[0]=="cpu") {
 309                  array_shift($info);  // pop off "cpu"
 310                  if(!$info[0]) array_shift($info); // pop off blank space (if any)
 311                  return $info;
 312              }
 313          }
 314  
 315          return false;
 316  
 317      }
 318  
 319      /* NOT IMPLEMENTED */
 320  	function MemInfo()
 321      {
 322          /*
 323  
 324          total:    used:    free:  shared: buffers:  cached:
 325  Mem:  1055289344 917299200 137990144        0 165437440 599773184
 326  Swap: 2146775040 11055104 2135719936
 327  MemTotal:      1030556 kB
 328  MemFree:        134756 kB
 329  MemShared:           0 kB
 330  Buffers:        161560 kB
 331  Cached:         581384 kB
 332  SwapCached:       4332 kB
 333  Active:         494468 kB
 334  Inact_dirty:    322856 kB
 335  Inact_clean:     24256 kB
 336  Inact_target:   168316 kB
 337  HighTotal:      131064 kB
 338  HighFree:         1024 kB
 339  LowTotal:       899492 kB
 340  LowFree:        133732 kB
 341  SwapTotal:     2096460 kB
 342  SwapFree:      2085664 kB
 343  Committed_AS:   348732 kB
 344          */
 345      }
 346  
 347  
 348      /*
 349          Remember that this is client load, not db server load!
 350      */
 351      var $_lastLoad;
 352  	function CPULoad()
 353      {
 354          $info = $this->_CPULoad();
 355          if (!$info) return false;
 356  
 357          if (strncmp(PHP_OS,'WIN',3)==0) {
 358              return (integer) $info[0];
 359          }else {
 360              if (empty($this->_lastLoad)) {
 361                  sleep(1);
 362                  $this->_lastLoad = $info;
 363                  $info = $this->_CPULoad();
 364              }
 365  
 366              $last = $this->_lastLoad;
 367              $this->_lastLoad = $info;
 368  
 369              $d_user = $info[0] - $last[0];
 370              $d_nice = $info[1] - $last[1];
 371              $d_system = $info[2] - $last[2];
 372              $d_idle = $info[3] - $last[3];
 373  
 374              //printf("Delta - User: %f  Nice: %f  System: %f  Idle: %f<br>",$d_user,$d_nice,$d_system,$d_idle);
 375  
 376              $total=$d_user+$d_nice+$d_system+$d_idle;
 377              if ($total<1) $total=1;
 378              return 100*($d_user+$d_nice+$d_system)/$total;
 379          }
 380      }
 381  
 382  	function Tracer($sql)
 383      {
 384          $perf_table = adodb_perf::table();
 385          $saveE = $this->conn->fnExecute;
 386          $this->conn->fnExecute = false;
 387  
 388          global $ADODB_FETCH_MODE;
 389          $save = $ADODB_FETCH_MODE;
 390          $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
 391          if ($this->conn->fetchMode !== false) $savem = $this->conn->SetFetchMode(false);
 392  
 393          $sqlq = $this->conn->qstr($sql);
 394          $arr = $this->conn->GetArray(
 395  "select count(*),tracer
 396      from $perf_table where sql1=$sqlq
 397      group by tracer
 398      order by 1 desc");
 399          $s = '';
 400          if ($arr) {
 401              $s .= '<h3>Scripts Affected</h3>';
 402              foreach($arr as $k) {
 403                  $s .= sprintf("%4d",$k[0]).' &nbsp; '.strip_tags($k[1]).'<br>';
 404              }
 405          }
 406  
 407          if (isset($savem)) $this->conn->SetFetchMode($savem);
 408          $ADODB_CACHE_MODE = $save;
 409          $this->conn->fnExecute = $saveE;
 410          return $s;
 411      }
 412  
 413      /*
 414          Explain Plan for $sql.
 415          If only a snippet of the $sql is passed in, then $partial will hold the crc32 of the
 416              actual sql.
 417      */
 418  	function Explain($sql,$partial=false)
 419      {
 420          return false;
 421      }
 422  
 423  	function InvalidSQL($numsql = 10)
 424      {
 425  
 426          if (isset($_GET['sql'])) return;
 427          $s = '<h3>Invalid SQL</h3>';
 428          $saveE = $this->conn->fnExecute;
 429          $this->conn->fnExecute = false;
 430          $perf_table = adodb_perf::table();
 431          $rs = $this->conn->SelectLimit("select distinct count(*),sql1,tracer as error_msg from $perf_table where tracer like 'ERROR:%' group by sql1,tracer order by 1 desc",$numsql);//,$numsql);
 432          $this->conn->fnExecute = $saveE;
 433          if ($rs) {
 434              $s .= rs2html($rs,false,false,false,false);
 435          } else
 436              return "<p>$this->helpurl. ".$this->conn->ErrorMsg()."</p>";
 437  
 438          return $s;
 439      }
 440  
 441  
 442      /*
 443          This script identifies the longest running SQL
 444      */
 445  	function _SuspiciousSQL($numsql = 10)
 446      {
 447          global $ADODB_FETCH_MODE;
 448  
 449              $perf_table = adodb_perf::table();
 450              $saveE = $this->conn->fnExecute;
 451              $this->conn->fnExecute = false;
 452  
 453              if (isset($_GET['exps']) && isset($_GET['sql'])) {
 454                  $partial = !empty($_GET['part']);
 455                  echo "<a name=explain></a>".$this->Explain($_GET['sql'],$partial)."\n";
 456              }
 457  
 458              if (isset($_GET['sql'])) return;
 459              $sql1 = $this->sql1;
 460  
 461              $save = $ADODB_FETCH_MODE;
 462              $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
 463              if ($this->conn->fetchMode !== false) $savem = $this->conn->SetFetchMode(false);
 464              //$this->conn->debug=1;
 465              $rs = $this->conn->SelectLimit(
 466              "select avg(timer) as avg_timer,$sql1,count(*),max(timer) as max_timer,min(timer) as min_timer
 467                  from $perf_table
 468                  where {$this->conn->upperCase}({$this->conn->substr}(sql0,1,5)) not in ('DROP ','INSER','COMMI','CREAT')
 469                  and (tracer is null or tracer not like 'ERROR:%')
 470                  group by sql1
 471                  order by 1 desc",$numsql);
 472              if (isset($savem)) $this->conn->SetFetchMode($savem);
 473              $ADODB_FETCH_MODE = $save;
 474              $this->conn->fnExecute = $saveE;
 475  
 476              if (!$rs) return "<p>$this->helpurl. ".$this->conn->ErrorMsg()."</p>";
 477              $s = "<h3>Suspicious SQL</h3>
 478  <font size=1>The following SQL have high average execution times</font><br>
 479  <table border=1 bgcolor=white><tr><td><b>Avg Time</b><td><b>Count</b><td><b>SQL</b><td><b>Max</b><td><b>Min</b></tr>\n";
 480              $max = $this->maxLength;
 481              while (!$rs->EOF) {
 482                  $sql = $rs->fields[1];
 483                  $raw = urlencode($sql);
 484                  if (strlen($raw)>$max-100) {
 485                      $sql2 = substr($sql,0,$max-500);
 486                      $raw = urlencode($sql2).'&part='.crc32($sql);
 487                  }
 488                  $prefix = "<a target=sql".rand()." href=\"?hidem=1&exps=1&sql=".$raw."&x#explain\">";
 489                  $suffix = "</a>";
 490                  if ($this->explain == false || strlen($prefix)>$max) {
 491                      $suffix = ' ... <i>String too long for GET parameter: '.strlen($prefix).'</i>';
 492                      $prefix = '';
 493                  }
 494                  $s .= "<tr><td>".adodb_round($rs->fields[0],6)."<td align=right>".$rs->fields[2]."<td><font size=-1>".$prefix.htmlspecialchars($sql).$suffix."</font>".
 495                      "<td>".$rs->fields[3]."<td>".$rs->fields[4]."</tr>";
 496                  $rs->MoveNext();
 497              }
 498              return $s."</table>";
 499  
 500      }
 501  
 502  	function CheckMemory()
 503      {
 504          return '';
 505      }
 506  
 507  
 508  	function SuspiciousSQL($numsql=10)
 509      {
 510          return adodb_perf::_SuspiciousSQL($numsql);
 511      }
 512  
 513  	function ExpensiveSQL($numsql=10)
 514      {
 515          return adodb_perf::_ExpensiveSQL($numsql);
 516      }
 517  
 518  
 519      /*
 520          This reports the percentage of load on the instance due to the most
 521          expensive few SQL statements. Tuning these statements can often
 522          make huge improvements in overall system performance.
 523      */
 524  	function _ExpensiveSQL($numsql = 10)
 525      {
 526          global $ADODB_FETCH_MODE;
 527  
 528              $perf_table = adodb_perf::table();
 529              $saveE = $this->conn->fnExecute;
 530              $this->conn->fnExecute = false;
 531  
 532              if (isset($_GET['expe']) && isset($_GET['sql'])) {
 533                  $partial = !empty($_GET['part']);
 534                  echo "<a name=explain></a>".$this->Explain($_GET['sql'],$partial)."\n";
 535              }
 536  
 537              if (isset($_GET['sql'])) return;
 538  
 539              $sql1 = $this->sql1;
 540              $save = $ADODB_FETCH_MODE;
 541              $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
 542              if ($this->conn->fetchMode !== false) $savem = $this->conn->SetFetchMode(false);
 543  
 544              $rs = $this->conn->SelectLimit(
 545              "select sum(timer) as total,$sql1,count(*),max(timer) as max_timer,min(timer) as min_timer
 546                  from $perf_table
 547                  where {$this->conn->upperCase}({$this->conn->substr}(sql0,1,5))  not in ('DROP ','INSER','COMMI','CREAT')
 548                  and (tracer is null or tracer not like 'ERROR:%')
 549                  group by sql1
 550                  having count(*)>1
 551                  order by 1 desc",$numsql);
 552              if (isset($savem)) $this->conn->SetFetchMode($savem);
 553              $this->conn->fnExecute = $saveE;
 554              $ADODB_FETCH_MODE = $save;
 555              if (!$rs) return "<p>$this->helpurl. ".$this->conn->ErrorMsg()."</p>";
 556              $s = "<h3>Expensive SQL</h3>
 557  <font size=1>Tuning the following SQL could reduce the server load substantially</font><br>
 558  <table border=1 bgcolor=white><tr><td><b>Load</b><td><b>Count</b><td><b>SQL</b><td><b>Max</b><td><b>Min</b></tr>\n";
 559              $max = $this->maxLength;
 560              while (!$rs->EOF) {
 561                  $sql = $rs->fields[1];
 562                  $raw = urlencode($sql);
 563                  if (strlen($raw)>$max-100) {
 564                      $sql2 = substr($sql,0,$max-500);
 565                      $raw = urlencode($sql2).'&part='.crc32($sql);
 566                  }
 567                  $prefix = "<a target=sqle".rand()." href=\"?hidem=1&expe=1&sql=".$raw."&x#explain\">";
 568                  $suffix = "</a>";
 569                  if($this->explain == false || strlen($prefix>$max)) {
 570                      $prefix = '';
 571                      $suffix = '';
 572                  }
 573                  $s .= "<tr><td>".adodb_round($rs->fields[0],6)."<td align=right>".$rs->fields[2]."<td><font size=-1>".$prefix.htmlspecialchars($sql).$suffix."</font>".
 574                      "<td>".$rs->fields[3]."<td>".$rs->fields[4]."</tr>";
 575                  $rs->MoveNext();
 576              }
 577              return $s."</table>";
 578      }
 579  
 580      /*
 581          Raw function to return parameter value from $settings.
 582      */
 583  	function DBParameter($param)
 584      {
 585          if (empty($this->settings[$param])) return false;
 586          $sql = $this->settings[$param][1];
 587          return $this->_DBParameter($sql);
 588      }
 589  
 590      /*
 591          Raw function returning array of poll paramters
 592      */
 593  	function PollParameters()
 594      {
 595          $arr[0] = (float)$this->DBParameter('data cache hit ratio');
 596          $arr[1] = (float)$this->DBParameter('data reads');
 597          $arr[2] = (float)$this->DBParameter('data writes');
 598          $arr[3] = (integer) $this->DBParameter('current connections');
 599          return $arr;
 600      }
 601  
 602      /*
 603          Low-level Get Database Parameter
 604      */
 605  	function _DBParameter($sql)
 606      {
 607          $savelog = $this->conn->LogSQL(false);
 608          if (is_array($sql)) {
 609          global $ADODB_FETCH_MODE;
 610  
 611              $sql1 = $sql[0];
 612              $key = $sql[1];
 613              if (sizeof($sql)>2) $pos = $sql[2];
 614              else $pos = 1;
 615              if (sizeof($sql)>3) $coef = $sql[3];
 616              else $coef = false;
 617              $ret = false;
 618              $save = $ADODB_FETCH_MODE;
 619              $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
 620              if ($this->conn->fetchMode !== false) $savem = $this->conn->SetFetchMode(false);
 621  
 622              $rs = $this->conn->Execute($sql1);
 623  
 624              if (isset($savem)) $this->conn->SetFetchMode($savem);
 625              $ADODB_FETCH_MODE = $save;
 626              if ($rs) {
 627                  while (!$rs->EOF) {
 628                      $keyf = reset($rs->fields);
 629                      if (trim($keyf) == $key) {
 630                          $ret = $rs->fields[$pos];
 631                          if ($coef) $ret *= $coef;
 632                          break;
 633                      }
 634                      $rs->MoveNext();
 635                  }
 636                  $rs->Close();
 637              }
 638              $this->conn->LogSQL($savelog);
 639              return $ret;
 640          } else {
 641              if (strncmp($sql,'=',1) == 0) {
 642                  $fn = substr($sql,1);
 643                  return $this->$fn();
 644              }
 645              $sql = str_replace('$DATABASE',$this->conn->database,$sql);
 646              $ret = $this->conn->GetOne($sql);
 647              $this->conn->LogSQL($savelog);
 648  
 649              return $ret;
 650          }
 651      }
 652  
 653      /*
 654          Warn if cache ratio falls below threshold. Displayed in "Description" column.
 655      */
 656  	function WarnCacheRatio($val)
 657      {
 658          if ($val < $this->warnRatio)
 659               return '<font color=red><b>Cache ratio should be at least '.$this->warnRatio.'%</b></font>';
 660          else return '';
 661      }
 662  
 663  	function clearsql()
 664      {
 665          $perf_table = adodb_perf::table();
 666          $this->conn->Execute("delete from $perf_table where created<".$this->conn->sysTimeStamp);
 667      }
 668      /***********************************************************************************************/
 669      //                                    HIGH LEVEL UI FUNCTIONS
 670      /***********************************************************************************************/
 671  
 672  
 673      function UI($pollsecs=5)
 674      {
 675      global $ADODB_LOG_CONN;
 676  
 677      $perf_table = adodb_perf::table();
 678      $conn = $this->conn;
 679  
 680      $app = $conn->host;
 681      if ($conn->host && $conn->database) $app .= ', db=';
 682      $app .= $conn->database;
 683  
 684      if ($app) $app .= ', ';
 685      $savelog = $this->conn->LogSQL(false);
 686      $info = $conn->ServerInfo();
 687      if (isset($_GET['clearsql'])) {
 688          $this->clearsql();
 689      }
 690      $this->conn->LogSQL($savelog);
 691  
 692      // magic quotes
 693  
 694      if (isset($_GET['sql']) && get_magic_quotes_gpc()) {
 695          $_GET['sql'] = $_GET['sql'] = str_replace(array("\\'",'\"'),array("'",'"'),$_GET['sql']);
 696      }
 697  
 698      if (!isset($_SESSION['ADODB_PERF_SQL'])) $nsql = $_SESSION['ADODB_PERF_SQL'] = 10;
 699      else  $nsql = $_SESSION['ADODB_PERF_SQL'];
 700  
 701      $app .= $info['description'];
 702  
 703  
 704      if (isset($_GET['do'])) $do = $_GET['do'];
 705      else if (isset($_POST['do'])) $do = $_POST['do'];
 706       else if (isset($_GET['sql'])) $do = 'viewsql';
 707       else $do = 'stats';
 708  
 709      if (isset($_GET['nsql'])) {
 710          if ($_GET['nsql'] > 0) $nsql = $_SESSION['ADODB_PERF_SQL'] = (integer) $_GET['nsql'];
 711      }
 712      echo "<title>ADOdb Performance Monitor on $app</title><body bgcolor=white>";
 713      if ($do == 'viewsql') $form = "<td><form># SQL:<input type=hidden value=viewsql name=do> <input type=text size=4 name=nsql value=$nsql><input type=submit value=Go></td></form>";
 714      else $form = "<td>&nbsp;</td>";
 715  
 716      $allowsql = !defined('ADODB_PERF_NO_RUN_SQL');
 717      global $ADODB_PERF_MIN;
 718      $app .= " (Min sql timing \$ADODB_PERF_MIN=$ADODB_PERF_MIN secs)";
 719  
 720      if  (empty($_GET['hidem']))
 721      echo "<table border=1 width=100% bgcolor=lightyellow><tr><td colspan=2>
 722      <b><a href=http://adodb.sourceforge.net/?perf=1>ADOdb</a> Performance Monitor</b> <font size=1>for $app</font></tr><tr><td>
 723      <a href=?do=stats><b>Performance Stats</b></a> &nbsp; <a href=?do=viewsql><b>View SQL</b></a>
 724       &nbsp; <a href=?do=tables><b>View Tables</b></a> &nbsp; <a href=?do=poll><b>Poll Stats</b></a>",
 725       $allowsql ? ' &nbsp; <a href=?do=dosql><b>Run SQL</b></a>' : '',
 726       "$form",
 727       "</tr></table>";
 728  
 729  
 730           switch ($do) {
 731          default:
 732          case 'stats':
 733              if (empty($ADODB_LOG_CONN))
 734                  echo "<p>&nbsp; <a href=\"?do=viewsql&clearsql=1\">Clear SQL Log</a><br>";
 735              echo $this->HealthCheck();
 736              //$this->conn->debug=1;
 737              echo $this->CheckMemory();
 738              break;
 739          case 'poll':
 740              $self = htmlspecialchars($_SERVER['PHP_SELF']);
 741              echo "<iframe width=720 height=80%
 742                  src=\"{$self}?do=poll2&hidem=1\"></iframe>";
 743              break;
 744          case 'poll2':
 745              echo "<pre>";
 746              $this->Poll($pollsecs);
 747              break;
 748  
 749          case 'dosql':
 750              if (!$allowsql) break;
 751  
 752              $this->DoSQLForm();
 753              break;
 754          case 'viewsql':
 755              if (empty($_GET['hidem']))
 756                  echo "&nbsp; <a href=\"?do=viewsql&clearsql=1\">Clear SQL Log</a><br>";
 757              echo($this->SuspiciousSQL($nsql));
 758              echo($this->ExpensiveSQL($nsql));
 759              echo($this->InvalidSQL($nsql));
 760              break;
 761          case 'tables':
 762              echo $this->Tables(); break;
 763          }
 764          global $ADODB_vers;
 765          echo "<p><div align=center><font size=1>$ADODB_vers Sponsored by <a href=http://phplens.com/>phpLens</a></font></div>";
 766      }
 767  
 768      /*
 769          Runs in infinite loop, returning real-time statistics
 770      */
 771  	function Poll($secs=5)
 772      {
 773          $this->conn->fnExecute = false;
 774          //$this->conn->debug=1;
 775          if ($secs <= 1) $secs = 1;
 776          echo "Accumulating statistics, every $secs seconds...\n";flush();
 777          $arro = $this->PollParameters();
 778          $cnt = 0;
 779          set_time_limit(0);
 780          sleep($secs);
 781          while (1) {
 782  
 783              $arr = $this->PollParameters();
 784  
 785              $hits   = sprintf('%2.2f',$arr[0]);
 786              $reads  = sprintf('%12.4f',($arr[1]-$arro[1])/$secs);
 787              $writes = sprintf('%12.4f',($arr[2]-$arro[2])/$secs);
 788              $sess = sprintf('%5d',$arr[3]);
 789  
 790              $load = $this->CPULoad();
 791              if ($load !== false) {
 792                  $oslabel = 'WS-CPU%';
 793                  $osval = sprintf(" %2.1f  ",(float) $load);
 794              }else {
 795                  $oslabel = '';
 796                  $osval = '';
 797              }
 798              if ($cnt % 10 == 0) echo " Time   ".$oslabel."   Hit%   Sess           Reads/s          Writes/s\n";
 799              $cnt += 1;
 800              echo date('H:i:s').'  '.$osval."$hits  $sess $reads $writes\n";
 801              flush();
 802  
 803              if (connection_aborted()) return;
 804  
 805              sleep($secs);
 806              $arro = $arr;
 807          }
 808      }
 809  
 810      /*
 811          Returns basic health check in a command line interface
 812      */
 813  	function HealthCheckCLI()
 814      {
 815          return $this->HealthCheck(true);
 816      }
 817  
 818  
 819      /*
 820          Returns basic health check as HTML
 821      */
 822  	function HealthCheck($cli=false)
 823      {
 824          $saveE = $this->conn->fnExecute;
 825          $this->conn->fnExecute = false;
 826          if ($cli) $html = '';
 827          else $html = $this->table.'<tr><td colspan=3><h3>'.$this->conn->databaseType.'</h3></td></tr>'.$this->titles;
 828  
 829          $oldc = false;
 830          $bgc = '';
 831          foreach($this->settings as $name => $arr) {
 832              if ($arr === false) break;
 833  
 834              if (!is_string($name)) {
 835                  if ($cli) $html .= " -- $arr -- \n";
 836                  else $html .= "<tr bgcolor=$this->color><td colspan=3><i>$arr</i> &nbsp;</td></tr>";
 837                  continue;
 838              }
 839  
 840              if (!is_array($arr)) break;
 841              $category = $arr[0];
 842              $how = $arr[1];
 843              if (sizeof($arr)>2) $desc = $arr[2];
 844              else $desc = ' &nbsp; ';
 845  
 846  
 847              if ($category == 'HIDE') continue;
 848  
 849              $val = $this->_DBParameter($how);
 850  
 851              if ($desc && strncmp($desc,"=",1) === 0) {
 852                  $fn = substr($desc,1);
 853                  $desc = $this->$fn($val);
 854              }
 855  
 856              if ($val === false) {
 857                  $m = $this->conn->ErrorMsg();
 858                  $val = "Error: $m";
 859              } else {
 860                  if (is_numeric($val) && $val >= 256*1024) {
 861                      if ($val % (1024*1024) == 0) {
 862                          $val /= (1024*1024);
 863                          $val .= 'M';
 864                      } else if ($val % 1024 == 0) {
 865                          $val /= 1024;
 866                          $val .= 'K';
 867                      }
 868                      //$val = htmlspecialchars($val);
 869                  }
 870              }
 871              if ($category != $oldc) {
 872                  $oldc = $category;
 873                  //$bgc = ($bgc == ' bgcolor='.$this->color) ? ' bgcolor=white' : ' bgcolor='.$this->color;
 874              }
 875              if (strlen($desc)==0) $desc = '&nbsp;';
 876              if (strlen($val)==0) $val = '&nbsp;';
 877              if ($cli) {
 878                  $html  .= str_replace('&nbsp;','',sprintf($this->cliFormat,strip_tags($name),strip_tags($val),strip_tags($desc)));
 879  
 880              }else {
 881                  $html .= "<tr$bgc><td>".$name.'</td><td>'.$val.'</td><td>'.$desc."</td></tr>\n";
 882              }
 883          }
 884  
 885          if (!$cli) $html .= "</table>\n";
 886          $this->conn->fnExecute = $saveE;
 887  
 888          return $html;
 889      }
 890  
 891  	function Tables($orderby='1')
 892      {
 893          if (!$this->tablesSQL) return false;
 894  
 895          $savelog = $this->conn->LogSQL(false);
 896          $rs = $this->conn->Execute($this->tablesSQL.' order by '.$orderby);
 897          $this->conn->LogSQL($savelog);
 898          $html = rs2html($rs,false,false,false,false);
 899          return $html;
 900      }
 901  
 902  
 903  	function CreateLogTable()
 904      {
 905          if (!$this->createTableSQL) return false;
 906  
 907          $table = $this->table();
 908          $sql = str_replace('adodb_logsql',$table,$this->createTableSQL);
 909          $savelog = $this->conn->LogSQL(false);
 910          $ok = $this->conn->Execute($sql);
 911          $this->conn->LogSQL($savelog);
 912          return ($ok) ? true : false;
 913      }
 914  
 915  	function DoSQLForm()
 916      {
 917  
 918  
 919          $PHP_SELF = htmlspecialchars($_SERVER['PHP_SELF']);
 920          $sql = isset($_REQUEST['sql']) ? $_REQUEST['sql'] : '';
 921  
 922          if (isset($_SESSION['phplens_sqlrows'])) $rows = $_SESSION['phplens_sqlrows'];
 923          else $rows = 3;
 924  
 925          if (isset($_REQUEST['SMALLER'])) {
 926              $rows /= 2;
 927              if ($rows < 3) $rows = 3;
 928              $_SESSION['phplens_sqlrows'] = $rows;
 929          }
 930          if (isset($_REQUEST['BIGGER'])) {
 931              $rows *= 2;
 932              $_SESSION['phplens_sqlrows'] = $rows;
 933          }
 934  
 935  ?>
 936  
 937  <form method="POST" action="<?php echo $PHP_SELF ?>">
 938  <table><tr>
 939  <td> Form size: <input type="submit" value=" &lt; " name="SMALLER"><input type="submit" value=" &gt; &gt; " name="BIGGER">
 940  </td>
 941  <td align=right>
 942  <input type="submit" value=" Run SQL Below " name="RUN"><input type=hidden name=do value=dosql>
 943  </td></tr>
 944    <tr>
 945    <td colspan=2><textarea rows=<?php print $rows; ?> name="sql" cols="80"><?php print htmlspecialchars($sql) ?></textarea>
 946    </td>
 947    </tr>
 948   </table>
 949  </form>
 950  
 951  <?php
 952          if (!isset($_REQUEST['sql'])) return;
 953  
 954          $sql = $this->undomq(trim($sql));
 955          if (substr($sql,strlen($sql)-1) === ';') {
 956              $print = true;
 957              $sqla = $this->SplitSQL($sql);
 958          } else  {
 959              $print = false;
 960              $sqla = array($sql);
 961          }
 962          foreach($sqla as $sqls) {
 963  
 964              if (!$sqls) continue;
 965  
 966              if ($print) {
 967                  print "<p>".htmlspecialchars($sqls)."</p>";
 968                  flush();
 969              }
 970              $savelog = $this->conn->LogSQL(false);
 971              $rs = $this->conn->Execute($sqls);
 972              $this->conn->LogSQL($savelog);
 973              if ($rs && is_object($rs) && !$rs->EOF) {
 974                  rs2html($rs);
 975                  while ($rs->NextRecordSet()) {
 976                      print "<table width=98% bgcolor=#C0C0FF><tr><td>&nbsp;</td></tr></table>";
 977                      rs2html($rs);
 978                  }
 979              } else {
 980                  $e1 = (integer) $this->conn->ErrorNo();
 981                  $e2 = $this->conn->ErrorMsg();
 982                  if (($e1) || ($e2)) {
 983                      if (empty($e1)) $e1 = '-1'; // postgresql fix
 984                      print ' &nbsp; '.$e1.': '.$e2;
 985                  } else {
 986                      print "<p>No Recordset returned<br></p>";
 987                  }
 988              }
 989          } // foreach
 990      }
 991  
 992  	function SplitSQL($sql)
 993      {
 994          $arr = explode(';',$sql);
 995          return $arr;
 996      }
 997  
 998  	function undomq($m)
 999      {
1000      if (get_magic_quotes_gpc()) {
1001          // undo the damage
1002          $m = str_replace('\\\\','\\',$m);
1003          $m = str_replace('\"','"',$m);
1004          $m = str_replace('\\\'','\'',$m);
1005      }
1006      return $m;
1007  }
1008  
1009  
1010     /************************************************************************/
1011  
1012      /**
1013       * Reorganise multiple table-indices/statistics/..
1014       * OptimizeMode could be given by last Parameter
1015       *
1016       * @example
1017       *      <pre>
1018       *          optimizeTables( 'tableA');
1019       *      </pre>
1020       *      <pre>
1021       *          optimizeTables( 'tableA', 'tableB', 'tableC');
1022       *      </pre>
1023       *      <pre>
1024       *          optimizeTables( 'tableA', 'tableB', ADODB_OPT_LOW);
1025       *      </pre>
1026       *
1027       * @param string table name of the table to optimize
1028       * @param int mode optimization-mode
1029       *      <code>ADODB_OPT_HIGH</code> for full optimization
1030       *      <code>ADODB_OPT_LOW</code> for CPU-less optimization
1031       *      Default is LOW <code>ADODB_OPT_LOW</code>
1032       * @author Markus Staab
1033       * @return Returns <code>true</code> on success and <code>false</code> on error
1034       */
1035      function OptimizeTables()
1036      {
1037          $args = func_get_args();
1038          $numArgs = func_num_args();
1039  
1040          if ( $numArgs == 0) return false;
1041  
1042          $mode = ADODB_OPT_LOW;
1043          $lastArg = $args[ $numArgs - 1];
1044          if ( !is_string($lastArg)) {
1045              $mode = $lastArg;
1046              unset( $args[ $numArgs - 1]);
1047          }
1048  
1049          foreach( $args as $table) {
1050              $this->optimizeTable( $table, $mode);
1051          }
1052      }
1053  
1054      /**
1055       * Reorganise the table-indices/statistics/.. depending on the given mode.
1056       * Default Implementation throws an error.
1057       *
1058       * @param string table name of the table to optimize
1059       * @param int mode optimization-mode
1060       *      <code>ADODB_OPT_HIGH</code> for full optimization
1061       *      <code>ADODB_OPT_LOW</code> for CPU-less optimization
1062       *      Default is LOW <code>ADODB_OPT_LOW</code>
1063       * @author Markus Staab
1064       * @return Returns <code>true</code> on success and <code>false</code> on error
1065       */
1066      function OptimizeTable( $table, $mode = ADODB_OPT_LOW)
1067      {
1068          ADOConnection::outp( sprintf( "<p>%s: '%s' not implemented for driver '%s'</p>", __CLASS__, __FUNCTION__, $this->conn->databaseType));
1069          return false;
1070      }
1071  
1072      /**
1073       * Reorganise current database.
1074       * Default implementation loops over all <code>MetaTables()</code> and
1075       * optimize each using <code>optmizeTable()</code>
1076       *
1077       * @author Markus Staab
1078       * @return Returns <code>true</code> on success and <code>false</code> on error
1079       */
1080      function optimizeDatabase()
1081      {
1082          $conn = $this->conn;
1083          if ( !$conn) return false;
1084  
1085          $tables = $conn->MetaTables( 'TABLES');
1086          if ( !$tables ) return false;
1087  
1088          foreach( $tables as $table) {
1089              if ( !$this->optimizeTable( $table)) {
1090                  return false;
1091              }
1092          }
1093  
1094          return true;
1095      }
1096      // end hack
1097  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1