<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>RealityForge.org</title>
 <link href="http://realityforge.org/atom.xml" rel="self"/>
 <link href="http://realityforge.org/"/>
 <updated>2010-09-05T15:51:19+10:00</updated>
 <id>http://realityforge.org</id>
 <author>
   <name>Peter Donald</name>
   <email>peter@realityforge.org</email>
 </author>

 
 <entry>
   <title>Multi-value LIKE parameters in SQL</title>
   <link href="http://realityforge.org/code/2010/09/05/multi-value-like-parameters-in-sql.html"/>
   <updated>2010-09-05T00:00:00+10:00</updated>
   <id>http://realityforge.org/code/2010/09/05/multi-value-like-parameters-in-sql</id>
   <content type="html">&lt;p&gt;Thinking in &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt;, thinking in terms of sets took me a while to achieve. In the beginning I often lapsed into procedural thinking and relied heavily on stored procedures. Often I find myself of learning one more feature that makes me re-evaluate how I have written &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt; in the past.&lt;/p&gt;
&lt;p&gt;Learning about &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms186243.aspx&quot;&gt;recursive common table expressions&lt;/a&gt; made me change the way I queried hierarchial data. Table valued functions had a similar impact particularly when using &lt;a href=&quot;http://www.sqlteam.com/article/using-cross-apply-in-sql-server-2005&quot;&gt;&lt;span class=&quot;caps&quot;&gt;CROSS&lt;/span&gt; &lt;span class=&quot;caps&quot;&gt;APPLY&lt;/span&gt;&lt;/a&gt; . However sometimes it is just the combination of simple features that produce something interesting.&lt;/p&gt;
&lt;p&gt;I was tasked with creating a report searching for people based on a search string that a user supplies. The search string is space separated and all the terms in the search need to be matched. So if a user supplies the search phrase &amp;#8220;Jam Wa&amp;#8221; then the query must return return a person named &amp;#8220;Walker, James&amp;#8221; and &amp;#8220;James Walker&amp;#8221; but not &amp;#8220;Brian Walker&amp;#8221;.&lt;/p&gt;
&lt;p&gt;The solution is presented below. Once I realized that the rvalue of the &lt;span class=&quot;caps&quot;&gt;LIKE&lt;/span&gt; operator could be a column expression then it was simple to use a common table expression MatchSet, a table of like clauses. The only trick was ensuring that the number of rows returned joined against MatchSet was equal to the number of rows in MatchSet. This ensured that all terms in the query were matched.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;sql&quot;&gt;&lt;span class=&quot;k&quot;&gt;DECLARE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SearchString&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;VARCHAR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SearchString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Jam Wal&amp;#39;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;WITH&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MatchSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Match&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
 &lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt;
   &lt;span class=&quot;s1&quot;&gt;&amp;#39;%&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;%&amp;#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Match&lt;/span&gt;
 &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;Warehouse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fnSplit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SearchString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tblPhysicalUnit&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ID&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;IN&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ID&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;tblPhysicalUnit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;P&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;JOIN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MatchSet&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ON&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DisplayString&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;LIKE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Match&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;GROUP&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ID&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;HAVING&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;COUNT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;COUNT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MatchSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;</content>
 </entry>
 
 <entry>
   <title>HTML 5 Canvas Sheet Fire Effect</title>
   <link href="http://realityforge.org/code/2010/05/19/html5-canvas-sheet-fire-effect.html"/>
   <updated>2010-05-19T00:00:00+10:00</updated>
   <id>http://realityforge.org/code/2010/05/19/html5-canvas-sheet-fire-effect</id>
   <content type="html">&lt;center&gt;
&lt;canvas id=&quot;sheetFireCanvas&quot; width=&quot;300&quot; height=&quot;50&quot;&gt;Your browser does not support the canvas element. If it did you would see sheet fire here.&lt;/canvas&gt;

&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
var InitialMin = 0.4;
var DecayRate = 0.95;
var GeneratorRowCount = 4;

var RowCount;
var ColumnCount;
var CurrentImageIndex;
var ImageHeight;
var FlameImage;
var ImageData;

