Browse Source

Adds PHP YAF to benchmark

Ilya Sabelnikov 12 years ago
parent
commit
e927d87260

+ 13 - 0
config/php.ini

@@ -868,6 +868,7 @@ default_socket_timeout = 60
 ;
 extension=apc.so
 extension=phalcon.so
+extension=yaf.so
 ;extension=php_bz2.dll
 ;extension=php_curl.dll
 ;extension=php_fileinfo.dll
@@ -1864,3 +1865,15 @@ ldap.max_links = -1
 ; End:
 [apc]
 apc.stat = 0
+
+[yaf]
+yaf.library =
+yaf.action_prefer = 0
+yaf.lowcase_path = 0
+yaf.use_spl_autoload = 0
+yaf.forward_limit = 5
+yaf.name_suffix = 1
+yaf.name_separator=
+yaf.cache_config = 1
+yaf.environ = product
+yaf.use_namespace = 0

+ 9 - 6
installer.py

@@ -8,7 +8,7 @@ class Installer:
   ############################################################
   def install_software(self):
     if self.benchmarker.install == 'all' or self.benchmarker.install == 'server':
-        self.__install_server_software()    
+        self.__install_server_software()
 
     if self.benchmarker.install == 'all' or self.benchmarker.install == 'client':
         self.__install_client_software()
@@ -24,7 +24,7 @@ class Installer:
     # Prerequisites
     #######################################
     self.__run_command("sudo apt-get update", True)
-    self.__run_command("sudo apt-get upgrade", True)    
+    self.__run_command("sudo apt-get upgrade", True)
     self.__run_command("sudo apt-get install build-essential libpcre3 libpcre3-dev libpcrecpp0 libssl-dev zlib1g-dev python-software-properties unzip git-core libcurl4-openssl-dev libbz2-dev libmysqlclient-dev mongodb-clients libreadline6-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt-dev libgdbm-dev ncurses-dev automake libffi-dev htop libtool bison libevent-dev libgstreamer-plugins-base0.10-0 libgstreamer0.10-0 liborc-0.4-0 libwxbase2.8-0 libwxgtk2.8-0 libgnutls-dev libjson0-dev libmcrypt-dev libicu-dev cmake gettext", True)
 
     self.__run_command("cp ../config/benchmark_profile ../../.bash_profile")
@@ -94,7 +94,7 @@ class Installer:
     #
     # go
     #
-    
+
     self.__run_command("curl http://go.googlecode.com/files/go1.1rc1.linux-amd64.tar.gz | tar xvz")
 
     #
@@ -125,6 +125,9 @@ class Installer:
     self.__run_command("git clone git://github.com/phalcon/cphalcon.git")
     self.__run_command("sudo ./install", cwd="cphalcon/build")
 
+    # YAF
+    self.__run_command("sudo pecl install yaf")
+
     #
     # Haskell
     #
@@ -142,7 +145,7 @@ class Installer:
     self.__run_command("sudo ringo-admin install ringo/stick")
     self.__run_command("sudo ringo-admin install oberhamsi/reinhardt")
     self.__run_command("sudo ringo-admin install grob/ringo-sqlstore")
-    
+
     #
     # Mono
     #
@@ -360,14 +363,14 @@ class Installer:
 
     # Insert data
     mysql -uroot -psecret < create.sql
-    
+
     ##############################
     # Postgres
     ##############################
     sudo useradd benchmarkdbuser -p benchmarkdbpass
     sudo -u postgres psql template1 < create-postgres-database.sql
     sudo -u benchmarkdbuser psql hello_world < create-postgres.sql
-    
+
     sudo mv postgresql.conf /etc/postgresql/9.1/main/postgresql.conf
     sudo mv pg_hba.conf /etc/postgresql/9.1/main/pg_hba.conf
     sudo -u postgres -H /etc/init.d/postgresql restart

+ 0 - 0
php-yaf/.gitignore


+ 42 - 0
php-yaf/README.md

