« May 2008 | Main | July 2008 »
June 30, 2008
Towards Object Oriented Programming in Lua
I've spent a lot of the weekend working on our Lua course ... and for those of you new to this language I'll be sharing a few snippets with you here on "The Horse's Mouth" over coming weeks. Today, I've got a short section which starts to introduce how you can do OO programming in Lua. The section of notes goes on to cover all the OO classics such as Encapsulation, Polymorphism and Inheritance and the course examples for this module are online via here
In Lua, we can keep functions in a table too, and we can bind a series of "metamethods" to a table which give it additional properties We also have syntactic sugar to make the new structures look and run sweetly. All of which leads to an effective Object Oriented capability in Lua, although without the classic keywords "class", "method", "private" etc.
Here are some of the basics - the use of the "." operator, and the storage of a piece of code as a first class function alongside the data.
stuff = {}
stuff["john"] = 14
stuff.dick = 24
function stuff.henry(value)
return value * 2
end
print (stuff.john)
print (stuff["dick"])
print (stuff.henry(16))
print (stuff["john"])
If you're trying to work out the difference between the "." operator and the use of a subscript in square brackets ... don't. They mean the same thing!
Here's how that program runs:
[trainee@easterton u107]$ lua dibdab
14
24
32
14
24
34
[trainee@easterton u107]$
Posted by gje at 06:26 AM | Comments (0)
More about Graham Ellis of Well House ConsultantsJune 29, 2008
Co-routines in Lua - co-operative processing
CoRoutines in Lua allow you to have a number of pieces of co-operative code which (whilst they’re not running in parallel in a true multithreaded way) allow you to progress through multiple strands of your code at the sametime.
Let’s take an example. I have a rather large text file that lists out all the railway stations in the British Isles, together with the number of passengers joining the railway and leaving the railway there, and various other miscellaneous bits of data, and I want to iterate through the data processing it.
The data format is rather ugly - sometimes the numbers are quoted and sometimes not, and there are commas in the numbers over 999 too. Spaces and tabs mean different things, and zero is actually represented by "-". I would love to write code that’s a simple loop that says "get station" as a function call, which would read from the file and process and return the next line ... but there are all sorts of issues with static variables that would need to be considered.
Lua’s "coroutine"s can be created, then resumed (until they yield) time and again, so that in effect using them is like walking up to a coffee machine and pressing the button for the next cup ... which will keep coming while there’s coffee in the machine.
Here’s a snippet of code to call a coroutine ...
instream = coroutine.create(recordfeeder)
while coroutine.status(instream) ~= "dead" do
coroutine.resume(instream)
if fields then
-- process those fields
end
end
Yes, it does look very similar to Java’s iterators, or Python’s generators.
So why don’t I loop through all the records in my incoming file and produce a table of station objects, then write another loop to handle them? Because I don’t really want or need to have 2520 station objects or tables from Waterloo (88,219,856 passengers per year) to Tyndrum Lower (17 passengers in a year) in memory after reading through my data - I want to filter on the fly. Rather than filling a reservoir with water (and having to build it big enough) then draining all the water back out, I prefer to have a pipe with a tap which I can turn on when I need the next record.
The Complete source code for the example I'm talking about here is available here on our web site
Posted by gje at 05:21 PM | Comments (0)
June 28, 2008
Conversion of c/r line ends to l/f line ends
Situation - Excel saved file that I want to read into a Lua program I'm writing on Linux. End of line characters on the Excel file are [cr], and Linux used [lf]. Quick solution - sed
sed 's/\x0d/\x0a/g' stationusage.txt > st2.txt
Literally "substitute globally every hex 0D with a hex 0A"
Posted by gje at 11:52 AM | Comments (0)
June 27, 2008
Some sideways thoughts on the news
"Women to be more equal than men" said the headline on the newspaper sitting on the desk where I was working yesterday - and it struck me that we're more and more in George Orwell's world of Animal Farm and 1984, with some crazy doublespeak and perhaps the thought police out to ensure that everything is done their way. Listening to the BBC's radio coverage later in the day, as I drove home, it seems like something of non-story, allowing employers to select a new employee based on their ethnic background or gender provided that the ethnic background is NOT British and the gender is NOT male and also provided that the candidates being chosen between are otherwise equally qualified. I'm not entirely sure I like the sound of this - on one hand, it's very rare that candidate who are so equal as to make it impossible to select between the otherwise offer - at least in our business, so it would be a non-event. But then I recall being in South Africa some three years ago, and talking with a number of young white men who told me that it was supposed to be equal in job applications there now but it wasn't - they were discriminated against - and I have a disquiet of the same thing coming to this country. Much much better to have a true equality of opportunity without laws that even hint at encouraging positive discrimination.
"I only have the same number of officers as the previous chief constable had 10 years ago" whined the Chief Constable of Lincolnshire in an item following on the radio, telling us how hard done by his force is. In fact it put in such a big extra rates demand on the local population that the council is having to re-issue lower tax demands after they were capped. But hang on a minute - why does he need more officers - or even the same number - when technology has moved on so far and should have lead to a system under which each officer can do a lot more work? Perhaps there's something wrong here, too?
And so the radio moved on to a discussion between two Anglicans - one supporting the view that homosexuals should have a full and equal role in the church, and the other the view that The Bible speaks against it, so it should be eliminated from the church. Stopped at Oxford service area, I made a note of some particularly questionable statement made during the argument, but I can't read my own scrawl now so I'm not able to quote it back word by word. In fact, the whole thing seems so irrelevant to me that I can't even recall which side came up with the particular crass piece of propaganda that made up the third news item in a row that left me wondering at the sanity of our leaders, order keepers, and spiritual guides.
Posted by gje at 08:53 PM | Comments (0)
June 26, 2008
cannot restore segment prot after reloc message - PHP / httpd
Here's a message that we got yesterday when building some of the machines on our Lamp deployment course
[root@easterton apache2]# ./bin/apachectl start
Syntax error on line 233 of /usr/local/apache2/conf/httpd.conf:
Cannot load /usr/local/apache2/modules/libphp5.so into server: /usr/local/apache2/modules/libphp5.so: cannot restore segment
prot after reloc: Permission denied
[root@easterton apache2]#
This is NOT a syntax error in the httpd.conf file in spite of the error message - but it does (correctly) point to a line number at which it had an issue.
And in this case the issue is ... the security setting for SELinux that was selected at the time the operating system was installed. To get past the problem and allow the PHP Install to complete, we just turned enforcement off ..
[root@easterton apache2]# setenforce 0
[root@easterton apache2]# ./bin/apachectl start
[root@easterton apache2]#
(Note Linux's usual "no news is good news" confirmation that this has worked!)
Extra Note - the setenforce 0 should also be run before you do your make install for PHP ... to prevent the following error:
Installing PEAR environment: /usr/local/lib/php
/home/graham/haddenham/php-5.2.5/sapi/cli/php: error while loading
shared libraries: /usr/local/mysql/lib/libmysqlclient.so.16: cannot
restore segment prot fter reloc: Permission denied
make[1]: *** [install-pear-installer] Error 127
make: *** [install-pear] Error 2
Posted by gje at 06:36 AM | Comments (0)
Useful link: PHP training
June 25, 2008
Virtual Hosting on Apache httpd - a primer example
A single web server computer, running a single Apache httpd daemon, can serve many domains through virtual hosting - usually "named virtual hosting" which allows a single IP address to be used for all the different domains.
Here is how it works ...
• you set up all your defaults in the main httpd.conf file
• your FIRST virtual host contains everything that differs from these defaults for hosts that are not otherwise defined in any later virtualhost blocks, and also for any requests that do not include a host name.
• subsequent virtual host blocks provide the changes from the initial defaults for specific hosts or hosts, as specified by the servername directive(s) within each block.
Here's an example of the end on an httpd.conf file
NameVirtualHost *:80
#
<VirtualHost *:80>
</VirtualHost>
#
include conf/stuffing.txt
#
<VirtualHost *:80>
ServerName www.hussey.co.uk
DocumentRoot /home/hussey/html
CustomLog /home/hussey/logs/villagepeople.log combined
</VirtualHost>
all host names are served by the defaults, except www.hussey.co.uk which has a different document root and log file. There's also probably another virtual host included in stuffing.txt ....
<VirtualHost *:80>
ServerName www.royaloak.waddy
DocumentRoot /home/royaloak/html
CustomLog /home/hussey/logs/villagepeople.log combined
</VirtualHost>
Yes - the domain www.royaloak.waddy is also served from a different directory.
Above example from yesterday's Linux Web Server course
Posted by gje at 09:16 AM | Comments (0)
June 24, 2008
FTP - how not to corrupt data (binary v ascii)
Greetings from Aylesbury ... where I am spending much of this week during the day giving a Linux (LAMP) course, and much of the evening catching up on work. So just a brief tip today ..
If you're transferring files with FTP, remember to specify Binary mode!.
Perhaps advise you've heard before and not fully understood why or perhaps - like most of us - something you've heard, forgotten, and then transferred a file to find that your hard-gotten data is corrupted.
In the default (ASCII) mode of transfer between windows and Linux / Unix systems, FTP translates new line sequences c/r, l/f to just l/f, or vice versa - thus effectively corrupting zip files, tar files, etc. It's made the worse by the fact that the mapping doesn't exactly reverse when you transfer the file the other way ... so a transfer from Linux to Windows in ASCII, followed by a transfer back also in ASCII leaves you with a corrupted file
Posted by gje at 10:25 PM | Comments (0)
June 22, 2008
Short circuit evaluation (lazy operator) in Lua
In Lua, if a partial expression evaluates to true the following section will NOT be evaluated if it follows an or because the whole thing cannot be true.
If a partial expression evaluates to false, the following section will NOT be evaluated if it follow an and because the whole thing must be true.
If you find this a bit theoretic, try a real life example ...
If you're going to buy a kebab OR Fish and Chips and you find the kebab shop open, you won't bother to carry on up the road to the chippy because you have already met your needs.
If you require a hammer AND nails, but you can't find a hammer, you won't go and search for the nails because even if you find them, they're not going to be much use to you!
Let's see some code ...
function agelimit(incoming)
return type(incoming) == "number" and incoming or 18
end
-- And the code to call that function ...
print (agelimit(10))
print (agelimit(12))
print (agelimit("fourteen"))
print (agelimit(16))
And when you run that, you get ...
[trainee@easterton u106]$ lua lazy
10
12
18
16
[trainee@easterton u106]$
If you're wanting to learn to program in Lua and you're looking for a training course, please ask us (email info@wellho.net). Although we're not [yet?] offering a scheduled public course, we are running private courses for two different groups:
• Delegates with no prior programming experience
• Delegates who have programming experience, but are new to Lua.
Course can be run for groups of 3 to 10 delegates, and vary in length from 2 to 4 days depending on the background of the delegates, the size of the class, and just how deep you want us to go into certain aspects.
Some sample quotations:
• At our training centre - Melksham, Wiltshire, England
• At your office in the UK - example - Coventry, England
• At your office in the Ireland - example - Dublin
• At your office in the USA - example - New York State
Posted by gje at 12:42 AM | Comments (0)
June 21, 2008
Two PHP include files to make easy web site indexing and navigation
My 'work' in campaigning for an appropriate train service on our local "TransWilts" line started three years ago now (!) with the Save the Train web site ... and grew to include the First Great Western coffeeshop (forum) covering all services in a wedge to the West of London, once we realised that we're not alone here in Wiltshire in feeling that the Passenger (and want-to-be passenger)'s voice doesn't get heard in the corridors of power at the Department for Transport, at First Group, and at the various town and county halls - that public rail transport is an area where the customer is NOT always of top priority to the specifier, operator or public servant.
There's a steadily increasing flow of "documents" associated with all this work - ranging from informational photographs to show locations through spread sheets and timetables and other documents released to us under Freedom of Information and other disclosure rules ... and a need to make them more easily available. And so the site at raildocuments.org.uk which Lee (of canber) is looking after.
How to look after these documents? Well - for the initial stages I've used two simple PHP files that can be called up from the home page (or any other page, come to think of it!)
The first script - (see code here) - generates links to all the subdirectories which have their own home pages, and it references them by the subject of the index page.
The second script - (see code here) - generates links to all the individual files within other specified subdirectories.
Together, the two provide a quick and neat set of navigation tools to allow users to find the document the need quickly and easily on a site of modest size, and provide the site owner / maintainer with a structure in which he can add in extra resources / documents without having to go through a procedure to update all the links and indexes.
See the current docs using the scripts here ...
Posted by gje at 02:02 PM | Comments (0)
Useful link: PHP training
June 20, 2008
Plenty of car parking at Well House Manor, Hotel, Melksham
In an ideal world, business at Well House Manor would be evenly spread through the day ... but it doesn't always work out that way. This morning, we were serving breakfast for two dozen in "The Wilts", for our hotel guests - NOT part of the two dozen - in "The Whitworth" - and we had a small group arriving for a catered meeting in "The Berks" from 9 O'clock.
Fortunately, we have plenty of parking and we designed our layout to allow people to park on the grass
from time to time - and this is what happened this morning. I counted some 26 cars, with space for another half dozen too.
Some of the "rules" we have applied to our parking:
a) There should be off-road parking for ALL visitors. We do not want people to park in neighbouring streets.
b) Cars should be able to park and leave in any order - no blocking in
c) No mud bath to get to your car
d) Staff cars are to be parked in the worst spaces - not the best ones right by the entrance!
Posted by gje at 12:49 PM | Comments (0)
June 19, 2008
Accounts in PHP - an OO demo
I've written a new demonstration in PHP ...
* a base class of line items for your accounts
* subclasses for bills and invoices you issue
* a sample application that takes a number of bill and invoice items and produces an accounts table and total
All in the ONE course file as a demo ... here.
For a "live" application, the classes would probable be held in a separate file so that they could be shared across between a whole lot of different pages, and of course they would use a lot more attributes and be populated from files or databases
The example will work equally well in PHP5 and PHP4, even though you'll have been told that the OO model has changed between the two version!
Posted by gje at 07:42 PM | Comments (0)
Useful link: PHP training
June 18, 2008
Adding a button to a web page to print the page
How to add a "print me" button on your web page which (err) lets you print your web page ;-)
<form>
<input type=button value="Print me!" onClick="javascript:window.print()">
</form>
Here it is to try out:
Posted by gje at 05:56 PM | Comments (0)
June 17, 2008
Astroturfing - the online definition
Have you noticed how a "real life" term can sometimes get used for an online application? I came across one today - astroturfing which I am told by someone who really knows about these things is now illegal in the UK.
Let's start in real life. Have you even stood at a market stall, as the guy on the stand sells a job lot of meat at five quid to the audience ... "and I have more the same" and they all go for a fiver. Great fun to watch, lovely way to do things - although perhaps more historic than present day. But how to get the price up? How about introducing a stooge in the audience who bids, or taking bids "off the wall" from a fictitious bidder? Not quite the right thing to do.
"Astroturfing" is the same thing on line - setting up another site that's a forum or a chat room, and seeding it with posts and recommendations about your own products. You'll help your search engine rankings, and you'll help to persuade people who reach your site that others (!) recommend you. Hmm - sounds like deceitful advertising and a con to me.
Posted by gje at 08:22 PM | Comments (0)
June 16, 2008
PHP - Sanitised application principles for security and useability
When you write a simple web based application, such as a tax calculator, it's always a good ides to echo back the values that your user filled in to the initial form as a part of the response page. That way, anyone who prints out the resulting screen will know just WHAT the question was that the page answers!
It's also a good idea (a VERY good idea - read mandatory) to sanitise the user's inputs, checking against injection attacks using dingle quotes, < characters, & characters, and so on. These checks help avoid injection attacks with Javascript and HTML, and prepare you against injection attacks against a database you may add later
When you echo back the results page and present a further copy of the form that can be filled in, you should echo the values that the user entered the previous time ... and you need to be careful to sanitise the string and make sure it will accept space characters by quoting back the value when you echo it. Users often need to correct or modify values and resubmit forms, and it's very antisocial of the programmer to present them with a completely blank form as a punishment for making just one mistake!
Finally, keep the bulk of your PHP towards the top of your code and the HTML towards the bottom. That way, you can easily change the look and feel of the page without having to rework the logic, or can easily change the logic without major work on the look and feel
These are techniques that we'll teach you from day one of our PHP Programming Course and we continue with on our PHP Techniques Workshop.
I have just written and presented, in front of my delegates, an example to show these principles all in a single piece of code.
You can see the source here and run it here.
Posted by gje at 06:24 PM | Comments (0)
Useful link: PHP training
June 15, 2008
Software - changes and delays. But courses must run on time!
"The first 90% of a job takes the first 90% of the time ... and the last 10% takes the second 90%." Software projects - so often - seem to overrun, with the job looking like it's nearly done but not quite there while final little bits get sorted out.
"Just as we get used to the look of your web site, you going and $%^&*!@ change it." Have you ever said that, or thought it? I know that I get comfortable with a look and feel and navigation scheme at times, just to find that it's been altered.
I was reminded of these issues a couple of hours ago, with an incoming email humorously announcing the new release of a web site / forum that I frequent (or used to when I had time!) from time to time:
Well grahame, about 6 months ago you may remember us announcing that we were working on a new design (yeah, another one) and we were of the thinking that it would take a week or two to clean up the Webforumz habitat to give it a new look. I think we may have miscalculated just a tad in that prediction however, finally, and after much blood sweat and tears we release Webforumz habitat version 6 million and four. http://www.webforumz.com/
There you go, Rob - a "plug" for your site and your new look and feel. I wish I had time to participate as much as I used to, but I think I'm now in a mode where I have to be very careful what I take on. In both the Hotel AND the training businesses, it is critically important that services are delivered on time, after all, and that is where my priority has to be.
Off in a minute to Chippenham station, to collect a customer off the 21:31 arrival there. He'll be staying with us this week and attending the PHP Course that starts tomorrow morning at 09:00, sharp!
Posted by gje at 08:35 PM | Comments (0)
CSS training - Cascading Style Sheets (UK course)
It's Sunday ... and I've been teaching Cascading Style Sheets (or rather "I've been teaching a customer about cascading style sheets") ... one of our delegates for this week's PHP course asked me to spend a few hours going through CSS with him ahead of time.
Here's an example ... using the "KISS" approach (Keep it Simple, Stupid) to avoid the whole thing getting too complex for its own good. I've chosen to post this today to show you just how much better it is to use classes and divs than other more complex specifiers on standard HTML elements - for I have only to add in another surrounding tag and my standard classes would fail, but the classes go on working.
The source code:
<html>
<head>
<style>
table table {
align: center;
color: red;
background: blue;
}
table table tr td {
padding-left: 100px;
color: yellow;
background: green;
}
.maths{
padding-left: 100px;
color: green;
background: yellow;
}
</style>
</head>
<body>
Flubber<br />
<table width=100%><tr><td width=100% align=center>
<table border=1>
<tr><th>Say what</th><th>To whom</th></tr>
<tr><td><div align=center class=maths>Hello</div></td>
<td>World</td></tr></table>
</td></tr></table>
<br />
</body>
</html>
How it looks:

