The AMP Tango

I have recently moved to a smaller city that can’t quite boast of the public transport system that Mumbai provides to its citizens. It does exist on paper, and when you go out you do have the option of trying to locate a public utility bus or train. But that task is so difficult that most people cave in to the temptation of flagging an auto rickshaw. Even if it costs up to ten times the price of a bus.

Which brings us to another problem that the people of Mumbai never have to face – auto rickshaw drivers often quote a fixed price to take you to your destination. That figure doesn’t always correspond to what the meter might have indicated had it been used. So you can either yield to their demands while feeling frustrated at being robbed in broad daylight, or haggle with them to bring them down to what you might consider a fair price. And if you don’t like haggling too much, the experience isn’t going to be very pleasant.

I spent the afternoon haggling with some rather brilliant code, trying to coax it to work as it was advertised it would. I’m documenting the efforts I went through out here so that I can reduce some of the agony the next time I have to do this.

A Brief Background

Developers and software managers everywhere laud the power and elegance of the Apache, MySQL and PHP stack. Several commercial outfits have built their entire business model around them. I have been going through the ritual of installing these three on Windows for a long time now and yet, I stumble every time I try to integrate them.

Installing Apache is a cinch. The developers have packaged it into a very nice installer that sets it up on your system within minutes. The default settings are fine enough for almost anybody who does not want to play system administrator. And you don’t even need to restart your system in most cases.

Integrating PHP on top of Apache used to be a bit of a task, but lately it’s been becoming easier. I had to add 3 lines to the Apache httpd.conf file to get it to work. There is a huge dependency on the PHP initialization file, php.ini, but the risk is reduced because the default settings in that file too are sufficient for a typical developer machine.

MySQL too comes with its own installer that takes away most of the pain from the setup process.

The Problem

But this is where the ease of use disappears. Making MySQL work with the Apache and PHP stack always seems to be a pain. Since I don’t do this very often, I can’t remember the integration recipe very well. I’m usually not even sure if I faced the same problems the last time around – much less the resolution.

This article is a guideline for me to follow the next time I have to go through installing these applications. The problem I faced and its resolution is still fresh in my mind since I only stepped through it this afternoon.

It all started when I attempted to load the php_mysqli.dll extension to integrate MySQL into the stack. For extensions to load, PHP needs to be given the path to the folder where the .dll files are stored. The default location is the “ext” folder under the PHP root folder. This path is defined in the variable “extensions_dir” in php.ini.

For some reason the path was not interpreted correctly by PHP on start-up. The Apache error log kept showing the following error –

PHP Warning: PHP Startup: Unable to load dynamic library ‘E:\\apps\\php-5.2.3\\ext\\php_mysqli.dll’ – The specified module could not be found.\r\n in Unknown on line 0

The double backslashes in the path baffled me because the value in php.ini was definitely not typed that way. It is a common convention to escape certain characters by placing the backslash before it, so I felt that this was mangling the path.

Resolutions

I searched the web and found that many people have faced this issue. The solutions proposed were varied.

Some suggested that the library file libmysql.dll bundled with PHP 5.2.3 was buggy. I replaced it with the recommended earlier version (from PHP 5.2.1) but the error still persisted. Others suggested that the extensions that were needed could be moved to the System32 folder, so that they would be found by the PATH system variable. But I refused to corrupt my OS folders with such unnecessary files.

The obvious other solution was to add the extensions folder to my system path, which I duly did. But to my surprise the extension still didn’t load. I checked and rechecked that the folder was included in the system path.

By chance I happened to run a script in my browser that called the phpinfo() function. Browsing through the values, I came upon the Apache Environment section that described how Apache interacted within the OS. And that’s where I found the problem. For some reason, even after a restarting the service, Apache continued to maintain the old system variables in its memory. Because of this, PHP didn’t know where to search for extensions and kept returning the same error.

Restarting Windows solved the problem.

I still haven’t figured out why the “extensions_dir” variable doesn’t work as expected. I have tried various combinations of front- and backslashes, besides experimenting with several relative and absolute path names without any luck. Backslashes are always escaped in the error log, although front slashes are left as-is.

In all, I learnt that restarting your machine does often solve problems – not through magic but through simply realigning different portions of memory that may be connected in some obscure manner. Not bad for an afternoon.

WAMP Installation Checklist

