private function getRawData()
 {
     if ($this->rawData === null) {
         $type = $this->getDataType();
         $data = $this->getData();
         switch ($type) {
             case self::DATATYPE_TEXT:
                 // In this storage type, the changes are stored on the object.
                 $data = $data;
                 break;
             case self::DATATYPE_FILE:
             default:
                 throw new Exception(pht('Hunk has unsupported data type "%s"!', $type));
         }
         $format = $this->getDataFormat();
         switch ($format) {
             case self::DATAFORMAT_RAW:
                 // In this format, the changes are stored as-is.
                 $data = $data;
                 break;
             case self::DATAFORMAT_DEFLATED:
                 $data = PhabricatorCaches::inflateData($data);
                 break;
             default:
                 throw new Exception(pht('Hunk has unsupported data encoding "%s"!', $type));
         }
         $this->rawData = $data;
     }
     return $this->rawData;
 }
 public static function getLiveServers()
 {
     $cache = PhabricatorCaches::getRequestCache();
     $refs = $cache->getKey(self::KEY_REFS);
     if (!$refs) {
         $refs = self::newRefs();
         $cache->setKey(self::KEY_REFS, $refs);
     }
     return $refs;
 }
 protected function run()
 {
     $this->setEngines(PhabricatorFactEngine::loadAllEngines());
     while (!$this->shouldExit()) {
         PhabricatorCaches::destroyRequestCache();
         $iterators = $this->getAllApplicationIterators();
         foreach ($iterators as $iterator_name => $iterator) {
             $this->processIteratorWithCursor($iterator_name, $iterator);
         }
         $this->processAggregates();
         $this->log(pht('Zzz...'));
         $this->sleep(60 * 5);
     }
 }
Esempio n. 4
0
 private function runLoop()
 {
     do {
         PhabricatorCaches::destroyRequestCache();
         $this->stillWorking();
         $messages = $this->protocolAdapter->getNextMessages($this->pollFrequency);
         if (count($messages) > 0) {
             foreach ($messages as $message) {
                 $this->routeMessage($message);
             }
         }
         foreach ($this->handlers as $handler) {
             $handler->runBackgroundTasks();
         }
     } while (!$this->shouldExit());
 }
Esempio n. 5
0
 private function getEngine()
 {
     $options = $this->options;
     $viewer = $this->getViewer();
     $viewer_key = $viewer->getCacheFragment();
     ksort($options);
     $engine_key = serialize($options);
     $engine_key = PhabricatorHash::digestForIndex($engine_key);
     $cache = PhabricatorCaches::getRequestCache();
     $cache_key = "remarkup.engine({$viewer_key}, {$engine_key})";
     $engine = $cache->getKey($cache_key);
     if (!$engine) {
         $engine = PhabricatorMarkupEngine::newMarkupEngine($options);
         $cache->setKey($cache_key, $engine);
     }
     return $engine;
 }
