680 lines
26 KiB
PHP
680 lines
26 KiB
PHP
<?php
|
|
/*
|
|
* Copyright (C) 2023 Xibo Signage Ltd
|
|
*
|
|
* Xibo - Digital Signage - https://xibosignage.com
|
|
*
|
|
* This file is part of Xibo.
|
|
*
|
|
* Xibo is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* any later version.
|
|
*
|
|
* Xibo is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with Xibo. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
namespace Xibo\XTR;
|
|
|
|
use Carbon\Carbon;
|
|
use Xibo\Entity\Task;
|
|
use Xibo\Factory\DisplayFactory;
|
|
use Xibo\Factory\LayoutFactory;
|
|
use Xibo\Factory\TaskFactory;
|
|
use Xibo\Support\Exception\NotFoundException;
|
|
|
|
/**
|
|
* Class StatsMigrationTask
|
|
* @package Xibo\XTR
|
|
*/
|
|
class StatsMigrationTask implements TaskInterface
|
|
{
|
|
use TaskTrait;
|
|
|
|
/** @var TaskFactory */
|
|
private $taskFactory;
|
|
|
|
/** @var DisplayFactory */
|
|
private $displayFactory;
|
|
|
|
/** @var LayoutFactory */
|
|
private $layoutFactory;
|
|
|
|
/** @var bool Does the Archive Table exist? */
|
|
private $archiveExist;
|
|
|
|
/** @var array Cache of displayIds found */
|
|
private $displays = [];
|
|
|
|
/** @var array Cache of displayIds not found */
|
|
private $displaysNotFound = [];
|
|
|
|
/** @var Task The Stats Archive Task */
|
|
private $archiveTask;
|
|
|
|
/** @inheritdoc */
|
|
public function setFactories($container)
|
|
{
|
|
$this->taskFactory = $container->get('taskFactory');
|
|
$this->layoutFactory = $container->get('layoutFactory');
|
|
$this->displayFactory = $container->get('displayFactory');
|
|
return $this;
|
|
}
|
|
|
|
/** @inheritdoc */
|
|
public function run()
|
|
{
|
|
$this->migrateStats();
|
|
}
|
|
|
|
/**
|
|
* Migrate Stats
|
|
* @throws \Xibo\Support\Exception\NotFoundException
|
|
*/
|
|
public function migrateStats()
|
|
{
|
|
// Config options
|
|
$options = [
|
|
'killSwitch' => (int)$this->getOption('killSwitch', 0),
|
|
'numberOfRecords' => (int)$this->getOption('numberOfRecords', 10000),
|
|
'numberOfLoops' => (int)$this->getOption('numberOfLoops', 1000),
|
|
'pauseBetweenLoops' => (int)$this->getOption('pauseBetweenLoops', 10),
|
|
'optimiseOnComplete' => (int)$this->getOption('optimiseOnComplete', 1),
|
|
];
|
|
|
|
// read configOverride
|
|
$configOverrideFile = $this->getOption('configOverride', '');
|
|
if (!empty($configOverrideFile) && file_exists($configOverrideFile)) {
|
|
$options = array_merge($options, json_decode(file_get_contents($configOverrideFile), true));
|
|
}
|
|
|
|
if ($options['killSwitch'] == 0) {
|
|
// Stat Archive Task
|
|
$this->archiveTask = $this->taskFactory->getByClass('\Xibo\XTR\\StatsArchiveTask');
|
|
|
|
// Check stat_archive table exists
|
|
$this->archiveExist = $this->store->exists('SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = :name', [
|
|
'name' => 'stat_archive'
|
|
]);
|
|
|
|
// Get timestore engine
|
|
$timeSeriesStore = $this->timeSeriesStore->getEngine();
|
|
|
|
if ($timeSeriesStore == 'mongodb') {
|
|
// If no records in both the stat and stat_archive then disable the task
|
|
$statSql = $this->store->getConnection()->prepare('SELECT statId FROM stat LIMIT 1');
|
|
$statSql->execute();
|
|
|
|
$statArchiveSqlCount = 0;
|
|
if ($this->archiveExist) {
|
|
/** @noinspection SqlResolve */
|
|
$statArchiveSql = $this->store->getConnection()->prepare('SELECT statId FROM stat_archive LIMIT 1');
|
|
$statArchiveSql->execute();
|
|
$statArchiveSqlCount = $statArchiveSql->rowCount();
|
|
}
|
|
|
|
if (($statSql->rowCount() == 0) && ($statArchiveSqlCount == 0)) {
|
|
$this->runMessage = '## Stat migration to Mongo' . PHP_EOL ;
|
|
$this->appendRunMessage('- Both stat_archive and stat is empty. '. PHP_EOL);
|
|
|
|
// Disable the task and Enable the StatsArchiver task
|
|
$this->log->debug('Stats migration task is disabled as stat_archive and stat is empty');
|
|
$this->disableTask();
|
|
|
|
if ($this->archiveTask->isActive == 0) {
|
|
$this->archiveTask->isActive = 1;
|
|
$this->archiveTask->save();
|
|
$this->store->commitIfNecessary();
|
|
|
|
$this->appendRunMessage('Enabling Stats Archive Task.');
|
|
$this->log->debug('Enabling Stats Archive Task.');
|
|
}
|
|
} else {
|
|
// if any of the two tables contain any records
|
|
$this->quitMigrationTaskOrDisableStatArchiveTask();
|
|
}
|
|
|
|
$this->moveStatsToMongoDb($options);
|
|
}
|
|
|
|
// If when the task runs it finds that MongoDB is disabled,
|
|
// and there isn't a stat_archive table, then it should disable itself and not run again
|
|
// (work is considered to be done at that point).
|
|
else {
|
|
if ($this->archiveExist) {
|
|
$this->runMessage = '## Moving from stat_archive to stat (MySQL)' . PHP_EOL;
|
|
|
|
$this->quitMigrationTaskOrDisableStatArchiveTask();
|
|
|
|
// Start migration
|
|
$this->moveStatsFromStatArchiveToStatMysql($options);
|
|
} else {
|
|
// Disable the task
|
|
|
|
$this->runMessage = '## Moving from stat_archive to stat (MySQL)' . PHP_EOL ;
|
|
$this->appendRunMessage('- Table stat_archive does not exist.' . PHP_EOL);
|
|
|
|
$this->log->debug('Table stat_archive does not exist.');
|
|
$this->disableTask();
|
|
|
|
// Enable the StatsArchiver task
|
|
if ($this->archiveTask->isActive == 0) {
|
|
$this->archiveTask->isActive = 1;
|
|
$this->archiveTask->save();
|
|
$this->store->commitIfNecessary();
|
|
|
|
$this->appendRunMessage('Enabling Stats Archive Task.');
|
|
$this->log->debug('Enabling Stats Archive Task.');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public function moveStatsFromStatArchiveToStatMysql($options)
|
|
{
|
|
|
|
$fileName = $this->config->getSetting('LIBRARY_LOCATION') . '.watermark_stat_archive_mysql.txt';
|
|
|
|
// Get low watermark from file
|
|
$watermark = $this->getWatermarkFromFile($fileName, 'stat_archive');
|
|
|
|
$numberOfLoops = 0;
|
|
|
|
while ($watermark > 0) {
|
|
$count = 0;
|
|
/** @noinspection SqlResolve */
|
|
$stats = $this->store->getConnection()->prepare('
|
|
SELECT statId, type, statDate, scheduleId, displayId, layoutId, mediaId, widgetId, start, `end`, tag
|
|
FROM stat_archive
|
|
WHERE statId < :watermark
|
|
ORDER BY statId DESC LIMIT :limit
|
|
');
|
|
$stats->bindParam(':watermark', $watermark, \PDO::PARAM_INT);
|
|
$stats->bindParam(':limit', $options['numberOfRecords'], \PDO::PARAM_INT);
|
|
|
|
// Run the select
|
|
$stats->execute();
|
|
|
|
// Keep count how many stats we've inserted
|
|
$recordCount = $stats->rowCount();
|
|
$count+= $recordCount;
|
|
|
|
// End of records
|
|
if ($this->checkEndOfRecords($recordCount, $fileName) === true) {
|
|
$this->appendRunMessage(PHP_EOL. '# End of records.' . PHP_EOL. '- Dropping stat_archive.');
|
|
$this->log->debug('End of records in stat_archive (migration to MYSQL). Dropping table.');
|
|
|
|
// Drop the stat_archive table
|
|
/** @noinspection SqlResolve */
|
|
$this->store->update('DROP TABLE `stat_archive`;', []);
|
|
|
|
$this->appendRunMessage(__('Done.'. PHP_EOL));
|
|
|
|
// Disable the task
|
|
$this->disableTask();
|
|
|
|
// Enable the StatsArchiver task
|
|
if ($this->archiveTask->isActive == 0) {
|
|
$this->archiveTask->isActive = 1;
|
|
$this->archiveTask->save();
|
|
$this->store->commitIfNecessary();
|
|
|
|
$this->appendRunMessage('Enabling Stats Archive Task.');
|
|
$this->log->debug('Enabling Stats Archive Task.');
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
// Loops limit end - task will need to rerun again to start from the saved watermark
|
|
if ($this->checkLoopLimits($numberOfLoops, $options['numberOfLoops'], $fileName, $watermark) === true) {
|
|
break;
|
|
}
|
|
$numberOfLoops++;
|
|
|
|
$temp = [];
|
|
|
|
$statIgnoredCount = 0;
|
|
foreach ($stats->fetchAll() as $stat) {
|
|
$watermark = $stat['statId'];
|
|
|
|
$columns = 'type, statDate, scheduleId, displayId, campaignId, layoutId, mediaId, widgetId, `start`, `end`, tag, duration, `count`';
|
|
$values = ':type, :statDate, :scheduleId, :displayId, :campaignId, :layoutId, :mediaId, :widgetId, :start, :end, :tag, :duration, :count';
|
|
|
|
// Get campaignId
|
|
if (($stat['type'] != 'event') && ($stat['layoutId'] != null)) {
|
|
try {
|
|
// Search the campaignId in the temp array first to reduce query in layouthistory
|
|
if (array_key_exists($stat['layoutId'], $temp)) {
|
|
$campaignId = $temp[$stat['layoutId']];
|
|
} else {
|
|
$campaignId = $this->layoutFactory->getCampaignIdFromLayoutHistory($stat['layoutId']);
|
|
$temp[$stat['layoutId']] = $campaignId;
|
|
}
|
|
} catch (NotFoundException $error) {
|
|
$statIgnoredCount+= 1;
|
|
$count = $count - 1;
|
|
continue;
|
|
}
|
|
} else {
|
|
$campaignId = 0;
|
|
}
|
|
|
|
$params = [
|
|
'type' => $stat['type'],
|
|
'statDate' => Carbon::createFromTimestamp($stat['statDate'])->format('U'),
|
|
'scheduleId' => (int) $stat['scheduleId'],
|
|
'displayId' => (int) $stat['displayId'],
|
|
'campaignId' => $campaignId,
|
|
'layoutId' => (int) $stat['layoutId'],
|
|
'mediaId' => (int) $stat['mediaId'],
|
|
'widgetId' => (int) $stat['widgetId'],
|
|
'start' => Carbon::createFromTimestamp($stat['start'])->format('U'),
|
|
'end' => Carbon::createFromTimestamp($stat['end'])->format('U'),
|
|
'tag' => $stat['tag'],
|
|
'duration' => isset($stat['duration']) ? (int) $stat['duration'] : Carbon::createFromTimestamp($stat['end'])->format('U') - Carbon::createFromTimestamp($stat['start'])->format('U'),
|
|
'count' => isset($stat['count']) ? (int) $stat['count'] : 1,
|
|
];
|
|
|
|
// Do the insert
|
|
$this->store->insert('INSERT INTO `stat` (' . $columns . ') VALUES (' . $values . ')', $params);
|
|
$this->store->commitIfNecessary();
|
|
}
|
|
|
|
if ($statIgnoredCount > 0) {
|
|
$this->appendRunMessage($statIgnoredCount. ' stat(s) were ignored while migrating');
|
|
}
|
|
|
|
// Give SQL time to recover
|
|
if ($watermark > 0) {
|
|
$this->appendRunMessage('- '. $count. ' rows migrated.');
|
|
|
|
$this->log->debug('MYSQL stats migration from stat_archive to stat. '.$count.' rows effected, sleeping.');
|
|
sleep($options['pauseBetweenLoops']);
|
|
}
|
|
}
|
|
}
|
|
|
|
public function moveStatsToMongoDb($options)
|
|
{
|
|
|
|
// Migration from stat table to Mongo
|
|
$this->migrationStatToMongo($options);
|
|
|
|
// Migration from stat_archive table to Mongo
|
|
// After migration delete only stat_archive
|
|
if ($this->archiveExist) {
|
|
$this->migrationStatArchiveToMongo($options);
|
|
}
|
|
}
|
|
|
|
function migrationStatToMongo($options)
|
|
{
|
|
|
|
$this->appendRunMessage('## Moving from stat to Mongo');
|
|
|
|
$fileName = $this->config->getSetting('LIBRARY_LOCATION') . '.watermark_stat_mongo.txt';
|
|
|
|
// Get low watermark from file
|
|
$watermark = $this->getWatermarkFromFile($fileName, 'stat');
|
|
|
|
$numberOfLoops = 0;
|
|
|
|
while ($watermark > 0) {
|
|
$count = 0;
|
|
$stats = $this->store->getConnection()
|
|
->prepare('SELECT * FROM stat WHERE statId < :watermark ORDER BY statId DESC LIMIT :limit');
|
|
$stats->bindParam(':watermark', $watermark, \PDO::PARAM_INT);
|
|
$stats->bindParam(':limit', $options['numberOfRecords'], \PDO::PARAM_INT);
|
|
|
|
// Run the select
|
|
$stats->execute();
|
|
|
|
// Keep count how many stats we've inserted
|
|
$recordCount = $stats->rowCount();
|
|
$count+= $recordCount;
|
|
|
|
// End of records
|
|
if ($this->checkEndOfRecords($recordCount, $fileName) === true) {
|
|
$this->appendRunMessage(PHP_EOL. '# End of records.' . PHP_EOL. '- Truncating and Optimising stat.');
|
|
$this->log->debug('End of records in stat table. Truncate and Optimise.');
|
|
|
|
// Truncate stat table
|
|
$this->store->update('TRUNCATE TABLE stat', []);
|
|
|
|
// Optimize stat table
|
|
if ($options['optimiseOnComplete'] == 1) {
|
|
$this->store->update('OPTIMIZE TABLE stat', []);
|
|
}
|
|
|
|
$this->appendRunMessage(__('Done.'. PHP_EOL));
|
|
|
|
break;
|
|
}
|
|
|
|
// Loops limit end - task will need to rerun again to start from the saved watermark
|
|
if ($this->checkLoopLimits($numberOfLoops, $options['numberOfLoops'], $fileName, $watermark) === true) {
|
|
break;
|
|
}
|
|
$numberOfLoops++;
|
|
|
|
$statCount = 0;
|
|
foreach ($stats->fetchAll() as $stat) {
|
|
// We get the watermark now because if we skip the records our watermark will never reach 0
|
|
$watermark = $stat['statId'];
|
|
|
|
// Get display
|
|
$display = $this->getDisplay((int) $stat['displayId']);
|
|
|
|
if (empty($display)) {
|
|
$this->log->error('Display not found. Display Id: '. $stat['displayId']);
|
|
continue;
|
|
}
|
|
|
|
$entry = [];
|
|
|
|
$entry['statDate'] = Carbon::createFromTimestamp($stat['statDate']);
|
|
$entry['type'] = $stat['type'];
|
|
$entry['fromDt'] = Carbon::createFromTimestamp($stat['start']);
|
|
$entry['toDt'] = Carbon::createFromTimestamp($stat['end']);
|
|
$entry['scheduleId'] = (int) $stat['scheduleId'];
|
|
$entry['mediaId'] = (int) $stat['mediaId'];
|
|
$entry['layoutId'] = (int) $stat['layoutId'];
|
|
$entry['display'] = $display;
|
|
$entry['campaignId'] = (int) $stat['campaignId'];
|
|
$entry['tag'] = $stat['tag'];
|
|
$entry['widgetId'] = (int) $stat['widgetId'];
|
|
$entry['duration'] = (int) $stat['duration'];
|
|
$entry['count'] = (int) $stat['count'];
|
|
|
|
// Add stats in store $this->stats
|
|
$this->timeSeriesStore->addStat($entry);
|
|
$statCount++;
|
|
}
|
|
|
|
// Write stats
|
|
if ($statCount > 0) {
|
|
$this->timeSeriesStore->addStatFinalize();
|
|
} else {
|
|
$this->appendRunMessage('No stat to migrate from stat to mongo');
|
|
$this->log->debug('No stat to migrate from stat to mongo');
|
|
}
|
|
|
|
// Give Mongo time to recover
|
|
if ($watermark > 0) {
|
|
$this->appendRunMessage('- '. $count. ' rows migrated.');
|
|
$this->log->debug('Mongo stats migration from stat. '.$count.' rows effected, sleeping.');
|
|
sleep($options['pauseBetweenLoops']);
|
|
}
|
|
}
|
|
}
|
|
|
|
function migrationStatArchiveToMongo($options)
|
|
{
|
|
|
|
$this->appendRunMessage(PHP_EOL. '## Moving from stat_archive to Mongo');
|
|
$fileName = $this->config->getSetting('LIBRARY_LOCATION') . '.watermark_stat_archive_mongo.txt';
|
|
|
|
// Get low watermark from file
|
|
$watermark = $this->getWatermarkFromFile($fileName, 'stat_archive');
|
|
|
|
$numberOfLoops = 0;
|
|
|
|
while ($watermark > 0) {
|
|
$count = 0;
|
|
/** @noinspection SqlResolve */
|
|
$stats = $this->store->getConnection()->prepare('
|
|
SELECT statId, type, statDate, scheduleId, displayId, layoutId, mediaId, widgetId, start, `end`, tag
|
|
FROM stat_archive
|
|
WHERE statId < :watermark
|
|
ORDER BY statId DESC LIMIT :limit
|
|
');
|
|
$stats->bindParam(':watermark', $watermark, \PDO::PARAM_INT);
|
|
$stats->bindParam(':limit', $options['numberOfRecords'], \PDO::PARAM_INT);
|
|
|
|
// Run the select
|
|
$stats->execute();
|
|
|
|
// Keep count how many stats we've processed
|
|
$recordCount = $stats->rowCount();
|
|
$count+= $recordCount;
|
|
|
|
// End of records
|
|
if ($this->checkEndOfRecords($recordCount, $fileName) === true) {
|
|
$this->appendRunMessage(PHP_EOL. '# End of records.' . PHP_EOL. '- Dropping stat_archive.');
|
|
$this->log->debug('End of records in stat_archive (migration to Mongo). Dropping table.');
|
|
|
|
// Drop the stat_archive table
|
|
/** @noinspection SqlResolve */
|
|
$this->store->update('DROP TABLE `stat_archive`;', []);
|
|
|
|
$this->appendRunMessage(__('Done.'. PHP_EOL));
|
|
|
|
break;
|
|
}
|
|
|
|
// Loops limit end - task will need to rerun again to start from the saved watermark
|
|
if ($this->checkLoopLimits($numberOfLoops, $options['numberOfLoops'], $fileName, $watermark) === true) {
|
|
break;
|
|
}
|
|
$numberOfLoops++;
|
|
$temp = [];
|
|
|
|
$statIgnoredCount = 0;
|
|
$statCount = 0;
|
|
foreach ($stats->fetchAll() as $stat) {
|
|
// We get the watermark now because if we skip the records our watermark will never reach 0
|
|
$watermark = $stat['statId'];
|
|
|
|
// Get display
|
|
$display = $this->getDisplay((int) $stat['displayId']);
|
|
|
|
if (empty($display)) {
|
|
$this->log->error('Display not found. Display Id: '. $stat['displayId']);
|
|
$statIgnoredCount+= 1;
|
|
continue;
|
|
}
|
|
|
|
$entry = [];
|
|
|
|
// Get campaignId
|
|
if (($stat['type'] != 'event') && ($stat['layoutId'] != null)) {
|
|
try {
|
|
// Search the campaignId in the temp array first to reduce query in layouthistory
|
|
if (array_key_exists($stat['layoutId'], $temp)) {
|
|
$campaignId = $temp[$stat['layoutId']];
|
|
} else {
|
|
$campaignId = $this->layoutFactory->getCampaignIdFromLayoutHistory($stat['layoutId']);
|
|
$temp[$stat['layoutId']] = $campaignId;
|
|
}
|
|
} catch (NotFoundException $error) {
|
|
$statIgnoredCount+= 1;
|
|
continue;
|
|
}
|
|
} else {
|
|
$campaignId = 0;
|
|
}
|
|
|
|
$statDate = Carbon::createFromTimestamp($stat['statDate']);
|
|
$start = Carbon::createFromTimestamp($stat['start']);
|
|
$end = Carbon::createFromTimestamp($stat['end']);
|
|
|
|
$entry['statDate'] = $statDate;
|
|
$entry['type'] = $stat['type'];
|
|
$entry['fromDt'] = $start;
|
|
$entry['toDt'] = $end;
|
|
$entry['scheduleId'] = (int) $stat['scheduleId'];
|
|
$entry['display'] = $display;
|
|
$entry['campaignId'] = (int) $campaignId;
|
|
$entry['layoutId'] = (int) $stat['layoutId'];
|
|
$entry['mediaId'] = (int) $stat['mediaId'];
|
|
$entry['tag'] = $stat['tag'];
|
|
$entry['widgetId'] = (int) $stat['widgetId'];
|
|
$entry['duration'] = (int) $end->diffInSeconds($start);
|
|
$entry['count'] = isset($stat['count']) ? (int) $stat['count'] : 1;
|
|
|
|
// Add stats in store $this->stats
|
|
$this->timeSeriesStore->addStat($entry);
|
|
$statCount++;
|
|
}
|
|
|
|
if ($statIgnoredCount > 0) {
|
|
$this->appendRunMessage($statIgnoredCount. ' stat(s) were ignored while migrating');
|
|
}
|
|
|
|
// Write stats
|
|
if ($statCount > 0) {
|
|
$this->timeSeriesStore->addStatFinalize();
|
|
} else {
|
|
$this->appendRunMessage('No stat to migrate from stat archive to mongo');
|
|
$this->log->debug('No stat to migrate from stat archive to mongo');
|
|
}
|
|
|
|
// Give Mongo time to recover
|
|
if ($watermark > 0) {
|
|
if ($statCount > 0) {
|
|
$this->appendRunMessage('- '. $count. ' rows processed. ' . $statCount. ' rows migrated');
|
|
$this->log->debug('Mongo stats migration from stat_archive. '.$count.' rows effected, sleeping.');
|
|
}
|
|
sleep($options['pauseBetweenLoops']);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Get low watermark from file
|
|
function getWatermarkFromFile($fileName, $tableName)
|
|
{
|
|
|
|
if (file_exists($fileName)) {
|
|
$file = fopen($fileName, 'r');
|
|
$line = fgets($file);
|
|
fclose($file);
|
|
$watermark = (int) $line;
|
|
} else {
|
|
// Save mysql low watermark in file if .watermark.txt file is not found
|
|
/** @noinspection SqlResolve */
|
|
$statId = $this->store->select('SELECT MAX(statId) as statId FROM '.$tableName, []);
|
|
$watermark = (int) $statId[0]['statId'];
|
|
|
|
$out = fopen($fileName, 'w');
|
|
fwrite($out, $watermark);
|
|
fclose($out);
|
|
}
|
|
|
|
// We need to increase it
|
|
$watermark+= 1;
|
|
$this->appendRunMessage('- Initial watermark is '.$watermark);
|
|
|
|
return $watermark;
|
|
}
|
|
|
|
// Check if end of records
|
|
function checkEndOfRecords($recordCount, $fileName)
|
|
{
|
|
|
|
if ($recordCount == 0) {
|
|
// No records in stat, save watermark in file
|
|
$watermark = -1;
|
|
|
|
$out = fopen($fileName, 'w');
|
|
fwrite($out, $watermark);
|
|
fclose($out);
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Check loop limits
|
|
function checkLoopLimits($numberOfLoops, $optionsNumberOfLoops, $fileName, $watermark)
|
|
{
|
|
|
|
if ($numberOfLoops == $optionsNumberOfLoops) {
|
|
// Save watermark in file
|
|
$watermark = $watermark - 1;
|
|
$this->log->debug(' Loop reached limit. Watermark is now '.$watermark);
|
|
|
|
$out = fopen($fileName, 'w');
|
|
fwrite($out, $watermark);
|
|
fclose($out);
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Disable the task
|
|
function disableTask()
|
|
{
|
|
|
|
$this->appendRunMessage('# Disabling task.');
|
|
$this->log->debug('Disabling task.');
|
|
|
|
$this->getTask()->isActive = 0;
|
|
$this->getTask()->save();
|
|
|
|
$this->appendRunMessage(__('Done.'. PHP_EOL));
|
|
|
|
return;
|
|
}
|
|
|
|
// Disable the task
|
|
function quitMigrationTaskOrDisableStatArchiveTask()
|
|
{
|
|
|
|
// Quit the migration task if stat archive task is running
|
|
if ($this->archiveTask->status == Task::$STATUS_RUNNING) {
|
|
$this->appendRunMessage('Quitting the stat migration task as stat archive task is running');
|
|
$this->log->debug('Quitting the stat migration task as stat archive task is running.');
|
|
return;
|
|
}
|
|
|
|
// Mark the Stats Archiver as disabled if it is active
|
|
if ($this->archiveTask->isActive == 1) {
|
|
$this->archiveTask->isActive = 0;
|
|
$this->archiveTask->save();
|
|
$this->store->commitIfNecessary();
|
|
|
|
$this->appendRunMessage('Disabling Stats Archive Task.');
|
|
$this->log->debug('Disabling Stats Archive Task.');
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// Cahce/Get display
|
|
function getDisplay($displayId)
|
|
{
|
|
|
|
// Get display if in memory
|
|
if (array_key_exists($displayId, $this->displays)) {
|
|
$display = $this->displays[$displayId];
|
|
} elseif (array_key_exists($displayId, $this->displaysNotFound)) {
|
|
// Display not found
|
|
return false;
|
|
} else {
|
|
try {
|
|
$display = $this->displayFactory->getById($displayId);
|
|
|
|
// Cache display
|
|
$this->displays[$displayId] = $display;
|
|
} catch (NotFoundException $error) {
|
|
// Cache display not found
|
|
$this->displaysNotFound[$displayId] = $displayId;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return $display;
|
|
}
|
|
}
|