Archive for the 'Life as a hoster' Category

Life as a hoster, PHP

How I PHP: multiple inheritance

Officially PHP doesn’t support multiple inheritance. There are several ways around this, without having to duplicate code.

Wrapper

The most commonly used method is to use a wrapper object.

<?php
 
abstract class FsNode
{
  public $path;
 
  public function __construct($path) {
    $this->path = $path;
  }
 
  public function rename($newname) {
    rename($this->path, $newname);
    $this->path = $newname;
  }
}
 
class File extends FsNode
{
  public function getContents() {
    return file_get_contents($this->path);
  }
}
 
class Dir extends FsNode
{
  public function scandir() {
    return scandir($this->path);
  }
}
 
class Symlink
{
  protected $node;
 
  public function __construct($node) {
    $this->node  = $node;
  }
 
  public function target($resolve=false) {
    return $resolve ? realpath($this->node->path) : readlink($this->node->path);
  }
 
  public function __call($method, $args) {
    return call_user_func_array(array($this->node, $method), $args);
  }
}
 
$dir = new Dir("/proc");
$linktodir = new Symlink(new Dir("/proc/self"));
 
var_dump($linktodir->scandir()); // Will be called through __call()
echo $linktodir->target(true), "\n";

A disadvantage is that is no longer possible to see if a node is a dir by using instanceof. Also, if most of the methods are defined in the wrapped class, this solution will hurt performance.

Mixin

A far more interesting approach is to use a mixins. When you call a non-static method, $this is always passed to that method. This is also the case if the calling object is not inherited from the called class. We can use that to our advantage to do the reverse of the wrapper.

abstract class FsNode
{
  public $mixin;
  public $path;
 
  public function __construct($path, $mixin=null) {
    $this->path = $path;
    $this->mixin = $mixin;
  }
 
  function rename($newname) {
    rename($this->path, $newname);
    $this->path = $newname;
  }
 
  public  function __call($method, $args) {
    if (isset($this->mixin) && ctype_alnum($method) && is_callable(array($this->mixin, $method))) {
      return eval("return {$this->mixin}::$method(" . (!empty($args) ? '$args[' . join('], $args[', array_keys($args)) . ']' : '') . ");");
    }
    trigger_error("Call to undefined method " . get_class($this) . "::$method()", E_USER_ERROR);
  }
}
 
class File extends FsNode
{
  public function getContents() {
    return file_get_contents($this->path);
  }
}
 
class Dir extends FsNode
{
  public function scandir() {
    return scandir($this->path);
  }
}
 
class Symlink extends FsNode
{
  public function target($resolve=false) {
    return $resolve ? realpath($this->path) : readlink($this->path);
  }
}
 
$dir = new Dir("/proc");
$linktodir = new Dir("/proc/self", 'Symlink');
 
var_dump($linktodir->scandir());
echo $linktodir->target(true), "\n"; // Will be called through __call()

caveat: The Symlink class is never instantiated. Properties defined in the Symlink class are ignored. Also, since Symlink doesn’t extends Dir, it’s not possible to access protected properties defined in Dir.

Compile time mixin

To see if a node is a symlink, you would need to do

if (isset($file->mixin) && ($file->mixin === 'Symlink' || is_subclass_of($file->mixin, 'Symlink'))) {
  //...
}

It would be nicer if you could simply use instance of. This is only possible by defining all combination. We can still use mixins though to prevent having to duplicate code.

abstract class FsNode
{
  protected $mixin;
  // Same as above
}
 
class File extends FsNode
{
  // Same as above
}
 
class Dir extends FsNode
{
  // Same as above
}
 
interface Symlink
{}
 
abstract class Symlink_Methods extends FsNode
{
  public function target($resolve=false) {
    return $resolve ? realpath($this->path) : readlink($this->path);
  }
}
 
class SymlinkFile extends File implements Symlink
{
  protected $mixin = 'Symlink_Methods';
}
 
class SymlinkDir extends Dir implements Symlink
{
  protected $mixin = 'Symlink_Methods';
}
 
$dir = new Dir("/proc");
$linktodir = new SymlinkDir("/proc/self");
 
var_dump($linktodir->scandir());
echo $linktodir->target(true), "\n"; // Will be called through __call()
 
