showsumstats.php3 16.1 KB
Newer Older
Leigh B. Stoller's avatar
Leigh B. Stoller committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
<?php
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2003 University of Utah and the Flux Group.
# All rights reserved.
#
include("defs.php3");
include("showstuff.php3");

#
# Standard Testbed Header
#
PAGEHEADER("Testbed Summary Stats");

#
# Only known and logged in users can end experiments.
#
$uid = GETLOGIN();
LOGGEDINORDIE($uid);
$isadmin = ISADMIN($uid);

# Summary data for admins only.
if (!$isadmin) {
    USERERROR("You are not allowed to view this page!", 1);
}

# Page args,
if (! isset($showby)) {
    $showby = "users";
}
if (! isset($sortby)) {
Leigh B. Stoller's avatar
Leigh B. Stoller committed
32
    $sortby = "pdays";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
}
if (! isset($range)) {
    $range = "epoch";
}

echo "<b>Show: <a class='static' href='showexpstats.php3'>
                  Experiment Stats</a>,
               <a class='static' href='showstats.php3'>
                  Testbed Stats</a>.
      </b><br>\n";

echo "<b>Show by: ";
# By Users.
if ($showby != "users") {
    echo "<a class='static' href='showsumstats.php3?showby=users'>
             Users</a>, ";
}
else {
    echo "Users, ";
}
# By Projects
if ($showby != "projects") {
    echo "<a class='static' href='showsumstats.php3?showby=projects'>
             Projects</a>, ";
}
else {
    echo "Projects. ";
}
echo "</b><br>\n";

echo "<b>Range: ";
if ($range != "epoch") {
    echo "<a class='static'
            href='showsumstats.php3?showby=$showby&sortby=$sortby&range=epoch'>
            Epoch</a>, ";
}
else {
    echo "Epoch, ";
}
if ($range != "day") {
    echo "<a class='static'
            href='showsumstats.php3?showby=$showby&sortby=$sortby&range=day'>
            Day</a>, ";
}
else {
    echo "Day, ";
}
if ($range != "week") {
    echo "<a class='static'
            href='showsumstats.php3?showby=$showby&sortby=$sortby&range=week'>
            Week</a>, ";
}
else {
    echo "Week, ";
}
if ($range != "month") {
    echo "<a class='static'
            href='showsumstats.php3?showby=$showby&sortby=$sortby&range=month'>
            Month</a>, ";
}
else {
    echo "Month. ";
}
echo "</b><br><br>\n";