And you can see the full source listing on its own page here and run it for yourself here
Posted by gje at 02:56 PM | Comments (0)
June 14, 2008
A warm welcome for visitors from the USA
As a hotel, we're here to provide a service to our customers ... and that service includes making them feel at "home away from home", perhaps on their first visit to the UK. There are - literally - millions of visitors to the UK from the USA alone. With two senior members of our team originating from the USA, but now living in the UK, we're better placed than most to provide that warm welcome.
Just this morning, I chatted over breakfast with a guest from the USA who's been with us for the week - a working trip for him, from Southern Georgia to visit a business in Wiltshire. Breakfast was served earlier than normal as he had leave in time to catch his return flight from Heathrow, and conversation ranged from the lovely old villages such as Lacock [pictured, left] where he was taken last night by the business he was visiting, through to whether he should bring his wife next time (he would like to now that he's seen teh country!) and to Pennsylvania - where he originated from, and my wife Lisa went to High School.
So it's not only about making visitors feel at home - it's about all those little extras too. Mayo for a sandwich. Talk of Condiments rather that sauces. Having adaptors to hand for electrical equipment. TVs that deliver not only the UK channels but also a wide range of others that include news of the USA. Rooms that have minifridges, internet access and superking beds even when let as singles. And accepting payment by American Express as well as Visa and Mastercard.
Visa and Mastercard are accepted in "virtually every location you can think of" but American Express is "not as widely accepted in the UK" - source Stick it on the card and personal experience too. However, Amercian Express is a very popular business card - especially for visitors from the USA, and that's our business ... so, yes, we accept Amex alongside the other cards.
Posted by gje at 12:56 PM | Comments (0)
June 13, 2008
Comparing Objects in C++
Comparing two objects
You can run a method on an object in C++ (or in any other OO language) to find an attribute of that object - let's say how costly it is (example, how costly it is to jave your group see a film). But you can't really run a method on TWO or more objects, which is what you would need to do if you were looking for the cosylier.
Solution ... call a method on one object and pass the secondf method in as a parameter ... so the call might look like this:
Film * pry_c = Babysitting[0]->seeer(Babysitting[1]);
You'll notice that the call returns an object of the type that you're comaring and not a cost value. If you want to find the most expensive, you can always call the method that tells you the price of the returned object, but if you wrote the code the other way around you wouldn't be able to get the other details of the object (e.g. which film) from the value you got back.
Here's the code of the seeer method:
Film * Film::seeer(Film * that) {
if (this->see() > that->see()) return this;
return that;
}
this is a reserved word in C++, referring to the current object. that is just my choice of name for the other object we're comparing to.
Comparing a whole array of objects
When it comes to comparing a whole lot of objects, there's a different issue - you can't define a mehod with a completely unknown number of paramaters and it would be hard to code anyway. So to find the costlIEST, you are best advised to use a static method ... so the call would look something like this:
Film * pry_c = Film::seeest(Babysitting,3);
And here's the code for that method:
Film * Film::seeest(Film ** options, int owmany) {
Film * sofar = options[0];
for (int i=1; i<owmany; i++) {
sofar = sofar->seeer(options[i]);
}
return sofar;
}
This starts off by taking element zero as the costliest, then compares it (or the costliest so far) to all the other films in the array .. using the "sofar" varaible to keep note of the costliest so far.
In other languages such as Perl, PHP and Python, you can dynically expand a list or array, and you have functions to tell you how long it is. That is NOT the case in C++, so the method in this example is also provided with a count to tell it how many items to check. The alternative technology here would be to have an array that's longer than you need and put a cardinal value (such as a NULL) after the ens of the data, as is done when you make char arrays into strings.
And Finally
This example is demonstrated using a base class of "Film", but in fact the full example that I wrote during the course this week uses classes of type "Cinema" and "Blockbuster" both of which are derived from "Film". This is a really excellent example of the use of inheritance and polymorphism, as there was only one set of comparators to write and I can use them to compare two cinemas, two blockbusters, or one of each.
You can see the full source code of this example here and learn about things like this on our C++ Course.
Posted by gje at 10:53 AM | Comments (0)
June 12, 2008
What a lot of files! (C++ / Polymorphism demo)
There were no less than SEVEN files in the example I wrote to show a "simple" demonstration of polymorphism in C++ yesterday ...
1. The methods for a base class of file objects - Film.cpp
2. The extra methods on top of the base class for a derived class of Blockbuster objects - Blockbuster.cpp
3. The extra methods on top of the base class for a derived class Cinema.cpp
4. The header file Film.h, for inclusion in each of the above
5. The header file Cinema.h for inclusion in that extended class and the test application
6. The header file Blockbuster.h for inclusion in that extended class and the test application
7. The test application - flix.cpp
Why so many files?
a) Because C++ is a language that is designed for the larger application, and it's not really intended for tiny programs such as this - the seven files are indeed a lot to start off with, but the code can be extended from this trivial job up to something much MUCH bigger.
b) Because each of the sections might be maintained by a separate programmer and so it's a good structure through which that maintainance can be done independently
c) Because the use of header files which are included in two or more of the sections of program allows the programmers to maintain a single set of method descriptions rather than duplicated code, with all the synchronisation and extra headaches that might bring.
And these are all excellent reasons, aren't they?
The complete example is in our source code library. But I have NOT put all seven files up separately, to produce a heptagonal array of extra window when you click on the link ... just click here for a single extra window containing all the source to see the whole example in one go.
Posted by gje at 08:16 AM | Comments (0)
June 11, 2008
Spam Filters ... are working!
From my email this morning ...
Did you receive the e-mail which I sent to you recently (copied here-below)? Please confirm since I have had problems lately with emails intercepted by spam-filters set too high.
"Dear xxxxx. I don't know you, and the email below this header is an unsolicited, bulk sales pitch. It's exactly the sort of thing that my spam filters should catch!"
Posted by gje at 08:28 AM | Comments (0)
June 10, 2008
The Composting Cone Challenge
How fortunate - the odd remaining space at the Garden centre appeared to be one right outside the main door - as we had come to collect a bulky item. But as we pulled into it, we noticed it said "reserved for director". Hmm - a sign points towards the overflow car park and we head off down that tarmaced road that turns into a stony, dusty track.
"Staff car park ONLY" says that opening on the right, with lines of cars behind it - but we carry on along the track to a more remote spot which is clearly in regular use, judging by the one-way-only back gate that's provided (one of those dreadful enclosed turnstiles to make SURE it's only used for in not out) to get into the back of the garden centre.
"Customer Service" says the counter just behind the pay desks at the Garden Centre, and having come along to collect that bulky item - a composting cone which had been ordered and paid for on line, that was the natural desk to go to.
"Oh no - you have to go to reception for that" says the young lady on the counter. And upon further quizzing her, we learn where we can find the reception desk. "Over there ...", pointing up a passageway.
The first unlabelled desk up the passageway is guarded by a formidable lady who tells us that it's NOT reception (I think it was the garden furniture sales desk) as so we explore onwards.
"Is this reception?" I ask the kindly looking lady as the desk a few yards from the main entrance, and I am assured that it is. And Yay! we're there. "We have come to collect this cone" I say handing her the sheet of paper. "You need to go to Customer Service" she tells us ...
That's not the end of the story either, but I think I've said enough to make my point! And I look at such things and try to learn from them for our own customer facing business. A couple of our mantra, confirmed by the garden centre story ...
• Customer parking is a priority over staff parking
• If a customer asks ANY member of staff, that member of staff should take care of the customer him/herself, or if passing they need to pass the customer on to a more appropriate team member they should do so personally.
And on that basis, while I was writing this short article, I have given assistance in using the coffee machine, checked out two guests, and given directions to the Bowerhill industrial area of Melksham, to which we are the nearest hotel.
P.S. We got our composting cone after dealing with five more people. I wonder if it would have been easier at any of the other garden centres - perhaps we should try one of them next time?
Posted by gje at 08:15 AM | Comments (0)
Compiling C programs with gcc - an overview
Gcc - the "Gnu Compiler Collection" - is used to compile AND to link C language programs in an open source environment. A single command - gcc runs a series of phases that take you from source code through to an executable program file, with the actual steps taken works out based on:
• the extensions you give for the files
• command line options
Here are the phases:
1. The C preprocessor (cpp)
2. The C Compiler
3. The Link Loader (ld)
The C Preprocessor takes directives in the source file (that's lines that start with a # character) and acts on them as appropriate - "including" standard files of definitions, replacing "defined" constants via macros, and so on.
The C Compiler takes the preprocessor output and converts it from an ASCII English-like source code into binary code suitable for running on the particular target machine. But is is NOT a complete program yet - just a section of code / a component that needs to be joined to other components.
The last phase - the Link Loader takes all of your components, adds to them others from standard libraries, and creates a complete executable program.
Notes:
a) You'll usually run a whole series of preprocessors and compiles before running a single load, as most programs comprise many source files. Example:
gcc -c tom.c
gcc -c dick.c
gcc -c harry.c
gcc -o tom tom.o dick.o harry.o
In this example, each of three source files is compiled into an object file, and those object files are them joined into an executable file. The -c options is "compile only", and the -o option requests an output file of a none-default name.
b) If you fail to give a -o options on the gcc run that generates a program file, you'll produce a program file called a.out
c) You can do a compile and load all at once:
gcc -o tom tom.c dick.c harry.c
but as your program gets larger, that gets to be more and more repeated compile work when you'll only be changing one or two out of (perhaps) hundreds of source files at a time
d) You can use the make utility to store all your gcc - and other - commands used to build a program, and by noting down in that file a series of dependencies you can
• ensure that only the phases that need re-doing are done
• store the sometimes-complex gcc instructions so you don't have to keep retyping them.
Posted by gje at 07:04 AM | Comments (0)
June 09, 2008
Dynamic Memory Allocation in C
In C, you give fixes sizes for arrays at compile time .... which means you either have to know ahead of time how big something will be, or allow enough space for the worst case scenario.
Rather than using arrays, you can use pointers to the memory heap - and in this way you can use functions to give you dynamic memory allocation:
malloc - allocate a specific memory block
calloc - allocate an array of specific memory blocks
realloc - expand or contract a calloced block
free - release a malloced block
cfree - release a realloced block
There's an example showing how these functions can be used to dynamically load a file with a variable number of variable length records here
Posted by gje at 03:13 PM | Comments (0)
June 08, 2008
What are Unions (C programming)
Structures are used to hold a whole lot of different pieces of data in a collection - by element name not number. Sometimes, you’ll only want to hold some elements of your structure in specific circumstances - a good example is where you have a whole lot of similar things you’re describing, but only a limited range of elements applied to each.
A very good example in real ’system’ programming is an X Windows event - each has a time stamp and a sequence number, and an event type, and each has a target window. But only some of them have X and Y co-ordinates, only some of them have keypresses and statuses, and so on. One possible way of holding such events would be a sparsely populated structure, but in practise this would be very wasteful of memory - so a union is used.
Posted by gje at 03:09 PM | Comments (0)
June 07, 2008
Talk on TransWilts train service to Green Party
This morning, I gave a talk on the "TransWilts" train service - the loss of most trains in 2006 and the campaign for the return of something more appropriate - to the Green Party's Regional meeting in Trowbridge. Here's my presentation, which I'll admit to writing in the few hours ahead of the talk!
Intro
This morning I was watching the BBC news channel.
India. 60% still rely on bus, but cars growing, And gas guzzlers too. "Everyone has the right to travel" becomes "everyone has the right to a car" in the eyes of the motor manufacturers. Result ... traffic chaos, CO2 and other gases and fumes, bus lanes causing road rage, depletion of resources, and a major problem with accidents and injuries on a poorly regulated network.
Yes - people should be able to travel - and the private car has its place - but there are other options too. For the past three years, I have been particularly concerned with travel along what has become known as the A350 corridor - itself a dreadfully biased name based on a road designation.
History
The TransWilts Route .... five largest towns ... not only size but requirement to travel.

