Skip to content

Commit

Permalink
Merge pull request #82 from andig/master
Browse files Browse the repository at this point in the history
Fix missing console tool updates from pr #80
  • Loading branch information
andig committed Dec 24, 2013
2 parents 26e2600 + b1fd768 commit b6fbd9b
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 83 deletions.
21 changes: 18 additions & 3 deletions lib/Volkszaehler/Util/Console.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,13 @@ class Console {
/**
* @param array $options Associative short/long options array in getopt syntax
*/
public function __construct($argv, $parameters) {
public function __construct($parameters) {
$this->parameters = $parameters;

$this->options = getopt(join('', array_keys($parameters)), array_values($parameters));

$this->commands = array();
$argv = $GLOBALS['argv'];

for ($i=1; $i<count($argv); $i++) {
$arg = $argv[$i];
if (preg_match('#^[-/]+(.+)#', $arg, $m)) {
Expand Down Expand Up @@ -74,7 +75,7 @@ public function getCommand($command = null) {
* @param string $parameter short or long parameter name
* @return array options, FALSE if not set
*/
function getOption($parameter, $default = false) {
function getMultiOption($parameter, $default = array()) {
$candidates = array($parameter);

// add matching short/long options to candidates
Expand All @@ -91,6 +92,8 @@ function getOption($parameter, $default = false) {
foreach ($candidates as $candidate) {
if (isset($this->options[$candidate])) {
$optVal = $this->options[$candidate];
// use true to indicate option is set
if ($optVal == false) $optVal = true;
if (is_array($optVal))
$val = array_merge($val, $optVal);
else
Expand All @@ -101,6 +104,18 @@ function getOption($parameter, $default = false) {
return count($val) ? $val : $default;
}

/**
* Get short or long options value
* @param string $parameter short or long parameter name
* @return mixed option value, true if set
*/
function getSimpleOption($parameter, $default = null) {
// make sure default is passed as array
$default = is_array($default) ? $default : array($default);
$res = $this->getMultiOption($parameter, $default);
return $res[0];
}

/**
* Check if script is run from console
*/
Expand Down
168 changes: 88 additions & 80 deletions misc/tools/aggregate.php
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<?php
/**
* Data aggregation command line tool
* Frontend controller for Util\Aggregation
*
* To setup aggregation job run crontab -e
* 0 0 * * * /usr/bin/php cron.php
* 0 0 * * * /usr/bin/php aggregate.php -m delta -l hour -l day
*
* @author Andreas Goetz <cpuidle@gmx.de>
* @copyright Copyright (c) 2013, The volkszaehler.org project
Expand Down Expand Up @@ -33,10 +34,7 @@

require_once VZ_DIR . '/lib/bootstrap.php';

/**
* @author Andreas Goetz <cpuidle@gmx.de>
*/
class Cron {
class AggregationController {
/**
* @var \Doctrine\ORM\EntityManager Doctrine EntityManager
*/
Expand All @@ -46,101 +44,98 @@ class Cron {

public function __construct() {
$this->em = Volkszaehler\Router::createEntityManager(true); // get admin credentials
$this->aggregator = new Util\Aggregation($this->em->getConnection());
}

/**
* Aggregate channel
* (Re)create aggregation table
*/
public function aggregate($uuid, $levels, $mode, $period) {
// loop through all aggregation levels
foreach ($levels as $level) {
if (!Util\Aggregation::isValidAggregationLevel($level))
throw new \Exception('Unsupported aggregation level ' . $level);
public function cmdCreate() {
$conn = $this->em->getConnection();

$msg = "Performing '" . $mode . "' aggregation";
if ($uuid) $msg .= " for UUID " . $uuid;
echo($msg . " on '" . $level . "' level.\n");
$rows = $this->aggregator->aggregate($uuid, $level, $mode, $period);
echo("Updated $rows rows.\n");
}
echo("Recreating aggregation table.\n");
$conn->executeQuery('DROP TABLE IF EXISTS `aggregate`');
$conn->executeQuery(
'CREATE TABLE `aggregate` (' .
' `id` int(11) NOT NULL AUTO_INCREMENT,' .
' `channel_id` int(11) NOT NULL,' .
' `type` tinyint(1) NOT NULL,' .
' `timestamp` bigint(20) NOT NULL,' .
' `value` double NOT NULL,' .
' `count` int(11) NOT NULL,' .
' PRIMARY KEY (`id`),' .
' UNIQUE KEY `ts_uniq` (`channel_id`,`type`,`timestamp`)' .
')');
}

/**
* Optimize data and aggregate tables
*/
public function cmdOptimize() {
$conn = $this->em->getConnection();

echo("Optimizing aggregate table.\n");
$conn->executeQuery('OPTIMIZE TABLE aggregate');
echo("Optimizing data table (slow).\n");
$conn->executeQuery('OPTIMIZE TABLE data');
}

/**
* Clear aggregate table for channel
* @todo add levels support
*/
public function clear($uuid) {
$msg = "Clearing aggregation table";
if ($uuid) $msg .= " for UUID " . $uuid;
echo($msg . ".\n");
$this->aggregator->clear($uuid);
echo("Done clearing aggregation table.\n");
}
public function cmdClear($uuids) {
foreach ($uuids as $uuid) {
$msg = "Clearing aggregation table";
if ($uuid) $msg .= " for UUID " . $uuid;
echo($msg . ".\n");

public function run($command, $uuids, $levels, $mode, $period = null) {
$this->aggregator = new Util\Aggregation($this->em->getConnection());
$this->aggregator->clear($uuid);
echo("Done clearing aggregation table.\n");
}
}

if (!in_array($mode, array('full', 'delta')))
/**
* Aggregate selected channels and levels
*/
public function cmdAggregate($uuids, $levels, $mode, $period = null) {
if (!in_array($mode, array('full', 'delta'))) {
throw new \Exception('Unsupported aggregation mode ' . $mode);
}

$conn = $this->em->getConnection();
// loop through all uuids
foreach ($uuids as $uuid) {
// loop through all aggregation levels
foreach ($levels as $level) {
if (!Util\Aggregation::isValidAggregationLevel($level))
throw new \Exception('Unsupported aggregation level ' . $level);

if ($command == 'create') {
echo("Recreating aggregation table.\n");
$conn->executeQuery('DROP TABLE IF EXISTS `aggregate`');
$conn->executeQuery(
'CREATE TABLE `aggregate` (' .
' `id` int(11) NOT NULL AUTO_INCREMENT,' .
' `channel_id` int(11) NOT NULL,' .
' `type` tinyint(1) NOT NULL,' .
' `timestamp` bigint(20) NOT NULL,' .
' `value` double NOT NULL,' .
' `count` int(11) NOT NULL,' .
' PRIMARY KEY (`id`),' .
' UNIQUE KEY `ts_uniq` (`channel_id`,`type`,`timestamp`)' .
')');
}
elseif ($command == 'optimize') {
echo("Optimizing aggregate table.\n");
$conn->executeQuery('OPTIMIZE TABLE aggregate');
echo("Optimizing data table (slow).\n");
$conn->executeQuery('OPTIMIZE TABLE data');
}
elseif ($command == 'clear') {
// loop through all uuids
if (is_array($uuids)) {
foreach ($uuids as $uuid) {
$this->clear($uuid, $levels, $mode, $period);
}
}
else {
$this->clear(null, $levels, $mode, $period);
}
}
elseif ($command == 'aggregate' || $command == 'run') {
// loop through all uuids
if (is_array($uuids)) {
foreach ($uuids as $uuid) {
$this->aggregate($uuid, $levels, $mode, $period);
}
}
else {
$this->aggregate(null, $levels, $mode, $period);
$msg = "Performing '" . $mode . "' aggregation";
if ($uuid) $msg .= " for UUID " . $uuid;
echo($msg . " on '" . $level . "' level.\n");

$rows = $this->aggregator->aggregate($uuid, $level, $mode, $period);
echo("Updated $rows rows.\n");
}
}
else
throw new \Exception('Unknown command ' . $command);
}
}

$console = new Util\Console($argv, array('u:'=>'uuid:', 'm:'=>'mode:', 'l:'=>'level', 'p:'=>'period', 'h'=>'help'));

if ($console::isConsole()) {
$help = $console->getOption('h');
$uuid = $console->getOption('u');
$mode = $console->getOption('m', array('delta'));
$level = $console->getOption('l', array('day'));
$period = $console->getOption('p');
if (Util\Console::isConsole()) {
$console = new Util\Console(array(
'u:'=>'uuid:',
'm:'=>'mode:',
'l:'=>'level',
'p:'=>'period',
'h'=>'help'));

// make sure uuid array is populated
$uuid = $console->getMultiOption('u', array(null));
$level = $console->getMultiOption('l', array('day'));
$mode = $console->getSimpleOption('m', 'delta');
$period = $console->getSimpleOption('p');
$help = $console->getSimpleOption('h');

$commands = $console->getCommand();

Expand All @@ -161,10 +156,23 @@ public function run($command, $uuids, $levels, $mode, $period = null) {
echo("Create monthly and daily aggregation data since last run for specified UUID\n");
}

$cron = new Cron();
$job = new AggregationController();

foreach ($commands as $command) {
$cron->run($command, $uuid, $level, $mode[0], $period[0]);
switch ($command) {
case 'create':
$job->cmdCreate();
break;
case 'clear':
$job->cmdClear($uuid);
break;
case 'aggregate':
case 'run';
$job->cmdAggregate($uuid, $level, $mode, $period);
break;
default:
throw new \Exception('Invalid command \'' . $command . '\'.');
}
}
}
else
Expand Down

0 comments on commit b6fbd9b

Please sign in to comment.