function sheetFire()
{
  var LastImageData = ImageData[CurrentImageIndex];
  CurrentImageIndex = (CurrentImageIndex == 0) ? 1 : 0;
  var CurrentImageData = ImageData[CurrentImageIndex];
  var column;

  for( column = 0; column &lt; ColumnCount; column++ )
  {
    CurrentImageData[ column ] = (Math.random( ) * (1 - InitialMin)) + InitialMin;
  }

  for( var row = 1; row &lt; RowCount; row++ )
  {
    var rowOffset = row * ColumnCount;
    var lastRowOffset = rowOffset - ColumnCount;
    var lastLastRowOffset = lastRowOffset - ColumnCount;
    var lastLastLastRowOffset = lastRowOffset - ColumnCount;
    for( column = 0; column &lt; ColumnCount; column++ )
    {
      var leftColumn = (column == 0) ? ColumnCount - 1 : column;
      var rightColumn = (column == ColumnCount - 1) ? 0 : column;

      // top
      var accum = LastImageData[ leftColumn + rowOffset ];
      accum += LastImageData[ column + rowOffset ];
      accum += LastImageData[ rightColumn + rowOffset ];

      //current
      accum += LastImageData[ leftColumn + lastRowOffset ];
      accum += LastImageData[ column + lastRowOffset ] * 2;
      accum += LastImageData[ rightColumn + lastRowOffset ];

      var divisor = 7;
      if( lastLastLastRowOffset &gt; 0 )
      {
        accum += LastImageData[ leftColumn + lastLastLastRowOffset ];
        accum += LastImageData[ column + lastLastLastRowOffset ];
        accum += LastImageData[ rightColumn + lastLastLastRowOffset ];
        divisor += 3;
      }

      if( lastLastRowOffset &gt; 0 )
      {
        accum += LastImageData[ leftColumn + lastLastRowOffset ];
        accum += LastImageData[ column + lastLastRowOffset ];
        accum += LastImageData[ rightColumn + lastLastRowOffset ];
        divisor += 3;
      }

      CurrentImageData[ column + rowOffset ] = (accum / divisor) * (DecayRate + ((Math.random( ) - 0.5) * InitialMin / 4));
    }
  }

  var pix = FlameImage.data;
  // Loop over each pixel and set pixel values.
  var pix_index = pix.length - 4;
  for( var i = ColumnCount * GeneratorRowCount; i &lt; CurrentImageData.length; i ++ )
  {
    pix[pix_index  ] = Math.floor( CurrentImageData[ i ] * 256 ); // red channel
    pix_index -= 4;
  }

  var context = document.getElementById( 'sheetFireCanvas' ).getContext( '2d' );
  context.save( );
  context.putImageData( FlameImage, 0, 0 );

  context.restore( );
}

function initializeSheetFire()
{
  var i;
  canvas = document.getElementById( 'sheetFireCanvas' );
  if( canvas.getContext )
  {
    ImageHeight = canvas.height;
    RowCount = ImageHeight + GeneratorRowCount;
    ColumnCount = canvas.width;

    FlameImage = canvas.getContext( '2d' ).createImageData( ColumnCount, ImageHeight );
    var pix = FlameImage.data;
    for( i = 0; i &lt; pix.length; i += 4 )
    {
      pix[i  ] = 0; // red channel
      pix[i + 1] = 0;
      pix[i + 2] = 0;
      pix[i + 3] = 255;
    }
    ImageData = new Array( 2 );
    for( var image_index = 0; image_index &lt; 2; image_index++ )
    {
      var data = new Array( RowCount * ColumnCount );
      ImageData[image_index] = data;
      for( i = 0; i &lt; data.length; i ++ )
      {
        data[i] = 0;
      }
    }
    CurrentImageIndex = 0;
    sheetFire( );
    setInterval( 'sheetFire()', 100 );
  }
}

initializeSheetFire( );

