I know little about the new features in PHP 5.3 (shame on me) so the talks by Scott MacVicar and Sebastian Bergmann should be well worth taking in. Stuart Herbert's talk on PHP frameworks is sure to be interesting and no doubt will create plenty of audience discussion. There is lots more with talks about security, cloud computing and a term I had never heard before, database sharding.

My small contribution to the event is to put together a couple of demo applications for the Zero stand. Given my main thing is language interop I thought to start with some PHP/Java Bridge examples. The BIRT stuff I rambled about the other day fits nicely and produces some glossy charts just perfect for a demo [:o)

Thanks to Rob we also have a demo using Apache POI (the project name is a story in itself). POI is interesting because it provides a cross platform library for reading and writing Microsoft Office file formats. POI is really easy to use, just grab the download from the POI web site and extract the three JAR files. In Zero they need to go into the lib directory.

<?php

java_import("org.apache.poi.hslf.HSLFSlideShow");

java_import("org.apache.poi.hslf.usermodel.SlideShow");

$fs = new Java("java.io.FileInputStream", "/test.ppt");

$hsss = new HSLFSlideShow($fs);

$ss = new SlideShow($hsss);

foreach ($ss->getSlides() as $slide) {

echo $slide->getTitle();

}

?>

The code simply iterates through the titles of each PowerPoint slide. All very straightforward and just the tip of the iceberg for what POI can do.

Tuesday, February 17, 2009

PHP is designed to run in multithreaded web servers (such as Apache and IIS). What this means in practice is that a single PHP process concurrently processes multiple browser requests. It does this by having multiple threads, each of which handles one HTTP request at a time.

PHP can also be built for non multithreaded web servers. In this deployment model life is somewhat different because the web server spawns multiple PHP processes. When requests arrive in the web server it farms them out among its pool of PHP worker processes. Each worker process handles just one request at a time.

The pool of worker processes can grow and shrink over time to allow for busy periods. Zero is multithreaded so it handles multiple web requests concurrently in the same process.

I’ve been playing with the Eclipse Business Intelligence and Reporting Tools project (BIRT). BIRT is an open source Eclipse project that provides a whole bunch of stuff around designing and deploying reports and charts. It has a Java API and so I thought it would make a nice demonstration of the PHP/Java Bridge in Zero.

The problem is that BIRT needs to be started once, and only once, in any given process. Once it has been started up, then it is plain sailing to load reports and render them to HTML. The BIRT runtime should be kept around until the process shuts down.

This sounds suspiciously like a singleton pattern (or anti-pattern if you prefer). The trouble is that process wide singletons are hard to implement correctly in PHP. You might think the following snippet would work:

class Singleton {

private static $birt = NULL;

static function getInstance() {

if (self::$birt == NULL) {

self::$birt = new BIRT(...);

}

return self::$birt;

}

}

There are two problems with this. First, at the end of the current request, all statics are cleared away so $birt is reset to NULL. What we want is the BIRT runtime to be kept around forever (or at least until the process shuts down).

The second problem is that on a multithreaded PHP runtime each PHP request gets an independent set of static and global variables. If two requests are being processed, and each calls getInstance, then they will both create an instance of the BIRT class.

The design intent in PHP is that each request looks like it is running in a single threaded PHP process, even though it is actually running in a multithreaded PHP process. But what I want is one (yes really one!) object in a process which can be shared amongst all the threads. The reason this works is that the BIRT runtime is thread safe, meaning that it can be safely used by multiple threads at the same time.

The solution for me turned out to be the Zero Global Context. The Global Context is a storage area in Zero where just about anything can be put. Different bits of the Global Context have different life times. For example, the /request zone is only kept around for the current request. I opted to put the BIRT runtime in the /tmp zone so that it is kept around for the life time of the process. It is also available to all threads running in the same process.

The final piece of the jigsaw was to ensure only one thread actually created the BIRT runtime. Dealing with multiple threads can be something of a headache as race conditions are easily created.

The Global Context provides a solution (albeit slightly crufty) with locking commands. Each thread does a lock, checks to see if the BIRT runtime has already been created (if not then it creates it and puts it in the /tmp zone) and then unlocks.

With a bit of luck I'll get this written up in an developerWorks article soon as the reports look really sweet (cross tabs, charts, compound reports and so).

Subscribe To Ants Blog

About Me

I am a software developer at Celebrus, a small innovative software house based in Newbury, England. I write high performance Java applications for customer intelligence and real time audience personalisation.