At the turn of the millennium, a single morning and evening train provided a peak commuter flow from Frome, Westbury, Trowbridge and Melksham to Chippenham and Swindon. And then in May 2001, the service was increased to 5 trains each way daily.
Very much a minimum cost operation by Wesssex Trains (and actually done, I believe, to earn them pots of extra money under ORCATS which distributes farebox revenue between multiple operators on a line in proportion to the number of trains they run rather than passenger counts on their trains), poorly publicised, old trains, frequently cancelled, a lack of facilities at Melksham in particular - never the less, traffic grew compound at 35% per annum according to the office of the rail Regulator.
BUT that was from a very low base - you up the number of trains from one to five per day, add 35% passengers each year. After one year, the average train is actually carrying less than 50% of the load of the one train a year before, although by the time five years have elapsed all the trains are much busier than the one that you had in 2000 and you have a SUCCESS STORY.
Problem was ... the Strategic Rail Authority surveyed all the trains over a few days in 2002, and used those figures as the basis on which to specify the service to be run under the next Franchise, with a major new timetable from December 2006 for 10 years. Growth rates of around 0.8% to 1.5% were assumed around the region - but then they applied a travel growth figure to train growth which is not at all the same thing. That's why you may have heard of severe overcrowding all over the place - from Severn Tunnel Junction to Trowbridge, and from Oxford to Exeter. The First group, who won the franchise, knew no better than to take the DfT's figures for the more local Wessex Trains area - after all, they were just the InterCity expres train provider and the trusted the DfT where, after all, the guy in charge at the Rail section that had taken over from the SRA by the time tha franchise was let was "one of their own".
A double-whamee on the "TransWilts" though - Low growth forecast from an uncharacteristically low data set while the new service settled in resulted in the complete withdrawal of the new Swindon - Southampton service, and a specification that called for just two round trips a day. Although the spec (SLC2) called for morning and evening peak services in to and out of Swindon, some clever clogs noticed that if you ran the train in to Swindon as early as possibly allowed in the morning, and returned it as late as allowed in the evening, you could run the line without hiring a train to run on it at all - just by using "marginal time" off another line. And those nice people at the DfT even allowed the specification to be changed tp make this cunning plan work.
So, in December 2006 a service that had become popular - a busy 08:18 from Melksham to Swindon, people arriving in the town by rail at 09:00. Leaving Melksham in the middle of the day, or at 17:11, arriving back from Swindon at 18:09. And three other services too. Typical loadings - around 50% of seats taken, 120000 journeys per annum and with capacity to grow.