if ($dir instanceof Dir)  ; // True
if ($dir instanceof Symlink)  ; // False
if ($linktodir instanceof Dir)  ; // True
if ($linktodir instanceof Symlink)  ; // True

Life as a hoster, PHP

Suhosin patch for PHP 5.3

The hardened-php project has yet to release a suhosin patch for PHP 5.3.0. We’re already using PHP 5.3, therefore I’ve modified the 0.9.7 patch for 5.2.10 to work with 5.3.0.

-> Download Suhosin patch for PHP 5.3 <-

Javeline / Ajax.org, Life as a hoster, PHP

How I PHP: How to take a website offline.

I’ve seen a lot of methods used to take a website temporarily off-line for maintenance. Most involve a using PHP to disable the site or renaming the index file. There is however a far better method of doing this, by placing the following in the vhost file or in an .htaccess file in the document root:

Header always set Retry-After "Thu, 18 Jun 2009 08:00:00 +0200"
Redirect 503 /

This way you are sure no part of the site is used. Also by returning a 503 http response, search-engine crawlers will not reindex your site right at the moment it is down. You can use ‘ErrorDocument’ to place a different text than the apache default.

Erlang, Javeline / Ajax.org, Life as a hoster, MySQL, PHP, Replies

An alternative way of EAV modelling

I was reading this month’s php|architect. It has a nice article about EAV modeling. I had seen this db structure in other project, but didn’t know that it was called EAV. For those who don’t read php|architect, EAV describes a method of saving a large set of attributes, only some of which apply to an individual entity. Normally you would create a table, with a row for each entity and save each attribute in a column. With EAV you save each attribute as a row.

This makes selecting the data quite tedious. If you can life with some constraints, there is an easier way to do this.
Continue Reading »

Life as a hoster, My linux desktop, PHP

How to get a file extension

How to get a file extension in PHP:

$ext = pathinfo($file_name, PATHINFO_EXTENSION);

How to get a file extension in Perl:

my $ext = ($file_name =~ m/([^.]+)$/)[0];

How to get a file extension in Ruby:

ext = File.extname(file_name)

How to get a file extension in Bash:

