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