Friday 31 July 2009

Setting Cache-Control headers and expanding hard drive size in VMWare Server 2.0

This morning I went in the back garden and tried to take some butterfly photos as there were lots of Painted ladys about, and a few whites as well. After sorting the photos on my comp and backing them up, I did a bit more work on my website.

I wanted to try and fix the "The XML source file is unavailable for viewing" error message that I would get in IE when trying to view source. Using Fiddler2, I found that deleting the Cache-Control header would let me view source okay. The Cache-Control header causing the problem was
no-store, no-cache, must-revalidate, post-check=0, pre-check=0

I did some googling and tried putting
<FilesMatch "\.(php)$">
Header set Cache-Control "max-age=3600, must-revalidate"
</FilesMatch>
in my .htaccess file. Unfortunately, I now just got a 500 internal server error. After checking in /etc/apache2/mods-enabled and /etc/apache2/mods-available, I saw that mod_Headers wasn't enabled, but was available. So I did
sudo a2enmod headers
sudo /etc/init.d/apache2 restart

After enabling mod_headers, the page would load, but I was getting 2 sets of Cache-Control headers,
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Cache-Control: max-age=3600, must-revalidate


So I tried changing my .htaccess rule to:
<FilesMatch "\.(php)$">
Header unset Cache-Control
Header set Cache-Control "max-age=3600, must-revalidate"
</FilesMatch>

I also checked all the .conf files in /etc/apache2 and subfolders to see if there were any cache settings in there - there weren't.

But reloading the page, I still got 2 sets of Cache-Control headers.

I tried adding the Cache-Control Header in my Nginx site config on the web server
add_header Cache-Control "max-age=3600, must-revalidate";
But after restarting Nginx, then loading the a page from the web server, I was still getting the same two sets of Cache-Control Headers.

I checked a normal website, and that had normal Cache-Control headers, so it obviously wasn't something funny on my computer adding an extra Cache-Control header to all files. I then checked a non-php file from my own website, and that had just one Cache-Control header, the one I had set in my .htaccess file. So it seemed that PHP was setting a Cache-Control header, and it couldn't be overwritten by the Server (maybe the Server was sending its headers before PHP?)

After lunch I went on Animal Crossing for a bit. Then I tried to find out what it was in my pages that was causing the
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
header to be sent. Doing some research on this, I found it was down to PHP's session management, and the setting of session.cache_limiter in php.ini.

Now I knew this, I had to try and find what cache header would work well for my purposes. I couldn't set Cache-Control: no-cache, as this would mean that the page source would be unviewable in IE (not a problem in itself, but I was having trouble viewing my 404 page in IE6 yesterday, and think it might have to do with IE not caching the page).

Unfortunately the settings that allowed cache weren't any good either - on the an image page the user can change the size that they are viewing an image at. For users without javascript, this involves setting a cookie (which contains their preferred viewing size), then reloading the page, and the image will be sized according to the value stored in the cookie. However, if the page is cached, then when the page is reloaded, it will be reloaded from cache, and so the image is still displayed the same size.

I even tried sending a Cache-Control header of max-age=1, must-revalidate, but this only seemed to contact the server every other page refresh. Eventually I tried not sending any Cache-Control header at all, and this seemed to do the trick - the browser would contact the server for each page request, but you could also view source. I also tried Cache-Control: private, must-revalidate, post-check=0, pre-check=0, and this seemed to work okay as well.

My Ubuntu Virtual Machine was saying that it had run out of hard drive space (I had allocated it 8GB). Yesterday evening I had changed the hard drive size in VMWare Server 2 so that the hard drive size for Ubuntu was 10GB. However, today I was still getting the same message from Ubuntu that it couldn't install any updates because there wasn't enough space.

I found that when you increase the hard drive size in Ubuntu, it doesn't change the size of the partition that Ubuntu is installed on. Doing some googling, it seemed that you should run GParted from the Ubuntu Live CD to increase the partition size.

Unfortunately I couldn't find the ISO file of Ubuntu anywhere, I guess I deleted it. I did have a Kubuntu iso though, so I tried booting the Virtual Machine with that. This turned out to be quite difficult, as the VMWare start up screen that says what key to press for the boot menu only pops up for about half a second.

When I had worked out what key to press (esc) to get into the boot menu, it was still quite difficult as you only get a very short time to press they key, and also you can't keep bashing escape until you get into the boot menu as if you press escape after the boot menu has opened, it will close.

After booting into the Kubuntu iso image, I found that it didn't have any Live option, and I couldn't see any option to run gparted there either. I tried a few physical CDs, and found one with Paragon Partition Magic (or something like that). I booted the virtual machine with that, but couldn't find any way to actually increase the main partition size.

So I downloaded the gparted ISO from the gparted site, which didn't actually take very long, and booted into it. Again, I couldn't see any way to increase the size of the main partition. However, after I had read the GParted Documentation - Getting Free Space, I figured out how to do it.

The problem was that I had my main partition, then an extended partition with the swap space, then the unallocated space. What I had to do was increase the extended partition to use up all the free space. This moved the unallocated space into the extended partition. I then had extend the swap space to use up all the unallocated space. Then reduce the swap space and move it to behind the unallocated space. Then reduce the extended partiton and move it to the right of the unallocated space. Then I could finally extend the main partition into the unallocated space.

After doing all that and pressing apply, I found that the final stage (increasing the size of the main partition) didn't work. I tried resizing the final partition again, and it worked okay. I was left with about 7MB of unallocated space that the main partition couldn't expand into, so I just expanded the swap space into that.

Ubuntu seems to still work okay, and now I can install the updates.

After doing that, I tried setting the correct expires/cache headers in nginx. At first I thought the headers weren't working at all, as firefox was still checking whether each file had been modified or not, and the web server was sending back a 304 Not modified header. I wanted to get it so that firefox didn't bother sending a HTTP request to check if the file had been modified or not at all.

It turned out that actually my expires directive in Nginx was working okay, why firefox was checking whether the files were up to date was because I was refreshing the page. I guess it should have been obvious to me, but I didn't think of the difference between refreshing the page and just loading the page normally.

After that I was going to install PHP 5.3.0 on the web server (currently I have 5.3.0RC3 installed on there). However, I remembered that ImageMagick was going to be updated to try and fix a problem I was having with images' XMP being corrupted after conversion. So I thought it would be sensible to get the updated version of ImageMagick before I compiled PHP 5.3.0 (since otherwise I would have to recompile PHP again when I did update ImageMagick).

I had a look on the ImageMagick website, but looking at the changelog, it didn't seem like a fix had been committed yet (I only reported it a few days ago, so not surprising). So I think I'll wait for that before I do much more work on my website. I've got tons of photos that need sorting and processing to work on in the meantime.

After dinner I was processing some pics, then a Southern FM Party In The Park track came on winamp so I got Moccle to come and listen to how skill the Southern FM DJs were. Then they had Tommi at Party in the park!!! So we started listening to that sone, which sounded like they must have been miming. The chorus bit was based on the Oompa Loompa song.

Moccle said that Blackout crew had a new song that was an Oompa Loompa song remix, so we tried to find that, but couldn't find the proper video for it on youtube. However, I did find a load of grime remixes of various songs, e.g. Pingu Riddim:

The weather today was mostly sunny in the morning and first part of the afternoon, then overcast the rest of the day.

Food
Breakfast: Blood Orange Marmalade toast sandwich; cup o' tea.
Lunch: Smoked ham with mustard, sliced Vine Tomato, sliced peppers, and iceberg lettuce sandwich; Nectarine; slice of Sultana and cherry fruit cake; Time Out (single); cup o' tea.
Dinner: Battered fish portion; fishcake; potatoes; peas; salt; ground black pepper; tomato ketchup. Pudding was a Peach & Passion fruit creamy yoghurt. Coffee; 1 piece Sainsbury's caramel chocolate; 1 piece Sainsbury's Truffle chocolate; 1 piece Sainsbury's Turkish delight chocolate; Coffee.

Thursday 30 July 2009

This morning I had received another reply on the WebFaction forums to my post about the $_SERVER['REDIRECT_STATUS'] being incorrect, and they suggested using Apache with mod_fcgid and the worker MPM instead of Nginx and spawn-fcgi.

I did a bit of googling, but couldn't find anything comparing these 2 methods of running PHP, so posted back to ask if they knew how they compared. I'm guessing that they don't know how they compare, but worth asking anyway. Unfortunately I don't have the knowledge to do a comparison between them both myself.

After looking into that, I read a thread on The WebSqueeze about converting from XHTML to HTML5. That got me wondering about whether XHTML documents with RDFa require the XHTML+RDFa 1.0 Doctype. Looking at the Conformance Requirements for RDFa, it seemed like it should be okay with the HTML5 doctype.

