<?xml version="1.0" encoding="utf-8"?>
<rss version="0.92">
<channel>
<title>mythago.net - Sean Pringle</title>
<link>http://mythago.net</link>
<description></description>
<language>en</language>
<item>
<title>cPanel Parked vs Addon Domains</title>
<link>http://mythago.net/blog/20061004a.html</link>
<description>&lt;p&gt;Recently I started using a web hosting company that uses &lt;a href=&quot;http://www.cpanel.net/&quot;&gt;cPanel&lt;/a&gt; providing only &lt;b&gt;Parked Domains&lt;/b&gt; and not &lt;b&gt;Addon Domains&lt;/b&gt;. As you may know, a &lt;i&gt;Parked Domain&lt;/i&gt; allows people to surf to a website via a secondary domain name (basically just a website alias) while an &lt;i&gt;Addon Domain&lt;/i&gt; has its own separate location on the webserver acting as a different website on the same hosting account.&lt;/p&gt;
&lt;p&gt;Being quite ready to use an Addon Domain or two this lacklustre service disapointed me! Upon further investigation in retrospect, the hosting package description and the T&amp;amp;C appeared conveniently vague on the subject. Not to be deterred, &lt;a href=&quot;http://httpd.apache.org/&quot;&gt;Apache&lt;/a&gt;'s &lt;a href=&quot;http://httpd.apache.org/docs/1.3/mod/mod_rewrite.html&quot;&gt;mod_rewrite&lt;/a&gt; allows one to get around this little hurdle quite simply by using the following &lt;a href=&quot;http://httpd.apache.org/docs/1.3/howto/htaccess.html&quot;&gt;.htaccess&lt;/a&gt; file:&lt;/p&gt;
&lt;pre&gt;Options FollowSymLinks

RewriteEngine on

RewriteCond %{HTTP_HOST} alpha\.net
RewriteCond %{REQUEST_URI} !^/alpha\.net/
RewriteRule ^(.*)$ /alpha.net/$1 [L]

RewriteCond %{HTTP_HOST} beta\.net
RewriteCond %{REQUEST_URI} !^/beta\.net/
RewriteRule ^(.*)$ /beta,net/$1 [L]
&lt;/pre&gt;
&lt;p&gt;This invisibly transforms a URL:&lt;/p&gt;
&lt;pre&gt;http://alpha.net/  --&amp;gt;  http://alpha.net/alpha.net/
http://beta.net/   --&amp;gt;  http://beta.net/alpha.net/
&lt;/pre&gt;
&lt;p&gt;And results in the following directory structure:&lt;/p&gt;
&lt;pre&gt;public_html/
public_html/.htaccess
public_html/alpha.net/
public_html/beta.net/
&lt;/pre&gt;
&lt;p&gt;Easy!&lt;/p&gt;</description>
<pubDate>Wed, 04 Oct 2006 07:00:00 +1000</pubDate>
</item>
<item>
<title>1/10 of a Picture</title>
<link>http://mythago.net/blog/20060912a.html</link>
<description>&lt;p&gt;&lt;a href=&quot;http://mythago.net/examples/words.rv&quot;&gt;Random words pulled from the internet&lt;/a&gt; create a far more interesting day dream than real sentances :-)&lt;/p&gt;</description>
<pubDate>Tue, 12 Sep 2006 07:00:00 +1000</pubDate>
</item>
<item>
<title>Raven: A Scripting Language for MySQL</title>
<link>http://mythago.net/blog/20060809c.html</link>
<description>&lt;p&gt;I've been using a home grown scripting language called &lt;a href=&quot;http://mythago.net/language.html&quot;&gt;Raven&lt;/a&gt; for a couple of years now. I think it is a good tool for working with MySQL, particularly when one needs to crank out a quick script on the fly using simple and readable code. Currently it spends a lot of time &lt;a href=&quot;http://mythago.net/blog/20060807b.html&quot;&gt;talking to my cluster&lt;/a&gt;. &lt;b&gt;Here are the basics...&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;i&gt;Connect to the Database:&lt;/i&gt;&lt;/p&gt;
&lt;pre&gt;'mysql://user:password@localhost/test' open as $mysql 
&lt;/pre&gt;
&lt;p&gt;&lt;i&gt;Select some records:&lt;/i&gt;&lt;/p&gt;
&lt;pre&gt;'SELECT * FROM mytable' $mysql query as $result 
&lt;/pre&gt;
&lt;p&gt;&lt;i&gt;Get the number of selected records:&lt;/i&gt;&lt;/p&gt;
&lt;pre&gt;$result selected as $num_rows 
&lt;/pre&gt;
&lt;p&gt;&lt;i&gt;Iterate over the result set and output a CSV:&lt;/i&gt;&lt;/p&gt;
&lt;pre&gt;$result each as $record 
    $record ',' join print &amp;quot;\n&amp;quot; print 