Replace by a round trip from Swindon at 06:15 in the morning to Westbury, which gets back at a quarter to eight, and another round trip at 18:45, getting back at 20:20. It's far too long a day to be of practical use to most people, and so each of the supposedly peak trains that was retained is now a shadow of its former self and the other two trains are, frankly, virtually empty stock workings.

Campaign
The "Save the Train" Campaign, based in Melksham, was set up after the poorly advertised consultation about the new service had been completed in Summer 2005. Working with all the major players, it is our intent to regain and retain an appropriate service.We have had some success - indeed I have a validated draft timetable for next December which, however, I see see slipping away from us at the moment.
In February, First stated that they would require an annual subsidy of 110k to run the service; peanuts really, if you think of it - it's a pound for each journey at 2006 levels, or 50p per journey in 3 years time if the same growth rate can be resumed and there's no reason why not.
At a meeting with the same grouping in May, it was stated that 330k per annum is now required ... the whole thing is like a game of dare and who can make the most out of whom, with brinkmanship and politics and shareholders playing a major role, and with the passengers being the pawns in the game.
Railway Economics
Who runs the railways?
Network Rail
Train Operating Company
Rolling Stock Providers
And they all point at each other if you ask them a question!
Who controls/finances the railways and makes major decisions?
The Department for Transport
Train Operating Company
Local Transport Authority or PTE
And they all point at each other if you ask them a question!
An example
Look at the "TransWilts", with a service running every 3 hours from Swindon
to Salisbury or Frome, and including a proper peak hour provision.
Rolling Stock Hire - one train - 250,000
Four complete crews - 50k (driver) 30k (conductor) - 330,000
Network Rail Access charges - 250,000
Ancillary (servicing, fuel, etc) 100,000
Total cost - just under 1 million pounds.
Farebox income:
120000 journeys at 5 pounds each - 600,000
Unfortunately, it's not that straightforward though ... if First doesn't run the train, then it has learned (since December 2006) that passengers from all stations except Melksham will divert via Bath, cram onto overcrowded trains it's running up there anyway. First still get the money - but Trowbridge to Swindon commuters take 60 minutes rather that 35 each way. FOR ROAD SCHEMES SUCH AS THE PROPOSED WESTBURY BYPASS, 44p per minute wasted is allowed in the justification case, but in the case of rail it's "Screw the passenger!".
And don't forget that First also runs the Chippenham - Melksham - Trowbridge bus including, it is noted, a service at almost exactly the same time as the one train that does generate traffic. When I last took a look ... there were 3 on the bus and 20 on the train from Chippenham at around 7 p.m.
Cutting Travel
And here's another thought. Do people need to travel so much?
- Moving nearer to work
- More provision of local services
- Working from Home
- Staying away rather than long distance commuting
Looking forward
The roads are clogged ...