Then I did some reading on RDFa and HTML5, and it seemed like Ian Hickson is very much against RDFa in HTML, and had even invented a rival format - microdata, which seems a bit more long winded than RDFa (due to xmlns being deprecated in HTML5 I guess).

Luckily it seems that RDFa support in HTML5 is still being pushed, and hopefully xml namespaces support will be included as well (see section 1.5.3 The xmlns: attribute of HTML5+RDFa Editor's Draft.

After lunch I went on Animal Crossing, then I did some work on my website. In reading the RDFa articles earlier, I noticed that they used dataType and content attributes. I hadn't used these at all in marking up my photos metadata, so I started editing my page to include these where appropriate. w3Schools has a good list and examples of possible dataType attribute values.

When I was going through my webpage, and checking what dataType properties should have, by inspecting their value in Adobe Bridge, I found that there were two properties for Aperture, and they had different values as well - exif:FNumber and exif:ApertureValue. Doing some googling I found that exif:FNumber was the one I wanted. This post explains the difference: Difference between exif:FNumber and exif:ApertureValue.

After dinner I watched 'Follow the Boys' with Moccle, which was mmm maniacal. It's just a load of mostly raddish (well, I guess depends on your musical tastes) musical performances. Orson Welles the magician was quite good though.

I did a little more website work, trying to get my 404 page to work in IE6, then went to bed.

The weather today was windy, with a mixture of sun, cloud, and showers.

Food
Breakfast: Blood Orange marmalade toast sandwich; cup o' tea.
Lunch: Smoked ham with mustard, sliced vine tomato, sliced peppers, and iceberg lettuce sandwich; ½ big banana; nectarine; 2x Jaffa Cakes; Time Out (single); cup o' tea.
Dinner: Chilli bean burger in a bun with grated cheese, tomato ketchup, sliced peppers, and iceberg lettuce; Vegetable fake cup a soup; Barbeque chicken wing. Coffee. Pudding was home-made ice cream with chocolate sauce. Piece of Sainsbury's caramel chocolate; Piece of Sainsbury's turkish delight chocolate; Piece of Sainsbury's truffle chocolate.

Wednesday 29 July 2009

Sorting photos

This morning I wrote a reply to a guy from Brazil who sent me a letter with a rare Tazo he had a swap of. I spent a while trying to decide what Tazo(s) to send to him with my reply. Since he said he had sent me a rare one, I decided to send him the 2 very rare Walkerman Tazos that I had swaps of.

I also installed OpenOffice.org 3.1. I had some trouble installing it, as it said it couldn't find openofficeorg22.msi to uninstall my old version of Open Office (version 2.2 I guess). What I did was to delete the Open Office program folder, and then run the Windows Install Clean Up program to remove the Windows Installer entry for Open Office. After that, OpenOffice.org 3.1 would install okay.

Also in the morning, I processed some more pics and checked my spleenmail. I had had a reply to my post on the WebFaction forums about the $_SERVER['REDIRECT_STATUS'] being 200 when it should be 404, so I did a bit of googling based on the reply given there, but couldn't find anything to solve my problem, so posted a reply asking for more help.

After lunch I went on Animal for a bit, then I updated my spreadsheet of photography equipment with stuff I'd bought over the past few months. I sorted the photos I'd processed earlier today, and then did a backup.

I sorted some more photos, then started reading the Olympus EP-1 review on DPReview.

After dinner I watched an episode of The Equalizer, then finished reading the Olympus EP-1 review on DPReview. I sorted a few more photos, read about whether it was possible to run Mac OSX apps on Linux (it's not), and also read the review of the Panasonic GH-1 on The Luminous Landscape.

The weather today was rainy all day.

Food
Breakfast: Blood Orange Marmalade toast sandwich; cup o' tea.
Lunch: Smoked ham with mustard, sliced vine tomato, sliced peppers, and iceberg lettuce sandwich; Satsuma; Apple, Raisin and Cinnamon cookie; 2x Jaffa cakes; cup o' tea; 1 piece of Sainsburys' truffle chocolate; 1 piece of Sainsburys' Turkish delight chocolate.
Dinner: Shepherd's pie; green beans; carrots; gravy. Pudding was Rhubarb crumble with custard and cream. Coffee; Chocolate toffee.

Tuesday 28 July 2009

With running NGinX, spawn-fcgi, and MySQL on my account with WebFaction, I have virtually no memory free. So I can either upgrade to a package with more memory (costs more obviously), or otherwise try and run less programs.

I was thinking that maybe I could stop using my own installation of NGinX and spawn-fcgi, and just use WebFaction's global PHP application. I wouldn't be able to use the Imagick PHP extension, but that's not too much of a problem, I'd just need to use the Command line Image Magick convert application instead. A bit slower than the Imagick PHP extension, but not too much of a problem.

However, then I realised that I would also need to be using the same version of MySQL that WebFaction's global PHP application was configured for. That would mean that I would need to keep track of whenever they updated their global MySQL version, and update mine also. This puts me off doing this for the moment. I'm not sure what version of MySQL their global PHP application was configured for, and whether it is a version supporting Triggers and Prepared Statements (which I need).

In the morning I did some more work on my photo website.

After lunch I went on Animal crossing, then did some more work on my photo website.

I went out in the garden for a bit, then decided to try and sort some of the photos in my 'Needs Sorting' folder, as I'm running out of space on the partition containing that folder (my 'Needs Sorting' folder is currently 161 GB, comprised of 23,381 Files and 671 Folders).

I moved a folder of Birdsfoot Trefoil photos from my Needs Sorting folder, and thought I might as well tag them with the correct Hierarchical keyword while I was also creating the correct Hierarchical Folder structure to store them in. After tagging them with the correct Hierarchical keyword in Adobe Bridge CS4, I decided that actually I would change the name of one of the upper level keywords in the Hierarchical keywords list.

This meant that I also had to delete the existing Hierarchical keywords that were embedded in the images' xmp. I unticked all the keywords for the images in the Keyword Panel in Adobe Bridge CS4, but when I viewed the Raw Data in the File Info panel, the old Hierarchical Keyword was still in the images' XMP.

Doing some googling I found Adobe Bridge CS4 - Remove keywords from a file. Normally when you have a file that has keywords (both Hierarchical and standard keywords), these keywords will appear in the keywords panel in Adobe Bridge CS4 in italic type. However, for my images, the Hierarchical Keywords weren't showing up in the Keywords panel, so I couldn't untick them. Also, the 'Remove Keywords' option on the Keywords panel was greyed out, so I couldn't use that to remove the keywords either.

I tried ticking a Hierarchical Keyword in the Keywords panel, and then alt-clicking that same Hierarchical Keyword to forcibly remove it, hoping Adobe Bridge CS4 would see also that the other Hierarchical Keyword in the XMP wasn't ticked, and should be removed. Unfortunately this didn't work.

However, ticking a keyword, and then using the 'Remove Keywords' option on the Keywords panel did work, and removed the old Hierarchical Keyword, So I could now add the Hierarchical Keyword again, and it would be the one with the upper level keyword that I had renamed.

The other thing I found was that the Hierarchical Keyword will only appear ticked in the Keywords panel of Adobe Bridge CS4 if the Hierarchical Keyword also exists as a normal keyword (dc:subject).

After dinner I watched an episode of 'The Equalizer'.

I was going through my Synkron backup tabs one by one because I knew on some tabs files weren't being copied (probably due to permission problems), so I wanted to check what the problem files were and try and fix them. One set of files I found weren't copying because they weren't encrypted. However, when I tried to decrypt them, I just got a message "An error occurred applying attributes to the file. Access is denied".

Googling for this error brings up a couple of different Microsoft Knowledgebase articles about fixing it, both with different solutons. I tried both solutions, but neither worked. Then reading other pages further down the Google results page, I found that actually it's not possible to decrypt encrypted files unless you encrypted them yourself or have the encryption key. The files in question were work files to go with a PHP book. Since obviously I didn't create them, or have the encryption key, and didn't need or use them anyway, I just deleted them.

I did some more photo editing/sorting, then went to bed.

The weather today was overcast nearly all day, though I don't think it actually rained.

Food
Breakfast: Blackcurrant jam toast sandwich; cup o' tea.
Lunch: Honey Roast Ham with mustard, sliced vine tomato, and iceberg lettuce sandwich; Banana; 2x Jaffa Cakes; cup o' tea; Sainsbury's truffle chocolate; Sainsbury's turkish delight chocolate.
Dinner: Spaghetti Carbonara; bits of bacon; broccoli. Pudding was an American style apple and raisin Brownie cookie and an American style Chocolate Brownie cookie. Coffee; Sainsbury's truffle chocolate.
Supper: Bourbon biscuit; custard cream; cup o' tea.

Monday 27 July 2009

Set up Thunderbird email client

This morning I checked my email, then after it stopped raining I went in the garden for a bit and tried to take some photos of a wet bee that was on some ragwort. Unfortunately none of the photos came out very well as the ragwort was always in front of the Bee's face.

After that I processed the pics, then tried to get email set up for my photo website. Since I want my emails to have the correct email address (rather than my hotmail address) when I reply to messages sent to me, I couldn't just get the messages re-directed to my hotmail account.

I didn't really want to be checking both my hotmail and website mail via webmail either, as it would mean having to login and check both hotmail and the website webmail each time I want to check my email. So I downloaded the Thunderbird email client, and also found a good guide to checking hotmail with Thunderbird, so I can check both my hotmail and website mail from Thunderbird.

After lunch I went on Animal Crossing, went on my comp for a bit, then when it had stopped raining I went in the garden again and tried to take some photos of a wet bee that was on some ragwort (probably the same bee as before). I had the same problems as before though with the ragwort getting in the way, so I probably still didn't get any good pics. After a bit the bee climbed on my hand, and it took ages until I could get it off (I didn't want to just push it off and annoy it).

The rest of the afternoon and part of the evening I did some more work on my photo website, and I also went out to try and take some photos of the sunset.

Food
Breakfast: Lemon marmalade toast sandwich; cup o' tea.
Lunch: 1½ cheese on toasts; satsuma; slice of home-made chocolate sponge cake with buttercream icing; chocolate digestive biscuit bar; cup o' tea.
Dinner: Chips; fried potato; bit of fried hash brown; slice of cheese & tomato pizza; peas. Pudding was a slice of jam swiss roll with blackcurrant juice and custard. Coffee
Supper: Custard cream; Crinkle crunch; cup o' tea.

Sunday 26 July 2009

Not much

This morning I went on Animal Crossing, and bought another red turnip seed fro Sow Joan. Unfortunate-la-chee, I had forgotten to go on Animal yesterday, and so both my existing Red turnips had withered, which means that I will have to water them both (and my new red turnip I planted today) for another whole week until I can sell them. Annoy-chee!

After church I went on Animal again until it was lunch time. After lunch I watched another WC Fields film with Moccle, then went to bed for a bit as I had a bad headache.

I helped L with his Manical Wiki until tea time. After tea I watched another WC Fields film with Moccle.

Then I checked the Canon lens forum on dpreview and also Juza Nature photography forums, while copying across and processing the photos on my D200 memory cards from the past few days.

After that I did some testing with exiftool on a file converted with Image Magick to see if I could see anything that might suggest why the XMP seemed to be corrupted on the converted file.

The weather was cloudy in the morning, then rainy in the afternoon and evening.

Food
Breakfast: Blood Orange Marmalade toast sandwich; cup o' tea.
Dinner: Chilli con carne; rice; tortilla chips; grated cheese. Pudding was ice cream with chocolate swiss roll. Coffee.
Tea: 3x Cheese Harvest Grain cracker sandwiches; White grapes; Slice of home-made chocolate sponge cake with vanilla buttercream; Fox's Triple; cup o' tea.

Saturday 25 July 2009

Image Magick messing up XMP

This morning I did some more work on my photo website, mainly checking if and where the PHP PEAR mail class was installed on the server with WebFaction.

For lunch we all went out on a picnic.

After lunch we came back home. I was having a problem with Image Magick corrupting/loosing the XMP embedded in my photos, so I wanted to check with the latest version of Image Magick to see if it still had the same problem. So I spent most of the afternoon re-compiling and installing Image Magick and the Imagick PHP extension.

Unfortunately, I still had the same problem, so I posted to the Image Magick forum. I also went on Wii Sports Resort a bit more, and watched a WC Fields film with Moccle.

In the evening, I went out to try and take some photos of the sunset. I did get some, but unfortunately the sun didn't light up the underneath of the clouds after it set (I waited ages to see if it would, but my wait was in vain).

Food
Breakfast: Chocolate crunch oat cereal; cup o' tea.
Lunch: Weird meat stuff with weird sauce stuff and iceberg lettuce in soggy bread (yuck!) sandwich; Satsuma; most of a caramel flavour kitkat (the wind blew some of it on the floor :( ; Coffee.
Dinner: 2x Corn beef and cheese fritters; 2x Hash Browns; baked beans; brown sauce. Pudding was Coffee custard with banana, tinned mandarin segments, and crushed biscuit. Coffee.

Friday 24 July 2009

Wii Sports Resort

Today I did some more work on my photo website. Moccle came home quite early in the afternoon as he had half the day off for going to a Windows 7 thing in Birmingham earlier in the week.

In the post Moccle had got Wii Sports Resort, so I played on that quite a bit.

Food
Breakfast: Blood Orange marmalade toast sandwich; cup o' tea.
Lunch: Peppered ham with sliced vine tomato, iceberg lettuce and sliced peppers sandwich; nectarine; Apple pie; Fox's Classic; cup o' tea.
Dinner: Battered fish portion; potatoes; peas; ground black pepper. Pudding was banoffee pie with squirty cream and chocolate sauce. Coffee; 3 pieces of Sainsbury's caramel chocolate.

Thursday 23 July 2009

Websiting

This morning I was doing some more work on my photo website. The main problem I had was that my custom XMP File Info panel wasn't saving the Iptc4xmpExt Location details correctly.

It took me quite a while to figure out what the problem was, and even longer to figure out how to fix it. The problem was that if I had a record that already had some Location Shown or Location Created data, if I clicked in any of those fields, and then saved, all the Location Shown or Location Created data would be lost.

To get round the XMP File Info SDK API not handling creation of array elements, what I had done was to make it so that when a LocationCreated or LocationShown element looses focus, I check if any LocationCreated or LocationShown data has been entered/exists, and then if it does, create a XMPTextInputMRU with an xmpArray property and a dataProvider (and of course the correct xmpPath). This then forces the XMP File Info Panel to create the necessary bag element, so that the array elements can be added to it.

The problem with this was that if the Location data already exists, then clicking in a Location field without editing it will cause the LocationCreated or LocationShown bag element to be created, so when the XMP File Info Panel is closed/saved, it will see the empty bag array and save it, thus overwriting the previously existing bag array with all your location data stored in it. It seems that the XMP File Info Panel won't actually attempt to save fields that haven't been edited, which is why the location data gets saved when you first enter it, but won't get saved if you click in a location field (but don't edit it) with existing data.

It took me quite a while to figure out how to only create the bag element when the data is first being entered, but not when the existing data is being edited. Eventually I found that I could just check whether the bag element existed, and if not then create it:
if(!xmpAccess.getPropertyList("Iptc4xmpExt:"+loc).toString())
{
//Create LocationCreated or LocationShown bag element
}


After lunch I went on Animal Crossing, then finished fixing my XMP File Info panel.

I went in the garden for a bit to try and take some photos, but it was too windy and all the plants were blowing about too much to get any photos of the insects on them.

Most of the afternoon and evening I was trying to figure out how to get a table to slideUp/slideDown or toggle() with jQuery, and also get the table width to be (and stay) 100% of the size of it's parent container. I found that my tables weren't wrapping to 100% of their parent container's width because I had put 'display: block' on the table, so removing this fixed the table width problem.

Whenever jQuery would show/hide a table though, it would make the table so it would no longer be 100% of its parent container's width. It seems that you can only change the height of a table if it is set to display block (or at least not whatever the default table display style is), and so this breaks the table's width. The solution was to wrap the table in a div, and then show/hide the div instead of the table.

It took me ages to figure those out though!

Also in the evening, I went out to try and get some sunset photos. It looked quite nice about an hour before sunset, but by the time I had got to the top of Lubenham Hill and set up my tripod (probably about 50mins before sunset), the sun had started to go behind a bank of cloud on the horizon, and was no longer lighting the fields.

Since I was there and had set my tripod and pano head up, I thought I might as well do a pano anyway.

Food
Breakfast: Blood Orange Marmalade toast sandwich; cup o' tea.
Lunch: Sicilian style ham with sliced vine tomato, iceberg lettuce and sliced peppers sandwich; Nectarine; Iced Lemon Madeira Layer cake; Fox's Triple; cup o' tea.
Dinner: Chicken pie; potatoes; peas; carrots; gravy. Pudding was Apricot crumble with custard. Coffee.

Wednesday 22 July 2009

Websiting

Last night it took me ages to get to sleep, and then I woke up at 3am and it took me ages to get to sleep again, so I didn't get up until 9am this morning.

I did some more work on my photo website and also watched some Citrus episodes and Parappa the Rapper episodes. Totally random, especially Citrus. As well as that, I also went in the garden and took a few photos. Hopefully got a couple of decent ones.

After lunch I went to help Trevor with his computer, then I went on Animal Crossing, then did some more website stuff.

I was trying to find a way to make a comma seperated list in HTML, ideally using the unordered list (ul) element. I found How to display UL elements as a flat comma-separated list and comma-separated list elements in CSS, but neither works in IE (not even IE8), so I think I'll stick with a basic comma separated text string rather than using a ul list element.

Food
Breakfast: Honey loops; cup o' tea.
Lunch: Sicilian style ham with sliced vine tomato and iceberg lettuce sandwich; Satsuma; Slice of Iced Lemon Madeira layer cake; Caramel flavoured chocolate KitKat; cup o' tea.
Dinner: Spaghetti Bolognese; ground black pepper; grated parmesan style cheese. Pudding was Oven heated apple pies with custard. Coffee. Sainsbury's caramel chocolate.

Tuesday 21 July 2009

Websiting

This morning I checked my email, then checked ebay, looking for fishing shirts/jackets that I could use as a photo shirt/jacket to carry lenses around. I found a few that looked like they might be okay, though it's hard to tell how big the actual pockets are, and whether my lenses would fit in them okay. The shirt that looked the best was the most expensive, and had a few bids on, while most other shirts were less than £10 starting price with zero or one bids.

I also tried to check an auction for a Canon 800mm/5.6 L IS lens that had been listed and finished while I was away last week. When we got back from holiday, and I was checking my emails, I noticed it had sold for quite a low price, but the seller hadn't listed anything previously for about a year (so looked like a hacked account), though they were accepting paypal. I wanted to check it again to see feedback had been left yet to confirm if the auction was legitimate or not. But when I clicked on it, I just got a message that the listing had been removed.

I guess that means that it wasn't legitimate, but quite annoying of ebay to just remove fake auction listings, so it looks like they never existed, rather than just leaving them and putting a notice on the listing page that the auction was not legitimate due to a hacked account or whatever.

After that I did some more website stuff. I found that a text string I was retrieving from the database using GROUP_CONCAT had the end missing, i.e. it had been truncated. I copied the truncated string into Open Office Writer, and did a word count, which showed that it only had 1024 characters. Doing some googling for this, I found (Trouble with CONCAT and Longtext) that 1024 is the default value for the MySQL system variable group_contact_max_len. Rather than changing my group_contact_max_len, I think I will just drop the GROUP_CONCAT, and instead extract all the rows and do the concatenating in PHP.

The rest of the day I did more website stuff, and also took a few photos in the garden (mainly just Ladybird larvae), though I don't think I got any good photos :(

For my photo website, I needed to use the Focal length symbol for indicating the aperture that the photo was taken at. Looking at the Wikipedia article on aperture, I noticed they just use a normal f in italics. I had a look at charmap, and there is actually a special character/symbol for indicating focal length - Æ’ (Latin Small Letter F With Hook). But when I looked at the wikipedia article for Æ’, it says
The italic Æ’ is, rarely, used as a script f, as a mathematical symbol for "function of", or to indicate aperture in photography (e.g. Æ’/2.8) in place of the more common italic f (in serif fonts) or oblique f (in sans-serif fonts).[1][2] In modern typography an italic or oblique f is generally preferred for these applications.[citation needed]
I guess it's also unlikely that anyone would search for Æ’/2.8, and so is better SEO to use an italicised f.

The weather was rain all morning, and a bit of the afternoon. The clouds started to clear later in the evening, though I didn't see any signs of a sunset.

Food
Breakfast: Honey loops; cup o' tea.
Lunch: Sicilian style ham with sliced vine tomato and iceberg lettuce sandwich; clementine; slice of Iced Lemon Madeira layer cake; Fox's Triple; cup o' tea.
Dinner: Chilli bean burger with melted Red Leicester cheese, tomato ketchup, and salad in a bun; Bowl of fake cup a soup vegetable soup. Pudding was Chocolate cup cake thingy. Coffee; Sainsbury's truffle chocolate.

Monday 20 July 2009

Websiting

This morning I did some more website stuff, watched In The Night Garden with L, vacuumed my room, then did more website stuff.

I needed to store a user preference value in javascript that would persist between page views. I found a cookie plugin for jQuery, which made setting cookies nice and easy. Then I thought that it might be a good idea to just have a 'prefs' cookie, and store the user preferences in it as a JSON object.

After some googling I found another jQuery plugin, JSONCookie. It seems to require a separate JSON decoding/encoding library, which is a bit strange, since jQuery must already have it's own JSON parser built in to parse JSON objects received with its $.getJSON() function.

Anyway, after getting that working, I realised that actually storing the user preferences all in one cookie might not be such a good idea, since it means that you have to parse the cookie contents each time you want to retrieve a value stored in the JSON cookie, rather than just referring to a single cookie that returns its value and doesn't need parsing. Also, if you are using one cookie, that cookie will need to be sent with all requests, whereas with seperate cookies you can ensure they are only with requests on a certain path.

If you have complicated/lots of user preferences to store though, then I think a JSON cookie would be a good idea.

After lunch I went on Animal Crossing, then I checked my spleenmail. I carried on working on my photo website for the rest of the day.

Food
Breakfast: Honey loops; cup o' tea.
Lunch: Mature cheddar cheese with iceberg lettuce sandwich; white grapes; slice of Ludlow Food Centre Shropshire Fruit Cake; Fox's Classic; cup o' tea.
2 o' clock snack: ½ Fudge Factory Chocolate Chip Cookie; cup o' tea.
Dinner: Bacon quiche; potatoes; peas. Pudding was spotted dick with custard. Coffee; Sainsbury's Turkish delight chocolate.

Sunday 19 July 2009

My trigger I wrote yesterday actually worked!

This morning I went on Animal Crossing, then went to Church. After dinner I went on Animal Crossing again, then watched 'If I had a Million' with Moccle.

After that I checked Deviant art, The Luminous Landscape, Andy Rouse's blog, Moose Peterson's blog, and John K's blog.

Then I started trying to write a mysql stored procedure to insert records into my location table if the record didn't already exist, since my attempt at writing a trigger to control record insertion yesterday didn't seem to work.

I had a bit of trouble getting my stored procedure working, and I couldn't find a PDF that I had used before that had a good tutorial on writing stored procedures and functions in mysql. Eventually I did get it working, I had made a few mistakes with my IF statements -
  • I had put IF condition SET instead of IF condition THEN SET
  • I had put ELSE IF instead of ELSEIF
  • and I had put ENDIF; instead of END IF;

After getting that working I tried inserting rows normally with the trigger in effect again, to make sure that I could insert rows okay with the trigger, just that it was causing the LAST_INSERT_ID() to be incorrect. It inserted a row again, then when I re-ran the INSERT statement, I got the id previous to the row that had just been inserted, rather than just 0 that I was getting yesterday.

I changed my trigger to assign the id that LAST_INSERT_ID() should have been returning to a variable (@id), then re-ran my INSERT operation followed by SELECT LAST_INSERT_ID(), @id; and it worked okay, LAST_INSERT_ID() was actually giving the correct id.

Anyway, after lots more testing, I found that even with my original trigger, if I ran my INSERT statement followed by SELECT LAST_INSERT_ID(), it would actually give the correct id/key. When I had been getting zero or the id/key previous to the row just inserted, I had just been running the INSERT statement, and then looking at the result that phpMyAdmin gave e.g.
INSERT INTO location SET City = 1, ProvinceState = 1, WorldRegion = 1 ON DUPLICATE KEY UPDATE id = LAST_INSERT_ID(id);
phpmyadmin would say
0 row(s) inserted.
Inserted row id: 25 ( Query took 0.0006 sec )
(the existing row id is actually 26)

However, running the query like
INSERT INTO location SET City = 1, ProvinceState = 1, WorldRegion = 1 ON DUPLICATE KEY UPDATE id = LAST_INSERT_ID(id);
SELECT LAST_INSERT_ID();

phpmyadmin would return the correct result (26).

I just tried it out on my actual website, and it seemed to work okay, so I guess it's just some weird bug in phpmyadmin where it doesn't print the correct inserted row id.

Also, Ubuntu updated phpMyAdmin again today, and again I had the same problem as when I upgraded Ubuntu - first the UID and GID of the page were of the wrong level so suPHP wouldn't allow PHP to parse the page, then the dreaded blank page problem. Luckily I had my previous blog post to refer back to: Fixing blank page problem in phpMyAdmin, and so fixing the white page problem was quite easy.

After getting that working I checked Macro Art In Nature, then did some more website stuff, but got stuck with some jQuery that wasn't working in IE.

The weather today was mainly cloudy with quite a few showers (some very heavy). There was a nice pinky sunset around the horizon where the sun sets, but I couldn't really see it due to the houses between me and the horizon. I could have gone out to try and see it, but by the time I had got to an open field past the houses, it probably would have finished (plus it was wet from all the rain so far today and looked like it might rain some more).

Food
Breakfast: Honey loops; cup o' tea.
Dinner: Nasi Goreng; Noodles; Chicken Nuggets. Pudding was a couple of pancakes with golden syrup and squirty cream. Coffee.
Tea: Mature cheddar cheese with salad cream and iceberg lettuce sandwich; apple; slice of Ludlow Food Centre Shropshire Fruit cake; Orange Trophy; cup o' tea.

Saturday 18 July 2009

Websiting

This morning I checked my email, and bythom.com, then refilled the pond with Ben as the water level was getting quite low. The water butt was quite full, and there were mushrooms in the grass, so it must have rained quite a bit here while we were away.

After that I edited my crontab on the webserver to try and start NGinx, spawn-fcgi and MySQL every 30 minutes. I found a good Shell script to restart MySQL server if it is killed or not working. However, I ended up not using that script as a cron job, but rather just trying to start mysqld_safe since that's easier (doesn't require me to edit the shell script at all, which I don't really know anything about, and also WebFaction suggest just trying to start mysqld_safe from a cron job).

After lunch I read dpreview for a bit, then did some more work on my website. I changed my slideshow so that the border round an image would be calculated as a percentage size of the size that the image was being displayed at. After getting that working, I updated the javascript file on the web server. I didn't have any images on the webserver, so I had to upload one (through the site, not FTP).

The image upload went okay, which was good, but when I tried to view the page for the image, I got the error:
directory index of "/path/to/file" is forbidden
I looked at the various Nginx logs for the site, but couldn't really see what the problem was (probably just because I'm not very good at deciphering them). I looked at the .conf file for my site and saw the problem - I had a rewrite rule that didn't start with a forward slash (NginX requires a forward slash at the start of url pattern matches, while apache requires there not to be a forward slash). So I added the forward slash in, restarted Nginx, and the page worked. Yay!

In the afternoon and a bit of the evening, I was trying to work out how I could keep from inserting duplicate records in a table where the columns can be NULL. Reading the comments on the MySQL Manual page for CREATE TRIGGER, it seems that you could do this by checking if the row you want to insert already exists, then if it does try and insert a unique value in a special table that already has that unique value in it. This should fail, and then cause your operation that fired the trigger to fail as well.

I first tried to write my trigger so that if the row already existed, then it would try and insert a row with the id of the row that already existed, and since the id column is a primary key, this would fail and cause the insert not to occur. I thought I would try doing this on the table that I'm trying to insert the row to, to avoid having a special table just to break transactions.

However, the problem with this is that I since I was trying to use the trigger to insert the duplicate key/id into the same table that had the trigger on it, the insertion caused by the trigger would fire the trigger, and it would get into an infinite loop. I didn't actually try this, but did do some googling to check whether this would cause an infinite loop, and it seems that it would: MySQL Trigger: ERROR 1442 (HY000): Cant update table 'tbl' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.

I was thinking that maybe I should just use a stored procedure or function to insert any data to this particular table, but then I saw the comment on the MySQL Triggers page by S Roberts on June 2 2009 2:34pm, which suggests setting the id/key of the row you are trying to insert to a row that already exists. Trying this in phpMyAdmin, it seemed to be working great! I found that I didn't even need to be inserting/setting the id/key in the INSERT that fired the trigger, setting NEW.id in the trigger to an id that already existed would still cause the INSERT to abort.

Now, my table looked like this:
CREATE TABLE IF NOT EXISTS `location` (
`id` int(10) unsigned NOT NULL auto_increment,
`Sublocation` int(10) unsigned default NULL,
`City` int(10) unsigned default NULL,
`ProvinceState` int(10) unsigned default NULL,
`country` int(10) unsigned default NULL,
`WorldRegion` int(10) unsigned default NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=21 ;

INSERT INTO `location` (`id`, `Sublocation`, `City`, `ProvinceState`, `country`, `WorldRegion`) VALUES
(20, NULL, 1, NULL, NULL, NULL),
(19, NULL, NULL, 1, NULL, NULL),
(1, NULL, 1, 1, NULL, NULL);

My trigger was
CREATE TRIGGER locationUniqueCheck BEFORE INSERT ON location
FOR EACH ROW
SET NEW.id = (SELECT id FROM location WHERE
IF(ISNULL(NEW.Sublocation), ISNULL(location.Sublocation), location.Sublocation = NEW.Sublocation) AND
IF(ISNULL(NEW.City), ISNULL(location.City), location.City = NEW.City) AND
IF(ISNULL(NEW.ProvinceState), ISNULL(location.ProvinceState), location.ProvinceState = NEW.ProvinceState) AND
IF(ISNULL(NEW.country), ISNULL(location.country), location.country = NEW.country) AND
IF(ISNULL(NEW.WorldRegion), ISNULL(location.WorldRegion), location.WorldRegion = NEW.WorldRegion)
LIMIT 1
);

I found that when inserting to the table
INSERT INTO location SET City=1 ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id)
would insert zero rows and return the id of the existing row where City=1 and everything else was NULL
INSERT INTO location SET ProvinceState=1 ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id)
would insert zero rows and return the id of the existing row where ProvinceState=1 and everything else was NULL
INSERT INTO location SET City=1, ProvinceState=1 ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id)
would insert zero rows but would return 0 as the id, rather than the id of the row that was matched in the trigger.

