private static function Execute($Service, $Method, $Call) { $OldService = self::$_Service; $OldMethod = self::$_Method; if ($Service !== null) { self::$_Service = $Service; } if ($Method !== null) { self::$_Method = $Method; } self::Stop($OldService); self::Stop($OldService . ':' . $OldMethod); self::Start(self::$_Service); self::Start(self::$_Service . ':' . self::$_Method); self::$_Stack->push(self::$_Service . ':' . self::$_Method); $Count = self::$_Stack->count(); if ($Count > F::Get('MSS')) { // Max Stack Size F::Set('MSS', $Count); } $FnOptions = self::loadOptions(); $Call = self::Merge($FnOptions, $Call); if (null === self::getFn(self::$_Method) && !self::_loadSource(self::$_Service)) { # trigger_error('Service: '.self::$_Service.' not found'); self::Log('Service: ' . self::$_Service . ' not found', LOG_WARNING); $Result = is_array($Call) && isset($Call['Fallback']) ? $Call['Fallback'] : null; } else { $F = self::getFn(self::$_Method); if (is_callable($F)) { if (!isset($Call['No Memo']) && isset($FnOptions['Contract'][self::$_Service][self::$_Method]['Memo'])) { $Memo = [self::$_Service, self::$_Method]; foreach ($FnOptions['Contract'][self::$_Service][self::$_Method]['Memo'] as $Key) { $Key = self::Dot($Call, $Key); if (null === $Key) { } else { $Memo[] = $Key; } } $CacheID = sha1(j($Memo)); } $ST = 0; if (isset($CacheID) && ($Result = self::Get($CacheID)) !== null) { self::Log(self::$_Service . ':' . self::$_Method . '(' . $CacheID . ') memoized.', LOG_INFO, 'Performance'); } else { if (isset($FnOptions['Contract'][self::$_Service][self::$_Method]['RTTL']) && !isset($Call['RTTL'])) { $Call['RTTL'] = $FnOptions['Contract'][self::$_Service][self::$_Method]['RTTL']; } if (isset($Call['RTTL']) and isset($CacheID) && isset(self::$_Options['Codeine']['Run Cache Enabled']) && self::$_Options['Codeine']['Run Cache Enabled'] === true) { $RTTL = $Call['RTTL']; unset($Call['RTTL']); $Result = self::Execute('Code.Run.Cached', 'Run', ['Run' => ['Service' => self::$_Service, 'Method' => self::$_Method, 'Call' => $Call, 'CacheID' => $CacheID, 'RTTL' => $RTTL, 'Memo' => $Memo]]); } else { $ST = microtime(true); $Result = $F($Call); // Real Run Here $ST = microtime(true) - $ST; } } // if (self::$_Performance) self::Counter(self::$_Service . '.' . self::$_Method); if (!isset($Call['No Memo']) && isset($CacheID) && $ST > self::$_Options['Codeine']['Memo Threshold']) { self::Set($CacheID, $Result); } } else { $Result = isset($Call['Fallback']) ? $Call['Fallback'] : null; } } self::Stop(self::$_Service); self::Stop(self::$_Service . ':' . self::$_Method); self::Start($OldService); self::Start($OldService . ':' . $OldMethod); self::$_Service = $OldService; self::$_Method = $OldMethod; self::$NC++; self::$_Stack->pop(); return $Result; }
<?php /* Codeine * @author bergstein@trickyplan.com * @description * @package Codeine * @version 8.x */ setFn('Do', function ($Call) { if (self::$_Performance or F::Environment() === 'Development') { $Call['Performance']['Summary']['Time'] = round((microtime(true) - Started) * 1000); $Call['Performance']['Summary']['Calls'] = array_sum(self::$_Counters['C']); arsort(self::$_Counters['T']); F::Log('Max stack size: ' . F::Get('MSS'), LOG_NOTICE, 'Performance'); F::Log('Total time: ' . round($Call['Performance']['Summary']['Time']) . ' ms', LOG_NOTICE, 'Performance'); F::Log('Total calls: ' . $Call['Performance']['Summary']['Calls'], LOG_NOTICE, 'Performance'); F::Log('Total time per call: ' . round($Call['Performance']['Summary']['Time'] / $Call['Performance']['Summary']['Calls'], 2) . ' ms', LOG_NOTICE, 'Performance'); F::Log('Memory: ' . memory_get_usage(true) / 1024 . 'Kb ', LOG_NOTICE, 'Performance'); F::Log('Peak memory: ' . memory_get_peak_usage(true) / 1024 . 'Kb', LOG_NOTICE, 'Performance'); foreach (self::$_Counters['T'] as $Key => $Value) { if (!isset(self::$_Counters['C'][$Key])) { self::$_Counters['C'][$Key] = 1; } $Class = ['ATime' => LOG_DEBUG, 'RTime' => LOG_DEBUG, 'ACalls' => LOG_DEBUG, 'RCalls' => LOG_DEBUG, 'TimePerCall' => LOG_DEBUG]; $Call['RTime'] = round($Value / $Call['Performance']['Summary']['Time'] * 100, 2); $Call['RCalls'] = round(self::$_Counters['C'][$Key] / $Call['Performance']['Summary']['Calls'] * 100, 2); $Call['ATime'] = round($Value); $Call['ACalls'] = self::$_Counters['C'][$Key]; $Call['TimePerCall'] = round($Value / self::$_Counters['C'][$Key], 2); if (isset($Call['Alerts']['Yellow'])) { foreach ($Call['Alerts']['Yellow'] as $Metric => $Limit) {
<?php /* Codeine * @author bergstein@trickyplan.com * @description Memoize call * @package Codeine * @version 8.x */ setFn('Run', function ($Call) { $Hash = [$Call['Run']['Service'], $Call['Run']['Method']]; foreach ($Call['Run']['Call']['Contract'][$Call['Run']['Method']]['Call'] as $Key => $Argument) { if (isset($Call['Run']['Call'][$Key])) { $Hash[] = $Call['Run']['Call'][$Key]; } } $Hash = serialize($Hash); $Call['Run']['Call']['Memo'] = true; $Result = F::Get($Hash); if ($Result === null) { $Result = self::Execute($Call['Run']['Service'], $Call['Run']['Method'], $Call['Run']['Call']); F::Set($Hash, $Result); } return $Result; });
<?php /* Codeine * @author bergstein@trickyplan.com * @package Codeine * @version 8.x */ setFn('Open', function ($Call) { return true; }); setFn('Read', function ($Call) { if (isset($Call['Where']['ID'])) { return F::Get($Call['Where']['ID']); } else { return null; } }); setFn('Write', function ($Call) { if (isset($Call['Where']['ID'])) { F::Set($Call['Where']['ID'], $Call['Data']); } elseif (isset($Call['Data']['ID'])) { F::Set($Call['Data']['ID'], $Call['Data']); } return $Call['Data']; }); setFn('Close', function ($Call) { return true; }); setFn('Execute', function ($Call) { return true; });
* @author bergstein@trickyplan.com * @description * @package Codeine * @version 8.x */ setFn('beforeEntityRead', function ($Call) { if (isset($Call['Where']['ID'])) { if (is_array($Call['Where']['ID'])) { /*foreach($Call['Where']['ID'] as $CID => $ID) if (($Call['Data'][$ID] = F::Get('GEC:'.$Call['Entity'].':'.$ID)) !== null) { F::Log('GEC optimizes '.$Call['Entity'].':'.$CID, LOG_NOTICE); unset($Call['Where']['ID'][$CID]); }*/ } else { if (($Call['Data'][$Call['Where']['ID']] = F::Get('GEC:' . $Call['Entity'] . ':' . $Call['Where']['ID'])) !== null) { F::Log('GEC optimizes ' . $Call['Entity'] . ':' . $Call['Where']['ID'], LOG_NOTICE); unset($Call['Where']['ID']); } } if (empty($Call['Where']['ID']) or empty($Call['Where'])) { $Call['Skip Read'] = true; } } return $Call; }); setFn('afterEntityRead', function ($Call) { if (isset($Call['Fields'])) { } else { if (isset($Call['Data']['ID'])) { F::Set('GEC:' . $Call['Entity'] . ':' . $Call['Data']['ID'], $Call['Data']);
if (isset($Call['Storage'])) { $Call = F::Apply('IO', 'Open', $Call); if ($Call['Link'] === null) { return null; } return F::Run($Call['Driver'], null, $Call); } else { F::Log('IO Null Storage: ', LOG_ERR); return null; } }); setFn('Rollback', function ($Call) { if (isset($Call['Storage'])) { $Call = F::Apply('IO', 'Open', $Call); if ($Call['Link'] === null) { return null; } return F::Run($Call['Driver'], null, $Call); } else { F::Log('IO Null Storage: ', LOG_ERR); return null; } }); setFn('Shutdown', function ($Call) { foreach ($Call['Storages'] as $StorageName => $Storage) { if (null !== F::Get($StorageName)) { F::Run('IO', 'Close', $Call, ['Storage' => $StorageName]); } } return $Call; });