#
# This version prints out the simple summary info for the entire table.
# No ranges, just ordered. 
#
function showsummary ($showby, $sortby) {
    switch ($showby) {
        case "projects":
	    $which = "pid";
	    $table = "project_stats";
	    $title = "Project Summary Stats (Epoch)";
	    $link  = "showproject.php3?pid=";
	    break;
        case "users":
	    $which = "uid";
	    $table = "user_stats";
	    $title = "User Summary Stats (Epoch)";
	    $link  = "showuser.php3?target_uid=";
	    break;
        default:
	    USERERROR("Invalid showby argument: $showby!", 1);
    }
120
    $wclause = "";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
121 122
    switch ($sortby) {
        case "pid":
123 124
	    $order   = "pid";
	    $wclause = "where pid!='$TBOPSPID'";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
	    break;
        case "uid":
	    $order = "uid";
	    break;
        case "pnodes":
	    $order = "allexpt_pnodes desc";
	    break;
        case "pdays":
	    $order = "pnode_days desc";
	    break;
        case "edays":
	    $order = "expt_days desc";
	    break;
        default:
	    USERERROR("Invalid sortby argument: $sortby!", 1);
    }

    $query_result =
	DBQueryFatal("select $which, allexpt_pnodes, ".
		     "allexpt_pnode_duration / (24 * 3600) as pnode_days, ".
		     "allexpt_duration / (24 * 3600) as expt_days ".
		     "from $table where allexpt_pnodes!=0 ".
147
		     "$wclause ".
Leigh B. Stoller's avatar
Leigh B. Stoller committed
148 149
		     "order by $order");

150 151 152 153
    if (mysql_num_rows($query_result) == 0) {
	USERERROR("No summary stats of interest!", 1);
    }

154 155 156 157
    #
    # Gather some totals first.
    #
    $pnode_total  = 0;
158 159
    $pdays_total  = 0;
    $edays_total  = 0;
160 161
    while ($row = mysql_fetch_assoc($query_result)) {
	$pnodes  = $row["allexpt_pnodes"];
162 163
	$pdays   = $row["pnode_days"];
	$edays   = $row["expt_days"];
164 165
	
	$pnode_total  += $pnodes;
166 167
	$pdays_total  += $pdays;
	$edays_total  += $edays;
168 169 170 171 172 173 174 175 176 177
    }

    SUBPAGESTART();
    echo "<table>
           <tr><td colspan=2 nowrap align=center>
               <b>Totals</b></td>
           </tr>
           <tr><td nowrap align=right><b>Pnodes</b></td>
               <td align=left>$pnode_total</td>
           </tr>
178 179
           <tr><td nowrap align=right><b>Pnode Days</b></td>
               <td align=left>$pdays_total</td>
180
           </tr>
181 182
           <tr><td nowrap align=right><b>Expt Days</b></td>
               <td align=left>$edays_total</td>
183 184 185 186
           </tr>
          </table>\n";
    SUBMENUEND_2B();
    
Leigh B. Stoller's avatar
Leigh B. Stoller committed
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
    echo "<center><b>$title</b></center><br>\n";
    echo "<table align=center border=1>
          <tr>
             <th><a class='static'
                    href='showsumstats.php3?showby=$showby&sortby=$which'>
                    $which</th>
             <th><a class='static'
                    href='showsumstats.php3?showby=$showby&sortby=pnodes'>
                    Pnodes</th>
             <th><a class='static'
                    href='showsumstats.php3?showby=$showby&sortby=pdays'>
                    Pnode Days</th>
             <th><a class='static'
                    href='showsumstats.php3?showby=$showby&sortby=edays'>
                    Expt Days</th>
          </tr>\n";

204
    mysql_data_seek($query_result, 0);    
Leigh B. Stoller's avatar
Leigh B. Stoller committed
205 206 207 208 209 210 211 212 213 214 215 216 217 218
    while ($row = mysql_fetch_assoc($query_result)) {
	$heading = $row[$which];
	$pnodes  = $row["allexpt_pnodes"];
	$phours  = $row["pnode_days"];
	$ehours  = $row["expt_days"];

	echo "<tr>
                <td><A href='$link${heading}'>$heading</A></td>
                <td>$pnodes</td>
                <td>$phours</td>
                <td>$ehours</td>
              </tr>\n";
    }
    echo "</table>\n";
219
    SUBPAGEEND();
Leigh B. Stoller's avatar
Leigh B. Stoller committed
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
}

#
# COmparison functions for sort.
#
function intcmp ($a, $b) {
    if ($a == $b) return 0;
    return ($a > $b) ? -1 : 1;
}
function pnodecmp ($a, $b) {
    return intcmp($a["pnodes"], $b["pnodes"]);
}
function pdaycmp ($a, $b) {
    return intcmp($a["pseconds"], $b["pseconds"]);
}
function edaycmp ($a, $b) {
    return intcmp($a["eseconds"], $b["eseconds"]);
}