The MySQL Manual does say
If you use INSERT IGNORE and the row is ignored, the AUTO_INCREMENT counter is not incremented and LAST_INSERT_ID() returns 0, which reflects that no row was inserted.
But I'm not using INSERT IGNORE, and it seems weird how it works when only inserting one column value, but not two.

Food
Breakfast: Lemon marmalade toast sandwich; cup o' tea.
Lunch: Mature cheddar cheese with iceberg lettuce sandwich; nectarine; slice of Ludlow Food Centre Carrot Cake; Chocolate Brownie bite; cup o' tea.
Dinner: 2x posh cumberland sausages; baked beans; fish & chip shop chips (from yesterday); salt. Pudding was some of Macky's Mackie's ice cream

Friday 17 July 2009

Back from holiday

For the past week I haven't been able to do any blog posts as I've been on Holiday in Shropshire with Clare, Brian and L, and we didn't have any internet access at the cottage we were staying in.

We were actually going to come back tomorrow, but it had been raining continuously since about 12pm yesterday, and the forecast was for more rain for the rest of today. So since we couldn't really go out anywhere, and there wasn't anything to do in the cottage (other than play on Harvest on Ben's DS), we decided to come home this morning.

When we got home, the door was unlocked, and Moccle's mate Ben was here, but he's never seen any of us before, and we've never seen him before, so skill and embarrassing for him.

In the living room there were some skill people, and you can see what they've been getting up to while we were away in these videos that Luke and Moccle's mate Ben made:


Luke was still in bed when we got back. Skill and embarrassing for him as well. Moccle had also made a Neighbours video:


I did take loads of photos while we were away, but I don't think any of them will be that great as the weather was mainly overcast, we didn't visit anywhere near sunrise or sunset (when the light is best, if it's not overcast), and I didn't really have the time to look for good compositions, as no-one wanted to wait around for ages for me.

In the evenings (and afternoons when we didn't go out), since there wasn't anything else to do, I just played Harvest Moon on Ben's DS, watched Ben play on Harvest Moon or Wario Master of Disguise, or watched In The Night Garden and Berenstain Bears on TV (the cottage had a TV with freeSat, but the TV was totally small).

I took my tripod and pano head, but only used it once, as carrying it made changing lenses from the LowePro Slingshot a pain. I think I will have to try getting something like a fishing shirt that I can carry my lenses in, and then hopefully I would be able to carry the tripod and still change lenses easily.

We visited quite a few of the old towns around, which I mainly used the Tokina 10-17mm/3.5-4.5 fisheye lens to take photos of the old buildings with.

When we got back home, after unpacking my stuff, and watching the Barney McGroo Tube videos, I started to check my email (at about 1pm), and I had, like, 213 emails or sumat.

Then it took me until about 7pm to finish going through all the emails. After that I checked dpreview, then I watched a WC Fields film with Moccle.

Food
Breakfast: Bowl of chocolate crunch oat cereal; cup o' tea.
Lunch: Mellow cheese with crunchy salad sandwich; banana; slice of Ludlow Food Centre Carrot cake; cup o' tea.
Dinner: Battered fish; chips (both from Fish & Chip shop); salt; vinegar. Pudding was a cherry yoghurt. Coffee; Green & Black's Maya Gold chocolate.

Friday 10 July 2009

Finally got MySQL working

This morning I tried installing MySQL 5.4.1 on my web server, in the hopes that it would work with the Innobase (InnoDB) plugin, unlike MySQL 5.4.0.

Well, it installed okay, and I could start mysqld_safe okay, but when I tried to set the root password with mysqladmin, I got the error
mysqladmin: connect to server at 'localhost' failed
error: 'Can't create a new thread (errno 11); if you are not out of available memory, you can consult the manual for a possible OS-dependent bug'


I stopped mysqld, edited the InnoDB settings in the my.cnf file to use less memory, deleted the InnoDB log files, and then started mysqld_safe again, but this time got an error about the database being corrupt.

So I deleted the mysql data directory, installed the base database (mysql_install_db) again, then started mysqld again. But then I found I couldn't do anything, I kept getting an error
-bash: fork: Resource temporarily unavailable
Problem was, because I couldn't start any new processes, I couldn't get the pid of any running processes and kill them.

So I raised a ticket with WebFaction, and they killed some processes for me. I realised that running Apache (I had 6 httpd processes running), NginX, spawn-fcgi (4 processes), mysqld_safe and mysqld was using far too much memory, as I only have 80MB available to me on the plan I'm using.

The apache processes were set to try and start if not already running every 20 minutes, so I had to edit my crontab, comment out that line, then stop apache. I edited the mysql my.cnf file again, and made the memory for innodb even lower:
# Set buffer pool size to 50-80% of your computer's memory
innodb_buffer_pool_size=10M
innodb_additional_mem_pool_size=4M
#
# Set the log file size to about 25% of the buffer pool size
innodb_log_file_size=3M
innodb_log_buffer_size=1M


mysqld_safe would now start okay, and the innobase plugin would load, however checking the mysql log I see
090710 5:56:58 [Warning] option 'innodb-buffer-pool-size': signed value 10485760 adjusted to 67108864
090710 5:56:58 [Warning] option 'innodb-log-file-size': signed value 3145728 adjusted to 33554432
090710 5:56:58 [Warning] option 'innodb-log-buffer-size': signed value 1048576 adjusted to 2097152


So I don't know if the minimum innodb-buffer-pool-size is 64MB, minimum innodb-log-file-size is 32MB and minimum innodb_log_buffer_size is 2MB?

In the evening I watched 'Mississippi', a WC Fields and Bing Crosby film. Quite boring really, was mainly just Bing Crosby singing. I also got some stuff ready for going on holiday with Clare, Ben, and Brian tomorrow.

Food
Breakfast: Lemon marmalade toast sandwich; cup o' tea.
Lunch: Ham with sliced vine tomato and iceberg lettuce sandwich; Caramel Rocky; cup o' tea.
Dinner: Battered fish portion; mashed potato; peas; black pepper; vinegar. Pudding was a couple of slices of malt loaf with butter.

Thursday 9 July 2009

Still trying to install MySQL

This morning I just sorted/processed some more photos in my 'Needs sorting' folder.

After lunch I went on Animal Crossing for a bit, and a cat came round my house. I did some more photo sorting/processing, then WebFaction had replied to my ticket to say they don't have SELinux enabled on the Server I'm hosted on.

With SELinux being ruled out as the cause of my problems with running MySQL 5.4.0 with the Innobase (InnoDB) plugin, I did more testing the rest of the day, but still couldn't get mysqld_safe to start, and would get an error in the log
Can't create interrupt-thread (error 11, errno: 11)

Eventually I ended up installing MySQL 5.1.36, which I think is the latest stable version, 5.4 is just a beta, and this worked okay. I really want to use a version of MySQL 5.4 as it is compatible with the mysql native drivers for PHP, however, a working MySQL with InnoDB is more important to me than being able to use mysqlnd.

In the evening I also watched 'From Russia with Love' with Moccle and L.

The weather was a mixture of cloud and sun, quite windy at times, but the day ended with hardly any cloud.

Food
Breakfast: Lemon marmalade toast sandwich; cup o' tea.
Lunch: Ham with sliced Vine Tomato and Iceberg Lettuce sandwich; grapes; Viennese Whirl; Caramel Rocky; Cup o' tea.
Dinner: Baked beans; 2x sausage rolls; potatoes; Brown sauce. Pudding was a Viennese Whirl. Coffee; Quality Street.

Wednesday 8 July 2009

Trying to install MySQL

This morning I tried to install MySQL 5.4.0 on the web server, but without success. First I found that when doing a make install, I was getting the same error as when I tried to make MySQL 5.4.1 yesterday, i.e.
libtool: fork: Resource temporarily unavailable

Reviewing the output in the shell, I could see this occured when it got to
Making install in dbdict
So I changed my configuration options from --plugings=max to --plugins=innobase as InnoDB is the only plugin I actually need at the moment.

After changing that, mysql installed okay, but when I tried to start mysqld_safe, it exited straight away. After trying changing various configuration options, I decided to delete it and try installing again. While I was waiting I read some photo websites. But after installing it again, it still wouldn't work. In the error log it had
InnoDB: Error: pthread_create returned 11

Googling for this error only brought up a couple of pages of results, and I only found one which seemed to be relevant (quite a few of the results were copies of the same thing), and in this case they solved it by disabling SELinux.

So I raised tickets with WebFaction for both the libtool: fork: Resource temporarily unavailable and InnoDB: Error: pthread_create returned 11 errors. Possibly the errors aren't due to the Server setup, but rather something I'm doing, and so WebFaction won't be able to help, but I won't know if I don't ask them.

After lunch I went on Animal Crossing, then I read an article on Object Oriented PHP, as I really need to learn how to do OOP, as I currently only write procedural style PHP. The article was very good and helpful, but I can't figure out how to convert my existing code to classes.

I decided that I would take a break from doing website stuff, and sorted some of my photos that were in my 'Needs Sorting' folder.

After dinner I finished watching Red Cliff 2 with Moccle, but it took ages as the subtitles kept going out of sync. I found a program that lets you re-sync the subs, but it was still quite difficult to get the subs and speech in sync correctly. It didn't really have any pointless bits in it, unlike the first film. And since you already know all the characters from the first film, it's not hard to keep track of all the different characters, unlike the first film.

After that I did some more photo editing/sorting.

Food
Breakfast: Strawberry jam toast sandwich; cup o' tea.
Lunch: Slice of roast beef, sliced vine tomato, iceberg lettuce, and mustard sandwich; grapes; caramel Rocky; cup o' tea.
Dinner: Chilli con carne; Rice; Tortilla chips; grated cheese. Pudding was Neapolitan ice cream with necatrine. Coffee; 2x white chocolate buttons; Cadbury's Roses.

Tuesday 7 July 2009

Websiting

This morning I did some more work on the slideshow for my photo website. I wanted to make it so when a thumbnail image is clicked, the large version of that image immediately starts downloading for display, and so would have to cancel the download of the image that was previously loading.

I store the currently loading image in a property of my slideshow object called 'currentlyLoading'. I thought I would be able to cancel the download by just deleting that property e.g.
slideshow.currentlyLoading.parentNode.removeChild(slideshow.currentlyLoading);
delete slideshow.currentlyLoading;


However, this didn't work. Using Fiddler to inspect the HTTP requests, I could see that the image would continue downloading even when I closed the browser!

Googling about this, most results seemed to just be about stopping images from starting downloading, rather than stopping an image that has already started downloading. However, I did find this post on stack overflow: Javascript: Cancel/Stop Image Requests.

After trying to load an image via AJAX so I would be able to stop the request, it seems that this is not possible in my case as my images are hosted on a different subdomain to my webpages, and cross domain AJAX is not possible due to security reasons. Looking at the jQuery docs, it seems that cross domain AJAX is possible, but only with JSON and pulling in an external script. So no good for downloading images.

I think I will need to just get my slideshow working at the very basic level for the moment, and then learn how to make an improved version in Flash.

After lunch I went on Animal Crossing. I went to the City, and got Kicks to shine my shoes by my style. I was wearing the explorer outfit, and he made my shoes Red, which I thought was a bit weird. Then I went into Gracie Gracie, and Gracie was there. I got her to give me some fashion advice, but she said my shoes didn't go with the rest of my outfit. Grrr! That Kicks!

I went to see Kicks about this, but all he would do is say that my shoes were looking really good and to come and see him again when they need another buff. Unfortunately you can't use your equipment in the city, otherwise I would have hit him repeatedly with my net.

I did some more work on my photo slideshow, trying to track down some errors, which took ages.

There was a thunderstorm, and my UPS beeped, so I switched my PC off for a bit, but everything seemed to be okay. When Lil' Lad got home though, he said that all the computers at school had turned off, so I guess it's just as well I have a UPS!

I think my basic slideshow is just about working now. I am getting some errors in Firefox, which I believe are probably to do with scope, though it's hard to tell as I think the problem is inside a

I had a problem with Opera in that it wasn't displaying the slideshow at all, and I couldn't work out why. As well as not displaying the images, after downloading the first image, it wouldn't download any more. My code for loading the images was as follows:
        var img = new Image();
this.currentlyLoading = i;
img.onload = function(jj){
return function(){

//Store this image in the loaded images array
jj.images[i] = this;

//Delete it from the imagesToLoad array
delete jj.imagesToLoad[i];

//Load the next image
for(i in jj.imagesToLoad)
{
jj.loadImage(i, jj.imagesToLoad[i]);
break;
}
}
}(this);
img.src = STATIC2+'/Img/'+data.filename;
$(img).addClass('slideShowImg').css({"display" : "none"}).attr("alt", data.Headline).appendTo('body');


Eventually I figured it out (well I think so anyway) - because the image's onload function needs to be evaluated, by the time the onload function is evaluated, the image's src has already been set, and so the onload event won't fire. So switching those last two lines, so the CSS etc. is set on the image before setting the src, means that the browser has enough time to evaluate the image's onload function before setting the image's src. Trying my site in IE8 and Firefox, both of these browsers worked okay without changing the above code.

After getting that working okay, I checked Dpreview and Moose News blog. Then I uploaded my site files to WebFaction, to test the site on the web server. After making changes to various files so the site should work on the web server, I tried uploading a photo through the site, but got the error
HTTP Error 413 - Request entity too large


Doing some googling, I found that you need to add client_max_body_size 200M (or however many MB your max upload size will be) to the server section in your nginx conf file: nginx 413 when uploading file 1mb or larger. I also added the lines to php.ini about max POST size and max upload size, then restarted spawn-fcgi and nginx. The file uploaded okay, but I got an error from Imagick about a folder not existing. So I checked, and the folder didn't exist, so I created it.

Since the upload process had created a database record for the image, I needed to delete that. However, when I deleted the main record, all records linked to it in other tables should also be deleted due to the Foreign Key Constraints, but they weren't. I checked whether a table had foreign key constraints SHOW CREATE TABLE tablename, and the foreign keys existed, but not the constraints.

I checked the Foreign Key constraints were in the SQL file I was importing, and they were, and it definitely said to use the InnoDB engine for each table. I tried dropping the database, and importing it again, but still the foreign key constraints weren't being set.

I thought maybe it was a problem with phpMyAdmin, but googling didn't turn up anything helpful along those lines. So I decided to try and import the file via the MySQL command line rather than phpMyAdmin, to see if it would work like that. Googling, I eventually turned up a tutorial on how to import a database from a file using the SQL command line, it's very simple as it says there, you just do SOURCE file.sql;

MySQL imported the files, but said it had 2 errors for most tables. Checking in PHPMyAdmin, all the tables were MyISAM! In phpMyAdmin, I opened a test database, and created a test table, and found that InnoDB wasn't listed as one of the possible storage engines. Much googling later, it seems that you must specify InnoDB as a plugin when you compile MySQL.

After finding that out, I decided to try and install MySQL 5.4.1, but when doing a make, I got an error saying
libtool: fork: Resource temporarily unavailable
According to this: libtool: fork: Resource temporarily unavailable, it seems that the problem is because my shell provider doesn't allow me to run enough simultaneous processes.

Rather than bothering WebFaction support with it, and since it's a beta version just for testing/development environments, I'll try again with MySQL 5.4.0 tomorrow (as it's getting late now).

In the evening I also watched quite a bit of Red Cliff 2 with Moccle.

The weather today was mainly cloudy, with a few sunny spells, and more rainy spells, with one or two lost of very heavy rain.

Food
Breakfast: Lemon marmalade toast sandwich; cup o' tea.
Lunch: Slice of cold cheese pizza; banana; slice of Moccle's chocolate birthday cake; cup o' tea.
Dinner: Cheapo sausage; Delee Pork & herb sausage; baked beans; brown sauce; potatoes. Pudding was trifle sponge with tinned peach slices and cold tinned custard. Coffee.
Supper: Hob-nob; cheapo shortbread finger; cup o' tea.

Monday 6 July 2009

Moccle's birthday

This morning I did some more work on the slideshow for my photo website. For Moccle's birthday present, I got him Sims 3 jointly with L.

I had coded it so when the page is loaded, I load up an animated 'loading' gif and some text saying 'loading image' until the first photo is downloaded and ready to be displayed.

However, I found that in IE7, after the loading GIF was loaded, the page would fill up with the 'loading image' text. Looking into this, I found that that IE triggers the image onload function every time the animated GIF sequence restarts. It seems that IE8 isn't affected by this bug, and I'm not currently intending to use the slideshow in IE6, so I just changed my code for the loading image to the below:
//Create the loading image
var img = new Image();
//IE7 fires the image onload event every time the animation sequence of an animated gif restarts, so we need to use onreadystatechange for IE instead
if(IE7)
{
img.onreadystatechange = function()
{
if(this.readyState == 'complete')
{
createLoadingGIF();
}
}
}
else
{
img.onload = function(){
createLoadingGIF();
}
}
function createLoadingGIF(){
slideshow.loading = $('<span><br /><br />LOADING IMAGE</span>');
slideshow.loading.prepend(img);
slideshow.loading.appendTo('#slideShowContainer');
}
img.src = STATIC1+'/images/LoadingGif.gif';


In the evening I watched Moonwalker with Moccle, which was quite weird and good. Kind of like a David Lynch film, but not dark, and with Michael Jackson.

After that I did some more website stuff. I kept getting Out of Memory errors in Firefox like
Error: uncaught exception: [Exception... "Out of Memory" nsresult: "0x8007000e (NS_ERROR_OUT_OF_MEMORY)" location: "JS frame :: http://static1.photosite.com/js.js :: anonymous :: line 33" data: no]
But despite commenting out various bits I couldn't find out what was causing this error.

The weather was mostly cloudy today and it rained quite a bit, with a few very heavy showers.

Food
Breakfast: Lemon marmalade toast sandwich; cup o' tea.
Lunch: Slice of roast beef with sliced vine tomato, mustard and iceberg lettuce sandwich; grapes; caramel Rocky; cup o' tea.
Dinner: Lasagne; mixed veg. Pudding was 1½ slices of Moccle's chocolate birthday cake that Clare made him with squirty cream. Coffee.
Supper: Cheapo shortbread finger; Hob-nob; coffee.

Sunday 5 July 2009

Sleeping

This morning I went on Animal Crossing and bought a red turnip from Sow Joan.

After Church, Clare and Brian went to Naseby for a Barbecue, whilst myself, Moccle and L had a barbecue in the garden using one of those tray barbecue things. Unfortunately the barbecue didn't last very long, and it lost its cooking power quite quickly.

After the barbecue, me and Moccle watched a bit of Red Cliff. Then Moccle said to stop watching it as he was too sleepy. I was sleepy as well, so I went to bed for the rest of the afternoon.

After tea I finished watching Red Cliff with Moccle.

Food
Breakfast: Lemon marmalade toast sandwich; cup o' tea.
Dinner: 2 pieces Barbecue chicken wings; Barbecued Chilli bean burger with barbecued vine tomato, barbecued yellow pepper, iceberg lettuce, grated mature cheddar cheese, and tomato ketchup in a barbecued bun. For pudding I had a slice of Lemon Drizzle cake.
Tea: Packet of prawn cocktail crisps; slice of roast beef with mustard, sliced vine tomato and iceberg lettuce sandwich; clementine; Viennese Whirl; Caramel Rocky; cup o' tea.

Saturday 4 July 2009

Websiting and Iggle Piggling

I woke up at 6am this morning, then had breakfast with L just after 7am. In the morning I finished working on the geocoding/google map functionality for panachallengetest.

In the afternoon I did some more work on my photo website. I was trying to find out how to check the progress of an image download with javascript, but it seems it's not possible. I found quite a few tutorials for javascript download progress bars, but all of them were based on downloading multiple files, and just increase the bar by a specified amount when a file has downloaded, e.g. if you had 5 files to download, each time one of the files was downloaded, the progress bar would go up by 20%.

It seems the only way to get a progress bar that will update gradually as a file is downloaded is to use flash, I don't have the time to mess around with Flash (since I don't know it), so I think I'll carry on working with my jQuery slideshow for the moment, and just have a spinning 'download in progress' icon.

In the evening I watched Dr. No with Moccle and L, and a couple of In The Night garden episodes on BBC iPlayer with L. Then I did some work in the garden, mainly moving the big pile of soil that I'd previously dug out of the pond, taking it away from the pond and dumping it by the fence, which is where Clare said she wanted it.

Also today I emptied out the bucket that Clare and Ben had put the animals that were in the pond when they emptied it out about a week ago. I thought everything in the bucket was dead, and although a lot of it was dead, there were about 5 damselfly nymphs that were covered in green algae (looked like it was growing on them), but were still alive. There was also one diving beetle, and 2 tiny snails, at least one of which was still alive. So I fished all those out, and put them back in the pond.

I seem to have got quite a few insect bites from working on the pond in the evening over the past week.

The weather today was warm and sunny, but not too hot, like it has been most of the past week.

Food
Breakfast: Bowl of Frosties; cup o' tea.
Lunch: Grated mature cheddar cheese with salad sandwich; clementine; slice of iced lemon drizzle cake (I Tom Hink it was called that anyway); Caramel Rocky; cup o' tea.
Dinner: 1½ slices Cheese deep pan pizza; 1 slice Pepperoni pizza; chips; salt; salad. Pudding was posh ice cream with banana. Coffee; 3 pieces Sainsbury's caramel chocolate.

Friday 3 July 2009

Websiting

This morning I woke up to heavy rain. After breakfast I vacuumed my room, then checked my email.

The rest of the day I spent working on adding geocoding to panachallengetest.

In the afternoon I also went on Animal Crossing as normal, and filled up the pond with water.

I did find out something useful today - how to pipe output of a PHP function that prints/echoes, like print_r() or var_dump(), to a variable. All you need to do is buffer the output of your script, and then dump the contents of the buffer into your variable e.g.
ob_start();
print_r($_POST);
$postContents = ob_get_contents();
ob_end_clean();


The weather this morning was overcast with a few heavy showers. In the afternoon the cloud gradually started to clear, then by sunset the sky was just about clear. Although there wasn't much cloud around, the sunset was still very nice, a sort of pinky purple clear sky.

Food
Breakfast: Bowl of Frosties; cup o' tea.
Lunch: Grated ature cheddar cheese with iceberg lettuce sandwich; clementine; grapes; Viennese Whirl; Caramel Rocky; cup o' tea.
Dinner: Birdseye lemony fish finger; fishcake; peas; potato; salt; tomato ketchup. Pudding was chocolate whip with tinned mandarin segments, fresh nectarine and a trifle sponge. Coffee; 3 pieces of Sainsbury's caramel chocolate.
Supper: Hobnob; custard cream; cup o' tea.

Thursday 2 July 2009

Websiting and ponding

Today I did some more work trying to get my jQuery slideshow to work. I spent nearly all the time trying to work out bugs in my code, nearly all typos. I think the only bug that wasn't a typo was in IE7.

With my page, the <body> doesn't have enough content to push it down to the bottom of the window. My slideshow script appends a div to body with CSS like:
.slideShowBG{
position: absolute;
top: 100px;
left: 30px;
bottom: 20px;
right: 30px;
background: #000;
padding: 40px;
text-align: center;
vertical-align: middle;
margin: 0 auto;
}

Also, my html has a height of 100%, and the body is not positioned.

In all browsers (well, I've not tested IE6), this makes the div stretch from 100px below the top of the page/window to 30px above the bottom of the page/window. Now in my javascript/jQuery, I am using this div as a border round the image, and resizing it when the image changes so it will always wrap the image being shown nicely, no matter what the image's aspect ratio.

When the image changes, what I am doing is shrinking both the div and image to nothing, then setting the div's height and width back to auto, so I can measure the div's height and width to see how much room there is to fit the image in. In all browsers I tested apart from IE7 this works fine, but in IE7 when the width and height on the div are changed to auto, or nothing (same thing), rather than the div stretching from 100px below the top of the page/window to 30px above the bottom of the page/window, as it was originally, it will now stretch from 100px below the top of the body to 30px above the bottom of the body. And because my page's body is very small, this makes the div very small.

I thought maybe jQuery was setting some other property on the div that was making it different to when it was originally inserted into the page, and this difference was causing it to be positioned relative to the body. However, looking at the css for the div in the IE Developer Toolbar, I couldn't see anything. So I just changed my code to calculate the div height based on the window height in IE7.

Another problem that I don't think was my fault was in IE8, I would get an error about
img.src is null or undefined
The problem with this error is that it was occurring inside an if statement that said
if(typeof((img = data[i].image)) != undefined)
data[i].image refers to an image, and is only set from that image's onload function, so there's no way it can exist without having an src.

The other thing with this error is that sometimes it would occur when switching to the 2nd image, sometimes on switching to the third image. If I refreshed the page without clearing the cache, then it would work okay. I'm thinking of changing the way the slideshow works, so I won't worry about this too much at the moment.

From about 8pm - 10.30pm (or maybe 10.45pm), I did some more work on the pond. It's all clayed up now, and needs the plants (and then water) adding. The plants were in rock-solid soil, so we left them in a wheelbarrow of water overnight, and Clare said she'd plant them early tomorrow morning.

Food
Breakfast: Strawberry jam toast sandwich; cup o' tea.
Lunch: Ham with mustard, iceberg lettuce and celery sandwich; clementine; Viennese Whirl; Rocky; cup o' tea.
Dinner: Savoury rice; ½ beef burger in ½ bun with grated mature cheddar cheese, tomato ketchup and iceberg lettuce; slice of bacon quiche. Pudding was some fresh pineapple and nectarine. Coffee.

Wednesday 1 July 2009

Websiting

This morning I did some more website stuff, trying to work out a good way to display a slideshow of images on my front page.

I wanted to check how javascript would get on with loading multiple images into the browser's cache, but since I'm testing the website locally, everything downloads almost instantly. I guess I could have tried uploading everything to the web server, but I have an approx 0.5MB/s (up to 8Mb/s) internet connection, so everything would still download pretty quickly anyway and I might not be able to see how well the javascript image loading was working.

So I started NetLimiter Lite 2, which was a bit of trouble as I'd disabled the NetLimiter Service, so I had to find it and then start it again. But when I finally got it started, it said my trial period was up and I needed to register.

NetLimiter isn't too expensive (about $20), but I thought I should check if there are any better programs or free ones that do the same job before shelling out for NetLimiter.

In my googling I came across this HOWTO: Install pyshaper (like netlimiter for linux). So I followed the guide there and set it up on my Ubuntu Virtual Machine (which is serving the local copy of my website). It seems to work okay so far, and is free, always a good plus.

Also in the morning, there was a young blackbird in the pond hole that Clare noticed. We weren't sure if it wanted to be in the hole to cool dow, or if it had fell in there and couldn't get out. I put a spade and a stick in the hole so it could climb up the spade handle or stick and escape if it wanted.

When I checked the hole again at about 10.30am, the bird was still in, so I went down in the hole to get it out. It wouldn't let me pick it up, but kept flapping its wings trying to fly away, so I managed to get my hands under it while it was flying up a little bit, then helped it up out of the hole. It ran away under the Salix bush, which was where I was planning to put it if I could pick it up, so I'm pretty sure it had got stuck in the hole and didn't want to be in there.

In the afternoon I carried on trying to make a slideshow with jQuery. The problem with jQuery is that things often seem not to work, and jQuery doesn't seem to have any error handling built in, so you just an error message like
Warning: function eval must be called directly, and not by way of a function of another name
Source File: http://static1.photosite.com/jquery-1.3.2.min.js
Line: 12

Which isn't very helpful for figuring out where your code is wrong.

In my case, I had some code that was working in IE7, but not Firefox. I was getting a list of images from the server, then putting them in an array like so:

//Load the images into cache
var images = [], img = new Image();
$(data).each(
function(){
img.src = STATIC2+'/Img/'+this.filename;
images.push($(img).clone());
}
)

and then trigger a function when the first image had loaded

$(images[0]).load(
function(){

alert('image loaded);
}
);


After commenting out various things and trying different stuff, I found out that load() must get messed up when cloning an image or something (well in Firefox anyway, as I said, still worked okay in IE7).
Changing the code to create a new image each time rather than cloning one image seemed to fix it:

//Load the images into cache
var images = [];
$(data).each(
function(){
var img = new Image();
img.src = STATIC2+'/Img/'+this.filename;
images.push(img);
}
)


After getting that working, I found that $(window).height() didn't get the correct window height in Chrome. It did give a value, though I'm not sure what, maybe the <body> height. It worked okay in Firefox 3.11 and IE 7, but I assume it doesn't work in any Webkit browsers. So to get the window width I instead had to use document.documentElement.clientHeight, which I think gives the correct window height cross browser.

Then I found that my page wasn't working in Opera. After trying lots of different stuff I discovered the problem - Opera is set to only check cached images every 5 hours. I had my image onload function in my script AFTER setting the src of the image. This meant that (in Opera) by the time it got to the image onload function in the script, the image had already loaded (since it was cached). So I had to move my onload function to before I set the src of the image.

After dinner I watched Mongol with Moccle, which was pretty good, but has a lot of bits where it just cuts from one to scene to another in the future, and doesn't explain what's happened between the scenes, e.g. you see him drowning in an iced over lake, then later he's just lying on the snow; he's got his head and hands shackled to a wooden board, then later he's somehow removed them; he doesn't have any followers and has just got out of prison, then later he's got a great army. And that's just a few examples.

Then I did some more website work. I found that IE7 was giving the height of a div about 20px more than all the other browsers, but I couldn't find any way to get it to give the same height as the other browsers.

Food
Breakfast: Bowl of Frosties; cup o' tea.
Lunch: 2x cheese on toasts; salad; stick of celery; ½ nectarine; Rocky; cup o' tea.
Dinner: Pasta twirls; tomato bolognese sauce; bacon. Pudding was a slice of Mandarin cheesecake. Coffee.
Supper: Milk chocolate digestive; custard cream; coffee.