And there is and will remain a travel need
There IS a strong case for a service - up to hourly in frequency (according to the County Council, who are one of the least rail friendly in the country). Major traffic flows have been identified and at present their is capacity although that could change if we become a major freight route from Southampton to the Midlands and North.
There are six SSTC (Strategically Significant Towns and Cities) along the TransWilts Route - with 5000 new homes in Trowbridge in the next 20 years, 50% growth in Melksham, and so on all along the route. And the roads are already over congested!
Passengers WILL use the train, but will NOT use the bus. And the bus will get clogged up on the roads anyway. There is a strong case for local bus feeders, for good road / rail interchange - bus, cycle, private car, taxi, and for buses to connect and provide services on lower level routes.
Where the future?
or 
Posted by gje at 06:28 PM | Comments (0)
June 06, 2008
Checking server performance for PHP generated pages
I had a couple of reports recently about web pages from our site being a little slow to load, and my independent spy tells me that they're not bad, but not the world's fastest either. And a little thought lead me to conclude that could be because of the various PHP scripting elements included at the front of each page.
How should I investigate this? I have added in a whole array of microtime(); captures at strategic points in the included code ... like
$timer[14] = microtime();
and I have added a labelling array too:
$tabo[14] = "Starting top of page preps";
And I have added an extra page in which uses the included code, producing an elapsed time analysis - loop code like
foreach (array_keys($timer) as $subs) {
list($ins,$outs) = explode(" ",$timer[$subs]);
# Normalise to second to retain accuracy
if ($oldout == 0) $oldout = $outs;
$elt = ($outs-$oldout) + $ins;
# Format time difference
$newelt = sprintf("%.4f",$elt - $oldelt);
$oldelt = $elt;
print "$elt<br>";
}
Suddenly ... from a black hole which holds the server response for around a second, a series of timings is revealed which gives the "game" away as to where it's worth looking at the efficiency. You can see how my test page runs here and compare it one I did during testing that started like this:
0 0.34967100 1212773196 .
1 0.34970500 1212773196 (0.0000) initialised page script.
2 0.35110600 1212773196 (0.0014) processed whcstd.
3 0.35263500 1212773196 (0.0015) processed webhelpers2.
4 0.23460400 1212773198 (1.8820) processed login.
5 0.23563200 1212773198 (0.0010) processed hotel.
6 0.23650700 1212773198 (0.0009) processed booking.
7 0.23667900 1212773198 (0.0002) recovered booking session.
8 0.23894900 1212773198 (0.0023) set up courses and calendars.
9 0.23900200 1212773198 (0.0001) 4 layer - preprocessor for special cases.
10 0.23907100 1212773198 (0.0001) 4 layer - finish previous page.
11 0.23945500 1212773198 (0.0004) 4 layer - prepare next page.
12 0.24002300 1212773198 (0.0006) 4 layer - Fill in page variables into template.
14 0.24747000 1212773198 (0.0074) Starting top of page preps.
15 0.24776500 1212773198 (0.0003) Connected to database and handled 'navigation on'.
16 0.59276600 1212773198 (0.3450) DDA preference, country, languages handled.
17 0.59296500 1212773198 (0.0002) Identifying browser string.
18 0.41007200 1212773200 (1.8171) Throttling back systems doing a denial of service.
19 0.41257100 1212773200 (0.0025) Recent history database tidied.
20 0.10485400 1212773201 (0.6923) 'See Also' links evaluated.
21 0.21190500 1212773201 (0.1071) User Comments handled.
22 0.21242300 1212773201 (0.0005) Course Price table loaded.
23 0.21324600 1212773201 (0.0008) User's language preference logged.
24 0.21483800 1212773201 (0.0016) Country identified and output tailored.
25 0.21498100 1212773201 (0.0001) Side image and world zone set.
26 0.21500600 1212773201 (0.0000) Top image and data mine set up for Google arrivals.
27 0.21505800 1212773201 (0.0001) Back links calculated.
28 0.21510800 1212773201 (0.0000) Amazon referrals handled.
29 0.21544600 1212773201 (0.0003) Changes to user preferences saved.
Posted by gje at 04:13 PM | Comments (0)
Useful link: PHP training
June 05, 2008
Slow boot and terminal start on Linux boxes
Now this was a mystery. I had two Linux boxes which booted perfectly when used inhouse, but very slowly indeed (10 minutes plus) when in use on a customer site. Very awkward really - we would test out the systems in Melksham and find them fine, but then they would fail in Bristol. Even calling up a terminal window took minutes!
A clue ... with pauses at networking, sendmail and sm-client ... the problem had to be DNS (domain name service) related, but I checked all the systems - good and bad - and found the same name servers in /etc/resolv.conf and the same host line in /etc/nsswitch.conf, namely
hosts files dns
It turns out that the problem is in /etc/hosts. My machines have names like holt.wellho.net, trowbridge.wellho.net, iford.wellho.net and easterton.wellho.net and if the /etc/hosts file contained both the short (trowbridge) and long (trowbridge.wellho.net) names against 127.0.0.1, it worked fine - but if the fully qualified name was missing it was going to DNS and failing to find it away from the office.
Isn't it gauling how - once you have spend what seems like an eternity trackinging something like this down - the final answer is so darned obvious!
Posted by gje at 09:23 PM | Comments (0)
Useful link: Linux training
June 04, 2008
Factory method example - Perl
Utility methods (factorys) are often used to create objects which may be of any of one of a series of different classes, depending on the data passed in. Have a look at this Perl program which reads in data from a log file and creates a list of web site visit objects:
use visit;
open (FH,"ac_20080527");
while ($line = <FH>) {
$current = make visit($line);
push @samples,$current;
}
make visit is actually creating objects of type robot or human - which happen to be subclasses of visit though they don't have to be. Here is the code:
package visit;
sub make {
package visit;
sub make {
$stuff = $_[1];
if ($stuff =~ /slurp|crawl|spider|bot/i) {
return (new robot($stuff));
} else {
return (new human($stuff));
}
}
The result is that the list in the main code ends up containing a list of objects of various types, and using polymorphic methods on those objects, very need code can be used to call in different features of each.
If you want to have a look at the complete source code of both the main application and the visit.pm module, you can open each of them in a separate window here and here. If you want to learn all about OO in Perl (it's great for larger scripting tasks) look at our Perl for Larger Projects Course ... you've just missed one, I'm afraid ... but there will be another one along later this year!
Posted by gje at 08:47 PM | Comments (0)
Useful link: Perl training
June 03, 2008
Example of OO in Perl
Although Perl 5 doesn't use the words "class", "method" or "object" (or any of the other common OO words), it never the less has a very good OO model indeed - here's the source code of an example, together with the result of running the sample. I'll then give you a few clues!
use train;
use bus;
push (@ptl, new train("07:17",2,75));
push (@ptl, new train("06:40",3,60));
push (@ptl, new bus("07:12",2,40));
push (@ptl, new bus("08:10",1,61));
for $tranbit (@ptl) {
print $tranbit;
print " ",$tranbit->getstaff();
print " ",$tranbit->getcapacity();
print " ",$tranbit->getwhat();
print "\n";
}
__END__
The stuff below is comments as held in this
file. Split it out to separate files if you
want to run it!
############### train.pm
package train;
use pt;
@ISA = ("pt");
sub getstaff {
return 1;
}
sub getwhat {
return ("Metal wheeler");
}
1;
############### bus.pm
package bus;
use pt;
@ISA = ("pt");
sub getstaff {
my ($self) = @_;
return $$self{nv};
}
sub getwhat {
return ("Rubber wheeler");
}
1;
####################### pt.pm
package pt;
sub new {
my($class,$time,$nv,$vc)=@_;
my %info;
$info{time} = $time;
$info{nv} = $nv;
$info{vc} = $vc;
bless \%info,$class;
}
sub getcapacity {
my ($self) = @_;
return $$self{nv}*$$self{vc};
}
1;
################## Runs as ...
j8pl grahamellis$ perl tharness
train=HASH(0x801c70) 1 150 Metal wheeler
train=HASH(0x815f60) 1 180 Metal wheeler
bus=HASH(0x815f9c) 2 80 Rubber wheeler
bus=HASH(0x815ff0) 1 61 Rubber wheeler
j8pl grahamellis$
Right. Now ...
A Perl package is a class
A Perl sub is used to define a method
The list @ISA defines inheritance
Perl's bless function defines the container for variables in the object
my defines a locally scoped variable
-> is used to invoke a method on an object
Posted by gje at 05:32 PM | Comments (0)
Useful link: Perl training
June 01, 2008
Python in an afternoon - a lecture for experienced programmers
Last Friday afternoon I was set a challenge - to present Python in three hours to a group of 20 very experience programmers who, however, knew nothing about this particular language.
The session was in Central London - my directions started off with "Get off the Tube at Oxford Circus", so Londoners will know just how central I mean - so I took First Great Western's Penzance express from Westbury into Paddington. It's great to have power at your seat for laptops these days, though the new airline style seats in second class (oops - standard class!) are a bit tight for working on, and the computer jump horribly when the guy in the seat ahead gets up or flops down.
"Python in a nutshell" - no - that's NOT what I entitled the talk, but I went through the various features that will be mainstream for this group (I had had their applications described to me ahead of time), and I concluded with an example which - in less that 1500 bytes including comments - shows a short and simple use of many of the features os the language.
• Variables and Loops
• Comments
• Lists, Tuples, Dictionary
• Functions, Modules, Object use
• Variable scope
• Documentation Strings
• Regular strings, triple quoted strings and raw strings
• Regular Expressions
• Formatted String Outputs
• File Statuses and File Handling.
• Prompting and reading from STDIN
• Exception handling and error exiting
In some horror, I notice that my example doesn't have a single if statement in it but - hey - I don't think I did too badly in getting so much in to a practical piece of code ... [source code here]
grahamellis$ python lfan
This is a program which reads a web server access log
file and counts the number of times each browser has
visited, outputting the results sorted by the number
of accesses
Press return to proceed
Processing 13973 kbytes
1 pd95215e4.dip.t-dialin.net
1 cache-ntc-ab01.proxy.aol.com
1 host-66-81-36-237.rev.o1.com
1 cache-mtc-al03.proxy.aol.com
[snip]
306 sjcd-webcache-3.cisco.com
309 193.116.20.220
327 crawler10.googlebot.com
348 crawler14.googlebot.com
407 ip68-110-77-129.ph.ph.cox.net
970 82-33-81-221.cable.ubr03.trow.blueyonder.co.uk
Total of 67756 visits from 5048 hosts
grahamellis$
How did the afternoon go? Well - I enjoyed it and my whole audience remained, right through to a quarter past five when I finished. A handful of excellent questions afterwards. And a comment from my contact there, who isn't technical himself and had meetings during the afternoon - "Graham - I came back at about five and looked in through the window. The degree of concentration after three hours from everyone was quite remarkable".
Posted by gje at 10:46 AM | Comments (0)
Useful link: Python training