Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/lib/adodb/adodb-perf.inc.php
Go to the documentation of this file.
00001 <?php
00002 /* 
00003 V5.14 8 Sept 2011   (c) 2000-2011 John Lim (jlim#natsoft.com). All rights reserved.
00004   Released under both BSD license and Lesser GPL library license. 
00005   Whenever there is any discrepancy between the two licenses, 
00006   the BSD license will take precedence. See License.txt. 
00007   Set tabs to 4 for best viewing.
00008   
00009   Latest version is available at http://adodb.sourceforge.net
00010   
00011   Library for basic performance monitoring and tuning.
00012   
00013   My apologies if you see code mixed with presentation. The presentation suits
00014   my needs. If you want to separate code from presentation, be my guest. Patches
00015   are welcome.
00016   
00017 */
00018 
00019 if (!defined('ADODB_DIR')) include_once(dirname(__FILE__).'/adodb.inc.php');
00020 include_once(ADODB_DIR.'/tohtml.inc.php');
00021 
00022 define( 'ADODB_OPT_HIGH', 2);
00023 define( 'ADODB_OPT_LOW', 1);
00024 
00025 global $ADODB_PERF_MIN;
00026 $ADODB_PERF_MIN = 0.05; // log only if >= minimum number of secs to run
00027 
00028 
00029 // returns in K the memory of current process, or 0 if not known
00030 function adodb_getmem()
00031 {
00032         if (function_exists('memory_get_usage'))
00033                 return (integer) ((memory_get_usage()+512)/1024);
00034         
00035         $pid = getmypid();
00036         
00037         if ( strncmp(strtoupper(PHP_OS),'WIN',3)==0) {
00038                 $output = array();
00039         
00040                 exec('tasklist /FI "PID eq ' . $pid. '" /FO LIST', $output); 
00041                 return substr($output[5], strpos($output[5], ':') + 1);
00042         } 
00043         
00044         /* Hopefully UNIX */
00045         exec("ps --pid $pid --no-headers -o%mem,size", $output);
00046         if (sizeof($output) == 0) return 0;
00047         
00048         $memarr = explode(' ',$output[0]);
00049         if (sizeof($memarr)>=2) return (integer) $memarr[1];
00050         
00051         return 0;
00052 }
00053 
00054 // avoids localization problems where , is used instead of .
00055 function adodb_round($n,$prec)
00056 {
00057         return number_format($n, $prec, '.', '');
00058 }
00059 
00060 /* obsolete: return microtime value as a float. Retained for backward compat */
00061 function adodb_microtime()
00062 {
00063         return microtime(true);
00064 }
00065 
00066 /* sql code timing */
00067 function adodb_log_sql(&$connx,$sql,$inputarr)
00068 {
00069     $perf_table = adodb_perf::table();
00070         $connx->fnExecute = false;
00071         $a0 = microtime(true);
00072         $rs = $connx->Execute($sql,$inputarr);
00073         $a1 = microtime(true);
00074 
00075         if (!empty($connx->_logsql) && (empty($connx->_logsqlErrors) || !$rs)) {
00076         global $ADODB_LOG_CONN;
00077         
00078                 if (!empty($ADODB_LOG_CONN)) {
00079                         $conn = $ADODB_LOG_CONN;
00080                         if ($conn->databaseType != $connx->databaseType)
00081                                 $prefix = '/*dbx='.$connx->databaseType .'*/ ';
00082                         else
00083                                 $prefix = '';
00084                 } else {
00085                         $conn = $connx;
00086                         $prefix = '';
00087                 }
00088                 
00089                 $conn->_logsql = false; // disable logsql error simulation
00090                 $dbT = $conn->databaseType;
00091                 
00092                 $time = $a1 - $a0;
00093         
00094                 if (!$rs) {
00095                         $errM = $connx->ErrorMsg();
00096                         $errN = $connx->ErrorNo();
00097                         $conn->lastInsID = 0;
00098                         $tracer = substr('ERROR: '.htmlspecialchars($errM),0,250);
00099                 } else {
00100                         $tracer = '';
00101                         $errM = '';
00102                         $errN = 0;
00103                         $dbg = $conn->debug;
00104                         $conn->debug = false;
00105                         if (!is_object($rs) || $rs->dataProvider == 'empty') 
00106                                 $conn->_affected = $conn->affected_rows(true);
00107                         $conn->lastInsID = @$conn->Insert_ID();
00108                         $conn->debug = $dbg;
00109                 }
00110                 if (isset($_SERVER['HTTP_HOST'])) {
00111                         $tracer .= '<br>'.$_SERVER['HTTP_HOST'];
00112                         if (isset($_SERVER['PHP_SELF'])) $tracer .= htmlspecialchars($_SERVER['PHP_SELF']);
00113                 } else 
00114                         if (isset($_SERVER['PHP_SELF'])) $tracer .= '<br>'.htmlspecialchars($_SERVER['PHP_SELF']);
00115                 //$tracer .= (string) adodb_backtrace(false);
00116                 
00117                 $tracer = (string) substr($tracer,0,500);
00118                 
00119                 if (is_array($inputarr)) {
00120                         if (is_array(reset($inputarr))) $params = 'Array sizeof='.sizeof($inputarr);
00121                         else {
00122                                 // Quote string parameters so we can see them in the
00123                                 // performance stats. This helps spot disabled indexes.
00124                                 $xar_params = $inputarr;
00125                                 foreach ($xar_params as $xar_param_key => $xar_param) {
00126                                         if (gettype($xar_param) == 'string')
00127                                         $xar_params[$xar_param_key] = '"' . $xar_param . '"';
00128                                 }
00129                                 $params = implode(', ', $xar_params);
00130                                 if (strlen($params) >= 3000) $params = substr($params, 0, 3000);
00131                         }
00132                 } else {
00133                         $params = '';
00134                 }
00135                 
00136                 if (is_array($sql)) $sql = $sql[0];
00137                 if ($prefix) $sql = $prefix.$sql;
00138                 $arr = array('b'=>strlen($sql).'.'.crc32($sql),
00139                                         'c'=>substr($sql,0,3900), 'd'=>$params,'e'=>$tracer,'f'=>adodb_round($time,6));
00140                 //var_dump($arr);
00141                 $saved = $conn->debug;
00142                 $conn->debug = 0;
00143                 
00144                 $d = $conn->sysTimeStamp;
00145                 if (empty($d)) $d = date("'Y-m-d H:i:s'");
00146                 if ($conn->dataProvider == 'oci8' && $dbT != 'oci8po') {
00147                         $isql = "insert into $perf_table values($d,:b,:c,:d,:e,:f)";
00148                 } else if ($dbT == 'odbc_mssql' || $dbT == 'informix' || strncmp($dbT,'odbtp',4)==0) {
00149                         $timer = $arr['f'];
00150                         if ($dbT == 'informix') $sql2 = substr($sql2,0,230);
00151 
00152                         $sql1 = $conn->qstr($arr['b']);
00153                         $sql2 = $conn->qstr($arr['c']);
00154                         $params = $conn->qstr($arr['d']);
00155                         $tracer = $conn->qstr($arr['e']);
00156                         
00157                         $isql = "insert into $perf_table (created,sql0,sql1,params,tracer,timer) values($d,$sql1,$sql2,$params,$tracer,$timer)";
00158                         if ($dbT == 'informix') $isql = str_replace(chr(10),' ',$isql);
00159                         $arr = false;
00160                 } else {
00161                         if ($dbT == 'db2') $arr['f'] = (float) $arr['f'];
00162                         $isql = "insert into $perf_table (created,sql0,sql1,params,tracer,timer) values( $d,?,?,?,?,?)";
00163                 }
00164                 
00165                 global $ADODB_PERF_MIN;
00166                 if ($errN != 0 || $time >= $ADODB_PERF_MIN) {
00167                         $ok = $conn->Execute($isql,$arr);
00168                 } else
00169                         $ok = true;
00170                 
00171                 $conn->debug = $saved;
00172                 
00173                 if ($ok) {
00174                         $conn->_logsql = true; 
00175                 } else {
00176                         $err2 = $conn->ErrorMsg();
00177                         $conn->_logsql = true; // enable logsql error simulation
00178                         $perf = NewPerfMonitor($conn);
00179                         if ($perf) {
00180                                 if ($perf->CreateLogTable()) $ok = $conn->Execute($isql,$arr);
00181                         } else {
00182                                 $ok = $conn->Execute("create table $perf_table (
00183                                 created varchar(50),
00184                                 sql0 varchar(250), 
00185                                 sql1 varchar(4000),
00186                                 params varchar(3000),
00187                                 tracer varchar(500),
00188                                 timer decimal(16,6))");
00189                         }
00190                         if (!$ok) {
00191                                 ADOConnection::outp( "<p><b>LOGSQL Insert Failed</b>: $isql<br>$err2</p>");
00192                                 $conn->_logsql = false;
00193                         }
00194                 }
00195                 $connx->_errorMsg = $errM;
00196                 $connx->_errorCode = $errN;
00197         } 
00198         $connx->fnExecute = 'adodb_log_sql';
00199         return $rs;
00200 }
00201 
00202         
00203 /*
00204 The settings data structure is an associative array that database parameter per element.
00205 
00206 Each database parameter element in the array is itself an array consisting of:
00207 
00208 0: category code, used to group related db parameters
00209 1: either
00210         a. sql string to retrieve value, eg. "select value from v\$parameter where name='db_block_size'", 
00211         b. array holding sql string and field to look for, e.g. array('show variables','table_cache'),
00212         c. a string prefixed by =, then a PHP method of the class is invoked, 
00213                 e.g. to invoke $this->GetIndexValue(), set this array element to '=GetIndexValue',
00214 2: description of the database parameter
00215 */
00216 
00217 class adodb_perf {
00218         var $conn;
00219         var $color = '#F0F0F0';
00220         var $table = '<table border=1 bgcolor=white>';
00221         var $titles = '<tr><td><b>Parameter</b></td><td><b>Value</b></td><td><b>Description</b></td></tr>';
00222         var $warnRatio = 90;
00223         var $tablesSQL = false;
00224         var $cliFormat = "%32s => %s \r\n";
00225         var $sql1 = 'sql1';  // used for casting sql1 to text for mssql
00226         var $explain = true;
00227         var $helpurl = "<a href=http://phplens.com/adodb/reference.functions.fnexecute.and.fncacheexecute.properties.html#logsql>LogSQL help</a>";
00228         var $createTableSQL = false;
00229         var $maxLength = 2000;
00230         
00231     // Sets the tablename to be used            
00232     static function table($newtable = false)
00233     {
00234         static $_table;
00235 
00236         if (!empty($newtable))  $_table = $newtable;
00237                 if (empty($_table)) $_table = 'adodb_logsql';
00238         return $_table;
00239     }
00240 
00241         // returns array with info to calculate CPU Load
00242         function _CPULoad()
00243         {
00244 /*
00245 
00246 cpu  524152 2662 2515228 336057010
00247 cpu0 264339 1408 1257951 168025827
00248 cpu1 259813 1254 1257277 168031181
00249 page 622307 25475680
00250 swap 24 1891
00251 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
00252 disk_io: (3,0):(3144904,54369,610378,3090535,50936192) (3,1):(3630212,54097,633016,3576115,50951320)
00253 ctxt 66155838
00254 btime 1062315585
00255 processes 69293
00256 
00257 */
00258                 // Algorithm is taken from
00259                 // http://social.technet.microsoft.com/Forums/en-US/winservergen/thread/414b0e1b-499c-411e-8a02-6a12e339c0f1/
00260                 if (strncmp(PHP_OS,'WIN',3)==0) {
00261                         if (PHP_VERSION == '5.0.0') return false;
00262                         if (PHP_VERSION == '5.0.1') return false;
00263                         if (PHP_VERSION == '5.0.2') return false;
00264                         if (PHP_VERSION == '5.0.3') return false;
00265                         if (PHP_VERSION == '4.3.10') return false; # see http://bugs.php.net/bug.php?id=31737
00266                         
00267                         static $FAIL = false;
00268                         if ($FAIL) return false;
00269                         
00270                         $objName = "winmgmts:{impersonationLevel=impersonate}!\\\\.\\root\\CIMV2";      
00271                         $myQuery = "SELECT * FROM Win32_PerfFormattedData_PerfOS_Processor WHERE Name = '_Total'";
00272                         
00273                         try {
00274                                 @$objWMIService = new COM($objName);
00275                                 if (!$objWMIService) {
00276                                         $FAIL = true;
00277                                         return false;
00278                                 }
00279                 
00280                                 $info[0] = -1;
00281                                 $info[1] = 0;
00282                                 $info[2] = 0;
00283                                 $info[3] = 0;
00284                                 foreach($objWMIService->ExecQuery($myQuery) as $objItem)  {
00285                                                 $info[0] = $objItem->PercentProcessorTime();
00286                                 }
00287                         
00288                         } catch(Exception $e) {
00289                                 $FAIL = true;
00290                                 echo $e->getMessage();
00291                                 return false;
00292                         }
00293                         
00294                         return $info;
00295                 }
00296                 
00297                 // Algorithm - Steve Blinch (BlitzAffe Online, http://www.blitzaffe.com)
00298                 $statfile = '/proc/stat';
00299                 if (!file_exists($statfile)) return false;
00300                 
00301                 $fd = fopen($statfile,"r");
00302                 if (!$fd) return false;
00303                 
00304                 $statinfo = explode("\n",fgets($fd, 1024));
00305                 fclose($fd);
00306                 foreach($statinfo as $line) {
00307                         $info = explode(" ",$line);
00308                         if($info[0]=="cpu") {
00309                                 array_shift($info);  // pop off "cpu"
00310                                 if(!$info[0]) array_shift($info); // pop off blank space (if any)
00311                                 return $info;
00312                         }
00313                 }
00314                 
00315                 return false;
00316                 
00317         }
00318         
00319         /* NOT IMPLEMENTED */
00320         function MemInfo()
00321         {
00322                 /*
00323 
00324         total:    used:    free:  shared: buffers:  cached:
00325 Mem:  1055289344 917299200 137990144        0 165437440 599773184
00326 Swap: 2146775040 11055104 2135719936
00327 MemTotal:      1030556 kB
00328 MemFree:        134756 kB
00329 MemShared:           0 kB
00330 Buffers:        161560 kB
00331 Cached:         581384 kB
00332 SwapCached:       4332 kB
00333 Active:         494468 kB
00334 Inact_dirty:    322856 kB
00335 Inact_clean:     24256 kB
00336 Inact_target:   168316 kB
00337 HighTotal:      131064 kB
00338 HighFree:         1024 kB
00339 LowTotal:       899492 kB
00340 LowFree:        133732 kB
00341 SwapTotal:     2096460 kB
00342 SwapFree:      2085664 kB
00343 Committed_AS:   348732 kB
00344                 */
00345         }
00346         
00347         
00348         /*
00349                 Remember that this is client load, not db server load!
00350         */
00351         var $_lastLoad;
00352         function CPULoad()
00353         {
00354                 $info = $this->_CPULoad();
00355                 if (!$info) return false;
00356                 
00357                 if (strncmp(PHP_OS,'WIN',3)==0) {
00358                         return (integer) $info[0];
00359                 }else {
00360                         if (empty($this->_lastLoad)) {
00361                                 sleep(1);
00362                                 $this->_lastLoad = $info;
00363                                 $info = $this->_CPULoad();
00364                         }
00365                         
00366                         $last = $this->_lastLoad;
00367                         $this->_lastLoad = $info;
00368                         
00369                         $d_user = $info[0] - $last[0];
00370                         $d_nice = $info[1] - $last[1];
00371                         $d_system = $info[2] - $last[2];
00372                         $d_idle = $info[3] - $last[3];
00373                         
00374                         //printf("Delta - User: %f  Nice: %f  System: %f  Idle: %f<br>",$d_user,$d_nice,$d_system,$d_idle);
00375                 
00376                         $total=$d_user+$d_nice+$d_system+$d_idle;
00377                         if ($total<1) $total=1;
00378                         return 100*($d_user+$d_nice+$d_system)/$total; 
00379                 }
00380         }
00381         
00382         function Tracer($sql)
00383         {
00384         $perf_table = adodb_perf::table();
00385                 $saveE = $this->conn->fnExecute;
00386                 $this->conn->fnExecute = false;
00387                 
00388                 global $ADODB_FETCH_MODE;
00389                 $save = $ADODB_FETCH_MODE;
00390                 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
00391                 if ($this->conn->fetchMode !== false) $savem = $this->conn->SetFetchMode(false);
00392                                 
00393                 $sqlq = $this->conn->qstr($sql);
00394                 $arr = $this->conn->GetArray(
00395 "select count(*),tracer 
00396         from $perf_table where sql1=$sqlq 
00397         group by tracer
00398         order by 1 desc");
00399                 $s = '';
00400                 if ($arr) {
00401                         $s .= '<h3>Scripts Affected</h3>';
00402                         foreach($arr as $k) {
00403                                 $s .= sprintf("%4d",$k[0]).' &nbsp; '.strip_tags($k[1]).'<br>';
00404                         }
00405                 }
00406                 
00407                 if (isset($savem)) $this->conn->SetFetchMode($savem);
00408                 $ADODB_CACHE_MODE = $save;
00409                 $this->conn->fnExecute = $saveE;
00410                 return $s;
00411         }
00412 
00413         /* 
00414                 Explain Plan for $sql.
00415                 If only a snippet of the $sql is passed in, then $partial will hold the crc32 of the 
00416                         actual sql.
00417         */
00418         function Explain($sql,$partial=false)
00419         {       
00420                 return false;
00421         }
00422         
00423         function InvalidSQL($numsql = 10)
00424         {
00425         
00426                 if (isset($_GET['sql'])) return;
00427                 $s = '<h3>Invalid SQL</h3>';
00428                 $saveE = $this->conn->fnExecute;
00429                 $this->conn->fnExecute = false;
00430         $perf_table = adodb_perf::table();
00431                 $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);
00432                 $this->conn->fnExecute = $saveE;
00433                 if ($rs) {
00434                         $s .= rs2html($rs,false,false,false,false);
00435                 } else
00436                         return "<p>$this->helpurl. ".$this->conn->ErrorMsg()."</p>";
00437                 
00438                 return $s;
00439         }
00440 
00441         
00442         /*
00443                 This script identifies the longest running SQL
00444         */      
00445         function _SuspiciousSQL($numsql = 10)
00446         {
00447                 global $ADODB_FETCH_MODE;
00448                 
00449             $perf_table = adodb_perf::table();
00450                         $saveE = $this->conn->fnExecute;
00451                         $this->conn->fnExecute = false;
00452                         
00453                         if (isset($_GET['exps']) && isset($_GET['sql'])) {
00454                                 $partial = !empty($_GET['part']);
00455                                 echo "<a name=explain></a>".$this->Explain($_GET['sql'],$partial)."\n";
00456                         }
00457                         
00458                         if (isset($_GET['sql'])) return;
00459                         $sql1 = $this->sql1;
00460                         
00461                         $save = $ADODB_FETCH_MODE;
00462                         $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
00463                         if ($this->conn->fetchMode !== false) $savem = $this->conn->SetFetchMode(false);
00464                         //$this->conn->debug=1;
00465                         $rs = $this->conn->SelectLimit(
00466                         "select avg(timer) as avg_timer,$sql1,count(*),max(timer) as max_timer,min(timer) as min_timer
00467                                 from $perf_table
00468                                 where {$this->conn->upperCase}({$this->conn->substr}(sql0,1,5)) not in ('DROP ','INSER','COMMI','CREAT')
00469                                 and (tracer is null or tracer not like 'ERROR:%')
00470                                 group by sql1
00471                                 order by 1 desc",$numsql);
00472                         if (isset($savem)) $this->conn->SetFetchMode($savem);
00473                         $ADODB_FETCH_MODE = $save;
00474                         $this->conn->fnExecute = $saveE;
00475                         
00476                         if (!$rs) return "<p>$this->helpurl. ".$this->conn->ErrorMsg()."</p>";
00477                         $s = "<h3>Suspicious SQL</h3>
00478 <font size=1>The following SQL have high average execution times</font><br>
00479 <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";
00480                         $max = $this->maxLength;
00481                         while (!$rs->EOF) {
00482                                 $sql = $rs->fields[1];
00483                                 $raw = urlencode($sql);
00484                                 if (strlen($raw)>$max-100) {
00485                                         $sql2 = substr($sql,0,$max-500);
00486                                         $raw = urlencode($sql2).'&part='.crc32($sql);
00487                                 }
00488                                 $prefix = "<a target=sql".rand()." href=\"?hidem=1&exps=1&sql=".$raw."&x#explain\">";
00489                                 $suffix = "</a>";
00490                                 if ($this->explain == false || strlen($prefix)>$max) {
00491                                         $suffix = ' ... <i>String too long for GET parameter: '.strlen($prefix).'</i>';
00492                                         $prefix = '';
00493                                 }
00494                                 $s .= "<tr><td>".adodb_round($rs->fields[0],6)."<td align=right>".$rs->fields[2]."<td><font size=-1>".$prefix.htmlspecialchars($sql).$suffix."</font>".
00495                                         "<td>".$rs->fields[3]."<td>".$rs->fields[4]."</tr>";
00496                                 $rs->MoveNext();
00497                         }
00498                         return $s."</table>";
00499                 
00500         }
00501         
00502         function CheckMemory()
00503         {
00504                 return '';
00505         }
00506         
00507         
00508         function SuspiciousSQL($numsql=10)
00509         {
00510                 return adodb_perf::_SuspiciousSQL($numsql);
00511         }
00512 
00513         function ExpensiveSQL($numsql=10)
00514         {
00515                 return adodb_perf::_ExpensiveSQL($numsql);
00516         }
00517 
00518         
00519         /*
00520                 This reports the percentage of load on the instance due to the most 
00521                 expensive few SQL statements. Tuning these statements can often 
00522                 make huge improvements in overall system performance. 
00523         */
00524         function _ExpensiveSQL($numsql = 10)
00525         {
00526                 global $ADODB_FETCH_MODE;
00527                 
00528             $perf_table = adodb_perf::table();
00529                         $saveE = $this->conn->fnExecute;
00530                         $this->conn->fnExecute = false;
00531                         
00532                         if (isset($_GET['expe']) && isset($_GET['sql'])) {
00533                                 $partial = !empty($_GET['part']);
00534                                 echo "<a name=explain></a>".$this->Explain($_GET['sql'],$partial)."\n";
00535                         }
00536                         
00537                         if (isset($_GET['sql'])) return;
00538                         
00539                         $sql1 = $this->sql1;
00540                         $save = $ADODB_FETCH_MODE;
00541                         $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
00542                         if ($this->conn->fetchMode !== false) $savem = $this->conn->SetFetchMode(false);
00543                         
00544                         $rs = $this->conn->SelectLimit(
00545                         "select sum(timer) as total,$sql1,count(*),max(timer) as max_timer,min(timer) as min_timer
00546                                 from $perf_table
00547                                 where {$this->conn->upperCase}({$this->conn->substr}(sql0,1,5))  not in ('DROP ','INSER','COMMI','CREAT')
00548                                 and (tracer is null or tracer not like 'ERROR:%')
00549                                 group by sql1
00550                                 having count(*)>1
00551                                 order by 1 desc",$numsql);
00552                         if (isset($savem)) $this->conn->SetFetchMode($savem);
00553                         $this->conn->fnExecute = $saveE;
00554                         $ADODB_FETCH_MODE = $save;
00555                         if (!$rs) return "<p>$this->helpurl. ".$this->conn->ErrorMsg()."</p>";
00556                         $s = "<h3>Expensive SQL</h3>
00557 <font size=1>Tuning the following SQL could reduce the server load substantially</font><br>
00558 <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";
00559                         $max = $this->maxLength;
00560                         while (!$rs->EOF) {
00561                                 $sql = $rs->fields[1];
00562                                 $raw = urlencode($sql);
00563                                 if (strlen($raw)>$max-100) {
00564                                         $sql2 = substr($sql,0,$max-500);
00565                                         $raw = urlencode($sql2).'&part='.crc32($sql);
00566                                 }
00567                                 $prefix = "<a target=sqle".rand()." href=\"?hidem=1&expe=1&sql=".$raw."&x#explain\">";
00568                                 $suffix = "</a>";
00569                                 if($this->explain == false || strlen($prefix>$max)) {
00570                                         $prefix = '';
00571                                         $suffix = '';
00572                                 }
00573                                 $s .= "<tr><td>".adodb_round($rs->fields[0],6)."<td align=right>".$rs->fields[2]."<td><font size=-1>".$prefix.htmlspecialchars($sql).$suffix."</font>".
00574                                         "<td>".$rs->fields[3]."<td>".$rs->fields[4]."</tr>";
00575                                 $rs->MoveNext();
00576                         }
00577                         return $s."</table>";
00578         }
00579         
00580         /*
00581                 Raw function to return parameter value from $settings.
00582         */
00583         function DBParameter($param)
00584         {
00585                 if (empty($this->settings[$param])) return false;
00586                 $sql = $this->settings[$param][1];
00587                 return $this->_DBParameter($sql);
00588         }
00589         
00590         /*
00591                 Raw function returning array of poll paramters
00592         */
00593         function PollParameters()
00594         {
00595                 $arr[0] = (float)$this->DBParameter('data cache hit ratio');
00596                 $arr[1] = (float)$this->DBParameter('data reads');
00597                 $arr[2] = (float)$this->DBParameter('data writes');
00598                 $arr[3] = (integer) $this->DBParameter('current connections');
00599                 return $arr;
00600         }
00601         
00602         /*
00603                 Low-level Get Database Parameter
00604         */
00605         function _DBParameter($sql)
00606         {
00607                 $savelog = $this->conn->LogSQL(false);
00608                 if (is_array($sql)) {
00609                 global $ADODB_FETCH_MODE;
00610                 
00611                         $sql1 = $sql[0];
00612                         $key = $sql[1];
00613                         if (sizeof($sql)>2) $pos = $sql[2];
00614                         else $pos = 1;
00615                         if (sizeof($sql)>3) $coef = $sql[3];
00616                         else $coef = false;
00617                         $ret = false;
00618                         $save = $ADODB_FETCH_MODE;
00619                         $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
00620                         if ($this->conn->fetchMode !== false) $savem = $this->conn->SetFetchMode(false);
00621                         
00622                         $rs = $this->conn->Execute($sql1);
00623                         
00624                         if (isset($savem)) $this->conn->SetFetchMode($savem);
00625                         $ADODB_FETCH_MODE = $save;
00626                         if ($rs) {
00627                                 while (!$rs->EOF) {
00628                                         $keyf = reset($rs->fields);
00629                                         if (trim($keyf) == $key) {
00630                                                 $ret = $rs->fields[$pos];
00631                                                 if ($coef) $ret *= $coef;
00632                                                 break;
00633                                         }
00634                                         $rs->MoveNext();
00635                                 }
00636                                 $rs->Close();
00637                         }
00638                         $this->conn->LogSQL($savelog);
00639                         return $ret;
00640                 } else {
00641                         if (strncmp($sql,'=',1) == 0) {
00642                                 $fn = substr($sql,1);
00643                                 return $this->$fn();
00644                         }
00645                         $sql = str_replace('$DATABASE',$this->conn->database,$sql);
00646                         $ret = $this->conn->GetOne($sql);
00647                         $this->conn->LogSQL($savelog);
00648                         
00649                         return $ret;
00650                 }
00651         }
00652         
00653         /*
00654                 Warn if cache ratio falls below threshold. Displayed in "Description" column.
00655         */
00656         function WarnCacheRatio($val)
00657         {
00658                 if ($val < $this->warnRatio) 
00659                          return '<font color=red><b>Cache ratio should be at least '.$this->warnRatio.'%</b></font>';
00660                 else return '';
00661         }
00662         
00663         function clearsql()
00664         {
00665                 $perf_table = adodb_perf::table();
00666                 $this->conn->Execute("delete from $perf_table where created<".$this->conn->sysTimeStamp);
00667         }
00668         /***********************************************************************************************/
00669         //                                    HIGH LEVEL UI FUNCTIONS
00670         /***********************************************************************************************/
00671 
00672         
00673         function UI($pollsecs=5)
00674         {
00675         global $ADODB_LOG_CONN;
00676         
00677     $perf_table = adodb_perf::table();
00678         $conn = $this->conn;
00679         
00680         $app = $conn->host;
00681         if ($conn->host && $conn->database) $app .= ', db=';
00682         $app .= $conn->database;
00683         
00684         if ($app) $app .= ', ';
00685         $savelog = $this->conn->LogSQL(false);  
00686         $info = $conn->ServerInfo();
00687         if (isset($_GET['clearsql'])) {
00688                 $this->clearsql();
00689         }
00690         $this->conn->LogSQL($savelog);
00691         
00692         // magic quotes
00693         
00694         if (isset($_GET['sql']) && get_magic_quotes_gpc()) {
00695                 $_GET['sql'] = $_GET['sql'] = str_replace(array("\\'",'\"'),array("'",'"'),$_GET['sql']);
00696         }
00697         
00698         if (!isset($_SESSION['ADODB_PERF_SQL'])) $nsql = $_SESSION['ADODB_PERF_SQL'] = 10;
00699         else  $nsql = $_SESSION['ADODB_PERF_SQL'];
00700         
00701         $app .= $info['description'];
00702         
00703         
00704         if (isset($_GET['do'])) $do = $_GET['do'];
00705         else if (isset($_POST['do'])) $do = $_POST['do'];
00706          else if (isset($_GET['sql'])) $do = 'viewsql';
00707          else $do = 'stats';
00708          
00709         if (isset($_GET['nsql'])) {
00710                 if ($_GET['nsql'] > 0) $nsql = $_SESSION['ADODB_PERF_SQL'] = (integer) $_GET['nsql'];
00711         }
00712         echo "<title>ADOdb Performance Monitor on $app</title><body bgcolor=white>";
00713         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>";
00714         else $form = "<td>&nbsp;</td>";
00715         
00716         $allowsql = !defined('ADODB_PERF_NO_RUN_SQL');
00717         global $ADODB_PERF_MIN;
00718         $app .= " (Min sql timing \$ADODB_PERF_MIN=$ADODB_PERF_MIN secs)";
00719         
00720         if  (empty($_GET['hidem']))
00721         echo "<table border=1 width=100% bgcolor=lightyellow><tr><td colspan=2>
00722         <b><a href=http://adodb.sourceforge.net/?perf=1>ADOdb</a> Performance Monitor</b> <font size=1>for $app</font></tr><tr><td>
00723         <a href=?do=stats><b>Performance Stats</b></a> &nbsp; <a href=?do=viewsql><b>View SQL</b></a>
00724          &nbsp; <a href=?do=tables><b>View Tables</b></a> &nbsp; <a href=?do=poll><b>Poll Stats</b></a>",
00725          $allowsql ? ' &nbsp; <a href=?do=dosql><b>Run SQL</b></a>' : '',
00726          "$form",
00727          "</tr></table>";
00728 
00729          
00730                 switch ($do) {
00731                 default:
00732                 case 'stats':
00733                         if (empty($ADODB_LOG_CONN))
00734                                 echo "<p>&nbsp; <a href=\"?do=viewsql&clearsql=1\">Clear SQL Log</a><br>";
00735                         echo $this->HealthCheck();
00736                         //$this->conn->debug=1;
00737                         echo $this->CheckMemory();              
00738                         break;
00739                 case 'poll':
00740                         $self = htmlspecialchars($_SERVER['PHP_SELF']);
00741                         echo "<iframe width=720 height=80% 
00742                                 src=\"{$self}?do=poll2&hidem=1\"></iframe>";
00743                         break;
00744                 case 'poll2':
00745                         echo "<pre>";
00746                         $this->Poll($pollsecs);
00747                         break;
00748                 
00749                 case 'dosql':
00750                         if (!$allowsql) break;
00751                         
00752                         $this->DoSQLForm();
00753                         break;
00754                 case 'viewsql':
00755                         if (empty($_GET['hidem']))
00756                                 echo "&nbsp; <a href=\"?do=viewsql&clearsql=1\">Clear SQL Log</a><br>";
00757                         echo($this->SuspiciousSQL($nsql));
00758                         echo($this->ExpensiveSQL($nsql));
00759                         echo($this->InvalidSQL($nsql));
00760                         break;
00761                 case 'tables': 
00762                         echo $this->Tables(); break;
00763                 }
00764                 global $ADODB_vers;
00765                 echo "<p><div align=center><font size=1>$ADODB_vers Sponsored by <a href=http://phplens.com/>phpLens</a></font></div>";
00766         }
00767         
00768         /*
00769                 Runs in infinite loop, returning real-time statistics
00770         */
00771         function Poll($secs=5)
00772         {
00773                 $this->conn->fnExecute = false;
00774                 //$this->conn->debug=1;
00775                 if ($secs <= 1) $secs = 1;
00776                 echo "Accumulating statistics, every $secs seconds...\n";flush();
00777                 $arro = $this->PollParameters();
00778                 $cnt = 0;
00779                 set_time_limit(0);
00780                 sleep($secs);
00781                 while (1) {
00782 
00783                         $arr = $this->PollParameters();
00784                         
00785                         $hits   = sprintf('%2.2f',$arr[0]);
00786                         $reads  = sprintf('%12.4f',($arr[1]-$arro[1])/$secs);
00787                         $writes = sprintf('%12.4f',($arr[2]-$arro[2])/$secs);
00788                         $sess = sprintf('%5d',$arr[3]);
00789                         
00790                         $load = $this->CPULoad();
00791                         if ($load !== false) {
00792                                 $oslabel = 'WS-CPU%';
00793                                 $osval = sprintf(" %2.1f  ",(float) $load);
00794                         }else {
00795                                 $oslabel = '';
00796                                 $osval = '';
00797                         }
00798                         if ($cnt % 10 == 0) echo " Time   ".$oslabel."   Hit%   Sess           Reads/s          Writes/s\n"; 
00799                         $cnt += 1;
00800                         echo date('H:i:s').'  '.$osval."$hits  $sess $reads $writes\n";
00801                         flush();
00802                         
00803                         if (connection_aborted()) return;
00804                         
00805                         sleep($secs);
00806                         $arro = $arr;
00807                 }
00808         }
00809         
00810         /*
00811                 Returns basic health check in a command line interface
00812         */
00813         function HealthCheckCLI()
00814         {
00815                 return $this->HealthCheck(true);
00816         }
00817         
00818                 
00819         /*
00820                 Returns basic health check as HTML
00821         */
00822         function HealthCheck($cli=false)
00823         {
00824                 $saveE = $this->conn->fnExecute;
00825                 $this->conn->fnExecute = false; 
00826                 if ($cli) $html = '';
00827                 else $html = $this->table.'<tr><td colspan=3><h3>'.$this->conn->databaseType.'</h3></td></tr>'.$this->titles;
00828                 
00829                 $oldc = false;
00830                 $bgc = '';
00831                 foreach($this->settings as $name => $arr) {
00832                         if ($arr === false) break;
00833                         
00834                         if (!is_string($name)) {
00835                                 if ($cli) $html .= " -- $arr -- \n";
00836                                 else $html .= "<tr bgcolor=$this->color><td colspan=3><i>$arr</i> &nbsp;</td></tr>";
00837                                 continue;
00838                         }
00839                         
00840                         if (!is_array($arr)) break;
00841                         $category = $arr[0];
00842                         $how = $arr[1];
00843                         if (sizeof($arr)>2) $desc = $arr[2];
00844                         else $desc = ' &nbsp; ';
00845                         
00846                         
00847                         if ($category == 'HIDE') continue;
00848                         
00849                         $val = $this->_DBParameter($how);
00850                         
00851                         if ($desc && strncmp($desc,"=",1) === 0) {
00852                                 $fn = substr($desc,1);
00853                                 $desc = $this->$fn($val);
00854                         }
00855                         
00856                         if ($val === false) {
00857                                 $m = $this->conn->ErrorMsg();
00858                                 $val = "Error: $m"; 
00859                         } else {
00860                                 if (is_numeric($val) && $val >= 256*1024) {
00861                                         if ($val % (1024*1024) == 0) {
00862                                                 $val /= (1024*1024);
00863                                                 $val .= 'M';
00864                                         } else if ($val % 1024 == 0) {
00865                                                 $val /= 1024;
00866                                                 $val .= 'K';
00867                                         }
00868                                         //$val = htmlspecialchars($val);
00869                                 }
00870                         }
00871                         if ($category != $oldc) {
00872                                 $oldc = $category;
00873                                 //$bgc = ($bgc == ' bgcolor='.$this->color) ? ' bgcolor=white' : ' bgcolor='.$this->color;
00874                         }
00875                         if (strlen($desc)==0) $desc = '&nbsp;';
00876                         if (strlen($val)==0) $val = '&nbsp;';
00877                         if ($cli) {
00878                                 $html  .= str_replace('&nbsp;','',sprintf($this->cliFormat,strip_tags($name),strip_tags($val),strip_tags($desc)));
00879                                 
00880                         }else {
00881                                 $html .= "<tr$bgc><td>".$name.'</td><td>'.$val.'</td><td>'.$desc."</td></tr>\n";
00882                         }
00883                 }
00884                 
00885                 if (!$cli) $html .= "</table>\n";
00886                 $this->conn->fnExecute = $saveE;
00887                         
00888                 return $html;   
00889         }
00890         
00891         function Tables($orderby='1')
00892         {
00893                 if (!$this->tablesSQL) return false;
00894                 
00895                 $savelog = $this->conn->LogSQL(false);
00896                 $rs = $this->conn->Execute($this->tablesSQL.' order by '.$orderby);
00897                 $this->conn->LogSQL($savelog);
00898                 $html = rs2html($rs,false,false,false,false);
00899                 return $html;
00900         }
00901         
00902 
00903         function CreateLogTable()
00904         {
00905                 if (!$this->createTableSQL) return false;
00906                 
00907                 $table = $this->table();
00908                 $sql = str_replace('adodb_logsql',$table,$this->createTableSQL);
00909                 $savelog = $this->conn->LogSQL(false);
00910                 $ok = $this->conn->Execute($sql);
00911                 $this->conn->LogSQL($savelog);
00912                 return ($ok) ? true : false;
00913         }
00914         
00915         function DoSQLForm()
00916         {
00917         
00918                 
00919                 $PHP_SELF = htmlspecialchars($_SERVER['PHP_SELF']);
00920                 $sql = isset($_REQUEST['sql']) ? $_REQUEST['sql'] : '';
00921 
00922                 if (isset($_SESSION['phplens_sqlrows'])) $rows = $_SESSION['phplens_sqlrows'];
00923                 else $rows = 3;
00924                 
00925                 if (isset($_REQUEST['SMALLER'])) {
00926                         $rows /= 2;
00927                         if ($rows < 3) $rows = 3;
00928                         $_SESSION['phplens_sqlrows'] = $rows;
00929                 }
00930                 if (isset($_REQUEST['BIGGER'])) {
00931                         $rows *= 2;
00932                         $_SESSION['phplens_sqlrows'] = $rows;
00933                 }
00934                 
00935 ?>
00936 
00937 <form method="POST" action="<?php echo $PHP_SELF ?>">
00938 <table><tr>
00939 <td> Form size: <input type="submit" value=" &lt; " name="SMALLER"><input type="submit" value=" &gt; &gt; " name="BIGGER">
00940 </td>
00941 <td align=right>
00942 <input type="submit" value=" Run SQL Below " name="RUN"><input type=hidden name=do value=dosql>
00943 </td></tr>
00944   <tr>
00945   <td colspan=2><textarea rows=<?php print $rows; ?> name="sql" cols="80"><?php print htmlspecialchars($sql) ?></textarea>
00946   </td>
00947   </tr>
00948  </table>
00949 </form>
00950 
00951 <?php
00952                 if (!isset($_REQUEST['sql'])) return;
00953                 
00954                 $sql = $this->undomq(trim($sql));
00955                 if (substr($sql,strlen($sql)-1) === ';') {
00956                         $print = true;
00957                         $sqla = $this->SplitSQL($sql);
00958                 } else  {
00959                         $print = false;
00960                         $sqla = array($sql);
00961                 }
00962                 foreach($sqla as $sqls) {
00963 
00964                         if (!$sqls) continue;
00965                         
00966                         if ($print) {
00967                                 print "<p>".htmlspecialchars($sqls)."</p>";
00968                                 flush();
00969                         }
00970                         $savelog = $this->conn->LogSQL(false);
00971                         $rs = $this->conn->Execute($sqls);
00972                         $this->conn->LogSQL($savelog);
00973                         if ($rs && is_object($rs) && !$rs->EOF) {
00974                                 rs2html($rs);
00975                                 while ($rs->NextRecordSet()) {
00976                                         print "<table width=98% bgcolor=#C0C0FF><tr><td>&nbsp;</td></tr></table>";
00977                                         rs2html($rs);
00978                                 }
00979                         } else {
00980                                 $e1 = (integer) $this->conn->ErrorNo();
00981                                 $e2 = $this->conn->ErrorMsg();
00982                                 if (($e1) || ($e2)) {
00983                                         if (empty($e1)) $e1 = '-1'; // postgresql fix
00984                                         print ' &nbsp; '.$e1.': '.$e2;
00985                                 } else {
00986                                         print "<p>No Recordset returned<br></p>";
00987                                 }
00988                         }
00989                 } // foreach
00990         }
00991         
00992         function SplitSQL($sql)
00993         {
00994                 $arr = explode(';',$sql);
00995                 return $arr;
00996         }
00997         
00998         function undomq($m) 
00999         {
01000         if (get_magic_quotes_gpc()) {
01001                 // undo the damage
01002                 $m = str_replace('\\\\','\\',$m);
01003                 $m = str_replace('\"','"',$m);
01004                 $m = str_replace('\\\'','\'',$m);
01005         }
01006         return $m;
01007 }
01008 
01009     
01010    /************************************************************************/
01011    
01035     function OptimizeTables()
01036     {
01037         $args = func_get_args();
01038         $numArgs = func_num_args();
01039         
01040         if ( $numArgs == 0) return false;
01041         
01042         $mode = ADODB_OPT_LOW; 
01043         $lastArg = $args[ $numArgs - 1];
01044         if ( !is_string($lastArg)) {
01045             $mode = $lastArg;
01046             unset( $args[ $numArgs - 1]);
01047         }
01048         
01049         foreach( $args as $table) {
01050             $this->optimizeTable( $table, $mode);
01051         }
01052         }
01053 
01066     function OptimizeTable( $table, $mode = ADODB_OPT_LOW) 
01067     {
01068         ADOConnection::outp( sprintf( "<p>%s: '%s' not implemented for driver '%s'</p>", __CLASS__, __FUNCTION__, $this->conn->databaseType));
01069         return false;
01070     }
01071     
01080     function optimizeDatabase() 
01081     {
01082         $conn = $this->conn;
01083         if ( !$conn) return false;
01084         
01085         $tables = $conn->MetaTables( 'TABLES');
01086         if ( !$tables ) return false;
01087 
01088         foreach( $tables as $table) {
01089             if ( !$this->optimizeTable( $table)) {
01090                 return false;
01091             }
01092         }
01093       
01094         return true;
01095     }
01096     // end hack 
01097 }
01098 
01099 ?>
 All Data Structures Namespaces Files Functions Variables Enumerations