&lt;/pre&gt;
&lt;p&gt;&lt;i&gt;Insert a record and return the last AUTO_INCREMENT value generated:&lt;/i&gt;&lt;/p&gt;
&lt;pre&gt;'INSERT INTO mytable (first_name, last_name) VALUES (&amp;quot;Sean&amp;quot;, &amp;quot;Pringle&amp;quot;)' 
$mysql query inserted as $record_id 
&lt;/pre&gt;
&lt;p&gt;&lt;i&gt;Retrieve a single record into local variables:&lt;/i&gt;&lt;/p&gt;
&lt;pre&gt;'SELECT first_name, last_name FROM mytable WHERE id = 10' 
$mysql query fetch values into $first_name , $last_name 
&lt;/pre&gt;
&lt;p&gt;&lt;i&gt;Update some records:&lt;/i&gt;&lt;/p&gt;
&lt;pre&gt;'UPDATE mytable SET field_1 = 10 WHERE field_2 &amp;lt; 100' $mysql query as $result 
&lt;/pre&gt;
&lt;p&gt;&lt;i&gt;Get the number of records affected by the update:&lt;/i&gt;&lt;/p&gt;
&lt;pre&gt;$result affected as $num_rows 
&lt;/pre&gt;
&lt;p&gt;The astute among you may have recognised Raven uses &lt;a href=&quot;http://en.wikipedia.org/wiki/Post_fix_notation&quot;&gt;Postfix Notation&lt;/a&gt;, and although it isn't very obvious here, Raven also uses whitespace to define code blocks (a la Python). The core library is made up of short functions using only English words and because I only care about talking to MySQL I can use:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;query&lt;/b&gt; instead of &lt;b&gt;mysql_query&lt;/b&gt;
&lt;li&gt;&lt;b&gt;fetch&lt;/b&gt; instead of &lt;b&gt;mysql_fetch_array&lt;/b&gt;
&lt;li&gt;&lt;b&gt;selected&lt;/b&gt; instead of &lt;b&gt;mysql_num_rows&lt;/b&gt;
&lt;li&gt;&lt;b&gt;inserted&lt;/b&gt; instead of &lt;b&gt;mysql_insert_id&lt;/b&gt;&lt;/ul&gt;
&lt;p&gt;Ahhh, the luxury of simplicity...&lt;/p&gt;
&lt;p&gt;The Raven engine is &lt;a href=&quot;http://mythago.net/source.html&quot;&gt;written in C&lt;/a&gt; and compiles to a very small (for a scripting language! ~100K) standalone binary on Linux.&lt;/p&gt;
&lt;p&gt;Postfix Notation and significant whitespace are not everyone's cup of tea, but I think the result here is quite elegant, particularly in combination with SQL which tries very hard to emulate natural langauge. And at the end of the day, I figure there are already plenty of people following the herd and using the well known scripting languages, so I might as well go have fun some place nobody else is :-)&lt;/p&gt;</description>
<pubDate>Wed, 09 Aug 2006 17:00:00 +1000</pubDate>
</item>
<item>
<title>MySQL Cluster @ Home</title>
<link>http://mythago.net/blog/20060807b.html</link>
<description>&lt;p&gt;&lt;a href=&quot;http://mythago.net/images/cluster_1.jpg&quot;&gt;&lt;img style=&quot;float:right&quot; src=&quot;http://mythago.net/images/cluster_1_thumb.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt; I'm building a MySQL Cluster which you can see pictured on the right. Partly it is for serious learning and testing purposes, and partly because it is winter Down Under and this keeps the office warm. The smallest desktop box goes particularly well under the desk as a heated foot rest :-)&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;Management Node: &lt;i&gt;PIII 700 Dell Laptop&lt;/i&gt;&lt;/b&gt; mal (My old faithful laptop.)
&lt;li&gt;&lt;b&gt;SQL Nodes: &lt;i&gt;2 x PIII 800 Dell Optiplexes&lt;/i&gt;&lt;/b&gt; inara, river (Optiplexii? Different form factor, doh! How messy. Had these two boxes laying around the office already.)
&lt;li&gt;&lt;b&gt;Data Nodes: &lt;i&gt;4 x PIII 1GHz clone boxes w/ 512Mb RAM&lt;/i&gt;&lt;/b&gt; simon, jayne, book, wash (Found these boxes cheap at an ex-gov computer market. Another 1Gb RAM each on order - how rare SDRAM is becoming - for some DataMemory breathing space.)&lt;/ul&gt;
&lt;p&gt;I have several other machines that participate sometimes, bringing the cluster size to 10. However this 7 box configuration is the usual size. In the long term I have a half height 19&amp;quot; rack salvaged from a University skip which I hope will eventually hold the data nodes. All that is lacking is a supply of ply board (a la early days at google) to act as shelves. Once storage is more compact I can start increasing the number of nodes.&lt;/p&gt;
&lt;p&gt;Ah, gotta love the heat and noise... I think come summer time I will be moving this thing into the basement...&lt;/p&gt;</description>
<pubDate>Mon, 07 Aug 2006 13:00:00 +1000</pubDate>
</item>
<item>
<title>Book: Mythago Wood (Robert Holdstock)</title>
<link>http://mythago.net/blog/20060705a.html</link>
<description>&lt;p&gt;&lt;a href=&quot;http://www.robertholdstock.com/&quot;&gt;&lt;img style=&quot;float:left&quot; src=&quot;http://mythago.net/images/mythago_wood.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt; I figured it was about time to mention this book. Those who have heard of &lt;a href=&quot;http://en.wikipedia.org/wiki/Mythago_Wood&quot;&gt;Mythago Wood&lt;/a&gt; will already have guessed the level of my appreciation for it, given the domain name of this website! My own copy of the book is rather older and more tattered than the image on the left due in no small part to the number of times I have read and re-read it.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Mythago Wood&lt;/b&gt;, along with sequels &lt;b&gt;Lavondyss&lt;/b&gt; and &lt;b&gt;The Hollowing&lt;/b&gt;, and parallel works such as &lt;b&gt;Merlin's Wood&lt;/b&gt;, are IMHO among the best fantasy novels ever written.&lt;/p&gt;
&lt;p&gt;Ryhope Wood, a small patch of primeval wildwood in post WWII England, hides a realm where space and time are warped and even the most ancient of humanity's myths and legends come alive as &lt;b&gt;mythagos&lt;/b&gt; (myth-imago; myth image).&lt;/p&gt;
&lt;p&gt;Many folk heros from different times appear side by side throughout the series and in multiple versions depending on just when their particular version of their myth originated. There is a decidedly un-merry Robin Hood; a wild Celtic princess version of Guinevere; a soldier hero from the WWI trenches and countless other myths both major and minor.&lt;/p&gt;
&lt;p&gt;Besides being a damn good story, Mythago Wood is a journey into the human soul, exploring the way our perception of history and our beliefs change over time, and more importantly, how distorted those ideas become with each retelling or reinterpretation.&lt;/p&gt;
&lt;p&gt;Set aside a weekend for this book, as it is one of those that is difficult to put down once you've started!&lt;/p&gt;</description>
<pubDate>Wed, 05 Jul 2006 07:00:00 +1000</pubDate>
</item>
<item>
<title>Oh The Humanity!</title>
<link>http://mythago.net/blog/20060704a.html</link>
<description>&lt;p&gt;&lt;a href=&quot;http://mythago.net/images/oh_the_humanity.jpg&quot;&gt;&lt;img style=&quot;float:right&quot; src=&quot;http://mythago.net/images/oh_the_humanity_sml.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt; Someone sent this around at work recently after a fairly significant software release. Quite appropriate some days considering that even a stringent QA process can't always prevent the end &lt;strike&gt;nitwits&lt;/strike&gt; users from panicking at the site of a slightly different screen layout.&lt;/p&gt;
&lt;p&gt;But, lo! We must not pick on our beloved users, for they are customers and therefore, by definition, always right. Therefore we shall bend our backs to the task of meeting their every need and holding their hands while they wander timidly through the valley of the shadow of mild uncertainty.&lt;/p&gt;
&lt;p&gt;Interestingly (yet unrelated really), the software codenames for each release have been working their way through the &lt;b&gt;sausages&lt;/b&gt;. They have included &lt;i&gt;Bierschinken&lt;/i&gt;, &lt;i&gt;Bockwurst&lt;/i&gt;, &lt;i&gt;Lincolnshire Pride&lt;/i&gt;, &lt;i&gt;Porterhouse&lt;/i&gt; and &lt;i&gt;Lap Cheong&lt;/i&gt;. Before that it was &lt;b&gt;cheeses&lt;/b&gt;, and before that, &lt;b&gt;antelopes&lt;/b&gt;.&lt;/p&gt;</description>
<pubDate>Tue, 04 Jul 2006 07:00:00 +1000</pubDate>
</item>
<item>
<title>Good, Fast, Cheap. Pick any two.</title>
<link>http://mythago.net/blog/20060512a.html</link>
<description>&lt;p&gt;Most people would have heard that saying before. It seems to hold up in most areas of life where pretty much everything has to follow this rule or be deemed practically or economically impossible. You can't buy a car that is good, fast and cheap. Nor a computer. Nor (insert-most-any-product-or-service-here). If your car is good and cheap then you probably won't be breaking any speed limits. If your computer is cheap and fast then it is likely to be of dubious reliability.&lt;/p&gt;
&lt;p&gt;The software industry is bound by the same restrictions. Traditionally having good software that gets the job done promptly and does it well means laying out significant sums of money. NASA's equipment has to be good and fast as their margin for error is so small, therefore their budget is large. Apple's products have a historical reputation for being good and fast and definitely not cheap. Microsoft's products have a reputation for being cheaper than Apple's, but also suffering somewhat in terms of speed and quality.&lt;/p&gt;
&lt;p&gt;It is interesting to consider how Open Source Software (OSS) fits into this model. Since OSS is generally free to use, it would appear that by definition OSS is cheap and must therefore be either fast or good but not both. Most end users, consciously or otherwise, also take the whole concept one step further and directly use cost as a yardstick to measure quality. Both assumptions are significant hurdles to OSS' adoption.&lt;/p&gt;
&lt;p&gt;The truth however is that the cost of software is not only in the initial outlay but also in the ongoing support and maintentance. In general, OSS used in a commerical setting has similar ongoing costs to proprietry software. The wildcard that OSS has up its sleeve in terms of cost is that proprietry software usually includes a form of licensing fees as well. Given that OSS support services, personnel and skills are becoming more easily available in the IT Industry the world over, certain elements of the OSS community are therefore beginning to be regarded as the ideal balance of &lt;i&gt;good&lt;/i&gt; and &lt;i&gt;fast&lt;/i&gt; and &lt;i&gt;cheap&lt;/i&gt;.&lt;/p&gt;
&lt;p&gt;Take for example, the &lt;b&gt;LAMP&lt;/b&gt; stack:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;Linux&lt;/b&gt; is quite respectable these days and many of the biggest players out there use it almost exclusively. It has its own share of warts and quirks, but Linux is worming its way into almost every niche in the market from the big iron to your mobile phone.
&lt;li&gt;&lt;b&gt;Apache&lt;/b&gt;. Far and away the most popular web server out there.
&lt;li&gt;&lt;b&gt;MySQL&lt;/b&gt;. For a long time MySQL was considered a toy database. In the last few years, that assumption is proving most definitely false. Can you say 6 million installations and growing?
&lt;li&gt;&lt;b&gt;PHP&lt;/b&gt; or &lt;b&gt;Perl&lt;/b&gt; or &lt;b&gt;Python&lt;/b&gt;. Scripting languages are nothing new, particularly OSS ones. Each of these have significant warts (some more so that others depending on whom you ask!), but their usage grows in comparison to more traditional compiled languages, regardless.&lt;/ul&gt;
&lt;p&gt;Therefore, I believe OSS does fit into the good/fast/cheap rule just like any other product and does not suffer in terms of quality just because its &lt;i&gt;perceived&lt;/i&gt; cost is low. The real secret is, OSS has the oportunity to be the best in all three areas in a way that proprietry software can never be. OSS is a communal activity in a capitalist market.&lt;/p&gt;</description>
<pubDate>Fri, 12 May 2006 07:00:00 +1000</pubDate>
</item>
<item>
<title>Major Release 2.0</title>
<link>http://mythago.net/blog/20060419a.html</link>
<description>&lt;p&gt;Returning to work recently after a couple weeks leave while my wife gave birth to our second child, I discovered one of the other software developers had modified the reason for absense section of my timetable to read &lt;b&gt;Major Release 2.0&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;Now as it happens none of my co-workers have kids. Therefore I felt I had to inform them that in fact it was only a &lt;b&gt;minor release&lt;/b&gt; at present, and the project would likely remain in a beta-testing phase for the next 18 years or so :-)&lt;/p&gt;
&lt;p&gt;Yes, OK on a serious note... another girl; 3.2 Kg; mum and daughter both well.&lt;/p&gt;</description>
<pubDate>Wed, 19 Apr 2006 07:00:00 +1000</pubDate>
</item>
<item>
<title>Gripe: PostgreSQL, MySQL 5, UNION and VIEW</title>
<link>http://mythago.net/blog/20060416a.html</link>
<description>&lt;p&gt;As demonstrated in &lt;a href=&quot;http://mythago.net/blog/20060405a.html&quot;&gt;Gripe: MySQL 5 - a VIEW could replace a MERGE table&lt;/a&gt;, MySQL 5 falls a little short when it comes to using indexes in a VIEW containing UNION. So I've tried PostgreSQL out, and much to my chagrin (being a happy little MySQL developer from way back), Postgres handles indexes in this scenario perfectly. Doh!&lt;/p&gt;
&lt;p&gt;Yet ultimately, I'm still up the proverbial creek. What I really want is the PostgreSQL query designer (equiv of MySQL query optimizer) coupled with MySQL's modular storage engine architecture, so &lt;a href=&quot;http://dev.mysql.com/doc/refman/5.0/en/federated-storage-engine.html&quot;&gt;FEDERATED&lt;/a&gt; tables could be used with a VIEW and a UNION as a form of distributed partitioning. Oh well. Back to the drawing board.&lt;/p&gt;</description>
<pubDate>Sun, 16 Apr 2006 07:00:00 +1000</pubDate>
</item>
<item>
<title>Gripe: MySQL 5 - a VIEW could replace a MERGE table</title>
<link>http://mythago.net/blog/20060405a.html</link>
<description>&lt;p&gt;BUT... Create the sub-tables exactly as you would for a MERGE table. Note the indexes.&lt;/p&gt;
&lt;pre&gt;create table chunk1 (num int, data varchar(255), key (num));
create table chunk2 (num int, data varchar(255), key (num));
&lt;/pre&gt;
&lt;p&gt;Create a VIEW that is simply a UNION of the data sets of the sub-tables.&lt;/p&gt;
&lt;pre&gt;create view chunk as select * from chunk1 union select * from chunk2;
&lt;/pre&gt;
&lt;p&gt;Create another VIEW that aggregates the sizes of the sub-tables.&lt;/p&gt;
&lt;pre&gt;create view counts as
      select count(*) as records, 1 as chunk from chunk1
