/** @return PsProfilerInterface */ private function getProfiler($profilerId) { //Не будем выполнять get_file_name($profilerId), так как нужно вернуть профайлер максимально быстро if ($this->CAHCE->has($profilerId)) { return $this->CAHCE->get($profilerId); } check_condition($profilerId, 'Profiler id cannot be empty.'); if (!$this->enabled) { return $this->CAHCE->set($profilerId, new PsProfilerEmpty($profilerId)); } $di = $this->getProfilerDi($profilerId); $pr = null; //Проверим текущий размер профайлера if ($di->isMaxSize(ConfigIni::profilingMaxFileSize())) { $locked = PsLock::lock(__CLASS__ . "::compressProfiler({$profilerId})", false); if ($locked) { $this->compressProfiler($di); PsLock::unlock(); } else { //Разимер превышен и мы не смогли получить лок для дампа профайлера. Не будем в этот раз вести профайлинг. $pr = new PsProfilerEmpty($profilerId); } } return $this->CAHCE->set($profilerId, $pr ? $pr : new PsProfilerImpl($profilerId)); }
function executeProcess(array $argv) { dolog('try to get lock'); $taken = PsLock::lock('mylock-wait', true); dolog('lock ' . ($taken ? 'taken' : 'not taken')); if ($taken) { sleep(10); PsLock::unlock(); dolog('lock released'); } }
private function executeImpl($lifeTimeOnCall, $__FUNCTION__) { if ($this->called) { return $this->executed; //--- } $this->called = true; $LOGGER = PsLogger::inst(__CLASS__); $LOGGER->info("Function [{$__FUNCTION__}] called."); $needProcess = false; $LOCKFILE = DirManager::autogen('service')->getDirItem(null, __CLASS__, 'lock'); if ($LOCKFILE->isFile()) { $lifeTime = $LOCKFILE->getFileLifetime(); $needProcess = !$lifeTime || !$lifeTimeOnCall || $lifeTime >= $lifeTimeOnCall; $LOGGER->info('{} process. Lock file modified {} seconds ago. Process delay: {} seconds.', $needProcess ? 'Need' : 'Not need', $lifeTime, $lifeTimeOnCall); } else { $needProcess = true; $LOGGER->info('Need process. Lock file is not exists.'); } if (!$needProcess) { return $this->executed; //--- } $locked = PsLock::lock(__CLASS__, false); $LOGGER->info('External process lock {} execution.', $locked ? 'acquired, start' : 'not acquired, skip'); if ($locked) { $LOCKFILE->touch(); PsUtil::startUnlimitedMode(); //Отпустим лок, так как внутри он может потребоваться для выполнения других действий, например для перестройки спрайтов PsLock::unlock(); //Начинаем выполнение $this->executed = true; $job = new ExternalProcessJob(); PsProfiler::inst(__CLASS__)->start(__FUNCTION__); $job->execute(); $secundomer = PsProfiler::inst(__CLASS__)->stop(); if ($secundomer) { $LOGGER->info("{$secundomer}"); } } return $this->executed; }
public function CreateSprite(CssSprite $sprite) { if ($sprite->exists()) { return; //--- Спрайт существует } $this->LOGGER->info("Waiting to make {$sprite}"); PsLock::lockMethod(__CLASS__, __FUNCTION__); try { if ($sprite->exists()) { $this->LOGGER->info('Sprite was created in another thread, skipping'); } else { $this->PROFILER->start('Sprite creation'); $this->CssSpriteGen->CreateSprite($sprite); $this->LOGGER->info('Sprite was successfully created, path: ' . $sprite->getCssDi()->getAbsPath()); $this->PROFILER->stop(); } } catch (Exception $ex) { PsLock::unlock(); throw $ex; } PsLock::unlock(); }
<?php require_once '../ToolsResources.php'; $CALLED_FILE = __FILE__; dolog('try to get lock'); $taken = PsLock::lock('mylock-nowait', false); dolog('lock ' . ($taken ? 'taken' : 'not taken')); if ($taken) { sleep(10); PsLock::unlock(); dolog('lock released'); }
/** * Метод открывает на картинке все ячейки, которые может открыть пользователь */ public function bindAllUserCells($userId = null) { $userId = AuthManager::extractUserId($userId); $canOpenCnt = $this->getUserCanOpenCellsCnt($userId); if ($canOpenCnt <= 0) { return; //--- } $this->LOGGER->info("Binding all cells of user {$userId} to img {$this->id}, can open {$canOpenCnt} cells."); PsLock::lock(__CLASS__ . $this->id); try { //Запросим ячейки снова, так как пока мы ждали блокировку, могло что-то случиться... $canOpenCnt = $this->getUserCanOpenCellsCnt($userId); if ($canOpenCnt > 0) { $this->copyCells($this->BEAN->getCells4UserBind($this->id, $canOpenCnt), $userId); } } catch (Exception $ex) { PsLock::unlock(); throw $ex; } PsLock::unlock(); }
/** * Метод вызывается для выполнения периодических задач cron * * @return type */ public function execute() { if ($this->called) { return $this->executed; //--- } $this->called = true; $LOGGER = PsLogger::inst(__CLASS__); $LOGGER->info('Executing {}', __CLASS__); /* * Получим список классов, которые нужно выполнить */ $processes = ConfigIni::cronProcesses(); if (empty($processes)) { $LOGGER->info('No cron processes configured, fast return...'); return $this->executed; //--- } $processes = array_unique($processes); $LOGGER->info('Configured processes: {}', array_to_string($processes)); foreach ($processes as $class) { if (!PsUtil::isInstanceOf($class, 'PsCronProcess')) { PsUtil::raise("Class {$class} cannot be executed as cron process, it should be instance of PsCronProcess"); } } $locked = PsLock::lock(__CLASS__, false); $LOGGER->info('Lock accured ? {}', var_export($locked, true)); if (!$locked) { return $this->executed; //--- } $LOCKFILE = DirManager::autoNoDel(DirManager::DIR_SERVICE)->getDirItem(null, __CLASS__, PsConst::EXT_LOCK); $LOCKFILE_LIFETIME = $LOCKFILE->getFileLifetime(); $MAX_LIFETIME = 5 * 60; $NED_PROCESS = $LOCKFILE_LIFETIME === null || $LOCKFILE_LIFETIME > $MAX_LIFETIME; $LOGGER->info("Lock file {}: {}", $LOCKFILE_LIFETIME === null ? 'NOT EXISTS' : 'EXISTS', $LOCKFILE->getRelPath()); if ($LOCKFILE_LIFETIME !== null) { $LOGGER->info('Last modified: {} seconds ago. Max process delay: {} seconds.', $LOCKFILE_LIFETIME, $MAX_LIFETIME); // } if (!$NED_PROCESS) { $LOGGER->info('Skip execution.'); //Отпустим лок PsLock::unlock(); //Выходим return $this->executed; //--- } //Обновим время последнего выполнения $LOCKFILE->touch(); //Отпустим лок, так как внутри он может потребоваться для выполнения других действий, например для перестройки спрайтов PsLock::unlock(); $LOGGER->info(); $LOGGER->info('External process execution started...'); //Запускаем режим неограниченного выполнения PsUtil::startUnlimitedMode(); //Начинаем выполнение $this->executed = true; //Создаём профайлер $PROFILER = PsProfiler::inst(__CLASS__); //Создадим конфиг выполнения процесса $config = new PsCronProcessConfig(); //Пробегаемся по процессам и выполняем. При первой ошибке - выходим. foreach ($processes as $class) { $LOGGER->info('Executing cron process {}', $class); $PROFILER->start($class); try { $inst = new $class(); $inst->onCron($config); $secundomer = $PROFILER->stop(); $LOGGER->info(" > Cron process '{}' executed in {} seconds", $class, $secundomer->getTotalTime()); } catch (Exception $ex) { $PROFILER->stop(); $LOGGER->info(" > Cron process '{}' execution error: '{}'", $class, $ex->getMessage()); } } $LOGGER->info('Removing cron lock file.'); $LOCKFILE->remove(); return $this->executed; }
/** * Метод выполняет дамп таблицы */ public static function dumpTable($idColumn, $table, array $where = array(), $order = null) { //Стартуем секундомер $secundomer = Secundomer::startedInst("Снятие дампа {$table}"); //Отключим ограничение по времени PsUtil::startUnlimitedMode(); //Получим экземпляр логгера $LOGGER = PsLogger::inst(__CLASS__); //Текущий пользователь $userId = AuthManager::getUserIdOrNull(); //Для логов, запросов и все остального $table = strtoupper(PsCheck::tableName($table)); //Макс кол-во записей $limit = PsDefines::getTableDumpPortion(); //Проверим наличие id $idColumn = PsCheck::tableColName($idColumn); $LOGGER->info('Dumping table {}. Id column: {}, limit: {}. User id: {}.', $table, $idColumn, $limit, $userId); //Получаем лок (без ожидания) $lockName = "DUMP table {$table}"; $locked = PsLock::lock($lockName, false); $LOGGER->info('Lock name: {}, locked ? {}.', $lockName, var_export($locked, true)); if (!$locked) { return false; //Не удалось получить лок } $zipDi = false; try { //ЗПРОСЫ: //1. Запрос на извлечение колва записей, подлежащих дампированию $queryCnt = Query::select("count({$idColumn}) as cnt", $table, $where); //2. Запрос на извлечение данных, подлежащих дампированию $queryDump = Query::select('*', $table, $where, null, $order, $limit); //3. Запрос на извлечение кодов дампируемых записей $selectIds = Query::select($idColumn, $table, $where, null, $order, $limit); //4. Запрос на удаление дампированных данных $queryDel = Query::delete($table, Query::plainParam("{$idColumn} in (select {$idColumn} from (" . $selectIds->build($delParams) . ') t )', $delParams)); //Выполним запрос для получения кол-ва записей, подлежащих дампу $cnt = PsCheck::int(array_get_value('cnt', PSDB::getRec($queryCnt, null, true))); $LOGGER->info('Dump recs count allowed: {}.', $cnt); if ($cnt < $limit) { $LOGGER->info('SKIP dumping table, count allowed ({}) < limit ({})...', $cnt, $limit); $LOGGER->info("Query for extract dump records count: {$queryCnt}"); PsLock::unlock($lockName); return false; } //Время дампа $date = PsUtil::fileUniqueTime(false); $time = time(); //Название файлов $zipName = $date . ' ' . $table; //Элемент, указывающий на zip архив $zipDi = DirManager::stuff(null, array(self::DUMPS_TABLE, $table))->getDirItem(null, $zipName, PsConst::EXT_ZIP); $LOGGER->info('Dump to: [{}].', $zipDi->getAbsPath()); if ($zipDi->isFile()) { $LOGGER->info('Dump file exists, skip dumping table...'); PsLock::unlock($lockName); return false; } //Комментарий к таблице $commentToken[] = "Date: {$date}"; $commentToken[] = "Time: {$time}"; $commentToken[] = "Table: {$table}"; $commentToken[] = "Manager: {$userId}"; $commentToken[] = "Recs dumped: {$limit}"; $commentToken[] = "Total allowed: {$cnt}"; $commentToken[] = "Query dump cnt: {$queryCnt}"; $commentToken[] = "Query dump data: {$queryDump}"; $commentToken[] = "Query dump ids: {$selectIds}"; $commentToken[] = "Query del dumped: {$queryDel}"; $comment = implode("\n", $commentToken); //Начинаем zip и сохраняем в него данные $zip = $zipDi->startZip(); $zip->addFromString($zipName, serialize(PSDB::getArray($queryDump))); $zip->setArchiveComment($comment); $zip->close(); $LOGGER->info('Data successfully dumped, zip comment:'); $LOGGER->info("[\n{$comment}\n]"); //Удалим те записи, дамп которых был снят $LOGGER->info('Clearing dumped table records...'); $affected = PSDB::update($queryDel); $LOGGER->info('Rows deleted: {}.', $affected); $LOGGER->info('Dumping is SUCCESSFULLY finished. Total time: {} sec.', $secundomer->stop()->getAverage()); } catch (Exception $ex) { PsLock::unlock($lockName); ExceptionHandler::dumpError($ex); $LOGGER->info('Error occured: {}', $ex->getMessage()); throw $ex; } return $zipDi; }
private function doCopy(DirItem $from, DirItem $to) { $from->assertIsImg(); PsLock::lockMethod(__CLASS__, __FUNCTION__); try { //Очистим нагенерённое для той картинки, В КОТОРУЮ копируем $this->doClean($to); //Картинка не была пересоздана в другом потоке SimpleImage::inst()->load($from)->save($to, SYSTEM_IMG_TYPE)->close(); } catch (Exception $ex) { PsLock::unlock(); throw $ex; } PsLock::unlock(); }