function showrange ($showby, $sortby, $range) {
240
    global $TBOPSPID, $TB_EXPTSTATE_ACTIVE;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
241
    $debug = 0;
242
    
Leigh B. Stoller's avatar
Leigh B. Stoller committed
243 244
    switch ($range) {
        case "day":
245
	    $span = 3600 * 24 * 1;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
246 247
	    break;
        case "week":
248
	    $span = 3600 * 24 * 7;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
249 250
	    break;
        case "month":
251
	    $span = 3600 * 24 * 31;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
252 253 254 255
	    break;
        default:
	    USERERROR("Invalid range argument: $range!", 1);
    }
256 257 258
    $wclause   = "($span)";
    $now       = time();
    $spanstart = $now - $span;
259 260 261 262 263 264 265

    # Summary info, indexed by pid and uid. Each entry is an array of the
    # summary info.
    $pid_summary = array();
    $uid_summary = array();

    #
266 267 268
    # First get current swapped in experiments. Instead of using reserved
    # table, use the experiment_stats record so we can more easily separate
    # pnodes from vnodes (although ignoring vnodes at the moment).
269 270
    #
    $query_result =
271
	DBQueryFatal("select e.pid,e.eid,e.expt_swap_uid as swapper, ".
272
		     "  UNIX_TIMESTAMP(now())-UNIX_TIMESTAMP(e.expt_swapped) ".
273 274 275 276 277 278
		     "   as swapseconds, r.pnodes,r.vnodes ".
		     " from experiments as e ".
		     "left join experiment_stats as s on s.exptidx=e.idx ".
		     "left join experiment_resources as r on s.rsrcidx=r.idx ".
		     "where e.state='" . $TB_EXPTSTATE_ACTIVE . "'" .
		     "  and e.pid!='$TBOPSPID' and ".
279
		     "      not (e.pid='ron' and e.eid='all') ");
280 281 282 283

    while ($row = mysql_fetch_assoc($query_result)) {
	$pid         = $row["pid"];
	$eid         = $row["eid"];
284
	$uid         = $row["swapper"];
285 286
	$swapseconds = $row["swapseconds"];
	$pnodes      = $row["pnodes"];
287
	$vnodes      = $row["vnodes"];
288

289 290
	if ($pnodes == 0)
	    continue;
291

292 293 294 295
	if ($debug)
	    echo "$pid $eid $uid $swapseconds $pnodes $vnodes<br>\n";

	if ($swapseconds > $span) {
296
	    $swapseconds = $span;
297 298 299
	    if ($debug)
		echo "Span to $swapseconds<br>\n";
	}
300

301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
	if (!isset($pid_summary[$pid])) {
	    $pid_summary[$pid] = array('pnodes'   => 0,
				       'pseconds' => 0,
				       'eseconds' => 0,
				       'current'  => 1);
	}
	if (!isset($uid_summary[$uid])) {
	    $uid_summary[$uid] = array('pnodes'   => 0,
				       'pseconds' => 0,
				       'eseconds' => 0,
				       'current'  => 1);
	}
	$pid_summary[$pid]["pnodes"]   += $pnodes;
	$pid_summary[$pid]["pseconds"] += $pnodes * $swapseconds;
	$pid_summary[$pid]["eseconds"] += $swapseconds;
	$uid_summary[$uid]["pnodes"]   += $pnodes;
	$uid_summary[$uid]["pseconds"] += $pnodes * $swapseconds;
	$uid_summary[$uid]["eseconds"] += $swapseconds;
319
    }
Leigh B. Stoller's avatar
Leigh B. Stoller committed
320 321

    $query_result =
322
	DBQueryFatal("select s.pid,s.eid,t.uid,t.action,t.exptidx, ".
323
		     "  r1.pnodes as pnodes1,r2.pnodes as pnodes2, ".
324
		     "  UNIX_TIMESTAMP(t.end_time) as ttstamp ".
325 326 327 328 329 330
		     " from testbed_stats as t ".
		     "left join experiment_stats as s on ".
		     "  s.exptidx=t.exptidx ".
		     "left join experiment_resources as r1 on ".
		     "  r1.idx=t.rsrcidx ".
		     "left join experiment_resources as r2 on ".
331
		     "  r2.idx=r1.lastidx and r1.lastidx is not null ".
Leigh B. Stoller's avatar
Leigh B. Stoller committed
332
		     "where t.exitcode = 0 && ".
333
		     "    ((UNIX_TIMESTAMP(now())-UNIX_TIMESTAMP(t.end_time))".
334
		     "     < $wclause) ".
335
		     "order by t.end_time");
Leigh B. Stoller's avatar
Leigh B. Stoller committed
336 337 338 339 340 341 342

    # Experiment start time, indexed by pid:eid.
    $expt_start = array();

    while ($row = mysql_fetch_assoc($query_result)) {
	$pid     = $row["pid"];
	$eid     = $row["eid"];
343
	$uid     = $row["uid"];
344
	$idx	 = $row["exptidx"];
Leigh B. Stoller's avatar
Leigh B. Stoller committed
345 346
	$tstamp  = $row["ttstamp"];
	$action  = $row["action"];
347 348
	$pnodes  = $row["pnodes1"];
	$pnodes2 = $row["pnodes2"];
Leigh B. Stoller's avatar
Leigh B. Stoller committed
349 350 351 352

	if ($pnodes == 0)
	    continue;

353 354 355 356 357 358 359 360 361 362 363 364
	#
	# If a swapmod, and there is no record, one of two things. Either
	# it was swapped in before the interval, or the experiment was
	# was swapped out, and the user did a swapmod on it. We need to
	# know that, since swapmod of a swapped out experiment does not
	# count! 
	# 
	if ($action == "swapmod" &&
	    ! isset($expt_start["$pid:$eid"])) {
	    $swapper_result =
		DBQueryFatal("select action from testbed_stats ".
			     "where exptidx=$idx and ".
365
			     "      UNIX_TIMESTAMP(end_time)<$tstamp ".
366
			     "order by end_time desc");
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381

	    while ($srow = mysql_fetch_assoc($swapper_result)) {
		$saction = $srow["action"];

		if ($saction != "swapmod")
		    break;
	    }
	    if (!$srow ||
		($saction == "swapout" || $saction == "preload"))
		continue;
	    
	    if ($debug)
		echo "M $pid $eid $idx $saction<br>\n";
	}

Leigh B. Stoller's avatar
Leigh B. Stoller committed
382 383 384
	if (!isset($pid_summary[$pid])) {
	    $pid_summary[$pid] = array('pnodes'   => 0,
				       'pseconds' => 0,
385 386
				       'eseconds' => 0,
				       'current'  => 0);
387 388
	}
	if (!isset($uid_summary[$uid])) {
Leigh B. Stoller's avatar
Leigh B. Stoller committed
389 390
	    $uid_summary[$uid] = array('pnodes'   => 0,
				       'pseconds' => 0,
391 392
				       'eseconds' => 0,
				       'current'  => 0);
Leigh B. Stoller's avatar
Leigh B. Stoller committed
393 394
	}

395
	if ($debug) 
396
	    echo "$idx $pid $eid $uid $tstamp $action $pnodes $pnodes2<br>\n";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
397 398 399 400 401 402 403 404 405 406 407 408

	switch ($action) {
        case "start":
        case "swapin":
	    $expt_start["$pid:$eid"] = array('pnodes' => $pnodes,
					     'uid'    => $uid,
					     'pid'    => $pid,
					     'stamp'  => $tstamp);
	    break;
        case "swapout":
        case "swapmod":
	    if (isset($expt_start["$pid:$eid"])) {
409
		# Use the original data, especially pnodes since if this
Leigh B. Stoller's avatar
Leigh B. Stoller committed
410
		# was a swapmod, the nodes are for the new config, not
411 412
		# the old config. Besides, we want to credit the original
		# swapper (in), not the current swapper/modder. 
Leigh B. Stoller's avatar
Leigh B. Stoller committed
413 414 415 416
		$uid    = $expt_start["$pid:$eid"]["uid"];
		$pnodes = $expt_start["$pid:$eid"]["pnodes"];
		$diff = $tstamp - $expt_start["$pid:$eid"]["stamp"];
	    }
417 418 419 420 421 422 423 424 425 426 427 428
	    else {
		#
                # The start was before the time span being looked at, so
                # no start/swapin event was returned. Add a record for it.
	        #
		$diff = $tstamp - $spanstart;
		if ($action == "swapmod") {
                    # A pain. We need the number of pnodes for the original
		    # version of the experiment, not the new version.
		    $pnodes = $pnodes2;
		}
	    }
429 430 431
	    if ($debug) 
		echo "S $pid $eid $uid $action $diff $pnodes $pnodes2<br>\n";
	    
432 433 434 435 436 437 438 439
	    $pid_summary[$pid]["pnodes"]   += $pnodes;
	    $pid_summary[$pid]["pseconds"] += $pnodes * $diff;
	    $pid_summary[$pid]["eseconds"] += $diff;
	    $uid_summary[$uid]["pnodes"]   += $pnodes;
	    $uid_summary[$uid]["pseconds"] += $pnodes * $diff;
	    $uid_summary[$uid]["eseconds"] += $diff;
	    unset($expt_start["$pid:$eid"]);
	    
Leigh B. Stoller's avatar
Leigh B. Stoller committed
440 441 442
	    # Basically, start the clock ticking again with the new
	    # number of pnodes.
	    if ($action == "swapmod") {
443 444 445 446
		# Yuck, we redefined uid/pnodes above, but we want to start the
		# new record for the current swapper/#pnodes.
		$expt_start["$pid:$eid"] = array('pnodes' => $row['pnodes1'],
						 'uid'    => $row['uid'],
Leigh B. Stoller's avatar
Leigh B. Stoller committed
447 448 449 450 451 452 453 454 455 456 457
						 'pid'    => $pid,
						 'stamp'  => $tstamp);
	    }
	    break;
	case "preload":
	case "destroy":
	    break;
        default:
	    TBERROR("Invalid action: $action!", 1);
	}
    }
458

Leigh B. Stoller's avatar
Leigh B. Stoller committed
459
    #
460
    # Anything still in the expt_start array is obviously still running,
461
    # but we caught those in the first query above, so we ignore them.
Leigh B. Stoller's avatar
Leigh B. Stoller committed
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497
    #
    
    switch ($showby) {
        case "projects":
	    $which = "pid";
	    $table = $pid_summary;
	    $title = "Project Summary Stats ($range)";
	    $link  = "showproject.php3?pid=";
	    break;
        case "users":
	    $which = "uid";
	    $table = $uid_summary;
	    $title = "User Summary Stats ($range)";
	    $link  = "showuser.php3?target_uid=";
	    break;
        default:
	    USERERROR("Invalid showby argument: $showby!", 1);
    }
    switch ($sortby) {
        case "pid":
        case "uid":
	    ksort($table);
	    break;
        case "pnodes":
	    uasort($table, "pnodecmp");
	    break;
        case "pdays":
	    uasort($table, "pdaycmp");
	    break;
        case "edays":
	    uasort($table, "edaycmp");
	    break;
        default:
	    USERERROR("Invalid sortby argument: $sortby!", 1);
    }

498 499 500 501
    #
    # Gather some totals first.
    #
    $pnode_total  = 0;
502 503
    $pdays_total  = 0;
    $edays_total  = 0;
504 505 506

    foreach ($table as $key => $value) {
	$pnodes  = $value["pnodes"];
507 508
	$pdays   = sprintf("%.2f", $value["pseconds"] / (3600 * 24));
	$edays   = sprintf("%.2f", $value["eseconds"] / (3600 * 24));
509

510 511 512
	if ($debug)
	    echo "$key $value[pseconds] $value[eseconds]<br>\n";
	
513
	$pnode_total  += $pnodes;
514 515
	$pdays_total  += $pdays;
	$edays_total  += $edays;
516 517 518 519 520 521 522 523 524 525
    }

    SUBPAGESTART();
    echo "<table>
           <tr><td colspan=2 nowrap align=center>
               <b>Totals</b></td>
           </tr>
           <tr><td nowrap align=right><b>Pnodes</b></td>
               <td align=left>$pnode_total</td>
           </tr>
526 527
           <tr><td nowrap align=right><b>Pnode Days</b></td>
               <td align=left>$pdays_total</td>
528
           </tr>
529 530
           <tr><td nowrap align=right><b>Expt Days</b></td>
               <td align=left>$edays_total</td>
531 532 533 534
           </tr>
          </table>\n";
    SUBMENUEND_2B();
    
535 536 537 538
    echo "<center>
               <b>$title</b><br>
               (includes current experiments (*))
          </center><br>\n";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557
    echo "<table align=center border=1>
          <tr>
             <th><a class='static'
                    href='showsumstats.php3?showby=$showby&sortby=$which&range=$range'>
                    $which</th>
             <th><a class='static'
                    href='showsumstats.php3?showby=$showby&sortby=pnodes&range=$range'>
                    Pnodes</th>
             <th><a class='static'
                    href='showsumstats.php3?showby=$showby&sortby=pdays&range=$range'>
                    Pnode Days</th>
             <th><a class='static'
                    href='showsumstats.php3?showby=$showby&sortby=edays&range=$range'>
                    Expt Days</th>
          </tr>\n";

    foreach ($table as $key => $value) {
	$heading = $key;
	$pnodes  = $value["pnodes"];
558
	$current = $value["current"];
559 560
	$pdays   = sprintf("%.2f", $value["pseconds"] / (3600 * 24));
	$edays   = sprintf("%.2f", $value["eseconds"] / (3600 * 24));
Leigh B. Stoller's avatar
Leigh B. Stoller committed
561 562 563 564 565 566

	# We caught a swapout, where the swapin was before the interval
	# being looked at.
	if (!$pnodes)
	    continue;

567 568 569 570 571
	if ($current)
	    $current = "*";
	else
	    $current = "";

Leigh B. Stoller's avatar
Leigh B. Stoller committed
572
	echo "<tr>
573
                <td><A href='$link${heading}'>$heading $current</A></td>
Leigh B. Stoller's avatar
Leigh B. Stoller committed
574
                <td>$pnodes</td>
575 576
                <td>$pdays</td>
                <td>$edays</td>
Leigh B. Stoller's avatar
Leigh B. Stoller committed
577 578 579
              </tr>\n";
    }
    echo "</table>\n";
580
    SUBPAGEEND();
Leigh B. Stoller's avatar
Leigh B. Stoller committed
581 582 583 584 585 586 587 588 589 590 591 592 593 594
}

if ($range == "epoch") {
    showsummary($showby, $sortby);
}
else {
    showrange($showby, $sortby, $range);
}

#
# Standard Testbed Footer
# 
PAGEFOOTER();
?>