Esempio n. 6
0
 public static function getLiveDevice()
 {
     $device_id = self::getDeviceID();
     if (!$device_id) {
         return null;
     }
     $cache = PhabricatorCaches::getRequestCache();
     $cache_key = 'almanac.device.self';
     $device = $cache->getKey($cache_key);
     if (!$device) {
         $viewer = PhabricatorUser::getOmnipotentUser();
         $device = id(new AlmanacDeviceQuery())->setViewer($viewer)->withNames(array($device_id))->executeOne();
         if (!$device) {
             throw new Exception(pht('This host has device ID "%s", but there is no corresponding ' . 'device record in Almanac.', $device_id));
         }
         $cache->setKey($cache_key, $device);
     }
     return $device;
 }
 public function testRequestCache()
 {
     $cache = PhabricatorCaches::getRequestCache();
     $test_key = 'unit.' . Filesystem::readRandomCharacters(8);
     $default_value = pht('Default');
     $new_value = pht('New Value');
     $this->assertEqual($default_value, $cache->getKey($test_key, $default_value));
     // Set a key, verify it persists.
     $cache = PhabricatorCaches::getRequestCache();
     $cache->setKey($test_key, $new_value);
     $this->assertEqual($new_value, $cache->getKey($test_key, $default_value));
     // Refetch the cache, verify it's really a cache.
     $cache = PhabricatorCaches::getRequestCache();
     $this->assertEqual($new_value, $cache->getKey($test_key, $default_value));
     // Destroy the cache.
     PhabricatorCaches::destroyRequestCache();
     // Now, the value should be missing again.
     $cache = PhabricatorCaches::getRequestCache();
     $this->assertEqual($default_value, $cache->getKey($test_key, $default_value));
 }
 protected function run()
 {
     do {
         PhabricatorCaches::destroyRequestCache();
         $tasks = id(new PhabricatorWorkerLeaseQuery())->setLimit(1)->execute();
         if ($tasks) {
             $this->willBeginWork();
             foreach ($tasks as $task) {
                 $id = $task->getID();
                 $class = $task->getTaskClass();
                 $this->log(pht('Working on task %d (%s)...', $id, $class));
                 $task = $task->executeTask();
                 $ex = $task->getExecutionException();
                 if ($ex) {
                     if ($ex instanceof PhabricatorWorkerPermanentFailureException) {
                         throw new PhutilProxyException(pht('Permanent failure while executing Task ID %d.', $id), $ex);
                     } else {
                         if ($ex instanceof PhabricatorWorkerYieldException) {
                             $this->log(pht('Task %s yielded.', $id));
                         } else {
                             $this->log(pht('Task %d failed!', $id));
                             throw new PhutilProxyException(pht('Error while executing Task ID %d.', $id), $ex);
                         }
                     }
                 } else {
                     $this->log(pht('Task %s complete! Moved to archive.', $id));
                 }
             }
             $sleep = 0;
         } else {
             // When there's no work, sleep for one second. The pool will
             // autoscale down if we're continuously idle for an extended period
             // of time.
             $this->willBeginIdle();
             $sleep = 1;
         }
         $this->sleep($sleep);
     } while (!$this->shouldExit());
 }
 /**
  * Determine if an application is installed and available to a viewer, by
  * application class name.
  *
  * To check if an application is installed at all, use
  * @{method:isClassInstalled}.
  *
  * @param string Application class name.
  * @param PhabricatorUser Viewing user.
  * @return bool True if the class is installed for the viewer.
  * @task meta
  */
 public static final function isClassInstalledForViewer($class, PhabricatorUser $viewer)
 {
     if ($viewer->isOmnipotent()) {
         return true;
     }
     $cache = PhabricatorCaches::getRequestCache();
     $viewer_phid = $viewer->getPHID();
     $key = 'app.' . $class . '.installed.' . $viewer_phid;
     $result = $cache->getKey($key);
     if ($result === null) {
         if (!self::isClassInstalled($class)) {
             $result = false;
         } else {
             $result = PhabricatorPolicyFilter::hasCapability($viewer, self::getByClass($class), PhabricatorPolicyCapability::CAN_VIEW);
         }
         $cache->setKey($key, $result);
     }
     return $result;
 }
 private function renderPhabricatorLogo()
 {
     $custom_header = PhabricatorCustomLogoConfigType::getLogoImagePHID();
     $logo_style = array();
     if ($custom_header) {
         $cache = PhabricatorCaches::getImmutableCache();
         $cache_key_logo = 'ui.custom-header.logo-phid.v3.' . $custom_header;
         $logo_uri = $cache->getKey($cache_key_logo);
         if (!$logo_uri) {
             $file = id(new PhabricatorFileQuery())->setViewer($this->getViewer())->withPHIDs(array($custom_header))->executeOne();
             if ($file) {
                 $logo_uri = $file->getViewURI();
                 $cache->setKey($cache_key_logo, $logo_uri);
             }
         }
         $logo_style[] = 'background-size: 40px 40px;';
         $logo_style[] = 'background-position: 0 0;';
         $logo_style[] = 'background-image: url(' . $logo_uri . ')';
     }
     $logo_node = phutil_tag('span', array('class' => 'phabricator-main-menu-eye', 'style' => implode(' ', $logo_style)));
     $wordmark_text = PhabricatorCustomLogoConfigType::getLogoWordmark();
     if (!strlen($wordmark_text)) {
         $wordmark_text = pht('Phabricator');
     }
     $wordmark_node = phutil_tag('span', array('class' => 'phabricator-wordmark'), $wordmark_text);
     return phutil_tag('a', array('class' => 'phabricator-main-menu-brand', 'href' => '/'), array(javelin_tag('span', array('aural' => true), pht('Home')), $logo_node, $wordmark_node));
 }
 public static function getLiveIndividualRef()
 {
     $cache = PhabricatorCaches::getRequestCache();
     $ref = $cache->getKey(self::KEY_INDIVIDUAL);
     if (!$ref) {
         $ref = self::newIndividualRef();
         $cache->setKey(self::KEY_INDIVIDUAL, $ref);
     }
     return $ref;
 }
 protected function applyFinalEffects(PhabricatorLiskDAO $object, array $xactions)
 {
     // After making any change to an SSH key, drop the authfile cache so it
     // is regenerated the next time anyone authenticates.
     $cache = PhabricatorCaches::getMutableCache();
     $authfile_key = PhabricatorAuthSSHKeyQuery::AUTHFILE_CACHEKEY;
     $cache->deleteKey($authfile_key);
     return $xactions;
 }
 private function didReadValue($format, $value)
 {
     switch ($format) {
         case self::CACHE_FORMAT_RAW:
             return $value;
         case self::CACHE_FORMAT_DEFLATE:
             return PhabricatorCaches::inflateData($value);
         default:
             throw new Exception(pht('Unknown cache format.'));
     }
 }