For the benefit of those struggling with the kind of problems I faced, here’s the complete checklist to follow when installing the AMP stack on Windows.

  1. Download and install Apache
  2. Download the PHP archive and unzip into a folder of your choice
  3. Add the following line to httpd.conf depending upon the version of Apache installed -LoadModule php5_module “E:/apps/php-5.2.3/php5apache2.dll”
    or
    LoadModule php5_module “E:/apps/php-5.2.3/php5apache2_2.dll”
  4. Add the following line to httpd.conf -AddType application/x-httpd-php .php
  5. Add the following line to httpd.conf -PHPIniDir “E:/apps/php-5.2.3”
  6. Add the PHP folder to the Windows PATH variable.
  7. Restart your system after completing the last step to make sure that Apache refreshes the environment values. For some reason this does not happen simply by restarting Apache.
  8. Download and install MySQL.
  9. Change the extension_dir variable in php.ini to point to the complete path to the extensions directory.
  10. Add the following line to php.ini -extension=php_mysqli.dll
  11. In some situations phpMyAdmin also requires the php_mcrypt.dll and php_mbstring.dll extensions enabled. If needed, uncomment their loader lines in php.ini
  12. Copy libmcrypt.dll to %SYSTEM% folder if you need the php_mcrypt.dll extension to work.

Keeping Count II – A Tale of Many Stores

In my previous post I described Daryl’s experience as a programmer writing an inventory control system for a candy store. Over the next few weeks Betty, the store owner, spread the word about Daryl’s fantastic inventory and billing management software amongst her friends. Daryl was flooded with requests for a computer application “just like the Betty’s”.

So he got down to work again. But Daryl now felt that writing inventory control wasn’t as much fun any more. So he wanted to get away with as little code, in the shortest amount of time as possible. He looked at what he had written for Betty and realised that most of the core inventory code was supposed to work exactly the same. All that was needed was to detail out some business specific stuff such as sale-units. This code could go into a thin layer on top of the code inventory module.

This is what his base Inventory class looks like.

class Inventory
{
    function AddUnits(Units:Number)
    {
        m_units += Units;
    }

    function RemoveUnits(Units:Number)
    {
        m_units -= Units;
    }

    function PrintUnits()
    {
        print("Remaining units: " + m_units);
    }
}

Daryl adds a member variable called FunctionReference and a method called SetUnitConvertor() to this class, which accepts a function reference as a parameter.

function SetUnitConvertor(ObjectReference:Object, FunctionReference:Function)
{
    m_unitConvertor = Delegate.create(ObjectReference, FunctionReference)
}

Then he modifies the PrintUnits() method to use this function reference.

function PrintUnits()
{
    print("Remaining units: " + m_unitConvertor(m_units));
}

He copies the Inventory class into the project for Mr. Coton’s cloth store and adds a class specific to that store inheriting from the Inventory class.

class ClothStoreInventory extends Inventory
{
    function ClothStoreInventory()
    {
        super.SetUnitConvertor(this, ConvertUnitsToLength);
    }

    function ConvertUnitsToLength(Units:Number)
    {
        // Find the total length of cloth sold
        return Units / 1000
    }
}

And another class is added for Mr. Chiseller’s consultancy firm.

class ConsultancyFirmInventory extends Inventory
{
    function ConvertUnitsToTime(Units:Number)
    {
        // Show the number of hours worked
        Seconds = Math.floor(Units / 1000);
        Minutes = Math.floor(Seconds / 60);
        Seconds = Seconds % 60;
        Hours = Math.floor(Minutes / 60);
        Minutes = Minutes % 60;
        return Hours + ":" + Minutes + ":" + Seconds;
    }
}

