diff --git a/src/storage/connection/base/AphrontDatabaseConnection.php b/src/storage/connection/base/AphrontDatabaseConnection.php index 150f43b96..5d7fd27e2 100644 --- a/src/storage/connection/base/AphrontDatabaseConnection.php +++ b/src/storage/connection/base/AphrontDatabaseConnection.php @@ -1,231 +1,225 @@ getTransactionKey(); if (!isset($levels[$key])) { $levels[$key] = array( 'read' => 0, 'write' => 0, ); } return $levels[$key]; } public function isReadLocking() { $levels = &$this->getLockLevels(); return ($levels['read'] > 0); } public function isWriteLocking() { $levels = &$this->getLockLevels(); return ($levels['write'] > 0); } public function startReadLocking() { $levels = &$this->getLockLevels(); ++$levels['read']; return $this; } public function startWriteLocking() { $levels = &$this->getLockLevels(); ++$levels['write']; return $this; } public function stopReadLocking() { $levels = &$this->getLockLevels(); if ($levels['read'] < 1) { throw new Exception('Unable to stop read locking: not read locking.'); } --$levels['read']; return $this; } public function stopWriteLocking() { $levels = &$this->getLockLevels(); if ($levels['write'] < 1) { throw new Exception('Unable to stop read locking: not write locking.'); } --$levels['write']; return $this; } protected function &getTransactionStack($key) { if (!self::$transactionShutdownRegistered) { self::$transactionShutdownRegistered = true; register_shutdown_function( array( 'AphrontDatabaseConnection', 'shutdownTransactionStacks', )); } if (!isset(self::$transactionStacks[$key])) { self::$transactionStacks[$key] = array(); } return self::$transactionStacks[$key]; } public static function shutdownTransactionStacks() { foreach (self::$transactionStacks as $stack) { if ($stack === false) { continue; } $count = count($stack); if ($count) { throw new Exception( 'Script exited with '.$count.' open transactions! The '. 'transactions will be implicitly rolled back. Calls to '. 'openTransaction() should always be paired with a call to '. 'saveTransaction() or killTransaction(); you have an unpaired '. 'call somewhere.', $count); } } } public function openTransaction() { $key = $this->getTransactionKey(); $stack = &$this->getTransactionStack($key); $new_transaction = !count($stack); // TODO: At least in development, push context information instead of // `true' so we can report (or, at least, guess) where unpaired // transaction calls happened. $stack[] = true; end($stack); $key = key($stack); if ($new_transaction) { $this->query('START TRANSACTION'); } else { $this->query('SAVEPOINT '.$this->getSavepointName($key)); } } public function isInsideTransaction() { $key = $this->getTransactionKey(); $stack = &$this->getTransactionStack($key); return (bool)count($stack); } public function saveTransaction() { $key = $this->getTransactionKey(); $stack = &$this->getTransactionStack($key); if (!count($stack)) { throw new Exception( "No open transaction! Unable to save transaction, since there ". "isn't one."); } array_pop($stack); if (!count($stack)) { $this->query('COMMIT'); } } public function saveTransactionUnless($cond) { if ($cond) { $this->killTransaction(); } else { $this->saveTransaction(); } } public function saveTransactionIf($cond) { $this->saveTransactionUnless(!$cond); } public function killTransaction() { $key = $this->getTransactionKey(); $stack = &$this->getTransactionStack($key); if (!count($stack)) { throw new Exception( "No open transaction! Unable to kill transaction, since there ". "isn't one."); } $count = count($stack); end($stack); $key = key($stack); array_pop($stack); if (!count($stack)) { $this->query('ROLLBACK'); } else { $this->query( 'ROLLBACK TO SAVEPOINT '.$this->getSavepointName($key) ); } } protected function getSavepointName($key) { return 'LiskSavepoint_'.$key; } } diff --git a/src/storage/queryfx/queryfx.php b/src/storage/queryfx/queryfx.php index 91cb5bb37..6195d9c88 100644 --- a/src/storage/queryfx/queryfx.php +++ b/src/storage/queryfx/queryfx.php @@ -1,70 +1,64 @@ executeRawQuery($query); } /** * @group storage */ function vqueryfx($conn, $sql, $argv) { array_unshift($argv, $conn, $sql); - hphp_workaround_call_user_func_array('queryfx', $argv); + call_user_func_array('queryfx', $argv); } /** * @group storage */ function queryfx_all($conn, $sql/*, ... */) { $argv = func_get_args(); - hphp_workaround_call_user_func_array('queryfx', $argv); + call_user_func_array('queryfx', $argv); return $conn->selectAllResults(); } /** * @group storage */ function queryfx_one($conn, $sql/*, ... */) { $argv = func_get_args(); - $ret = hphp_workaround_call_user_func_array('queryfx_all', $argv); + $ret = call_user_func_array('queryfx_all', $argv); if (count($ret) > 1) { throw new AphrontQueryCountException( 'Query returned more than one row.'); } else if (count($ret)) { return reset($ret); } return null; } function vqueryfx_all($conn, $sql, array $argv) { array_unshift($argv, $conn, $sql); - hphp_workaround_call_user_func_array('queryfx', $argv); + call_user_func_array('queryfx', $argv); return $conn->selectAllResults(); } diff --git a/webroot/index.php b/webroot/index.php index 37e22d8f3..9960f30c7 100644 --- a/webroot/index.php +++ b/webroot/index.php @@ -1,187 +1,178 @@ ', where '' ". "is one of 'development', 'production', or a custom environment."); } if (!function_exists('mysql_connect')) { phabricator_fatal_config_error( "The PHP MySQL extension is not installed. This extension is required."); } if (!isset($_REQUEST['__path__'])) { phabricator_fatal_config_error( "__path__ is not set. Your rewrite rules are not configured correctly."); } require_once dirname(dirname(__FILE__)).'/conf/__init_conf__.php'; $conf = phabricator_read_config_file($env); $conf['phabricator.env'] = $env; setup_aphront_basics(); phutil_require_module('phabricator', 'infrastructure/env'); PhabricatorEnv::setEnvConfig($conf); phutil_require_module('phabricator', 'aphront/console/plugin/xhprof/api'); DarkConsoleXHProfPluginAPI::hookProfiler(); phutil_require_module('phabricator', 'aphront/console/plugin/errorlog/api'); set_error_handler(array('DarkConsoleErrorLogPluginAPI', 'handleError')); set_exception_handler(array('DarkConsoleErrorLogPluginAPI', 'handleException')); foreach (PhabricatorEnv::getEnvConfig('load-libraries') as $library) { phutil_load_library($library); } $host = $_SERVER['HTTP_HOST']; $path = $_REQUEST['__path__']; switch ($host) { default: $config_key = 'aphront.default-application-configuration-class'; $config_class = PhabricatorEnv::getEnvConfig($config_key); PhutilSymbolLoader::loadClass($config_class); $application = newv($config_class, array()); break; } $application->setHost($host); $application->setPath($path); $application->willBuildRequest(); $request = $application->buildRequest(); $application->setRequest($request); list($controller, $uri_data) = $application->buildController(); try { $controller->willBeginExecution(); $controller->willProcessRequest($uri_data); $response = $controller->processRequest(); } catch (AphrontRedirectException $ex) { $response = id(new AphrontRedirectResponse()) ->setURI($ex->getURI()); } catch (Exception $ex) { $response = $application->handleException($ex); } $response = $application->willSendResponse($response); $response->setRequest($request); $response_string = $response->buildResponseString(); $code = $response->getHTTPResponseCode(); if ($code != 200) { header("HTTP/1.0 {$code}"); } $headers = $response->getCacheHeaders(); $headers = array_merge($headers, $response->getHeaders()); foreach ($headers as $header) { list($header, $value) = $header; header("{$header}: {$value}"); } // TODO: This shouldn't be possible in a production-configured environment. if (isset($_REQUEST['__profile__']) && ($_REQUEST['__profile__'] == 'all')) { $profile = DarkConsoleXHProfPluginAPI::stopProfiler(); $profile = '
'. ''. '>>> View Profile <<<'. ''. '
'; if (strpos($response_string, '') !== false) { $response_string = str_replace( '', ''.$profile, $response_string); } else { echo $profile; } } echo $response_string; /** * @group aphront */ function setup_aphront_basics() { $aphront_root = dirname(dirname(__FILE__)); $libraries_root = dirname($aphront_root); $root = null; if (!empty($_SERVER['PHUTIL_LIBRARY_ROOT'])) { $root = $_SERVER['PHUTIL_LIBRARY_ROOT']; } ini_set('include_path', $libraries_root.':'.ini_get('include_path')); @include_once $root.'libphutil/src/__phutil_library_init__.php'; if (!@constant('__LIBPHUTIL__')) { echo "ERROR: Unable to load libphutil. Update your PHP 'include_path' to ". "include the parent directory of libphutil/.\n"; exit(1); } // Load Phabricator itself using the absolute path, so we never end up doing // anything surprising (loading index.php and libraries from different // directories). phutil_load_library($aphront_root.'/src'); phutil_load_library('arcanist/src'); } function __autoload($class_name) { PhutilSymbolLoader::loadClass($class_name); } function phabricator_fatal_config_error($msg) { header('Content-Type: text/plain', $replace = true, $http_error = 500); $error = "CONFIG ERROR: ".$msg."\n"; error_log($error); echo $error; die(); } - -/** - * Workaround for HipHop bug, see Facebook Task #503624. - */ -function hphp_workaround_call_user_func_array($func, array $array) { - $f = new ReflectionFunction($func); - return $f->invokeArgs($array); -} -