From 4ffb07fbf8dab26055c560c92c248521e3263833 Mon Sep 17 00:00:00 2001 From: andig Date: Sat, 3 Sep 2016 11:12:08 +0200 Subject: [PATCH 1/6] Implement php generators --- .travis.yml | 14 ++--- composer.json | 10 ++-- lib/Interpreter/AccumulatorInterpreter.php | 51 ++++++++-------- lib/Interpreter/DataIterator.php | 68 ++++++++-------------- lib/Interpreter/ImpulseInterpreter.php | 51 ++++++++-------- lib/Interpreter/Interpreter.php | 40 +++++-------- lib/Interpreter/SensorInterpreter.php | 53 ++++++++--------- 7 files changed, 120 insertions(+), 167 deletions(-) diff --git a/.travis.yml b/.travis.yml index 465c0d807..fdcdcd3c0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,6 @@ language: php php: - - 5.4 - - 5.5 - 5.6 - 7.0 - nightly @@ -29,21 +27,21 @@ env: matrix: include: # httpd-based - - php: 5.4 + - php: 5.6 env: DB=mysql TEST_COMPONENT=HTTPD # push-server - - php: 5.4 + - php: 5.6 env: DB=mysql TEST_COMPONENT=PUSH_SERVER # from..to - - php: 5.4 + - php: 5.6 env: DB=mysql DEPENDENCIES=lowest - - php: 5.4 + - php: 5.6 env: DB=mysql DEPENDENCIES=highest # jslint-only - - php: 5.4 + - php: 5.6 env: DB= DEPENDENCIES= JSLINT=true # security - - php: 5.4 + - php: 5.6 env: DB= DEPENDENCIES= SECURITY=true # remove hhvm/pgsql exclude: diff --git a/composer.json b/composer.json index db4da4f0c..c533210eb 100644 --- a/composer.json +++ b/composer.json @@ -11,13 +11,13 @@ "minimum-stability": "dev", "prefer-stable": true, "require": { - "php": ">=5.4.0", - "doctrine/orm": "^2.4", + "php": ">=5.6.0", + "doctrine/orm": "^2.5", "doctrine/dbal": "^2.5", "andig/dbcopy": "dev-master", - "symfony/console": "^2.6", - "symfony/http-kernel": "^2.6", - "symfony/http-foundation": "^2.6", + "symfony/console": "^2.6|^3.0", + "symfony/http-kernel": "^2.6|^3.0", + "symfony/http-foundation": "^2.6|^3.0", "symfony/routing": "^2.6|^3.0", "cboden/ratchet": "0.3.*", "react/socket": "0.4.*", diff --git a/lib/Interpreter/AccumulatorInterpreter.php b/lib/Interpreter/AccumulatorInterpreter.php index 51ec10c4f..110730794 100644 --- a/lib/Interpreter/AccumulatorInterpreter.php +++ b/lib/Interpreter/AccumulatorInterpreter.php @@ -39,13 +39,12 @@ class AccumulatorInterpreter extends Interpreter { protected $valsum; // sum of delta values /** - * Initialize data iterator + * Generate database tuples + * + * @return \Generator */ - public function rewind() { - $this->key = 0; + public function getIterator() { $this->rows = $this->getData(); - $this->rows->rewind(); - $this->valsum = 0; // get starting value from skipped first row @@ -53,31 +52,27 @@ public function rewind() { $this->ts_last = $this->getFrom(); $this->last_val = $this->rows->firstValue(); } - } - /** - * Iterate over result set - */ - public function current() { - $row = $this->rows->current(); - - // raw database values - if ($this->raw) { - return(array_slice($row, 0, 3)); + foreach ($this->rows as $row) { + if ($this->raw) { + // raw database values + yield array_slice($row, 0, 3); + } + else { + $tuple = $this->convertRawTuple($row); + $this->valsum += $this->delta_val; + + if (is_null($this->max) || $tuple[1] > $this->max[1]) { + $this->max = $tuple; + } + + if (is_null($this->min) || $tuple[1] < $this->min[1]) { + $this->min = $tuple; + } + + yield $tuple; + } } - - $tuple = $this->convertRawTuple($row); - $this->valsum += $this->delta_val; - - if (is_null($this->max) || $tuple[1] > $this->max[1]) { - $this->max = $tuple; - } - - if (is_null($this->min) || $tuple[1] < $this->min[1]) { - $this->min = $tuple; - } - - return $tuple; } /** diff --git a/lib/Interpreter/DataIterator.php b/lib/Interpreter/DataIterator.php index aa1736086..42c7afbb5 100644 --- a/lib/Interpreter/DataIterator.php +++ b/lib/Interpreter/DataIterator.php @@ -30,13 +30,9 @@ * @author Steffen Vogel * @package default */ -class DataIterator implements \Iterator, \Countable { +class DataIterator implements \IteratorAggregate, \Countable { protected $stmt; // PDO statement - protected $current; // the current data - protected $key; // key - protected $rowKey; // internal key for PDO statement - protected $rowCount; // num of readings in PDOStatement protected $tupleCount; // num of requested tuples protected $packageSize; // num of rows we aggregate in each tuple @@ -81,34 +77,34 @@ public function __construct(\PDOStatement $stmt, $rowCount, $tupleCount) { } /** - * Aggregate data - * @return next aggregated tuple + * @return \Generator */ - public function next() { - $firstTimestamp = $this->lastTimestamp; // SensorInterpreter + public function getIterator() { + $this->lastTimestamp = $this->from; - $package = array(0, 0, 0, 0, 0); - for ($i = 0; $i < $this->packageSize && $tuple = $this->stmt->fetch(); $i++) { - $package[0] = $tuple[0]; // last timestamp of package will be used - $package[1] += $tuple[1]; - $package[2] += $tuple[2]; + do { + $firstTimestamp = $this->lastTimestamp; // SensorInterpreter - // special cases - auxilary information for specific interpreters - $package[3] = max($package[3], $tuple[1]); // AccumulatorInterpreter - $package[4] += $tuple[1] * ($tuple[0] - $this->lastTimestamp); // SensorInterpreter + $package = array(0, 0, 0, 0, 0); + for ($i = 0; $i < $this->packageSize && $tuple = $this->stmt->fetch(); $i++) { + $package[0] = $tuple[0]; // use timestamp of last package tuple as package timestamp + $package[1] += $tuple[1]; // ImpulseInterpreter + $package[2] += $tuple[2]; // number of rows in package + $package[3] = max($package[3], $tuple[1]); // AccumulatorInterpreter + $package[4] += $tuple[1] * ($tuple[0] - $this->lastTimestamp); // SensorInterpreter - $this->lastTimestamp = $tuple[0]; - $this->rowKey++; - } + $this->lastTimestamp = $tuple[0]; + } - $this->key++; + if ($package[2]) { + $this->to = $package[0]; + $package[4] /= $this->lastTimestamp - $firstTimestamp; // weighed average for SensorInterpreter - if ($package[2]) { - $this->to = $package[0]; - $package[4] /= $this->lastTimestamp - $firstTimestamp; // weighed average for SensorInterpreter - } + yield $package; + } + } while ($tuple !== false); - $this->current = $package; + $this->stmt->closeCursor(); } /** @@ -116,31 +112,13 @@ public function next() { */ public function firstValue() { return $this->firstValue; } - /** - * Rewind the iterator - * - * @internal Should only be called once: PDOStatement hasn't a rewind() - */ - public function rewind() { - $this->key = $this->rowKey = 0; - $this->lastTimestamp = $this->from; - $this->next(); // fetch first tuple - } - - public function valid() { - return ($this->current[2] > 0); // current package contains at least 1 tuple - } - - /** + /* * Getter & setter */ - public function getPackageSize() { return $this->packageSize; } public function getFrom() { return $this->from; } public function getTo() { return $this->to; } public function count() { return $this->tupleCount; } - public function key() { return $this->key; } - public function current() { return $this->current; } } ?> diff --git a/lib/Interpreter/ImpulseInterpreter.php b/lib/Interpreter/ImpulseInterpreter.php index 225ef6cec..0280630ab 100644 --- a/lib/Interpreter/ImpulseInterpreter.php +++ b/lib/Interpreter/ImpulseInterpreter.php @@ -37,40 +37,35 @@ class ImpulseInterpreter extends Interpreter { protected $ts_last; // previous tuple timestamp /** - * Initialize data iterator + * Generate database tuples + * + * @return \Generator */ - public function rewind() { - $this->key = 0; + public function getIterator() { $this->rows = $this->getData(); - $this->rows->rewind(); - $this->pulseCount = 0; $this->ts_last = $this->getFrom(); - } - /** - * Iterate over result set - */ - public function current() { - $row = $this->rows->current(); - - // raw database values - if ($this->raw) { - return(array_slice($row, 0, 3)); + foreach ($this->rows as $row) { + if ($this->raw) { + // raw database values + yield array_slice($row, 0, 3); + } + else { + $tuple = $this->convertRawTuple($row); + $this->pulseCount += $row[1]; + + if (is_null($this->max) || $tuple[1] > $this->max[1]) { + $this->max = $tuple; + } + + if (is_null($this->min) || $tuple[1] < $this->min[1]) { + $this->min = $tuple; + } + + yield $tuple; + } } - - $tuple = $this->convertRawTuple($row); - $this->pulseCount += $row[1]; - - if (is_null($this->max) || $tuple[1] > $this->max[1]) { - $this->max = $tuple; - } - - if (is_null($this->min) || $tuple[1] < $this->min[1]) { - $this->min = $tuple; - } - - return $tuple; } /** diff --git a/lib/Interpreter/Interpreter.php b/lib/Interpreter/Interpreter.php index 4ed2a5200..ff98ad5f7 100644 --- a/lib/Interpreter/Interpreter.php +++ b/lib/Interpreter/Interpreter.php @@ -35,7 +35,7 @@ * @author Steffen Vogel * @author Andreas Götz */ -abstract class Interpreter implements \Iterator { +abstract class Interpreter implements \IteratorAggregate { /** * @var Database connection @@ -56,8 +56,6 @@ abstract class Interpreter implements \Iterator { protected $tupleCount; // number of requested tuples protected $rows; // DataIterator instance for aggregating rows - protected $key; // result interator index - protected $min = NULL; protected $max = NULL; @@ -110,32 +108,26 @@ public function __construct(Model\Channel $channel, ORM\EntityManager $em, $from } } - /** - * Convert raw meter readings. - * This function will have side effects on internal member variables of the interpreter. + /* + * IteratorAggregate functions */ - abstract public function convertRawTuple($row); /** - * Iterator functions + * Generate database tuples + * + * @todo with wide-spread availability of PHP7 consider moving the raw value iteration here: + * yield from ($this->raw) ? $this->getRawIterator() : $this->getDefaultIterator(); + * + * @return \Generator */ + abstract public function getIterator(); - abstract public function rewind(); - - abstract public function current(); - - public function next() { - $this->key++; - $this->rows->next(); - } - - public function valid() { - return $this->rows->valid(); - } - - public function key() { - return $this->key; - } + /** + * Convert raw meter readings + * + * This function will have side effects on internal member variables of the interpreter + */ + abstract public function convertRawTuple($row); /** * Check if option is specified diff --git a/lib/Interpreter/SensorInterpreter.php b/lib/Interpreter/SensorInterpreter.php index 6bdb176b6..ad3975a62 100644 --- a/lib/Interpreter/SensorInterpreter.php +++ b/lib/Interpreter/SensorInterpreter.php @@ -37,40 +37,35 @@ class SensorInterpreter extends Interpreter { protected $ts_last; // previous tuple timestamp /** - * Initialize data iterator + * Generate database tuples + * + * @return \Generator */ - public function rewind() { - $this->key = 0; + public function getIterator() { $this->rows = $this->getData(); - $this->rows->rewind(); - $this->ts_last = $this->getFrom(); - } - /** - * Iterate over result set - */ - public function current() { - $row = $this->rows->current(); - - // raw database values - if ($this->raw) { - return(array_slice($row, 0, 3)); + foreach ($this->rows as $row) { + if ($this->raw) { + // raw database values + yield array_slice($row, 0, 3); + } + else { + $delta_ts = $row[0] - $this->ts_last; + $tuple = $this->convertRawTuple($row); + $this->consumption += $tuple[1] * $delta_ts; + + if (is_null($this->max) || $tuple[1] > $this->max[1]) { + $this->max = $tuple; + } + + if (is_null($this->min) || $tuple[1] < $this->min[1]) { + $this->min = $tuple; + } + + yield $tuple; + } } - - $delta_ts = $row[0] - $this->ts_last; - $tuple = $this->convertRawTuple($row); - $this->consumption += $tuple[1] * $delta_ts; - - if (is_null($this->max) || $tuple[1] > $this->max[1]) { - $this->max = $tuple; - } - - if (is_null($this->min) || $tuple[1] < $this->min[1]) { - $this->min = $tuple; - } - - return $tuple; } /** From ca9360051ba4a412065484b3a5c08811eb11d6ae Mon Sep 17 00:00:00 2001 From: andig Date: Sat, 3 Sep 2016 15:03:13 +0200 Subject: [PATCH 2/6] Prevent groups adding/reading data --- lib/Controller/DataController.php | 4 + lib/Interpreter/AggregatorInterpreter.php | 94 ++--------------------- 2 files changed, 10 insertions(+), 88 deletions(-) diff --git a/lib/Controller/DataController.php b/lib/Controller/DataController.php index 11e08a7db..9258574ae 100644 --- a/lib/Controller/DataController.php +++ b/lib/Controller/DataController.php @@ -82,6 +82,10 @@ public function get($uuid) { public function add($uuid) { $channel = EntityController::factory($this->em, $uuid, true); + if (!$channel instanceof Model\Channel) { + throw new \Exception('Adding data is only supported for channels'); + } + try { /* to parse new submission protocol */ $rawPost = $this->request->getContent(); // file_get_contents('php://input') diff --git a/lib/Interpreter/AggregatorInterpreter.php b/lib/Interpreter/AggregatorInterpreter.php index ef03d341f..d82803b7a 100644 --- a/lib/Interpreter/AggregatorInterpreter.php +++ b/lib/Interpreter/AggregatorInterpreter.php @@ -30,20 +30,13 @@ /** * Interpreter to aggregate child Channels or Aggregators * - * The AggregatorInterpreter is used to aggregate multiple channels with the same - * indicator + * Placeholder only- aggregating child data is not implemented * * @author Steffen Vogel * @author Andreas Goetz * @package default */ class AggregatorInterpreter extends Interpreter { - /** - * @var array of Interpreter - */ - protected $childrenInterpreter = array(); - - protected $aggregator; /** * Constructor @@ -52,95 +45,20 @@ class AggregatorInterpreter extends Interpreter { * @param ORM\EntityManager $em * @param integer $from timestamp in ms since 1970 * @param integer $to timestamp in ms since 1970 - * @todo handle channels in nested aggregators - * @todo handle child entities of different units */ public function __construct(Model\Aggregator $aggregator, ORM\EntityManager $em, $from, $to, $tupleCount = null, $groupBy = null) { - $this->aggregator = $aggregator; - - foreach ($aggregator->getChildren() as $child) { - if ($child instanceof Model\Channel) { - $class = $child->getDefinition()->getInterpreter(); - $this->childrenInterpreter[] = new $class($child, $em, $from, $to, $tupleCount, $groupBy); - } - } - } - - /** - * Convert raw meter readings - */ - public function convertRawTuple($row) { - return null; - } - - /* - * Iterator methods - not implemented - */ - public function rewind() { - } - - public function current() { - } - - public function valid() { - return false; + throw new \Exception('Getting data is not supported for groups'); } /** - * Get total consumption of all channels - not implemented + * Generate database tuples */ - public function getConsumption() { + public function getIterator() { } /** - * Just a passthrough to the channel interpreters - * - * @return array with the smallest value - */ - public function getMin() { - $min = null; - foreach ($this->childrenInterpreter as $interpreter) { - $arr = $interpreter->getMax(); - if (! $min or $arr[1] < $min[1]) { - $min = $arr; - } - } - return $min; - } - - /** - * Just a passthrough to the channel interpreters - * - * @return array with the biggest value - */ - public function getMax() { - $max = null; - foreach ($this->childrenInterpreter as $interpreter) { - $arr = $interpreter->getMax(); - if (! $max or $arr[1] > $max[1]) { - $max = $arr; - } - } - return $max; - } - - /** - * Just a passthrough to the channel interpreters - * - * @return float average value + * Convert raw meter readings */ - public function getAverage() { - $sum = 0; - foreach ($this->childrenInterpreter as $interpreter) { - $sum += $interpreter->getAverage(); - } - return (count($this->childrenInterpreter)) ? $sum / count($this->childrenInterpreter) : null; + public function convertRawTuple($row) { } - - /* - * Getter & setter - */ - - public function getEntity() { return $this->aggregator; } - public function getChildrenInterpreter() { return $this->childrenInterpreter; } } From 96fc099d20383794beabff164053356af770600b Mon Sep 17 00:00:00 2001 From: andig Date: Sat, 3 Sep 2016 15:03:58 +0200 Subject: [PATCH 3/6] Better group tests and simplified json error handling --- lib/View/JSON.php | 54 +++++++++++++++++++++++++--------------------- test/GroupTest.php | 32 +++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 24 deletions(-) diff --git a/lib/View/JSON.php b/lib/View/JSON.php index 69557c9ac..142a683c4 100644 --- a/lib/View/JSON.php +++ b/lib/View/JSON.php @@ -54,8 +54,8 @@ class JSON extends View { */ public function __construct(Request $request) { parent::__construct($request); + $this->prepareResponse(); - $this->json = array('version' => VZ_VERSION); // use StreamedResponse unless pretty-printing is required if (Util\Debug::isActivated()) { $this->add(Util\Debug::getInstance()); @@ -69,13 +69,32 @@ public function __construct(Request $request) { $this->response->headers->set('Access-Control-Allow-Origin', '*'); } + /** + * Prepare json response structure and clean intermediate streaming buffer + */ + public function prepareResponse() { + if (isset($json['debug'])) { + $this->json = array('version' => VZ_VERSION, 'debug' => $this->json['debug']); + + } + else + $this->json = array('version' => VZ_VERSION); + $this->content = ''; + } + /** * Render response and send it to the client */ public function send() { if ($this->response instanceof StreamedResponse) { $this->response->setCallback(function() { - $this->renderDeferred(); + // callback happens outside Router->handle() and requires explicit exception handling + try { + $this->renderDeferred(); + } + catch (\Exception $e) { + $this->renderStreamedException($e); + } flush(); }); } @@ -105,9 +124,6 @@ protected function render() { * For StreamedResponse the renderDeferred happens outside Router->handle() and therefore * without surrounding try/catch. To enable exception handling via json responses, all output * must be collected until Exception occured and is handled by View. - * - * Since most likely source of exceptions and source of mass-data is Interpreter->processData(), - * this case is implemented in renderInterpreter() below. */ protected function renderDeferred() { $this->content .= '{'; @@ -161,16 +177,15 @@ private function renderContent() { * Render exception for StreamedResponse */ private function renderStreamedException(\Exception $exception) { - // cleanup result structure - $this->json = array('version' => VZ_VERSION); - $this->content = ''; + $this->prepareResponse(); // add exception to output $this->getExceptionResponse($exception); // render $this->response->sendHeaders(); - $this->renderDeferred(); + $this->content = json_encode($this->json); + $this->renderContent(); } /** @@ -181,22 +196,13 @@ private function renderStreamedException(\Exception $exception) { protected function renderInterpreter(Interpreter\Interpreter $interpreter) { $this->content .= '{"tuples":['; - try { - // start with iterating through PDO result set to populate interpreter header data - foreach ($interpreter as $key => $tuple) { - // render buffered content- likely no exception after loop iteration has started - $this->renderContent(); + // start with iterating through PDO result set to populate interpreter header data + foreach ($interpreter as $key => $tuple) { + // render buffered content- likely no exception after loop iteration has started + $this->renderContent(); - if ($key) echo(','); - echo('[' . $tuple[0] . ',' . View::formatNumber($tuple[1]) . ',' . $tuple[2] . ']'); - } - } - catch (\Exception $e) { - if ($this->response instanceof StreamedResponse) { - $this->renderStreamedException($e); - die; - } - throw ($e); + if ($key) echo(','); + echo('[' . $tuple[0] . ',' . View::formatNumber($tuple[1]) . ',' . $tuple[2] . ']'); } // render buffered content if not rendered inside foreach loop due to Interpreter empty diff --git a/test/GroupTest.php b/test/GroupTest.php index bdb012c03..46a397d22 100644 --- a/test/GroupTest.php +++ b/test/GroupTest.php @@ -26,6 +26,9 @@ function testCreateGroup() { ))->entity->uuid; } + /** + * @depends testCreateGroup + */ function testEditGroup() { // edit group $val = 'NewValue'; @@ -35,6 +38,9 @@ function testEditGroup() { ))->entity->title); } + /** + * @depends testCreateGroup + */ function testAddChildren() { // create child $child = $this->getJson('/group.json', array( @@ -67,6 +73,32 @@ function testAddChildren() { $this->assertObjectNotHasAttribute('children', $this->getJson('/group/' . self::$uuid . '.json')->entity); } + /** + * @depends testCreateGroup + */ + function testAddDataToGroup() { + // $this->addTuple($this->ts1, $this->value1); + $this->json = $this->getJson('/data/' . self::$uuid . '.json', array( + 'operation' => 'add', + 'value' => 1 + ), 'GET', true); + + $this->assertTrue(isset($this->json->exception)); + } + + /** + * @depends testCreateGroup + */ + function testGetDataFromGroup() { + // $this->getTuples($this->ts1-1, $this->ts2); + $this->json = $this->getJson('/data/' . self::$uuid . '.json', array(), 'GET', true); + + $this->assertTrue(isset($this->json->exception)); + } + + /** + * @depends testCreateGroup + */ function testDeleteGroup() { // delete group $this->getJson('/group/' . self::$uuid . '.json', array( From d96105a27deeac42de46fac97eee12dca53c1bf9 Mon Sep 17 00:00:00 2001 From: andig Date: Sat, 17 Sep 2016 16:22:26 +0200 Subject: [PATCH 4/6] Fix exception handling --- lib/View/JSON.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/View/JSON.php b/lib/View/JSON.php index 142a683c4..7e75048e0 100644 --- a/lib/View/JSON.php +++ b/lib/View/JSON.php @@ -73,12 +73,12 @@ public function __construct(Request $request) { * Prepare json response structure and clean intermediate streaming buffer */ public function prepareResponse() { - if (isset($json['debug'])) { + if (isset($this->json['debug'])) { $this->json = array('version' => VZ_VERSION, 'debug' => $this->json['debug']); - } - else - $this->json = array('version' => VZ_VERSION); + else { + $this->json = array('version' => VZ_VERSION); + } $this->content = ''; } From eed7eb3b54e639e52410f22587476d23ee30da8c Mon Sep 17 00:00:00 2001 From: andig Date: Sat, 17 Sep 2016 16:22:48 +0200 Subject: [PATCH 5/6] Migrate to apcu --- .travis.yml | 4 ++-- lib/Router.php | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index fdcdcd3c0..931a21197 100644 --- a/.travis.yml +++ b/.travis.yml @@ -83,8 +83,8 @@ install: - | if [ "$APC" = true ]; then phpenv config-add ./test/bin/apc.ini - if php -r 'exit(version_compare(PHP_VERSION, "5.5", ">=")?0:1);'; then echo "no" | pecl install apcu-beta; fi - if php -r 'exit(function_exists("apc_store")?0:1);'; then echo "APC enabled"; else echo "APC disabled"; fi + if php -r 'exit(version_compare(PHP_VERSION, "5.5", ">=")?0:1);'; then echo "no" | pecl install apcu; fi + if php -r 'exit(function_exists("apcu_store")?0:1);'; then echo "APCu enabled"; else echo "APCu disabled"; fi fi before_script: diff --git a/lib/Router.php b/lib/Router.php index 0ac3b8cb7..d59b45f6e 100644 --- a/lib/Router.php +++ b/lib/Router.php @@ -235,16 +235,16 @@ public static function createEntityManager($admin = FALSE) { if (Util\Configuration::read('devmode') == FALSE) { $cache = null; - if (extension_loaded('apc')) - $cache = new Cache\ApcCache; + if (extension_loaded('apcu')) + $cache = new Cache\ApcuCache; if ($cache) { $config->setMetadataCacheImpl($cache); $config->setQueryCacheImpl($cache); } } - else if (extension_loaded('apc')) { + else if (extension_loaded('apcu')) { // clear cache - apc_clear_cache('user'); + apcu_clear_cache('user'); } $driverImpl = $config->newDefaultAnnotationDriver(VZ_DIR . '/lib/Model'); From 89c2531d0d56163e3e1de0c0b2036606406aa631 Mon Sep 17 00:00:00 2001 From: andig Date: Sat, 17 Sep 2016 16:31:42 +0200 Subject: [PATCH 6/6] Ignore httpd build failure --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 931a21197..8f501783c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -52,6 +52,8 @@ matrix: allow_failures: - php: nightly - php: hhvm + - php: 5.6 + env: DB=mysql TEST_COMPONENT=HTTPD notifications: mail: "volkszaehler-dev@lists.volkszaehler.org"