//--&gt;&lt;/script&gt;
&lt;/center&gt;
&lt;p&gt;I had a few hours to kill last Saturday so I was looking to try out some neat little programming hack &amp;#8230; possibly in a new programming language. I settled on playing with the &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; 5 Canvas component in javascript.&lt;/p&gt;
&lt;p&gt;Initially I built the traditional &amp;#8220;Hello World!&amp;#8221; program of the graphics world &amp;#8230; the Starfield effect! I was working on a 2d canvas but projecting from a 3D particle system. The maths are relatively easy to get right even if you are out of practice. However this was too easy and I grew bored even though I did create a fireworks system that looked pretty.&lt;/p&gt;
&lt;p&gt;I decided to move onto pixel based simulation and that is when I remembered the sheet fire effect as above. I used to love putting the effect in assembly demos back in the day. It is a simple system where each pixel is assigned a &lt;i&gt;heat&lt;/i&gt;. The heat of a pixel is a function of the average heat of the surrounding pixels in the previous time frame with more weight given to the pixels below the current pixel. The heat decays each time step. (i.e. heat rises and dissipates over time). The bottom row of pixels has randomly generated heat. The heat value is then mapped to a pixel value. In the example above I used a linear mapping between heat and intensity of the red color. A more interesting mapping could map heat values to a spectrum of colors such as red &amp;#8594; yellow &amp;#8594; blue &amp;#8594; white.&lt;/p&gt;
&lt;p&gt;While it was interesting to spend a few hours learning about the canvas component, I have decided that I really dislike javascript as a language. It has the significant advantage that it is ubiquitous and every Joe can almost be guaranteed to have it installed but as a developer the experience is somewhat lacking. Even with all the fancy debugging plugins provided with FireFox it was less than fun. I really felt the lack of static typing which is not something I have felt even in languages like Ruby.&lt;/p&gt;
&lt;p&gt;I put the sheet fire effect on one of the http &lt;a href=&quot;/errors/forbidden.html&quot;&gt;error pages&lt;/a&gt; so that I don&amp;#8217;t lose it. It will be interesting to see if the javascript still runs in a year or two or if it rots as the &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; 5 standard evolves.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Blog Rebooted</title>
   <link href="http://realityforge.org/2010/05/07/reblog.html"/>
   <updated>2010-05-07T00:00:00+10:00</updated>
   <id>http://realityforge.org/2010/05/07/reblog</id>
   <content type="html">&lt;p style=&quot;text-align:center;&quot;&gt;&lt;img src=&quot;http://bluemeanie.smugmug.com/photos/702685377_Cjhdt-S-1.jpg&quot; title=&quot;This is a tree down by the river near my place. It makes for an excellent location to read a book on a hot summer day&quot; alt=&quot;This is a tree down by the river near my place. It makes for an excellent location to read a book on a hot summer day&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Over the last few years I have blogged, wiki-ied and word-smithed in all sorts of random locations. While most of the stuff has been about programming in one form or another &amp;#8211; I have also spent a lot of time writing about beginner photography, image processing, rock climbing, caving and other things.&lt;/p&gt;
&lt;p&gt;Every time I start writing again it seems to be a new blog, in a new location with no reference to that which came before. Unfortunately as my interest wanes the site inevitably gets forgotten and passes into the void. Rather than seeing all the articles disappear again, I have decided to centralize my writing on this site. Rather than lock the articles away in some database, I have decided to store them in source control and generate a static site with &lt;a href=&quot;http://github.com/mojombo/jekyll&quot;&gt;Jekyll&lt;/a&gt; . I have imported the articles from the old realityforge.org blog and one of the blogger.com blogs that I once used. Content from my other blogs may appear in time (Or may not!).&lt;/p&gt;
&lt;p&gt;I suspect that I will get back to writing again once the post PhD haze has died down. When that time comes expect to see articles posted here.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>MMTk Tutorial</title>
   <link href="http://realityforge.org/code/2007/08/15/mmtk-tutorial.html"/>
   <updated>2007-08-15T00:00:00+10:00</updated>
   <id>http://realityforge.org/code/2007/08/15/mmtk-tutorial</id>
   <content type="html">&lt;p&gt;I was a little stressed earlier on today so I decided to relax by doing some coding and I have yet to really play down in the guts of MMTk so I decided to have a look at the tutorial. The tutorial available from the &lt;a href=&quot;http://jikesrvm.org/MMTk&quot;&gt;website&lt;/a&gt; is a little out of date but relatively easy to follow even if you have little knowledge about garbage collection literature. MMTk is designed to provide automatic memory management for different languages in different environments. Initially some of the abstractions within the toolkit seem somewhat academic but when viewed in this context it makes much more sense.&lt;/p&gt;