@@ -0,0 +1,42 @@
+# YAF PHP Benchmarking Test
+
+This is the YAF PHP portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+### JSON Encoding Test
+Use the PHP standard [JSON encoder](http://www.php.net/manual/en/function.json-encode.php)
+
+* [Test RawController::jsonAction()](app/modules/Bench/controllers/Raw.php)
+
+### Data-Store/Database Mapping Test
+
+* [Test RawController::dbAction()](app/modules/Bench/controllers/Raw.php)
+
+### Template (Fortunes) Test
+
+* [Test RawController::fortunesAction()](app/modules/Bench/controllers/Raw.php)
+
+## Infrastructure Software Versions
+
+The tests were run with:
+
+* [YAF 2.2.9](http://www.yafdev.com/)
+* [PHP Version 5.4.14](http://www.php.net/) with FPM, APC and YAF extension
+* [nginx 1.2.8](http://nginx.org/)
+* [MySQL 5.5.31](https://dev.mysql.com/)
+
+## Test URLs
+### JSON Encoding Test
+
+http://localhost:8080/bench/raw/json
+
+### Data-Store/Database Mapping Test
+
+http://localhost:8080/bench/raw/db
+
+### Variable Query Test
+
+http://localhost:8080/bench/raw/db?queries=5
+
+### Fortunes (Template) Test
+
+http://localhost:8080/bench/raw/fortunes

+ 0 - 0
php-yaf/__init__.py


+ 25 - 0
php-yaf/app/Bootstrap.php

@@ -0,0 +1,25 @@
+<?php
+
+use Yaf\Application;
+use Yaf\Bootstrap_Abstract as AbstractBootstrap;
+use Yaf\Dispatcher;
+use eYaf\Layout;
+
+class Bootstrap extends AbstractBootstrap
+{
+    /**
+     * @var Yaf\Config_Abstract
+     */
+    private $config = null;
+
+    public function _initConfig ()
+    {
+        $this->config = Application::app()->getConfig();
+    }
+
+    public function _initLayout (Dispatcher $dispatcher)
+    {
+        $dispatcher->setView(new Layout($this->config->get('application.layout.directory')));
+    }
+
+}

+ 23 - 0
php-yaf/app/conf/application.ini

@@ -0,0 +1,23 @@
+[common]
+application.directory = APP_PATH  "/app"
+application.modules = "Index,Bench"
+application.library = APP_PATH "/library"
+application.library.directory = APP_PATH "/library"
+application.view.ext = phtml
+application.layout.directory = APP_PATH  "/app/views/layouts"
+
+db.connections.default.dsn  = "mysql:host=localhost;port=3306;dbname=hello_world;charset=utf8"
+db.connections.default.user = benchmarkdbuser
+db.connections.default.pass = benchmarkdbpass
+db.connections.default.params.ATTR_ERRMODE = 2 ; PDO::ERRMODE_EXCEPTION
+db.connections.default.params.ATTR_PERSISTENT = TRUE
+
+[dev:common]
+application.dispatcher.throwException=1
+application.dispatcher.catchException=1
+application.debug = TRUE
+
+[product:common]
+application.dispatcher.throwException=0
+application.dispatcher.catchException=0
+application.debug = FALSE

+ 13 - 0
php-yaf/app/controllers/Index.php

@@ -0,0 +1,13 @@
+<?php
+
+use Yaf\Controller_Abstract as AbstractController;
+
+class IndexController extends AbstractController
+{
+
+    public function indexAction ()
+    {
+
+    }
+
+}

+ 62 - 0
php-yaf/app/modules/Bench/controllers/Raw.php

@@ -0,0 +1,62 @@
+<?php
+
+use Yaf\Controller_Abstract as AbstractController;
+
+class RawController extends AbstractController
+{
+
+    public function jsonAction ()
+    {
+        header('Content-type: application/json');
+        die(json_encode(array('message' => 'Hello World!')));
+    }
+
+    public function dbAction ()
+    {
+        $dbh = DatabaseManager::getInstance()->getConnection();
+
+        $query_count = (int) $this->getRequest()->get('queries', 1);
+
+        if (0 >= $query_count) {
+            $query_count = 1;
+        } elseif (500 < $query_count) {
+            $query_count = 500;
+        }
+
+        $arr = array();
+        $id = mt_rand(1, 10000);
+
+        $statement = $dbh->prepare('SELECT `randomNumber` FROM `World` WHERE `id` = :id');
+        $statement->bindParam(':id', $id, \PDO::PARAM_INT);
+
+        while (0 < $query_count--) {
+            $statement->execute();
+            $arr[] = array('id' => $id, 'randomNumber' => $statement->fetchColumn());
+            $id = mt_rand(1, 10000);
+        }
+
+        header('Content-type: application/json');
+        die(json_encode($arr));
+    }
+
+    public function fortunesAction ()
+    {
+        $view = $this->getView();
+        /* @var $view eYaf\Layout */
+
+        $view->setLayout('fortunes');
+
+        $dbh = DatabaseManager::getInstance()->getConnection();
+
+        $statement = $dbh->query('SELECT `id`, `message` FROM `Fortune`');
+
+        $arr = $statement->fetchAll(\PDO::FETCH_KEY_PAIR);
+        $arr[0] = 'Additional fortune added at request time.';
+
+        asort($arr);
+        $view->rows = $arr;
+
+        header('Content-Type: text/html; charset=utf-8');
+    }
+
+}

+ 12 - 0
php-yaf/app/modules/Bench/views/raw/fortunes.phtml

@@ -0,0 +1,12 @@
+<table>
+  <tr>
+    <th>id</th>
+    <th>message</th>
+  </tr>
+  <?php foreach ($rows as $id => $fortune) { ?>
+    <tr>
+      <td><?php echo htmlspecialchars($id, ENT_QUOTES, 'UTF-8'); ?></td>
+      <td><?php echo htmlspecialchars($fortune, ENT_QUOTES, 'UTF-8'); ?></td>
+    </tr>
+  <?php } ?>
+</table>

+ 1 - 0
php-yaf/app/views/layouts/fortunes.phtml

@@ -0,0 +1 @@
+<!DOCTYPE html><html><head><title>Fortunes</title></head><body><?php echo $_content_ ?></body></html>

+ 14 - 0
php-yaf/benchmark_config

@@ -0,0 +1,14 @@
+{
+  "framework": "yaf",
+  "tests": [{
+    "raw": {
+      "setup_file": "setup",
+      "json_url": "/bench/raw/json",
+      "db_url": "/bench/raw/db",
+      "query_url": "/bench/raw/db?queries=",
+      "fortune_url": "/bench/raw/fortunes",
+      "port": 8080,
+      "sort": 107
+    }
+  }]
+}

+ 37 - 0
php-yaf/deploy/nginx.conf

@@ -0,0 +1,37 @@
+worker_processes  8;
+
+events {
+    worker_connections  1024;
+}
+
+http {
+    include       /usr/local/nginx/conf/mime.types;
+    default_type  application/octet-stream;
+    sendfile      on;
+    keepalive_timeout  65;
+
+    server {
+        listen       8080;
+        server_name  localhost;
+
+        root /home/ubuntu/FrameworkBenchmarks/php-yaf/public/;
+        index  index.php;
+
+        location / {
+            try_files $uri /index.php?$args;
+
+            if (-f $request_filename) {
+                expires max;
+                break;
+            }
+        }
+
+        location ~ \.php$ {
+            try_files $uri =404;
+            fastcgi_pass   127.0.0.1:9001;
+            fastcgi_index  index.php;
+            include        /usr/local/nginx/conf/fastcgi_params;
+            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
+        }
+    }
+}

+ 165 - 0
php-yaf/library/DatabaseManager.php

@@ -0,0 +1,165 @@
+<?php
+
+use Yaf\Exception;
+
+/**
+ * Multi-connection database manager
+ *
+ * @author Ilya Sabelnikov <[email protected]>
+ */
+class DatabaseManager
+{
+
+    /**
+     * @var DatabaseManager
+     */
+    protected static $instance = null;
+
+    /**
+     * Initialized database connections
+     *
+     * @var array
+     */
+    protected $connections = array();
+
+    /**
+     * All database connection parameters
+     *
+     * @var array
+     */
+    protected $definedConnections = array();
+
+    private function __construct (array $definedConnections)
+    {
+        $this->definedConnections = $definedConnections;
+    }
+
+    /**
+     * @param array $definedConnections
+     * @return DatabaseManager
+     */
+    public static function getInstance ()
+    {
+        if ( ! isset(self::$instance)) {
+            $definedConnections = Yaf\Application::app()->getConfig()->get('db.connections')->toArray();
+            self::$instance = new self($definedConnections);
+            register_shutdown_function(array(self::$instance, 'resetInstance'));
+        }
+
+        return self::$instance;
+    }
+
+    /**
+     * Initialises database connection by given connection name
+     *
+     * @param string $connectionName
+     * @return \PDO
+     */
+    public function getConnection ($connectionName = 'default')
+    {
+        if ( ! isset($this->connections[$connectionName])) {
+            $this->connections[$connectionName] = $this->createPdoInstance($connectionName);
+        }
+
+        return $this->connections[$connectionName];
+    }
+
+    /**
+     * Initialize connection defined in application.ini under db.connection area
+     *
+     * @param string $connectionName
+     * @return \PDO
+     */
+    protected function createPdoInstance ($connectionName)
+    {
+        $options = $this->getConnectionOptions($connectionName);
+
+        $params = array();
+
+        if (isset($options['params']) && is_array($options['params'])) {
+            foreach ($options['params'] as $key => $val) {
+                $attributeName = '\\PDO::' . $key;
+
+                if ( ! defined($attributeName)) {
+                    throw new Exception(sprintf('Unknown PDO attribute "%s"', $attributeName));
+                }
+
+                $params[constant($attributeName)] = $val;
+            }
+        }
+
+        return new PDO($options['dsn'], $options['user'], $options['pass'], $params);
+    }
+
+    /**
+     * @param string $connectionName
+     * @throws Exception
+     * @return array
+     */
+    protected function getConnectionOptions ($connectionName)
+    {
+        if ( ! $this->hasConnectionOptions($connectionName)) {
+            throw new Exception(sprintf('Unknown connection alias "%s"', $connectionName));
+        }
+
+        return $this->definedConnections[$connectionName];
+    }
+
+    /**
+     * Check whether connection is defined within configuration file
+     *
+     * @param string $connectionName
+     * @return boolean
+     */
+    protected function hasConnectionOptions ($connectionName)
+    {
+        return isset($this->definedConnections[$connectionName]);
+    }
+
+    public function closeConnections ()
+    {
+        foreach (array_keys($this->connections) as $connectionName) {
+            $this->closeConnection($connectionName);
+        }
+    }
+
+    public function closeConnection ($connectionName = 'default')
+    {
+        if ( ! isset($this->connections[$connectionName])) {
+            return false;
+        }
+
+        unset($this->connections[$connectionName]);
+
+        return true;
+    }
+
+    /**
+     * Reset the internal static instance
+     *
+     * @return void
+     */
+    public static function resetInstance ()
+    {
+        if ( ! self::$instance) {
+            return;
+        }
+
+        self::$instance->reset();
+        self::$instance = null;
+    }
+
+    /**
+     * Reset this instance of the manager
+     *
+     * @return void
+     */
+    public function reset ()
+    {
+        $this->closeConnections();
+
+        $this->definedConnections   = array();
+    }
+
+}
+

+ 344 - 0
php-yaf/library/eYaf/Layout.php

@@ -0,0 +1,344 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+namespace eYaf;
+
+
+/**
+ * Layout class used for render layouts and views.
+ *
+ * Layout class allows to use of a base layout skeleton and render views inside
+ * this layout template.
+ * The concept is to not render and display the view template directly but storing it
+ * in {@link $content} property. Then will render the skeleton layout and
+ * pass the {@link $content} property to it.
+ * <code>
+ *  application/views/layouts/front.phtml
+ *
+ *  <html>
+ *      <head>
+ *          <title><?php echo $title ?></title>
+ *      </head>
+ *      <body>
+ *          <?= $_content_ // This is where your view from each action
+ *          will be displayed ?>
+ *      </body>
+ *  </html>
+ * </code>
+ *
+ * If no layout is defined then returns the renderd action view template.
+ *
+ * Also allows to set variable to views and access them from the base
+ * skeleton layout. In above layout $title variable is set to title tag.
+ * Then in a view template we can set the value for $title variable.
+ * <code>
+ *  application/views/index/index.phtml
+ *
+ *  <?php $this->title = "Index Action" ?>
+ *  <h1>Index Action</h1>
+ * </code>
+ *
+ * @author Andreas Kollaros <[email protected]>
+ *
+ */
+class Layout implements \Yaf\View_Interface
+{
+
+    /**
+     * The template engine to render views and layout templates.
+     *
+     * Default engine is Yaf\View\Simple
+     *
+     * @var Yaf\View\Simple
+     */
+    public $engine;
+
+    /**
+     * Options to be passed to template engine.
+     *
+     * @var array
+     */
+    protected $options=array();
+
+    /**
+     *
+     */
+    protected $layout_path;
+
+    /**
+     * The name of layout file without extension.
+     *
+     * @var string
+     */
+    protected $layout = 'layout';
+
+    /**
+     * Handles the rendered action view data.
+     *
+     * @var string
+     */
+    protected $content;
+
+    /**
+     * Array with assigned template variables.
+     *
+     * @var array
+     */
+    protected $tpl_vars = array();
+
+    /**
+     * Template directory.
+     *
+     * @var string
+     */
+    protected $tpl_dir;
+
+    /**
+     * Constructor
+     *
+     * @param array $options key/value pair of options to be assigned to
+     *                       template engine.
+     *
+     * @return void
+     */
+    public function __construct($path, $options=array())
+    {
+        $this->layout_path = $path;
+        $this->options = $options;
+
+
+    }
+
+    /**
+     * Return the instance of a template engine.
+     *
+     * @return Yaf\View\Simple
+     */
+    protected function engine()
+    {
+        $this->engine =  $this->engine ?: new \Yaf\View\Simple(
+            $this->tpl_dir,
+            $this->options
+        );
+
+        return $this->engine;
+    }
+
+    /**
+     * Create engine instance and set the path of views and layout templates.
+     *
+     * Layout path is set by default to layout directory inside views path.
+     *
+     * @param string $path The directory to set as the path.
+     *
+     * @return void
+     */
+    public function setScriptPath($path)
+    {
+        if (is_readable($path)) {
+            $this->tpl_dir = $path;
+            $this->engine()->setScriptPath($path);
+
+            // Overwirte layouts path by setting it where views path is.
+            // This will force layout in modules to be placed in
+            // modules/views/layouts directory
+            $this->layout_path = $path . "/layouts";
+
+            return true;
+        }
+
+        throw new \Exception("Invalid path: {$path}");
+    }
+
+    /**
+     * Getter method for views path.
+     *
+     * @return string
+     */
+    public function getScriptPath()
+    {
+        return $this->engine()->getScriptPath();
+    }
+
+    /**
+     * Setter for Layout::layout variable
+     *
+     * @param string $name the name of layout file without extension.
+     *
+     * @return void
+     */
+    public function setLayout($name)
+    {
+        $this->layout = $name;
+    }
+
+    /**
+     * Getter for Layout::layout variable
+     *
+     * @return string the name of layout file without extension
+     */
+    public function getLayout()
+    {
+        return $this->layout;
+    }
+
+
+    public function setLayoutPath($path)
+    {
+        $this->layout_path = $path;
+    }
+
+    /**
+     * Get full layout path with filename and extension.
+     *
+     * @return string
+     */
+    public function getLayoutPath()
+    {
+        $config = \Yaf\Application::app()->getConfig()->get('application');
+        return $this->layout_path . "/" . $this->layout . ".{$config->view->ext}";
+    }
+
+    /**
+     * Assign a variable to the template
+     *
+     * @param string $name  The variable name.
+     * @param mixed  $value The variable value.
+     *
+     * @return void
+     */
+    public function __set($name, $value)
+    {
+        $this->assign($name, $value);
+    }
+
+    /**
+     * Allows testing with empty() and isset() to work
+     *
+     * @param string $name
+     *
+     * @return boolean
+     */
+    public function __isset($name)
+    {
+        return (null !== $this->engine()->$name);
+    }
+
+    /**
+     * Allows unset() on object properties to work
+     *
+     * @param string $name
+     *
+     * @return void
+     */
+    public function __unset($name)
+    {
+        $this->engine()->clear($name);
+    }
+
+    /**
+     * Assign variables to the template
+     *
+     * Allows setting a specific key to the specified value, OR passing
+     * an array of key => value pairs to set en masse.
+     *
+     * @see __set()
+     *
+     * @param string|array $name  The assignment strategy to use (key or
+     *                            array of key => value pairs)
+     * @param mixed        $value (Optional) If assigning a named variable,
+     *                            use this as the value.
+     *
+     * @return void
+     */
+    public function assign($name, $value = null)
+    {
+
+        $this->tpl_vars[$name] = $value;
+
+        $this->engine()->assign($name, $value);
+    }
+
+    /**
+     * Assign variables by reference to the template
+     *
+     */
+    public function assignRef($name, &$value)
+    {
+        $this->tpl_vars[$name] = $value;
+
+        $this->engine()->assignRef($name, $value);
+    }
+
+    /**
+     * Clear all assigned variables
+     *
+     * Clears all variables assigned to Yaf\View either via
+     * {@link assign()} or property overloading
+     * ({@link __get()}/{@link __set()}).
+     *
+     * @return void
+     */
+    public function clearVars() {
+        $this->tpl_vars = array();
+        $this->engine()->clear();
+    }
+
+    /**
+     * Processes a view and returns the output.
+     *
+     * This method called once from controller to render the given view.
+     * So render the view at $this->content property and then render the
+     * layout template.
+     *
+     * @param string $tpl      The template to process.
+     * @param array  $tpl_vars Additional variables to be assigned to template.
+     *
+     * @return string The view or layout template output.
+     */
+    public function render($tpl, $tpl_vars=array()) {
+
+        $tpl_vars = array_merge($this->tpl_vars, $tpl_vars);
+
+        $this->content = $this->engine()->render($tpl, $tpl_vars);
+
+        // if no layout is defined,
+        // return the rendered view template
+        if (null == $this->layout) {
+
+            return $this->content;
+        }
+
+        // If we assign some variables into view template, then maybe we need
+        // them to layout view.
+        // Hack??
+        // Get template vars from view via Reflection class and assign them to
+        // layout view
+        $ref = new \ReflectionClass($this->engine());
+        $prop = $ref->getProperty('_tpl_vars');
+        $prop->setAccessible(true);
+        $view_vars = $prop->getValue($this->engine());
+
+        $tpl_vars = array_merge($tpl_vars, $view_vars);
+        $tpl_vars['_content_'] = $this->content;
+
+        return $this->engine()->render(
+            $this->getLayoutPath(),
+            $tpl_vars
+        );
+    }
+
+    /**
+     * Directly display the constens of a view / layout template.
+     *
+     * @param string $tpl      The template to process.
+     * @param array  $tpl_vars Additional variables to be assigned to template.
+     *
+     * @return void
+     */
+    public function display($tpl, $tpl_vars=array()) {
+        echo $this->render($tpl, $tpl_vars);
+    }
+
+}

BIN
php-yaf/public/favicon.ico


+ 5 - 0
php-yaf/public/index.php

@@ -0,0 +1,5 @@
+<?php
+
+define('APP_PATH', __DIR__ . '/..');
+$app = new Yaf\Application(APP_PATH . '/app/conf/application.ini', 'product');
+$app->bootstrap()->run();

+ 27 - 0
php-yaf/setup.py

@@ -0,0 +1,27 @@
+import subprocess
+import sys
+import setup_util
+from os.path import expanduser
+
+home = expanduser("~")
+
+def start(args):
+  setup_util.replace_text("php-yaf/app/conf/application.ini", "host=localhost", "host="+ args.database_host +"")
+  setup_util.replace_text("php-yaf/deploy/nginx.conf", "root .*\/FrameworkBenchmarks", "root " + home + "/FrameworkBenchmarks")
+
+  try:
+    subprocess.check_call("sudo chown -R www-data:www-data php-yaf", shell=True)
+    subprocess.check_call("sudo php-fpm --fpm-config config/php-fpm.conf -g " + home + "/FrameworkBenchmarks/php-yaf/deploy/php-fpm.pid", shell=True)
+    subprocess.check_call("sudo /usr/local/nginx/sbin/nginx -c " + home + "/FrameworkBenchmarks/php-yaf/deploy/nginx.conf", shell=True)
+    return 0
+  except subprocess.CalledProcessError:
+    return 1
+
+def stop():
+  try:
+    subprocess.call("sudo /usr/local/nginx/sbin/nginx -s stop", shell=True)
+    subprocess.call("sudo kill -QUIT $( cat php-yaf/deploy/php-fpm.pid )", shell=True)
+    subprocess.check_call("sudo chown -R $USER:$USER php-yaf", shell=True)
+    return 0
+  except subprocess.CalledProcessError:
+    return 1