Esempio n. 14
0
#!/usr/bin/env php
<?php 
$root = dirname(dirname(dirname(__FILE__)));
require_once $root . '/scripts/__init_script__.php';
$cache = PhabricatorCaches::getMutableCache();
$authfile_key = PhabricatorAuthSSHKeyQuery::AUTHFILE_CACHEKEY;
$authfile = $cache->getKey($authfile_key);
if ($authfile === null) {
    $keys = id(new PhabricatorAuthSSHKeyQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withIsActive(true)->execute();
    if (!$keys) {
        echo pht('No keys found.') . "\n";
        exit(1);
    }
    $bin = $root . '/bin/ssh-exec';
    foreach ($keys as $ssh_key) {
        $key_argv = array();
        $object = $ssh_key->getObject();
        if ($object instanceof PhabricatorUser) {
            $key_argv[] = '--phabricator-ssh-user';
            $key_argv[] = $object->getUsername();
        } else {
            if ($object instanceof AlmanacDevice) {
                if (!$ssh_key->getIsTrusted()) {
                    // If this key is not a trusted device key, don't allow SSH
                    // authentication.
                    continue;
                }
                $key_argv[] = '--phabricator-ssh-device';
                $key_argv[] = $object->getName();
            } else {
                // We don't know what sort of key this is; don't permit SSH auth.
 /**
  * Retrieve or build a graph cache bucket from the cache.
  *
  * Normally, this operates as a readthrough cache call. It can also be used
  * to force a cache update by passing the existing data to `$rebuild_data`.
  *
  * @param   int     Bucket key, from @{method:getBucketKey}.
  * @param   mixed   Current data, to force a cache rebuild of this bucket.
  * @return  array   Data from the cache.
  * @task cache
  */
 private function getBucketData($bucket_key, $rebuild_data = null)
 {
     $cache_key = $this->getBucketCacheKey($bucket_key);
     // TODO: This cache stuff could be handled more gracefully, but the
     // database cache currently requires values to be strings and needs
     // some tweaking to support this as part of a stack. Our cache semantics
     // here are also unusual (not purely readthrough) because this cache is
     // appendable.
     $cache_level1 = PhabricatorCaches::getRepositoryGraphL1Cache();
     $cache_level2 = PhabricatorCaches::getRepositoryGraphL2Cache();
     if ($rebuild_data === null) {
         $bucket_data = $cache_level1->getKey($cache_key);
         if ($bucket_data) {
             return $bucket_data;
         }
         $bucket_data = $cache_level2->getKey($cache_key);
         if ($bucket_data) {
             $unserialized = @unserialize($bucket_data);
             if ($unserialized) {
                 // Fill APC if we got a database hit but missed in APC.
                 $cache_level1->setKey($cache_key, $unserialized);
                 return $unserialized;
             }
         }
     }
     if (!is_array($rebuild_data)) {
         $rebuild_data = array();
     }
     $bucket_data = $this->rebuildBucket($bucket_key, $rebuild_data);
     // Don't bother writing the data if we didn't update anything.
     if ($bucket_data !== $rebuild_data) {
         $cache_level2->setKey($cache_key, serialize($bucket_data));
         $cache_level1->setKey($cache_key, $bucket_data);
     }
     return $bucket_data;
 }
Esempio n. 16
0
 private function writeCacheData(array $keys, array $blame)
 {
     $writes = array();
     foreach ($keys as $path => $key) {
         $value = idx($blame, $path);
         if ($value === null) {
             continue;
         }
         // For now, just store the entire value with a "raw" header. In the
         // future, we could compress this or use IDs instead.
         $value = "raw\n" . implode("\n", $value);
         $writes[$key] = $value;
     }
     if (!$writes) {
         return;
     }
     $cache = PhabricatorCaches::getImmutableCache();
     $data = $cache->setKeys($writes, phutil_units('14 days in seconds'));
 }
Esempio n. 17
0
 /**
  * Destroy the request cache.
  *
  * This is called at the beginning of each logical request.
  *
  * @return void
  */
 public static function destroyRequestCache()
 {
     self::$requestCache = null;
 }
 private function renderPhabricatorLogo()
 {
     $style_logo = null;
     $custom_header = PhabricatorEnv::getEnvConfig('ui.custom-header');
     if ($custom_header) {
         $cache = PhabricatorCaches::getImmutableCache();
         $cache_key_logo = 'ui.custom-header.logo-phid.v1.' . $custom_header;
         $logo_uri = $cache->getKey($cache_key_logo);
         if (!$logo_uri) {
             $file = id(new PhabricatorFileQuery())->setViewer($this->getUser())->withPHIDs(array($custom_header))->executeOne();
             if ($file) {
                 $logo_uri = $file->getViewURI();
                 $cache->setKey($cache_key_logo, $logo_uri);
             }
         }
         if ($logo_uri) {
             $style_logo = 'background-size: 96px 40px; ' . 'background-position: 0px 0px; ' . 'background-image: url(' . $logo_uri . ');';
         }
     }
     $color = PhabricatorEnv::getEnvConfig('ui.header-color');
     if ($color == 'light') {
         $color = 'dark';
     } else {
         $color = 'light';
     }
     return phutil_tag('a', array('class' => 'phabricator-main-menu-brand', 'href' => '/'), array(javelin_tag('span', array('aural' => true), pht('Home')), phutil_tag('span', array('class' => 'sprite-menu phabricator-main-menu-eye ' . $color . '-eye'), ''), phutil_tag('span', array('class' => 'sprite-menu phabricator-main-menu-logo ' . $color . '-logo', 'style' => $style_logo), '')));
 }
 /**
  * @task order
  */
 public function getOrderableColumns()
 {
     $cache = PhabricatorCaches::getRequestCache();
     $class = get_class($this);
     $cache_key = 'query.orderablecolumns.' . $class;
     $columns = $cache->getKey($cache_key);
     if ($columns !== null) {
         return $columns;
     }
     $columns = array('id' => array('table' => $this->getPrimaryTableAlias(), 'column' => 'id', 'reverse' => false, 'type' => 'int', 'unique' => true));
     $object = $this->newResultObject();
     if ($object instanceof PhabricatorCustomFieldInterface) {
         $list = PhabricatorCustomField::getObjectFields($object, PhabricatorCustomField::ROLE_APPLICATIONSEARCH);
         foreach ($list->getFields() as $field) {
             $index = $field->buildOrderIndex();
             if (!$index) {
                 continue;
             }
             $digest = $field->getFieldIndex();
             $key = $field->getModernFieldKey();
             $columns[$key] = array('table' => 'appsearch_order_' . $digest, 'column' => 'indexValue', 'type' => $index->getIndexValueType(), 'null' => 'tail', 'customfield' => true, 'customfield.index.table' => $index->getTableName(), 'customfield.index.key' => $digest);
         }
     }
     $cache->setKey($cache_key, $columns);
     return $columns;
 }
Esempio n. 20
0
<?php

phabricator_startup();
try {
    PhabricatorStartup::beginStartupPhase('libraries');
    PhabricatorStartup::loadCoreLibraries();
    PhabricatorStartup::beginStartupPhase('purge');
    PhabricatorCaches::destroyRequestCache();
    PhabricatorStartup::beginStartupPhase('sink');
    $sink = new AphrontPHPHTTPSink();
    try {
        PhabricatorStartup::beginStartupPhase('run');
        AphrontApplicationConfiguration::runHTTPRequest($sink);
    } catch (Exception $ex) {
        try {
            $response = new AphrontUnhandledExceptionResponse();
            $response->setException($ex);
            PhabricatorStartup::endOutputCapture();
            $sink->writeResponse($response);
        } catch (Exception $response_exception) {
            // If we hit a rendering exception, ignore it and throw the original
            // exception. It is generally more interesting and more likely to be
            // the root cause.
            throw $ex;
        }
    }
} catch (Exception $ex) {
    PhabricatorStartup::didEncounterFatalException('Core Exception', $ex, false);
}
function phabricator_startup()
{
 private function writeHealthRecord(array $record)
 {
     $cache = PhabricatorCaches::getSetupCache();
     $cache_key = $this->getHealthRecordCacheKey();
     $cache->setKey($cache_key, $record);
 }
 /**
  * @task pull
  */
 protected function run()
 {
     $argv = $this->getArgv();
     array_unshift($argv, __CLASS__);
     $args = new PhutilArgumentParser($argv);
     $args->parse(array(array('name' => 'no-discovery', 'help' => pht('Pull only, without discovering commits.')), array('name' => 'not', 'param' => 'repository', 'repeat' => true, 'help' => pht('Do not pull __repository__.')), array('name' => 'repositories', 'wildcard' => true, 'help' => pht('Pull specific __repositories__ instead of all.'))));
     $no_discovery = $args->getArg('no-discovery');
     $include = $args->getArg('repositories');
     $exclude = $args->getArg('not');
     // Each repository has an individual pull frequency; after we pull it,
     // wait that long to pull it again. When we start up, try to pull everything
     // serially.
     $retry_after = array();
     $min_sleep = 15;
     $max_futures = 4;
     $futures = array();
     $queue = array();
     while (!$this->shouldExit()) {
         PhabricatorCaches::destroyRequestCache();
         $pullable = $this->loadPullableRepositories($include, $exclude);
         // If any repositories have the NEEDS_UPDATE flag set, pull them
         // as soon as possible.
         $need_update_messages = $this->loadRepositoryUpdateMessages(true);
         foreach ($need_update_messages as $message) {
             $repo = idx($pullable, $message->getRepositoryID());
             if (!$repo) {
                 continue;
             }
             $this->log(pht('Got an update message for repository "%s"!', $repo->getMonogram()));
             $retry_after[$message->getRepositoryID()] = time();
         }
         // If any repositories were deleted, remove them from the retry timer map
         // so we don't end up with a retry timer that never gets updated and
         // causes us to sleep for the minimum amount of time.
         $retry_after = array_select_keys($retry_after, array_keys($pullable));
         // Figure out which repositories we need to queue for an update.
         foreach ($pullable as $id => $repository) {
             $monogram = $repository->getMonogram();
             if (isset($futures[$id])) {
                 $this->log(pht('Repository "%s" is currently updating.', $monogram));
                 continue;
             }
             if (isset($queue[$id])) {
                 $this->log(pht('Repository "%s" is already queued.', $monogram));
                 continue;
             }
             $after = idx($retry_after, $id, 0);
             if ($after > time()) {
                 $this->log(pht('Repository "%s" is not due for an update for %s second(s).', $monogram, new PhutilNumber($after - time())));
                 continue;
             }
             if (!$after) {
                 $this->log(pht('Scheduling repository "%s" for an initial update.', $monogram));
             } else {
                 $this->log(pht('Scheduling repository "%s" for an update (%s seconds overdue).', $monogram, new PhutilNumber(time() - $after)));
             }
             $queue[$id] = $after;
         }
         // Process repositories in the order they became candidates for updates.
         asort($queue);
         // Dequeue repositories until we hit maximum parallelism.
         while ($queue && count($futures) < $max_futures) {
             foreach ($queue as $id => $time) {
                 $repository = idx($pullable, $id);
                 if (!$repository) {
                     $this->log(pht('Repository %s is no longer pullable; skipping.', $id));
                     unset($queue[$id]);
                     continue;
                 }
                 $monogram = $repository->getMonogram();
                 $this->log(pht('Starting update for repository "%s".', $monogram));
                 unset($queue[$id]);
                 $futures[$id] = $this->buildUpdateFuture($repository, $no_discovery);
                 break;
             }
         }
         if ($queue) {
             $this->log(pht('Not enough process slots to schedule the other %s ' . 'repository(s) for updates yet.', new PhutilNumber(count($queue))));
         }
         if ($futures) {
             $iterator = id(new FutureIterator($futures))->setUpdateInterval($min_sleep);
             foreach ($iterator as $id => $future) {
                 $this->stillWorking();
                 if ($future === null) {
                     $this->log(pht('Waiting for updates to complete...'));
                     $this->stillWorking();
                     if ($this->loadRepositoryUpdateMessages()) {
                         $this->log(pht('Interrupted by pending updates!'));
                         break;
                     }
                     continue;
                 }
                 unset($futures[$id]);
                 $retry_after[$id] = $this->resolveUpdateFuture($pullable[$id], $future, $min_sleep);
                 // We have a free slot now, so go try to fill it.
                 break;
             }
             // Jump back into prioritization if we had any futures to deal with.
             continue;
         }
         $this->waitForUpdates($min_sleep, $retry_after);
     }
 }
 protected function run()
 {
     // The trigger daemon is a low-level infrastructure daemon which schedules
     // and executes chronological events. Examples include a subscription which
     // generates a bill on the 12th of every month, or a reminder email 15
     // minutes before a meeting.
     // Only one trigger daemon can run at a time, and very little work should
     // happen in the daemon process. In general, triggered events should
     // just schedule a task into the normal daemon worker queue and then
     // return. This allows the real work to take longer to execute without
     // disrupting other triggers.
     // The trigger mechanism guarantees that events will execute exactly once,
     // but does not guarantee that they will execute at precisely the specified
     // time. Under normal circumstances, they should execute within a minute or
     // so of the desired time, so this mechanism can be used for things like
     // meeting reminders.
     // If the trigger queue backs up (for example, because it is overwhelmed by
     // trigger updates, doesn't run for a while, or a trigger action is written
     // inefficiently) or the daemon queue backs up (usually for similar
     // reasons), events may execute an arbitrarily long time after they were
     // scheduled to execute. In some cases (like billing a subscription) this
     // may be desirable; in other cases (like sending a meeting reminder) the
     // action may want to check the current time and see if the event is still
     // relevant.
     // The trigger daemon works in two phases:
     //
     //   1. A scheduling phase processes recently updated triggers and
     //      schedules them for future execution. For example, this phase would
     //      see that a meeting trigger had been changed recently, determine
     //      when the reminder for it should execute, and then schedule the
     //      action to execute at that future date.
     //   2. An execution phase runs the actions for any scheduled events which
     //      are due to execute.
     //
     // The major goal of this design is to deliver on the guarantee that events
     // will execute exactly once. It prevents race conditions in scheduling
     // and execution by ensuring there is only one writer for either of these
     // phases. Without this separation of responsibilities, web processes
     // trying to reschedule events after an update could race with other web
     // processes or the daemon.
     // We want to start the first GC cycle right away, not wait 4 hours.
     $this->nextCollection = PhabricatorTime::getNow();
     do {
         PhabricatorCaches::destroyRequestCache();
         $lock = PhabricatorGlobalLock::newLock('trigger');
         try {
             $lock->lock(5);
         } catch (PhutilLockException $ex) {
             throw new PhutilProxyException(pht('Another process is holding the trigger lock. Usually, this ' . 'means another copy of the trigger daemon is running elsewhere. ' . 'Multiple processes are not permitted to update triggers ' . 'simultaneously.'), $ex);
         }
         // Run the scheduling phase. This finds updated triggers which we have
         // not scheduled yet and schedules them.
         $last_version = $this->loadCurrentCursor();
         $head_version = $this->loadCurrentVersion();
         // The cursor points at the next record to process, so we can only skip
         // this step if we're ahead of the version number.
         if ($last_version <= $head_version) {
             $this->scheduleTriggers($last_version);
         }
         // Run the execution phase. This finds events which are due to execute
         // and runs them.
         $this->executeTriggers();
         $lock->unlock();
         $sleep_duration = $this->getSleepDuration();
         $sleep_duration = $this->runNuanceImportCursors($sleep_duration);
         $sleep_duration = $this->runGarbageCollection($sleep_duration);
         $sleep_duration = $this->runCalendarNotifier($sleep_duration);
         $this->sleep($sleep_duration);
     } while (!$this->shouldExit());
 }
 /**
  * Test if we've survived through setup on at least one normal request
  * without fataling.
  *
  * If we've made it through setup without hitting any fatals, we switch
  * to render a more friendly error page when encountering issues like
  * database connection failures. This gives users a smoother experience in
  * the face of intermittent failures.
  *
  * @return bool True if we've made it through setup since the last restart.
  */
 public static final function isInFlight()
 {
     $cache = PhabricatorCaches::getServerStateCache();
     return (bool) $cache->getKey('phabricator.in-flight');
 }
 public function forcePopulatePKCS8Cache($pkcs8_key)
 {
     $entire_key = $this->getEntireKey();
     $cache_key = $this->getPKCS8CacheKey($entire_key);
     $cache = PhabricatorCaches::getImmutableCache();
     $cache->setKey($cache_key, $pkcs8_key);
 }
 public static function getViewerSpaces(PhabricatorUser $viewer)
 {
     $cache = PhabricatorCaches::getRequestCache();
     $cache_key = self::KEY_VIEWER . '(' . $viewer->getPHID() . ')';
     $result = $cache->getKey($cache_key);
     if ($result === null) {
         $spaces = self::getAllSpaces();
         $result = array();
         foreach ($spaces as $key => $space) {
             $can_see = PhabricatorPolicyFilter::hasCapability($viewer, $space, PhabricatorPolicyCapability::CAN_VIEW);
             if ($can_see) {
                 $result[$key] = $space;
             }
         }
         $cache->setKey($cache_key, $result);
     }
     return $result;
 }
 protected final function getTransactionHint(PhabricatorPolicyInterface $object)
 {
     $cache = PhabricatorCaches::getRequestCache();
     return $cache->getKey(self::getObjectPolicyCacheKey($object, $this));
 }
Esempio n. 28
0
 public static final function deleteSetupCheckCache()
 {
     $cache = PhabricatorCaches::getSetupCache();
     $cache->deleteKeys(array('phabricator.setup.needs-repair', 'phabricator.setup.issue-keys'));
 }
 protected function serveResource(array $spec)
 {
     $path = $spec['path'];
     $hash = idx($spec, 'hash');
     // Sanity checking to keep this from exposing anything sensitive, since it
     // ultimately boils down to disk reads.
     if (preg_match('@(//|\\.\\.)@', $path)) {
         return new Aphront400Response();
     }
     $type = CelerityResourceTransformer::getResourceType($path);
     $type_map = self::getSupportedResourceTypes();
     if (empty($type_map[$type])) {
         throw new Exception(pht('Only static resources may be served.'));
     }
     $dev_mode = PhabricatorEnv::getEnvConfig('phabricator.developer-mode');
     $map = $this->getCelerityResourceMap();
     $expect_hash = $map->getHashForName($path);
     // Test if the URI hash is correct for our current resource map. If it
     // is not, refuse to cache this resource. This avoids poisoning caches
     // and CDNs if we're getting a request for a new resource to an old node
     // shortly after a push.
     $is_cacheable = $hash === $expect_hash;
     $is_locally_cacheable = $this->isLocallyCacheableResourceType($type);
     if (AphrontRequest::getHTTPHeader('If-Modified-Since') && $is_cacheable) {
         // Return a "304 Not Modified". We don't care about the value of this
         // field since we never change what resource is served by a given URI.
         return $this->makeResponseCacheable(new Aphront304Response());
     }
     $cache = null;
     $data = null;
     if ($is_cacheable && $is_locally_cacheable && !$dev_mode) {
         $cache = PhabricatorCaches::getImmutableCache();
         $request_path = $this->getRequest()->getPath();
         $cache_key = $this->getCacheKey($request_path);
         $data = $cache->getKey($cache_key);
     }
     if ($data === null) {
         if ($map->isPackageResource($path)) {
             $resource_names = $map->getResourceNamesForPackageName($path);
             if (!$resource_names) {
                 return new Aphront404Response();
             }
             try {
                 $data = array();
                 foreach ($resource_names as $resource_name) {
                     $data[] = $map->getResourceDataForName($resource_name);
                 }
                 $data = implode("\n\n", $data);
             } catch (Exception $ex) {
                 return new Aphront404Response();
             }
         } else {
             try {
                 $data = $map->getResourceDataForName($path);
             } catch (Exception $ex) {
                 return new Aphront404Response();
             }
         }
         $xformer = $this->buildResourceTransformer();
         if ($xformer) {
             $data = $xformer->transformResource($path, $data);
         }
         if ($cache) {
             $cache->setKey($cache_key, $data);
         }
     }
     $response = new AphrontFileResponse();
     $response->setContent($data);
     $response->setMimeType($type_map[$type]);
     // NOTE: This is a piece of magic required to make WOFF fonts work in
     // Firefox and IE. Possibly we should generalize this more.
     $cross_origin_types = array('woff' => true, 'woff2' => true, 'eot' => true);
     if (isset($cross_origin_types[$type])) {
         // We could be more tailored here, but it's not currently trivial to
         // generate a comprehensive list of valid origins (an install may have
         // arbitrarily many Phame blogs, for example), and we lose nothing by
         // allowing access from anywhere.
         $response->addAllowOrigin('*');
     }
     if ($is_cacheable) {
         $response = $this->makeResponseCacheable($response);
     }
     return $response;
 }
Esempio n. 30
0
 private static function addNamespaceToCaches(array $caches)
 {
     $namespace = PhabricatorCaches::getNamespace();
     if (!$namespace) {
         return $caches;
     }
     foreach ($caches as $key => $cache) {
         $ncache = new PhutilKeyValueCacheNamespace($cache);
         $ncache->setNamespace($namespace);
         $caches[$key] = $ncache;
     }
     return $caches;
 }