&lt;p&gt;For example, &lt;i&gt;ObjectReference&lt;/i&gt; is used to refer to the client objects that MMTk is managing. Tasks (i.e. &lt;a href=&quot;http://en.wikipedia.org/wiki/Process_%28computing%29&quot;&gt;processes&lt;/a&gt; , &lt;a href=&quot;http://en.wikipedia.org/wiki/Thread_%28computer_science%29&quot;&gt;threads&lt;/a&gt; and &lt;a href=&quot;http://en.wikipedia.org/wiki/Fiber_%28computer_science%29&quot;&gt;fibers&lt;/a&gt; ) are not directly represented but the data required for those entities are represented by &lt;i&gt;CollectorContext&lt;/i&gt; and &lt;i&gt;MutatorContext&lt;/i&gt;. In gc literature a &lt;i&gt;collector&lt;/i&gt; is the task responsible for identifying and reclaiming the space used by client objects when they are no longer live. The &lt;i&gt;collector&lt;/i&gt; is for most parts a virtual machine managed entity that is triggered by various events. The &lt;i&gt;mutators&lt;/i&gt; are the tasks representing application functionality and generally responsible for allocating client objects.&lt;/p&gt;
&lt;p&gt;At the current time, in the Jikes &lt;span class=&quot;caps&quot;&gt;RVM&lt;/span&gt; the VM_Processor are both collectors and mutators at various times. This is enforced by MM_ProcessorContext that includes both the CollectorContext and MutatorContext classes. MM_ProcessorContext extends the mutator, rather than composes the mutator as the information in the MutatorContext is used very frequently. Every allocation needs to access mutator specific methods. By extending it rather than composing it the methods can be accessed directly rather than indirectly. This increases performance but I have never actually evaluated how much of an impact this has.&lt;/p&gt;
&lt;p&gt;In VMs that use native threads I would expect that mutators would be separate threads from collectors. In a StopTheWorld plan the collector threads would likely sit idle until a collection is triggered and all the mutator threads became idle. The mutator threads would most likely need to get to a gc safe location. GC safe locations are easy to do within the RVM&amp;#8217;s green threads but more &amp;#8220;interesting&amp;#8221; in native threads I would hazard to guess.&lt;/p&gt;
&lt;p&gt;Another trick that MMTk uses to improve performance is to separate out operations on global resources vs collector local resources or mutator local resources. For example, each mutator is likely to grab a block of memory from a global resource (synchronized) and allocate from that block (unsynchronized) until the local block runs out, at which point it would access the global resource again.&lt;/p&gt;
&lt;p&gt;The tutorial predates the separation of CollectorContext from MutatorContext (previously it seems to have been combined in a single PlanLocal class). Once I figured that out it was relatively easy to translate  the tutorials instructions into the new MMTk. Especially if you peek at some of the other classes in MMTk plan sub-packages.&lt;/p&gt;
&lt;p&gt;I think my next little experiment will be decorating objects with some before and after data. In theory it should be relatively easy and I guess I could look at refcount plans for hints &amp;#8211; I assume they have to store data around the object.&lt;/p&gt;
&lt;p&gt;Anyhoo &amp;#8211; I wonder if anyone else finds it relaxing to muck about coding up a garbage collector ? :)&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Fixed maximum space sizes</title>
   <link href="http://realityforge.org/code/2007/07/28/fixed-maximum-space-sizes.html"/>
   <updated>2007-07-28T00:00:00+10:00</updated>
   <id>http://realityforge.org/code/2007/07/28/fixed-maximum-space-sizes</id>
   <content type="html">&lt;p&gt;A few days ago I started to look into what it would take to get the &lt;a href=&quot;http://jikesrvm.org/&quot;&gt;Jikes &lt;span class=&quot;caps&quot;&gt;RVM&lt;/span&gt;&lt;/a&gt; running as a server with a large number of threads. Oh and by large, I mean somewhere in the vicinity of 80,000 threads on a modern desktop machine with 4GB of memory available. Almost every thread would maintain an open network connection (with an 8KB kernel buffer) and intermittently transmit a message.&lt;/p&gt;
&lt;p&gt;At the time I did not think it was an unreasonable demand. &lt;a href=&quot;http://www.erlang.org/&quot;&gt;Erlang&lt;/a&gt; can reportedly create a software isolated process in 3-400 bytes and &lt;a href=&quot;http://www.haskell.org/&quot;&gt;Haskell&lt;/a&gt; can create a thread in about 1KB. I have not investigated these claims but lets assume that these claims include runtime structures required to implement scheduling and garbage collection.&lt;/p&gt;
&lt;p&gt;I wanted to get each Jikes &lt;span class=&quot;caps&quot;&gt;RVM&lt;/span&gt; thread down to about 1KB for runtime structures, 4KB for the call stack, 4KB for the thread local allocator and another 8KB for each network connection. This would mean that I was looking at about 1.3GB &amp;#8220;overhead&amp;#8221; to create the threads before I added in any application logic. Not ideal but not too bad. I expected that that big challenge I was going to face was implementing a scheduler that had a decent response time and reasonable throughput. Unfortunately I hit a few problems before even getting to that step.&lt;/p&gt;
&lt;p&gt;When creating the stacks the Jikes &lt;span class=&quot;caps&quot;&gt;RVM&lt;/span&gt; allocates them into the Large Object Space (or &lt;span class=&quot;caps&quot;&gt;LOS&lt;/span&gt;). The &lt;span class=&quot;caps&quot;&gt;LOS&lt;/span&gt; is used as the runtime attempts to allocate a byte array in the default space. The allocation request first checks whether the allocation exceeds a threshold and if it does attempts to allocate the object in the &lt;span class=&quot;caps&quot;&gt;LOS&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Currently &lt;i&gt;spaces&lt;/i&gt; in MMTk are assigned an address range at build time. The address range is either based on a specific size (i.e. 32MB for the Immortal Space) or based on a proportion of the available space (i.e. 3% for the &lt;span class=&quot;caps&quot;&gt;LOS&lt;/span&gt;). The available space is from the end of the code in the bootimage (i.e. 0&amp;#215;57000000 + 24&amp;lt;&amp;lt;20) to the maximum mappable address (0xB0000000 on ia32-linux by default). Why it is not from the end of the reference map in the bootimage I am not entirely sure. Based on this the maximum size of the &lt;span class=&quot;caps&quot;&gt;LOS&lt;/span&gt; is around 40MB. Nowhere near enough for my purposes.&lt;/p&gt;
&lt;p&gt;Luckily it looks like MMTk will undergo some evolution in the near future. &lt;a href=&quot;http://jira.codehaus.org/browse/RVM-157&quot;&gt;&lt;span class=&quot;caps&quot;&gt;RVM&lt;/span&gt;-157&lt;/a&gt; describes the proposed changes. It looks like the management of address ranges and the management of memory chunks will be separated. Address ranges for spaces may still be defined at build time but it will be possible for &lt;i&gt;spaces&lt;/i&gt; to have overlapping address ranges. So the set of memory chunks allocated to a &lt;i&gt;space&lt;/i&gt; can grow or shrink based on actual usage rather than restricted by some artificial limitations.&lt;/p&gt;
&lt;p&gt;Some &lt;i&gt;Spaces&lt;/i&gt; may still need to have exclusive ownership of an address range for performance reasons. If a &lt;i&gt;Space&lt;/i&gt; exclusively owns an address range the cost for checking if an address is within a Space is just comparing an address to a start and end address. Non-exclusive ownership of an address range means that MMTk must maintain a map between memory chunks and the owning &lt;i&gt;Space&lt;/i&gt; and the cost of checking if an address is within a &lt;i&gt;Space&lt;/i&gt; is much higher. In a generational collector the (frequently called) write barriers must check whether an address is within the nursery &lt;i&gt;space&lt;/i&gt; and thus the nursery &lt;i&gt;space&lt;/i&gt; should have exclusive ownership of an address range to maintain an acceptable performance level.&lt;/p&gt;
&lt;p&gt;It was my first time looking at the MMTk code and in many ways it seems much nicer than the rest of the Jikes &lt;span class=&quot;caps&quot;&gt;RVM&lt;/span&gt; codebase and much more consistent. There is still a few uglies there and a bunch of undocumented assumptions but I guess that is going to be the case in any large codebase. There is a bunch of strange terminology in it but it could just be because I am unfamiliar with gc literature. i.e. A &lt;i&gt;Space&lt;/i&gt; defines; (1) an address range, (2) a set of allocated memory chunks and (3) a management policy. Personally I would have used the term &lt;i&gt;area&lt;/i&gt; as &lt;i&gt;space&lt;/i&gt; seems to easy to confuse with other aspects. Ohwell!&lt;/p&gt;
&lt;p&gt;I had planned to do most of the work to enable this myself but my first commit that I believed was largely performance neutral and was just a first step in refactoring seemed to raise the hackles of the &lt;span class=&quot;caps&quot;&gt;ANU&lt;/span&gt; contingent. Not surprising given they didn&amp;#8217;t really know where I was going with it and I am a self confessed ignoramus regarding garbage collection. They seem to have come up with a much more thought out plan than I had and Daniel may even tackle it in a few weeks. If not I will have to start hacking at it at a later stage.&lt;/p&gt;
&lt;p&gt;In the meantime I attempted to change the &lt;span class=&quot;caps&quot;&gt;RVM&lt;/span&gt; so that stacks are allocated in the Primitive Large Object Space (&lt;span class=&quot;caps&quot;&gt;PLOS&lt;/span&gt;) as they are basically a large byte array and the &lt;span class=&quot;caps&quot;&gt;PLOS&lt;/span&gt; can grow to 7% of the available space. Unfortunately that caused complete failure on the 64-bit build target, most likely due to alignment issues. I don&amp;#8217;t have any hardware available to test on so I reverted to allocating in the &lt;span class=&quot;caps&quot;&gt;LOS&lt;/span&gt;. Ugh.&lt;/p&gt;
&lt;p&gt;The last week I have been out of action due to illness and next week it looks like other parts of my PhD will need to be tackled. But hopefully I will get back to trying to enable large numbers of threads soon!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Testing Helpers in Rails</title>
   <link href="http://realityforge.org/code/rails/2007/06/14/testing-helpers-in-rails.html"/>
   <updated>2007-06-14T00:00:00+10:00</updated>
   <id>http://realityforge.org/code/rails/2007/06/14/testing-helpers-in-rails</id>
   <content type="html">&lt;p&gt;It can be useful at times to unit test helpers to make sure they generate correct html. It is not obvious how to do this at first. So far I have been testing my helper by defining a class &amp;#8220;MyClass&amp;#8221; at the top of my unit test and including all the appropriate modules. I also need to define a url_for method if I ever want to test helpers that generate links.&lt;/p&gt;
&lt;p&gt;The code follows (Replace MyHelper with your appropriate helper class);&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyClass&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ERB&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Util&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActionView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Helpers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;TagHelper&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActionView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Helpers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;UrlHelper&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MyHelper&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;url_for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;ActionController&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Routing&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Routes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reload&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActionController&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Routing&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Routes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;empty?&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;generated_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extra_keys&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActionController&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Routing&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Routes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;generate_extras&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;generated_path&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Then in my tests I do something like;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_revision_link&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;assert_equal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;lt;a href=&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;http://svn.sourceforge.net/viewvc/jikesrvm?view=rev&amp;amp;amp;revision=22&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;gt;22&amp;lt;/a&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;no&quot;&gt;MyClass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;revision_link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;22&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Seems easy enough to do in retrospect but things usually do.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Enhanced Rails Plugin to Validate (X)HTML and CSS</title>
   <link href="http://realityforge.org/code/rails/2007/05/09/enhanced-rails-plugin-to-validate-x-html-and-css.html"/>
   <updated>2007-05-09T00:00:00+10:00</updated>
   <id>http://realityforge.org/code/rails/2007/05/09/enhanced-rails-plugin-to-validate-x-html-and-css</id>
   <content type="html">&lt;p&gt;It feels like forever ago that I was last working with ruby on rails. But I am back hacking away at a few rails and I slowly getting more familiarity with ruby itself rather than just using it as part of the rails platform.&lt;/p&gt;
&lt;p&gt;Something I have wanted to do for a long time is automagically validate content such as (X)&lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;, &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt;, atom feeds etc that is generated by the web application. A while ago I put together the &lt;a href=&quot;/code/rails/2006/03/15/rails-plugin-to-validate-x-html-and-css.html&quot;&gt;assert-valid-asset&lt;/a&gt; plugin that allowed you to assert (in functional tests) that the content generated is valid. However you still had to explicitly call the assert.&lt;/p&gt;
&lt;p&gt;So recently I enhanced the plugin so that it can automatically validate generated content when configured to do so. To configure auto validation you need to set a class variable in Test::Unit::TestCase via code such as;&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Test&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Unit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;TestCase&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;auto_validate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Then anytime content is generated in tests (such as via get and post methods) it will check the mime type of the content. If the content has a mime type of &amp;#8216;text/html&amp;#8217; or &amp;#8216;text/xhtml&amp;#8217; it will pass it to the &amp;#8216;assert_valid_markup&amp;#8217; method. If the content is &amp;#8216;text/css&amp;#8217; then it will be validated by the &amp;#8216;assert_valid_css&amp;#8217; method.&lt;/p&gt;
&lt;p&gt;Of course you may have tests that generate invalid (X)&lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; or &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; (to work with specific unnamed browsers) and you may want to exclude these tests from the automatic content validation. This can be done by adding the test  symbol to the exclude list or alternatively by adding the desired test symbols to an include list. Both of the following examples have identical behavior;&lt;/p&gt;
&lt;p&gt;Example 1:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FooControllerTest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Test&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Unit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;TestCase&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;auto_validate_excludes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:test_foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:test_bar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_baz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Example 2:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FooControllerTest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Test&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Unit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;TestCase&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;auto_validate_includes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:test_baz&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_baz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h4&gt;Update 12th of May, 2010&lt;/h4&gt;
&lt;p&gt;The plugin is now available on GitHub. See the &lt;a href=&quot;http://github.com/realityforge/rails-assert-valid-asset&quot;&gt;GitHub project page&lt;/a&gt;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Smuggle</title>
   <link href="http://realityforge.org/code/2006/11/14/smuggle.html"/>
   <updated>2006-11-14T00:00:00+11:00</updated>
   <id>http://realityforge.org/code/2006/11/14/smuggle</id>
   <content type="html">&lt;p&gt;I needed to mirror some galleries from one &lt;a href=&quot;http://www.smugmug.com/&quot;&gt;smugmug&lt;/a&gt; &lt;a href=&quot;http://bluemeanie.smugmug.com/&quot;&gt;account&lt;/a&gt; to &lt;a href=&quot;http://lumc.smugmug.com/&quot;&gt;another&lt;/a&gt;. I thought about doing it manually but that idea seemed like way too much work.&lt;/p&gt;
&lt;p&gt;I found a python &lt;a href=&quot;http://www.dgrin.com/showthread.php?t=3853&quot;&gt;script&lt;/a&gt; by rutt that did a little bit of what I wanted and went to work hacking. This resulted in &lt;a href=&quot;/files/smuggle.py&quot;&gt;smuggle.py&lt;/a&gt; that may be useful if you ever have to programatically interact with the smugmug APIs. It will probably evolve as my needs change and as I actually start to learn python.&lt;/p&gt;
&lt;p&gt;&lt;del&gt;-The source is available from subversion.&lt;/del&gt;-&lt;/p&gt;
&lt;h4&gt;Update 12th of May, 2010&lt;/h4&gt;
&lt;p&gt;The subversion repository holding the original version of this has since gone away but in more recent times it has become easier to achieve this as there is a myriad of libraries out there. Below is an example in ruby of how easy it is to download images from a smugmug account. Upload is left as an exercise for the reader.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;smugmug&amp;#39;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;fileutils&amp;#39;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;net/http&amp;#39;&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Username&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;MyUser&amp;#39;&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Password&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;MyPassword&amp;#39;&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;AlbumIDs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1234&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Logging into &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Username&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sm&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;SmugMug&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;SmugMug&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Username&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;sm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; - &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;album_id&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;AlbumIDs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;include?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;album_id&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;FileUtils&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mkdir_p&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;album_id&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
       &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; has url &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;original_url&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
       &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;album_id&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image_id&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}#{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
       &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
         &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Net&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;HTTP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;URI&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;original_url&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
       &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exist?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;</content>
 </entry>
 
 <entry>
   <title>Moving from Eyelook to Smugmug</title>
   <link href="http://realityforge.org/code/2006/07/03/moving-from-eyelook-to-smugmug.html"/>
   <updated>2006-07-03T00:00:00+10:00</updated>
   <id>http://realityforge.org/code/2006/07/03/moving-from-eyelook-to-smugmug</id>
   <content type="html">&lt;p&gt;I needed to host photos from a recent trip to New Zealand. I started modifying &lt;a href=&quot;/code/rails/2006/04/21/eyelook-rails-photo-gallery.html&quot;&gt;eyelook&lt;/a&gt; to make it easier to do what I wanted such as geocoding, bulk upload, hierarchial grouping, different sizes, different layouts, themes etc. It was taking a bit of time so I decided to look around at existing services but none of them suited my needs.&lt;/p&gt;
&lt;p&gt;Then I found &lt;a href=&quot;http://www.smugmug.com/&quot;&gt;SmugMug&lt;/a&gt; and I was hooked. This is the best photo-sharing service I have seen. It seems to be aimed at professional photographers &amp;#8211; there is no free version but you get what you pay for. It is far from perfect but there is no way I would consider anything else at this stage.&lt;/p&gt;
&lt;p&gt;Luckily it has a referral system that gets you $5 off your first year if you indicate an account that got you onto the system so I got mine a little cheaper. I also helped out the friend that referred me by making it a little cheaper for them next year. If anyone wants to get same deal, it&amp;#8217;s simple: enter my email address ( peter at realityforge dot org ) or my coupon ( EqCTz7hz7wkW2 ) in the &amp;#8216;Referred by&amp;#8217; field on the signup form and you get $5 off.&lt;/p&gt;
&lt;p&gt;Best photo sharing service yet!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Eyelook: Rails photo gallery</title>
   <link href="http://realityforge.org/code/rails/2006/04/21/eyelook-rails-photo-gallery.html"/>
   <updated>2006-04-21T00:00:00+10:00</updated>
   <id>http://realityforge.org/code/rails/2006/04/21/eyelook-rails-photo-gallery</id>
   <content type="html">&lt;p&gt;Eyelook is a photo gallery I created over a weekend when I was home sick. It is amazing how productive rails can make you because within 8 hours I had the code in place and had set it up on my personal web server.&lt;/p&gt;
&lt;p&gt;Very little of that time was spent coding &amp;#8211; most of it was spent working on re-arranging the xhtml+css or figuring out how to go about &lt;a href=&quot;/code/rails/2006/04/06/loading-binary-data-into-rails-fixtures.html&quot;&gt;Loading Binary Data into Rails Fixtures.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Every eyelook application has a set of users who have a list of albums with pictures. The image data is stored in the database and cached on the filesystem on demand. This way a backup of the database backs up the complete system.&lt;/p&gt;
&lt;p&gt;An example of users page that lists galleries is&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;a href=&quot;/files/album_list.jpg&quot;&gt;&lt;img src=&quot;/files/album_list_small.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;You can select one of these galleries and it will bring up a list of images such as&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;a href=&quot;/files/photo_list.jpg&quot;&gt;&lt;img src=&quot;/files/photo_list_small.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;From there you can either download the original or can view a larger lightbox style image&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;&lt;a href=&quot;/files/lightbox.jpg&quot;&gt;&lt;img src=&quot;/files/lightbox_small.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;The admin section is not as sexy but it is functional.&lt;/p&gt;
&lt;h4&gt;Update 12th of May, 2010&lt;/h4&gt;
&lt;p&gt;The subversion repository holding the original version of this has since gone away but the code has been imported into GitHub. See the &lt;a href=&quot;http://github.com/realityforge/eyelook&quot;&gt;GitHub Project Page&lt;/a&gt; for further details.&lt;/p&gt;</content>
 </entry>
 
 
</feed>