ext=${file_name##*.}
name=${file_name%.*}

How to get a file extension in Python (thanks to Jensen):

import os
ext = os.path.splitext(file_name)[1]


Got more? Please post a comment.

Life as a hoster, My linux desktop, MySQL, PHP

Howto Install Xen+Lustre on Ubuntu Gutsy

Send in by Ruben Daniels

Lustre is one of the most popular upcoming open source cluster file systems out there. When you want to run Xen’s from a SAN using Lustre you need to support both in the Linux kernel. Both XEN and Lustre are near mature products. This means there is support for it. But it’s quite difficult to find the right source and to combine it with the right kernel source of each. It took me a week of trial and erroring until I found a combination that worked. Since Google wasn’t much help I wrote this article so it might help you. This installation is Ubuntu Gutsy specific. You can start out with a basic Gutsy installation. Hardy is getting Lustre support, but at the time of this writing the package doesnt match the default kernel of Hardy.

First we apt-get some utilities and Xen packages

apt-get install quilt libc6-xen libxen3.1 linux-image-xen linux-restricted-modules-xen linux-xen python-xen-3.1 xen-docs-3.1 xen-hypervisor-3.1 xen-image-2.6.19-4-server xen-ioemu-3.1 xen-tools xen-utils-3.1

Now we get the kernel from kernel.org

cd /usr/src
wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.22.tar.gz
tar -zxvf linux-2.6.22.tar.gz

The best matching (and stable) lustre source I’ve found is in the Hardy Lustre source package. So we get it and extra it manually:

wget http://ubuntu2.cica.es/ubuntu/ubuntu/pool/universe/l/lustre/lustre-source_1.6.4.2-1_all.deb
dpkg -x lustre-source_1.6.4.2-1_all.deb lustre-1.6.4.2
bunzip2 lustre-1.6.4.2/usr/src/lustre.tar.bz2
tar -xvf lustre-1.6.4.2/usr/src/lustre.tar
mv lustre-1.6.4.2/usr/src/modules/lustre/* lustre-1.6.4.2
rm -R lustre-1.6.4.2/usr -R

The official XEN kernel version is 2.6.18. This is way too old for newer machines. So we’ll get the Gutsy kernel source which contains XEN patches for our 2.6.22 kernel and apply them:

apt-get source linux-source-2.6.22
cd /usr/src/linux-source-2.6.22-2.6.22
cd debian/binary-custom.d/xen/patchset
patch -p1 /usr/src/linux-2.6.22 < 001*
patch -p1 /usr/src/linux-2.6.22 < 002*
patch -p1 /usr/src/linux-2.6.22 < 003*

Now we apply the lustre patches:

cd /usr/src/linux-2.6.22
ln -s /usr/src/lustre-1.6.4.2/lustre/kernel_patches/series/2.6.22-vanilla.series series
ln -s /usr/src/lustre-1.6.4.2/lustre/kernel_patches/patches patches
quilt -av push

Make the Kernel:

make distclean
cp debian/binary-custom.d/xen/patchset/config.i386 .
make menuconfig
make
make install modules_install

If you use kernel modules you need to run the following command to create the ram fs.

mkinitramfs -o /boot/initrd.img-2.6.22 2.6.22

Add the kernel to grub’s menu.lst. You could do this manually, but let’s just use the ubuntu script.

update-grub

Reboot the machine. After reboot build Lustre:

cd /usr/src/lustre-1.6.4.2
./configure --with-linux=/usr/src/linux-2.6.22
make
make install

Reboot the machine again. You should now have a working lustre/xen kernel.

Life as a hoster, PHP, Replies

Wrong PHP prediction: you don’t need to patch PHP to run multiple versions

I read an article on Michael Kimsals blog about how he is waiting for a patch to run different PHP versions on the same Apache server. I think he is misinformed and I highly doubt than someone will write that patch. The solution is here already.

You simple can’t have PHP4 and PHP5 both run as Apache2 module in the same process, because they use a lot of the same internal symbols (variables, function names, etc). If you would change that, nobody would be able to write any extensions which run both on PHP4 and PHP5. However you can run multiple PHP versions as CGI modules and there is no patch required for that.
Continue Reading »

Life as a hoster, PHP

Migrating from PHP4 to PHP5: A strategy for hosts

If you have a shared hosting company and are still running PHP4, you might feel the pressure rising. Articles like ‘Now showing: PHP’s true colors’ basically tell you to make the switch and take the hit, but they do not give any advice how to handle this.

The basic problem is that you can inform your customers that you’re migrating to PHP5, but if you can’t provide a testing platform for your customers, how are they going to know if migrating will break their sites.

A few months ago I’ve posted an article about running multiple Apache instances with different PHP versions. In that article I showed how to make multiple configurations running Apache on different IP addresses. By using different ports instead of different IP addresses, we can give our customers a way to check their site before it goes live.
Continue Reading »

Life as a hoster, PHP

Providing Joomla as shared hosting company

As a shared hosting company, it is nowadays almost required to provide one-click installable web applications to your customers. Packages like Joomla, OS-Commerce and WordPress come to mind.
Providing the installation for this isn’t hard. You can simply copy a directory and redirect. The real problem lies in managing the installed applications. You nor the customer wants to have an outdated version and since you provided the installation you need to provide the upgrade.

The ideal situation would be if Joomla would be installed at a central location, which would be used by all customers. Only configuration files and additional support files would be in the configuration directory. Keeping in mind that you, or at least we, don’t want to set additional limits to our customers, support files include additional languages, modules, etc.
Continue Reading »

Life as a hoster, PHP

Running multiple instances of Apache

Life as a shared hosting provider hasn’t become easier after PHP decided that they would allow compatibility breakage between mayor versions. Some providers managed to keep there customers satisfied while only supporting PHP 4, but lots of new projects are PHP 5 only and the problem will become even bigger when PHP 6 is released.

Usually a daemon (a service for you windows folks) is started once, with only one instance running. The same goes for Apache. However when we look closely at the apache config, we see that variables which prevent apache from being started twice, the pid file, lockfile and ip/port, can be configured. When starting apache, the config file can be specified, which allows to run multiple instances of apache (on different ip’s). Continue Reading »