- Timestamp:
- Oct 21, 2010, 2:45:13 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/ipp-20100823/tools/czartool/CzarDb.pm
r29124 r29515 11 11 our @ISA = qw(czartool::MySQLDb); # inherits from MySQLDb 12 12 13 # Override constructor 13 ########################################################################### 14 # 15 # Constructor (overrides superclass) 16 # 17 ########################################################################### 14 18 sub new { 15 19 my ($class) = @_; 16 20 17 # Call the constructor of the parent class , Person.18 my $self = $class->SUPER::new($_[1], $_[2], $_[3], $_[4], $_[5], $_[6]);21 # Call the constructor of the parent class 22 my $self = $class->SUPER::new($_[1], $_[2], $_[3], $_[4], $_[5], $_[6]); 19 23 20 24 bless $self, $class; … … 39 43 SQL 40 44 41 42 if (!$query->execute) { 43 44 return 0; 45 } 45 if (!$query->execute) {return 0;} 46 46 47 47 ${$labels} = $query->fetchall_arrayref(); … … 238 238 ########################################################################### 239 239 # 240 # Gets time series data and stores it to temp file 241 # 242 ########################################################################### 243 sub createTimeSeriesData { 244 my ($self, $label, $stage, $fromTime, $toTime, $minX, $maxX, $minY, $maxY, $timeDiff, $dataFile, $isLog) = @_; 245 246 ${$dataFile} = "/tmp/czarplot_gnuplot_".$label."_".$stage."_t.dat"; 247 248 open (GNUDAT, ">${$dataFile}") or print "* Problem opening gnuplot data file for plot for '$label' '$stage'\n"; 240 # Gets time min/max/diff for a given period 241 # 242 ########################################################################### 243 sub getTimeMinMaxDiff { 244 my ($self, $label, $stage, $fromTime, $toTime, $minX, $maxX, $timeDiff) = @_; 249 245 250 246 my $query = $self->{_db}->prepare(<<SQL); 251 247 SELECT 252 MIN(processed), GREATEST(MAX(pending), MAX(faults), max(processed)-min(processed)) AS maxY,253 LEAST(MIN(pending), MIN(faults), max(processed)-min(processed)) AS minY,254 248 DATE_FORMAT(MAX(timestamp),'$self->{_dateFormat}'), 255 249 DATE_FORMAT(MIN(timestamp),'$self->{_dateFormat}'), … … 262 256 if (!$query->execute) {return 0;} 263 257 264 my $minProcessed = undef; 265 my ($_maxY, $_minY, $_timeDiff); 266 ($minProcessed, $_maxY, $_minY, ${$maxX}, ${$minX}, $_timeDiff) = $query->fetchrow_array(); 267 268 if ($_maxY > ${$maxY}) {${$maxY} = $_maxY;} 269 if ($_minY < ${$minY}) {${$minY} = $_minY;} 258 my ($_timeDiff); 259 (${$maxX}, ${$minX}, $_timeDiff) = $query->fetchrow_array(); 260 270 261 if ($_timeDiff > ${$timeDiff}) {${$timeDiff} = $_timeDiff;} 271 262 263 return 1; 264 } 265 266 267 ########################################################################### 268 # 269 # Gets time series data and stores it to temp file 270 # 271 ########################################################################### 272 sub createTimeSeriesData { 273 my ($self, $label, $stage, $fromTime, $toTime, $minX, $maxX, $timeDiff, $dataFile, $isLog, $showCleanup, $firstDeriv) = @_; 274 275 my $query = $self->{_db}->prepare(<<SQL); 276 SELECT 277 MIN(processed) 278 FROM $stage 279 WHERE label LIKE '$label' 280 AND timestamp >= '$fromTime' AND timestamp <= '$toTime'; 281 SQL 282 283 if (!$query->execute) {return 0;} 284 my $minProcessed = scalar $query->fetchrow_array(); # TODO remove 272 285 if (!defined $minProcessed) {return 0;} 286 287 $self->getTimeMinMaxDiff($label, $stage, $fromTime, $toTime, $minX, $maxX, $timeDiff); 273 288 274 289 $query = $self->{_db}->prepare(<<SQL); 275 290 SELECT 276 DATE_FORMAT(timestamp, '$self->{_dateFormat}'), pending, faults, processed-$minProcessed291 timestamp, pending, faults, processed 277 292 FROM $stage 278 293 WHERE label LIKE '$label' … … 283 298 $query->execute; 284 299 285 # loop round results 300 ${$dataFile} = "/tmp/czarplot_gnuplot_".$label."_".$stage."_t.dat"; 301 open (GNUDAT, ">${$dataFile}") or print "* Problem opening gnuplot data file for plot for '$label' '$stage'\n"; 302 303 my $lastProcessed = -1; 304 my $lastPending = -1; 305 my $lastFaults = -1; 306 my $lastTimestamp = undef; 307 my $processed = 0; 308 my $runningProcessed = 0; 309 my $pending = 0; 310 my $faults = 0; 311 my $timestamp = undef; 286 312 while (my @row = $query->fetchrow_array()) { 287 my ($timestamp, $pending, $faults, $processed) = @row; 288 289 if ($isLog) { 290 291 $processed = log($processed + 1); 292 $pending = log($pending + 1); 293 $faults = log($faults + 1); 294 } 313 my ($thisTimestamp, $thisPending, $thisFaults, $thisProcessed) = @row; 314 315 if ($showCleanup ) { 316 317 $runningProcessed = $thisProcessed - $minProcessed; 318 } 319 elsif($lastProcessed != -1 && $thisProcessed > $lastProcessed) { 320 321 $runningProcessed = $runningProcessed + ($thisProcessed - $lastProcessed); 322 } 323 324 325 if ($firstDeriv) { 326 327 if (defined $lastTimestamp) { 328 329 my $timeDiff = $self->diffTimesInSecs($thisTimestamp, $lastTimestamp); 330 331 if ($thisProcessed > $lastProcessed){ 332 $processed = abs($thisProcessed - $lastProcessed)/$timeDiff; 333 #print "$processed = ($thisProcessed - $lastProcessed)/$timeDiff\n"; 334 } 335 else {$processed = 0;} 336 #$pending = abs($thisPending - $lastPending)/$timeDiff; 337 #$faults = abs($thisFaults - $lastFaults)/$timeDiff; 338 } 339 else { 340 $processed = 0; 341 $pending = 0; 342 $faults = 0; 343 } 344 } 345 elsif ($isLog) { 346 347 $processed = ($runningProcessed < 0) ? 0 : $runningProcessed; 348 $pending = ($thisPending < 0) ? 0 : $thisPending; 349 $faults = ($thisFaults < 0) ? 0 : $thisFaults; 350 351 $processed = log($runningProcessed + 1)/log(10); 352 $pending = log($thisPending + 1)/log(10); 353 $faults = log($faults + 1)/log(10); 354 } 355 else { 356 357 $processed = $runningProcessed; 358 $pending = $thisPending; 359 $faults = $thisFaults; 360 } 361 362 $timestamp = $self->getFormattedDate($thisTimestamp); 295 363 296 364 print GNUDAT "$timestamp $pending $faults $processed\n"; 365 366 $lastProcessed = $thisProcessed; 367 $lastPending = $thisPending; 368 $lastFaults = $thisFaults; 369 $lastTimestamp = $thisTimestamp; 297 370 } 298 371 … … 357 430 sub countProcessedPendingAndFaults { 358 431 my ($self, $label, $stage, $fromTime, $toTime, $processed, $pending, $faults) = @_; 359 360 432 361 433 my $query = $self->{_db}->prepare(<<SQL); … … 371 443 (${$pending}, ${$faults}) = $query->fetchrow_array(); 372 444 373 $query = $self->{_db}->prepare(<<SQL); 374 SELECT 375 MAX(processed) - MIN(processed) 376 FROM $stage 377 WHERE label LIKE '$label' 378 AND timestamp >= '$fromTime' AND timestamp <= '$toTime'; 379 SQL 380 $query->execute; 381 (${$processed}) = $query->fetchrow_array(); 445 ${$processed} = $self->countProcessed($label, $stage, $fromTime, $toTime); 446 447 return 1; 382 448 } 383 449 … … 502 568 print GNUDAT "$timestamp $available\n"; 503 569 } 570 504 571 close(GNUDAT); 505 572 506 573 return $dataFile; 507 574 } 508 ########################################################################### 509 # 510 # Determines how much has been processed in the provided interval of time 511 # (format: 1 HOUR, 1 MINUTE 1 DAY etc) 512 # 513 ########################################################################### 514 sub countProcessed { # TODO use time not interval 515 my ($self, $label, $stage, $interval) = @_; 575 576 ########################################################################### 577 # 578 # TODO implement isLog 579 # 580 ########################################################################### 581 sub createProcessingRateData { 582 my ($self, $stage, $label, $startDay, $endDay, $interval, $dataFile, $isLog) = @_; 583 584 my $startTime = $startDay; 585 my $endTime; 586 my $quit = 0; 587 my $processed; 588 my $pending; 589 my $faults; 590 my $timestamp; 591 ${$dataFile} = "/tmp/czarplot_gnuplot_".$label."_".$stage."_r.dat"; 592 open (GNUDAT, ">${$dataFile}") or print "* Problem opening gnuplot data file for plot for '$label' '$stage'\n"; 593 my $cleanupCarry = 0; 594 while(1) { 595 596 if (!$self->isBefore($startTime, $endDay)) {last;} 597 $endTime = $self->addInterval($startTime, $interval); 598 $self->countProcessedPendingAndFaults($label, $stage, $startTime, $endTime, \$processed, \$pending, \$faults); 599 $timestamp = $self->getFormattedDate($endTime); 600 print GNUDAT "$timestamp $processed 0 0\n"; 601 602 $startTime = $endTime; 603 } 604 605 close(GNUDAT) or print "* Problem closing gnuplot data file for rate plot for '$label' '$stage'\n" 606 } 607 608 ########################################################################### 609 # 610 # When did this stage finish? 611 # 612 ########################################################################### 613 sub getFinishTime { 614 my ($self, $label, $stage, $begin, $end) = @_; 516 615 517 616 my $query = $self->{_db}->prepare(<<SQL); 518 617 SELECT 519 MAX(processed) - MIN(processed)520 FROM $stage 618 timestamp, pending, faults 619 FROM $stage 521 620 WHERE label LIKE '$label' 522 AND timestamp > (now() - INTERVAL $interval); 523 SQL 524 $query->execute; 525 526 return scalar $query->fetchrow_array(); 527 } 528 621 AND timestamp >= '$begin' 622 AND timestamp <= '$end' 623 SQL 624 $query->execute; 625 626 my $array = $query->fetchall_arrayref(); 627 628 my $row; 629 my $thisPending = -1; 630 my $lastPending = -1; 631 my $thisFaults = -1; 632 my $lastFaults = -1; 633 my $timestamp; 634 my $started = undef; 635 my $finished = undef; 636 my $thisLeft = 0; 637 my $lastLeft = 0; 638 my $finishTimeout = "01:00:00"; 639 my $numRows = @{$array}; 640 print "$numRows rows\n"; 641 my $n = 0; 642 foreach $row ( @{$array} ){ 643 644 ($timestamp, $thisPending, $thisFaults) = @{$row}; 645 646 # print "$timestamp, $thisPending, $thisFaults\n"; 647 648 $thisLeft = $thisPending - $thisFaults; 649 $lastLeft = $lastPending - $lastFaults; 650 651 652 if ($n == 0 && $thisLeft > 0) { 653 654 print "Starting this time period with stuff pending ($thisLeft)\n"; 655 $started = $timestamp; 656 } 657 658 if (!defined $started && $lastLeft == 0 && $thisLeft > 0) { 659 660 $started = $timestamp; 661 print "STARTED at $started\n"; 662 } 663 664 if ($started && !defined $finished && $thisLeft == 0) { 665 666 $finished = $timestamp; 667 print "setting FINISHED to $finished\n"; 668 } 669 670 if (defined $finished) { 671 672 if ($thisLeft != 0) { 673 674 $finished = undef; 675 676 print "NEW pending at $timestamp\n"; 677 678 } 679 elsif ($thisLeft == 0) { 680 681 my $howLongFinished = $self->diffTimes($timestamp, $finished); 682 683 print "$howLongFinished = $timestamp, $finished\n"; 684 685 if ($self->isIntervalGreaterThan($howLongFinished, $finishTimeout)) { 686 687 print "0 pending for $howLongFinished. We're done \n"; 688 last; 689 } 690 691 } 692 693 } 694 695 696 $lastPending = $thisPending; 697 $lastFaults = $thisFaults; 698 $n++; 699 if ($n == $numRows) { 700 701 if ($thisLeft == 0) { 702 703 print "exceeded interval before reaching finished timeout\n"; 704 } 705 else { 706 print "Reached end of interval and not finished yet. $thisLeft left\n"; 707 } 708 } 709 } 710 711 if ($finished) { 712 713 my $timeTaken = $self->diffTimes($finished, $started); 714 print "FINISHED at $finished with $thisFaults remaining faults, time taken = $timeTaken\n"; 715 } 716 717 } 718 719 ########################################################################### 720 # 721 # Figures out if a stage has plateaued 722 # 723 ########################################################################### 724 sub hasPlateaued { 725 my ($self, $label, $stage, $end, $interval) = @_; 726 727 my $query = $self->{_db}->prepare(<<SQL); 728 SELECT 729 timestamp, pending, faults 730 FROM $stage 731 WHERE label LIKE '$label' 732 AND timestamp >= '$end - INTERVAL $interval' 733 AND timestamp <= '$end' 734 ORDER BY timestamp DESC; 735 SQL 736 $query->execute; 737 738 my $array = $query->fetchall_arrayref(); 739 740 my $thisPending = -1; 741 my $lastPending = -1; 742 my $thisFaults = -1; 743 my $lastFaults = -1; 744 my $timestamp; 745 my $thisLeft = 0; 746 my $lastLeft = 0; 747 my $row; 748 my $numRows = @{$array}; 749 my $n = 0; 750 foreach $row ( @{$array} ){ 751 752 ($timestamp, $thisPending, $thisFaults) = @{$row}; 753 754 $thisLeft = $thisPending - $thisFaults; 755 $lastLeft = $lastPending - $lastFaults; 756 757 print "$timestamp $thisPending\n"; 758 759 if ($n>0) { 760 761 #if () {} 762 763 } 764 765 $lastPending = $thisPending; 766 $lastFaults = $thisFaults; 767 $n++; 768 } 769 } 770 771 ########################################################################### 772 # 773 # Gets count of processed stuff in a given time period 774 # 775 ########################################################################### 776 sub countProcessed { 777 my ($self, $label, $stage, $begin, $end) = @_; 778 779 my $query = $self->{_db}->prepare(<<SQL); 780 SELECT 781 processed 782 FROM $stage 783 WHERE label LIKE '$label' 784 AND timestamp >= '$begin' 785 AND timestamp < '$end' 786 SQL 787 $query->execute; 788 789 my $processedArray = $query->fetchall_arrayref(); 790 791 my $processed; 792 my $thisCount = -1; 793 my $lastCount = -1; 794 my $count = 0; 795 foreach $processed ( @{$processedArray} ){ 796 797 ($thisCount) = @{$processed}; 798 799 if ($thisCount > $lastCount && $lastCount != -1) {$count = $count + ($thisCount - $lastCount);} 800 $lastCount = $thisCount; 801 } 802 803 return $count; 804 } 529 805 530 806 ########################################################################### … … 541 817 542 818 if (!$self->isBefore($thisDay, $endDay)) { 543 819 544 820 $quit = 1; 545 821 } … … 553 829 ########################################################################### 554 830 # 555 # Deletes all but one row per interval from all stage tables for all labels between the provided day 831 # Deletes all but one row per interval from all tables for the provided date range 832 # TODO this is very clumsy, I just have time to thinmk of something more elegant 556 833 # 557 834 ########################################################################### … … 566 843 my $totalDeleted = undef; 567 844 my $quit = 0; 845 my $query = undef; 568 846 while(!$quit) { 569 847 570 848 $toTime = $self->addInterval($fromTime, $interval); 571 849 if (!$self->isBefore($toTime, $endDay)) { 572 850 573 851 $toTime = $endDay; 574 852 $quit = 1; 575 853 } 576 854 577 855 my $stage = undef; 578 856 $totalDeleted = 0; … … 586 864 my ($label) = @{$row}; 587 865 588 my$query = $self->{_db}->prepare(<<SQL);866 $query = $self->{_db}->prepare(<<SQL); 589 867 SELECT COUNT(*) 590 868 FROM $stage … … 609 887 $totalDeleted += $toDelete; 610 888 } 611 } 889 890 } 891 892 # servers table 893 my $servers = undef; 894 if ($self->getServers(\$servers)) { 895 896 my $server = undef; 897 my $row = undef; 898 foreach $row ( @{$servers} ) { 899 my ($server) = @{$row}; 900 901 $query = $self->{_db}->prepare(<<SQL); 902 SELECT COUNT(*) 903 FROM servers 904 WHERE timestamp > '$fromTime' 905 AND timestamp <= '$toTime' 906 AND server = '$server' 907 SQL 908 $query->execute; 909 910 my $toDelete = scalar $query->fetchrow_array() - 1; 911 if ($toDelete > 0) { 912 913 $query = $self->{_db}->prepare(<<SQL); 914 DELETE FROM servers 915 WHERE timestamp > '$fromTime' 916 AND timestamp <= '$toTime' 917 AND server = '$server' ORDER BY timestamp DESC LIMIT $toDelete 918 SQL 919 $query->execute; 920 921 $totalDeleted += $toDelete; 922 } 923 } 924 } 925 926 # now deal with cluster_space table 927 $query = $self->{_db}->prepare(<<SQL); 928 SELECT COUNT(*) 929 FROM cluster_space 930 WHERE timestamp > '$fromTime' 931 AND timestamp <= '$toTime' 932 SQL 933 $query->execute; 934 935 my $toDelete = scalar $query->fetchrow_array() - 1; 936 if ($toDelete > 0) { 937 938 $query = $self->{_db}->prepare(<<SQL); 939 DELETE FROM cluster_space 940 WHERE timestamp > '$fromTime' 941 AND timestamp <= '$toTime' 942 ORDER BY timestamp DESC LIMIT $toDelete 943 SQL 944 $query->execute; 945 946 $totalDeleted += $toDelete; 947 } 948 612 949 print " * Deleted $totalDeleted between $fromTime and $toTime\n"; 613 950 $fromTime = $toTime; 614 951 } 952 } 953 954 ########################################################################### 955 # 956 # Optimizes all tables that need to be optimized 957 # 958 ########################################################################### 959 sub optimize { 960 my ($self) = @_; 961 962 my $stage = undef; 963 foreach $stage (@stages) { 964 965 $self->optimizeTable($stage); 966 } 967 968 $self->optimizeTable("cluster_space"); 969 $self->optimizeTable("servers"); 970 } 971 972 ########################################################################### 973 # 974 # Returns if a particular server has been down for a certain interval 975 # 976 ########################################################################### 977 sub isServerDown { 978 my ($self, $server, $interval) = @_; 979 980 my $query = $self->{_db}->prepare(<<SQL); 981 SELECT COUNT(*) 982 FROM servers 983 WHERE server = "$server" 984 AND timestamp > now() - INTERVAL $interval 985 SQL 986 987 $query->execute; 988 my $numOfReadings = scalar $query->fetchrow_array(); 989 990 if ($numOfReadings == 0) {return 0;} 991 992 $query = $self->{_db}->prepare(<<SQL); 993 SELECT COUNT(*) 994 FROM servers 995 WHERE server = "$server" 996 AND timestamp > now() - INTERVAL $interval 997 AND !running 998 SQL 999 1000 $query->execute; 1001 my $numNotRunning = scalar $query->fetchrow_array(); 1002 1003 if ($numOfReadings == $numNotRunning) {return 1;} 1004 1005 return 0; 1006 } 1007 1008 ########################################################################### 1009 # 1010 # Returns an array of servers 1011 # 1012 ########################################################################### 1013 sub getServers { 1014 my ($self, $servers) = @_; 1015 1016 my $query = $self->{_db}->prepare(<<SQL); 1017 SELECT DISTINCT server 1018 FROM servers 1019 SQL 1020 1021 if (!$query->execute) { 1022 1023 return 0; 1024 } 1025 1026 ${$servers} = $query->fetchall_arrayref(); 1027 1028 return 1; 615 1029 } 616 1030 … … 682 1096 INSERT INTO revision (revision) VALUES ($revision); 683 1097 SQL 684 $query->execute;1098 $query->execute; 685 1099 } 686 1100 … … 701 1115 SQL 702 1116 703 $query->execute;1117 $query->execute; 704 1118 my @row = $query->fetchrow_array(); 705 1119 … … 729 1143 foreach $stage (@stages) { 730 1144 731 my $query = $self->{_db}->prepare(<<SQL);1145 my $query = $self->{_db}->prepare(<<SQL); 732 1146 CREATE TABLE $stage ( 733 1147 timestamp TIMESTAMP DEFAULT NOW(), … … 758 1172 foreach $stage (@stages) { 759 1173 760 my $query = $self->{_db}->prepare(<<SQL);1174 my $query = $self->{_db}->prepare(<<SQL); 761 1175 ALTER TABLE $stage 762 1176 ADD COLUMN reverting TINYINT NOT NULL DEFAULT 0; … … 783 1197 foreach $stage (@stages) { 784 1198 785 my $query = $self->{_db}->prepare(<<SQL);1199 my $query = $self->{_db}->prepare(<<SQL); 786 1200 ALTER TABLE $stage 787 1201 ADD COLUMN processed BIGINT NOT NULL DEFAULT 0; 788 1202 SQL 789 1203 790 $query->execute;1204 $query->execute; 791 1205 } 792 1206 … … 808 1222 SQL 809 1223 810 $query->execute;1224 $query->execute; 811 1225 812 1226 $self->setRevision(4); … … 830 1244 SQL 831 1245 832 $query->execute;1246 $query->execute; 833 1247 834 1248 $self->setRevision(5); … … 854 1268 SQL 855 1269 856 $query->execute;857 } 858 859 my $query = $self->{_db}->prepare(<<SQL);860 CREATE INDEX serverIndex ON servers (timestamp, server);861 SQL 862 863 $query->execute;1270 $query->execute; 1271 } 1272 1273 my $query = $self->{_db}->prepare(<<SQL); 1274 CREATE INDEX serverIndex ON servers (timestamp, server); 1275 SQL 1276 1277 $query->execute; 864 1278 865 1279 … … 882 1296 SQL 883 1297 884 $query->execute;1298 $query->execute; 885 1299 886 1300 $self->setRevision(7); … … 906 1320 SQL 907 1321 908 $query->execute;1322 $query->execute; 909 1323 } 910 1324 … … 916 1330 SQL 917 1331 918 $query->execute;1332 $query->execute; 919 1333 920 1334 # insert stages into revert table … … 926 1340 ('$stage', 0); 927 1341 SQL 928 $query->execute;1342 $query->execute; 929 1343 } 930 1344 … … 951 1365 SQL 952 1366 953 $query->execute;1367 $query->execute; 954 1368 $query = $self->{_db}->prepare(<<SQL); 955 1369 CREATE TABLE hosts ( … … 960 1374 SQL 961 1375 962 $query->execute;963 964 $query = $self->{_db}->prepare(<<SQL);965 CREATE INDEX clusterSpaceIndex ON cluster_space (timestamp);966 SQL 967 968 $query->execute;1376 $query->execute; 1377 1378 $query = $self->{_db}->prepare(<<SQL); 1379 CREATE INDEX clusterSpaceIndex ON cluster_space (timestamp); 1380 SQL 1381 1382 $query->execute; 969 1383 970 1384 $self->setRevision(9); … … 984 1398 ALTER TABLE hosts 985 1399 ADD COLUMN writable TINYINT NOT NULL DEFAULT 0, 986 ADD COLUMN readable TINYINT NOT NULL DEFAULT 0;987 SQL 988 989 $query->execute;1400 ADD COLUMN readable TINYINT NOT NULL DEFAULT 0; 1401 SQL 1402 1403 $query->execute; 990 1404 991 1405 $self->setRevision(10); … … 1012 1426 SQL 1013 1427 1014 $query->execute;1015 $query = $self->{_db}->prepare(<<SQL);1016 CREATE INDEX burntoolIndex ON burntool (timestamp, label);1017 SQL 1018 1019 $query->execute;1428 $query->execute; 1429 $query = $self->{_db}->prepare(<<SQL); 1430 CREATE INDEX burntoolIndex ON burntool (timestamp, label); 1431 SQL 1432 1433 $query->execute; 1020 1434 1021 1435 $self->setRevision(11); … … 1039 1453 SQL 1040 1454 1041 $query->execute;1455 $query->execute; 1042 1456 1043 1457 $self->setRevision(12);
Note:
See TracChangeset
for help on using the changeset viewer.