The result of this hoopla is that the base class will always call the formatting function from its inherited class (which would be quite impossible otherwise without using a messy callback system, or hard-coding the object reference into the base class, or (gasp!) event generation.

“But why use a delegate, you silly goose! The base class can override the PrintUnits() method with whatever it wants to use in its place.”

Well, that’s true. But when you start overriding methods from the base class, it means that the base class has not been designed to anticipate future use. This is a very basic example. But if your PrintUnits() method becomes more elaborate, such as drawing a dialog box with icons and buttons, or maybe even handling multiple output devices such as printers and LCD tickers, replicating all that code in an inherited class is really bad design. By using a delegate, you also allow yourself room to use static utility classes for mundane functions such as this.

Keeping Count I – The Candy Shop

Its been quite a while since I wrote about a serious programming-specific problem. In this two part series I will show you a popular database normalization method, and an alternative use for delegates. All code is written in Flash ActionScript and is purely illustrative.

Betty Green runs a candy shop that is wildly popular with the neighbourhood kids. The sweets she sells are sold by weight or by piece, depending upon the type. For example, peppermints are sold by weight, while chocolate bars are sold by the number of bars purchased. Being a good manager, Betty also keeps a register to track the amount of items of each type that she’s sold. At the end of the day she totals up the register and updates her inventory for the next day.

The system itself is quite good, but Betty would prefer that she didn’t have to wait till the end of the day to check out on which items she’s running low on, because then it means that her supplier can be notified only the next day. If she could let him know sooner, then she could stock up again on the same day and not lose customers.

Betty has received a new computer on her birthday from her aunt, which she feels can be used to good effect in her store. Daryl, a friend of hers, is a computer geek of sorts who has offered to write a software application for her billing and inventory management. He offers her many snazzy features such as automatic SMS order placement to her supplier when inventory falls low, a digital gallery of candies that she can display on an LCD ticker outside her store and of course, email. But what really gets her attention is a boring feature called inventory management. That is, the computer keeps track of her inventory and can give her updates after every sale, which allows her to place orders immediately if stock runs low.

So Daryl gets down to work. One thing that keeps nagging him is that inventory is to be maintained in two different units – grams and number of items. In her book-register, Betty used to draw two columns – one for weight and one for pieces. Whenever a sale was made, she’d fill in the appropriate column based upon the type of sweet she sold. Now, why should the database care how she sells her sweets? That is something that only Betty needs to know when she makes inventory. Daryl designs his database with a single UnitsSold column, in which he stores the number of units of each sale. His application interprets the sale units depending upon the type of sweet and displays the value with the appropriate unit symbols.

This is a simple illustration of an extremely powerful concept in data processing. All data are eventually converted to integers for the processor to work upon. By understanding how those numbers are encoded for abstract data types, you not only understand what’s going on behind the scenes, you can also drop down into the primitive level to perform operations that are not supported on abstract data types. For example, bitwise operators will balk at strings, but will gladly accept integers.

You can easily tell when a person doesn’t understand this, because their tracking database for fifty different activities will contain fifty columns, some of which contain numeric values, some floating point, some boolean and some time. If new activities have to be added, they will add another column to the table and replace the database files. Everything looks okay until someone logs in the next time after the update and finds that their previous scores are all gone. Whoops!

In my next article I’ll explain how multiple data types can be parsed efficiently at runtime, without rewriting too much code. Stay tuned.

Learning ActionScript

When I first jumped into programming in ActionScript about a year ago, I was carrying a lot of baggage with me from 6 years of Director/Lingo development. I was expecting more than just a change in syntax – this was going to be a paradigm shift for me! From coding in a language that comes close to writing a sentence, to something that resembled a real programming language. Heck, it even had {}’s.

Thing’s didn’t go as smoothly as I had expected though. This was nothing like what I had expected or was used to. Code in separate text files? What in heavens name are classpaths? And why does this language have an overdose of ;’s? Being on a tight schedule didn’t help much. I threw in the towel, hacked together something using old school techniques, and just about threw out Flash from my arsenal.

But an opportunity presented itself to give a second shot at Flash. NPAPL contracted their website redesign to Fractal Ink and an important aspect of the project was their portfolio. Since they wanted a lot of glitz into the presentation, this task would generally have been assigned to the designers. But due to the immense volume of data involved (100+ projects), I figured that a data-driven solution would make more sense than having the design team churn out a multi-megabyte, timeline driven file.

So I got to work digging up tutorials on component development, database access and XML parsing. Since the site was being hosted on a Windows server meant that my PHP skills would be of limited help (we ended up using static XML files instead). But the Flash code was pristine. I had finally broken through the glass ceiling.

I don’t remember the instant at which the change came through. But even today as I look upon the code, it looks nice. Simple, easy, readable. It took less than a few seconds to understand how it all fits together. What I remember thinking at that time was “How will I do this in Director”. By abstracting my thoughts out of the unfamiliar syntax of ActionScript, I was able to work my way around the requirements and atleast devise a solution. What remained was a very simple translation exercise, which got underway with ease.

I’ve moved on a lot since then today. I’m not a Flash guru or anything. But then I’d rather not be stuck working in a single environment day-in day-out. The new world of the interweb is rich in technologies, and I’m going to taste them all.

Birds Banned in Mumbai

In an unprecedented move, that could have far reaching consequences on the country’s ornithological populace, the Balasaheb Thackarey led Shiv Sena has officially banned birds from entering the country’s financial capital, Mumbai. Shiv Sena spokespersons say it is an unfortunate step, but is required in order to maintain the dignity of statues and busts scattered throughout the city. Earlier, birds would use these statues as resting points, and defecate upon them. Post this ban, statues will finally be able to heave a sigh of relief for not being mistreated in such a manner. Shiv Sena leader Udhav Thackarey says, “Imagine how you would feel if a bird came and shat upon your brand new outfit? Such is the condition of statues in the city many of which are being subjected to such rude treatment within hours of dedication.”

When asked how the ban will be implemented given the communication barriers between humans and their feathered friends, several creative ideas have been put forth by party members –

  1. Installation of a fine wire net over the entire city with entrance/exit points for non-feathered creatures
  2. Satellite monitoring of the city’s precincts, along with James Bond-style satellite mounted laser’s to pinpoint and annihilate offending birds
  3. Worldwide extermination of birds (a bit difficult to implement given that Shiv Sena’s jurisdiction extends only within Dadar)

Sena leaders have promised their cadres to lay these plans before the state government and demand implementation at the earliest.

In related news, noted animal activist Maneka Gandhi has raised her voice firmly against the Sena stand. Joining hands with her are hard line animal rights organisations AHIMSA and PETA. Although details of their plan of action haven’t been revealed yet, spokespersons for both organisations say their plans will take flight soon.