Asterisk PBX Voicemail - Configuring and Sending Emails the Easy Way

February 24th, 2009 § 7

I have been very disappointed with the voicemail emailing capabilities of Asterisk PBX. If you need to use a SMTP host, it can be a time consuming task to configure sendmail, postfix, etc, to use an external SMTP provider. And once you get the emails to send, customizing and scripting is very limited.

I wanted to be able to use SMTP, add BCC and CC recipients, have full scripting control over the message body and subject, and attach the voicemail recording in the e-mail. It seemed like writing a script and using the ‘mailcmd’ setting in the [general] section of the asterisk voicemail.conf file was a suitable way to handle this, so I took this route.

» Read the rest of this entry «

How I sped up Smarty by 5x on Lighttpd

December 23rd, 2008 § 0

In this article I will discuss how I obtained a 5x speedup on a Smarty driven website on a Lighttpd Web server. This is achieved by enabling Lighttpd to a directly access and serve the cached files directly from the file system, rather than calling into Smarty.

Why is this approach so much faster?

Smarty’s caching engine does a great job at compiling the templates at the correct interval and this creates a drastic speedup compared to recompiling the template on each page request.

However, even when Smarty is serving up cached pages, there is a lot of overhead added to each request when compared to the Web server directly serving the cached page. This is because PHP is still being loaded, the Smarty library is being included, and a small amount of logic is being performed within Smarty before the cached page is finally being passed along.

Is this caching technique right for every situation?

In cases where the cache life must be very short due to frequent changes to the data being rendered, the approach I will explain in this article may not be viable. However, in these cases it would be still possible to use a push method to remove cache when the data changes, versus adding the overhead of checking for changes on each page request. In my opinion, this push approach to caching reduces the cost to the lowest possible value, so if the need for performance is of the utmost importance, then it makes sense to implement this approach.

In my case, the data changes occur infrequently and a combination of clearing the cache on a scheduled interval plus a method to manually force a recompilation of a specific page is adequate, and a worthwhile trade-off for the performance increase. Also, I am a performance junkie.

Implementation Notes

Since Smarty is a flexible library, every implementation is unique. So while I cannot give imperitive instructions on how you can implement this lighttpd cache, can explain how I did it.

This was my lighttpd configuration for the site prior to implementing the cache. It has a few basic rewrite rules so request for a (htm|html) file gets passed to the index.php. This file acts as a handler to determine the actual smarty template to load, enabling the use of friendly URLs.

$HTTP["host"] == "www.site.com" {
    server.document-root = "/var/www/site/html"
    url.rewrite = (
        "/(.*)\.(htm|html)(\?.*)??$" => "/index.php?p=$1",
        "/(.*)/(\?.*)??$" => "/index.php?p=$1",
        "/(.*)/(.*)/$" => "/index.php?p=$1/$2"
    )
}

And after implementing the cache, this is the lighttpd host configuration:

$HTTP["host"] =~ "www.site.com" {
    server.document-root = "/var/www/site/html"
    magnet.attract-physical-path-to = ("/var/www/site/html/rewrite.lua")
}

Below is the code for rewrite.lua (referenced in the lighttpd conf above) which implements to handle the rewrite rules. It checks the file system to determine if a cached file exists, and if so, it serves that file. Otherwise, it rewrites to the index.php handler so smarty can generate the new cache file.

The cache_path variable in the rewrite.lua script is my smarty cache dir ( $smarty->cache_dir ), plus the $smarty->cache_id (mine is blank, be sure to append it to the cache_path variable as a subdir of your smarty cache_dir)

At this point, lighttpd is rewriting all requests to my index.php handler since it will not find a cached copy in the the cache_path dir. I now have to work with the index.php handler file so Smarty will save the compiled HTML files into the cache_path defined in rewrite.lua. To do this, I wrote a custom cache handler function for smarty and stuck it in the index.php file. So far, my Smarty setup is looking like this:

The main thing here is that the caching is enabled, each request will recompile the template, the compile_id is blank, and the cache_dir matches what is set for cache_path in rewrite.lua.

The function server_rewrite_cache_handler() overrides the default smarty cache read/write/clear logic so that the file is saved in the correct directory structure that matches the request that was rewritten from lighttpd.

The one last thing is to disable several lines of code in the smarty/internals/core.write_cache_file.php, as by default Smarty will add some serialized data to the top of the cache data it passes to our custom cache handler function. The changes are shown below and occur around line 65 and 66 of the core.write_cache_file.php file.

    #$_cache_info = serialize($smarty->_cache_info);
    #$params['results'] = strlen($_cache_info) . "\n" . $_cache_info . $params['results'];

That is all, you should see a drastic speedup at this point.

PHP Array to Text Tables

October 31st, 2008 § 1

I needed this for a little project so I coded it up. I haven’t done a lot of tests but it works just fine for formatting the associative arrays I have run through it.

The class supports multi-line rows, limiting the width of the column, and automatically creating a heading based on the keys from the associative array.

Usage and Output Example

Text Table Formatted Output of above example:

+----------+----+---------------------+
| COMPANY  | ID |       BALANCE       |
+----------+----+---------------------+
| AIG      | 1  | -$99,999,999,999.00 |
| Wachovia | 2  | -$10,000,000.00     |
| HP       | 3  | $555,000.000.00     |
| IBM      | 4  | $12,000.00          |
+----------+----+---------------------+

Full class source code after the jump…
» Read the rest of this entry «

Benchmarking PDO and ADOdb Database Abstraction Libraries

June 23rd, 2008 § 2

I was unable to locate a satisfactory benchmark of PDO vs. ADOdb, so I decided create some to get an idea of the performance differences.

I expected PDO to beat ADOdb easily, since PDO is a native PHP library and requires no run-time include. See my Web App benchmarking methodology here to understand why I was unsatisfied with the existing PDO vs ADOdb and PEAR::NET library benchmarks I found online.

» Read the rest of this entry «

Convert from ADOdb Library to PDO

May 30th, 2008 § 0

In the past I used the ADOdb Database Abstraction Library for PHP for a lot of my PHP projects. However, PDO (PHP Data Objects) is now a better fit as it performs better for me and doesn’t require the inclusion of any libraries.

I wanted to make the switch not only for future projects, but also to go back into some of my existing projects that I maintain and covert from ADOdb to PDO. However, I didn’t want to alter thousands of calls to ADOdb methods.

The solution I came up with was to do some more work on my PDO Singleton Class. By adding in the ADOdb methods Execute(), qstr(), GetOne(), and an iterator for the adodb recordsets returned by Execute(), I was able to easily transition to PDO in projects with thousands of lines of code by including this class and creating a new instance of sdb() instead of NewADOConnection() and Connect().

$DB =& new sdb(”mysql:host=localhost;dbname=testdb”, ‘username’, ‘password’);

This is the equivalent of the following ADOdb code: (except it is a singleton)

$DB = NewADOConnection(’mysql’);
$DB->Connect(”localhost”, “username”, “password”, “testdb”);

You can now treat that $DB object just as you would with ADOdb to create a connection to the mysql database ‘testdb’. Note: I have not refactored the error or transaction functions as they were not used in the specific projects I needed this conversion in… but they would be very simple to add.

» Read the rest of this entry «

Where Am I?

You are currently browsing entries tagged with PHP at Tony Landis.