union select count(*) as records, 2 as chunk from chunk2;
&lt;/pre&gt;
&lt;p&gt;Now a &lt;b&gt;cool thing&lt;/b&gt; - use the counts VIEW to implement round robin INSERT operations for automatic load balancing between chunk tables. Extra cool if the &lt;a href=&quot;http://dev.mysql.com/doc/refman/5.0/en/federated-storage-engine.html&quot;&gt;FEDERATED&lt;/a&gt; engine is used for the sub-tables:&lt;/p&gt;
&lt;pre&gt;&amp;lt;?php
function next_chunk() {
    $rs = mysql_query('select chunk from counts order by records asc limit 1');
    list ($chunk) = mysql_fetch_array($rs);
    return $chunk;
}
$chunk = next_chunk();
mysql_query('insert into chunk'.$chunk.' (num, data) values (123, 'abc');
$chunk = next_chunk();
mysql_query('insert into chunk'.$chunk.' (num, data) values (456, 'def');
// ... 1000 times
?&amp;gt;
&lt;/pre&gt;
&lt;p&gt;... and finally a &lt;b&gt;crap thing&lt;/b&gt; that really is a show stopper:&lt;/p&gt;
&lt;pre&gt;explain select * from chunk where num = 123;
+-----+--------------+------------+------+------+------+-------+------+------+-------------+
| id  | select_type  | table      | type | keys | key  | k_len | ref  | rows | Extra       |
+-----+--------------+------------+------+------+------+-------+------+------+-------------+
|  1  | PRIMARY      | &amp;lt;derived2&amp;gt; | ALL  | NULL | NULL | NULL  | NULL | 1000 | Using where |
|  2  | DERIVED      | chunk1     | ALL  | NULL | NULL | NULL  | NULL |  500 |             |
|  3  | UNION        | chunk2     | ALL  | NULL | NULL | NULL  | NULL |  500 |             |
|NULL | UNION RESULT | &amp;lt;union2,3&amp;gt; | ALL  | NULL | NULL | NULL  | NULL | NULL |             |
+-----+--------------+------------+------+------+------+-------+------+------+-------------+
&lt;/pre&gt;
&lt;p&gt;&lt;b&gt;WTF, NO INDEXES?&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Try out the old MERGE table instead, and it uses the chunk sub-table indexes fine for this simple query. Turns out MySQL 5 forces a VIEW containing UNION to use the TEMPTABLE algorithm which always results in a table scan.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Worst. Decision. Ever.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;If ALGORITHM = MERGE worked with a VIEW using UNION, not only would we have an flexible replacement for MERGE tables, but unlike MERGE tables, &lt;i&gt;it would also work with the sub-tables using engines other than MyISAM&lt;/i&gt; like INNODB or even FEDERATED.&lt;/p&gt;
&lt;p&gt;/rant&lt;/p&gt;</description>
<pubDate>Wed, 05 Apr 2006 07:00:00 +1000</pubDate>
</item>
</channel>
</rss>