<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Chapeau</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/" />
    <link rel="self" type="application/atom+xml" href="http://chapeau.freevariable.com/atom.xml" />
    <id>tag:chapeau.freevariable.com,2009-03-27://1</id>
    <updated>2010-08-26T19:02:15Z</updated>
    <subtitle>Short technical articles about computing.</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 4.25</generator>

<entry>
    <title>Mostly-transparent memoization in Ruby</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2010/08/mostly-transparent-memoization-in-ruby.html" />
    <id>tag:chapeau.freevariable.com,2010://1.15</id>

    <published>2010-08-26T19:02:12Z</published>
    <updated>2010-08-26T19:02:15Z</updated>

    <summary>Here&apos;s an easy technique for automatically memoizing the results of method calls in Ruby. Let&apos;s say that we&apos;re interested in looking up instances of the Employee class by their employee ID numbers via a class method called find_first_by_empid. Furthermore, this...</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="ruby" label="ruby" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>Here's an easy technique for automatically memoizing the results of method calls in Ruby.  Let's say that we're interested in looking up instances of the <tt>Employee</tt> class by their employee ID numbers via a class method called <tt>find_first_by_empid</tt>.  Furthermore, this lookup might have to hit the disk or the network, so we want to invoke <tt>find_first_by_empid</tt> at most once for each employee ID.</p>

<p>We might want to just store employees in a hash, indexed by employee ID.  If the hash had an entry for a given ID, we'd know that we had already looked up the employee with that ID.  If not, we'd know that we needed to look up the employee with that ID and then place the employee object in the hash.  This solution is straightforward, but could prove tedious to implement in practice.  Fortunately, Ruby provides a mechanism to make this essentially transparent.</p>

<p>When you create a <tt>Hash</tt> in Ruby, you can create it in one of several ways.  You can just call the constructor <tt>Hash.new</tt> (or <tt>{}</tt>), in which case attempting to look up a key that is not in the table will return <tt>nil</tt>.  You can provide a single default object as an argument to the constructor, which will be returned instead of nil as the value for keys not in the table.  Finally, you can provide a block that describes <em>how to calculate</em> the value for a missing key.  This last option is interesting for the memoization application, since it mimics a straightforward implementation of <a href="http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_need">call-by-need</a>.</p>

<p><script src="http://gist.github.com/550434.js?file=memo.rb"></script><noscript>Please click <a href="http://gist.github.com/550434.js?file=memo.rb">here</a> to see the embedded code, or view this page outside of a feed reader.</noscript></p>

<p>The above code snippet shows an example of this technique.  When we ask <tt>employees</tt> for an employee ID that it doesn't already contain, it will invoke the block with itself and the missing key as arguments.  In executing the block, <tt>employees</tt> will insert a key-value pair in itself corresponding to the missing key and the result of the method call with that key as an argument.</p>

<p>There are some caveats here.  First, you need to make sure that your arguments are hashable.  It is also somewhat clunkier to deal with multiple arguments, since they must be in a list.  Also, it must be safe to memoize the function:  that is, as long as the hash exists, the memoized method must return the same value every time it is invoked with a given argument.  This technique isn't perfect (and almost certainly isn't novel), but it is a pretty slick way to keep from repeatedly invoking expensive methods and depends on nothing more than Ruby's standard library.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Updates to the wallaby API</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2010/06/updates-to-the-wallaby-api.html" />
    <id>tag:chapeau.freevariable.com,2010://1.14</id>

    <published>2010-06-08T14:53:21Z</published>
    <updated>2010-06-09T13:31:52Z</updated>

    <summary>If you&apos;ve built tools on the Wallaby API, you may be interested in some recent changes to the API; these are currently in source control and will appear in the upcoming 0.4.0 release of the wallaby agent and support libraries....</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="condor" label="condor" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="qmf" label="qmf" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="spqr" label="spqr" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="wallaby" label="wallaby" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>If you've built tools on the Wallaby API, you may be interested in some recent changes to the API; these are currently in source control and will appear in the upcoming 0.4.0 release of the wallaby agent and support libraries.</p>

<p>If you've been using a version of the Wallaby agent prior to 0.3.5, you'll want to note that the Wallaby classes are now in a different QMF package.  In older versions, the QMF package name was <tt>mrg.grid.config</tt>; now, the QMF package name is <tt>com.redhat.grid.config</tt>.  (The ruby module names implementing Wallaby still begin with <tt>Mrg::Grid</tt>, but this is unlikely to affect most users.)</p>

<p>If you've been using version 0.3.5 of the Wallaby agent, then you'll want to note that most of the "getter" methods have been replaced by QMF properties.  This should simplify most console applications.  We've also renamed some methods to make their functionality clearer.  The main changes are as follows:</p>

<ul>
<li>The <tt>Feature#getName</tt> method is now the <tt>name</tt> property</li>
<li>The <tt>Feature#getFeatures</tt> method is now the <tt>included_features</tt> property</li>
<li>The <tt>Feature#modifyFeatures</tt> method is now called <tt>modifyIncludedFeatures</tt></li>
<li>The <tt>Feature#getParams</tt> method is now the <tt>params</tt> property</li>
<li>The <tt>Feature#getParamMeta</tt> method is now the <tt>param_meta</tt> property</li>
<li>The <tt>Feature#getConflicts</tt> method is now the <tt>conflicts</tt> property</li>
<li>The <tt>Feature#getDepends</tt> method is now the <tt>depends</tt> property</li>
</ul><ul>
<li>The <tt>Group#getMembership</tt> method is now the <tt>membership</tt> property</li>
<li>The <tt>Group#getName</tt> method is now the <tt>name</tt> property</li>
<li>The <tt>Group#getFeatures</tt> method is now the <tt>features</tt> property</li>
<li>The <tt>Group#getParams</tt> method is now the <tt>params</tt> property</li>
</ul><ul>
<li>The <tt>Node#getIdentityGroup</tt> method is now the <tt>identity_group</tt> property</li>
<li>The <tt>Node#getMemberships</tt> method is now the <tt>memberships</tt> property</li>
</ul><ul>
<li>The <tt>Parameter#getType</tt> method is now the <tt>kind</tt> property</li>
<li>The <tt>Parameter#setType</tt> method is now called <tt>setKind</tt></li>
<li>The <tt>Parameter#getDescription</tt> method is now the <tt>description</tt> property</li>
<li>The <tt>Parameter#getDefault</tt> method is now the <tt>default</tt> property</li>
<li>The <tt>Parameter#getDefaultMustChange</tt> method is now the <tt>must_change</tt> property</li>
<li>The <tt>Parameter#setDefaultMustChange</tt> method is now called <tt>setMustChange</tt></li>
<li>The <tt>Parameter#getVisibilityLevel</tt> method is now the <tt>visibility_level</tt> property</li>
<li>The <tt>Parameter#getRequiresRestart</tt> method is now the <tt>requires_restart</tt> property</li>
<li>The <tt>Parameter#getDepends</tt> method is now the <tt>depends</tt> property</li>
<li>The <tt>Parameter#getConflicts</tt> method is now the <tt>conflicts</tt> property</li>
</ul><ul>
<li>The <tt>Subsystem#getParams</tt> method is now the <tt>params</tt> property</li>
</ul>

<p>For full documentation of the Wallaby API, please see the API documentation link on <a href="http://getwallaby.com/">getwallaby.com</a>.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Markdown documentation of QMF APIs</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2010/05/markdown-documentation-of-qmf-apis.html" />
    <id>tag:chapeau.freevariable.com,2010://1.13</id>

    <published>2010-05-13T22:53:16Z</published>
    <updated>2010-05-13T22:53:22Z</updated>

    <summary>Here&apos;s a cheap and cheerful little script I threw together to automatically generate Markdown-formatted documentation for my QMF methods. I used this to make the Wallaby API documentation. Please visit the site and enable Javascript to see the embedded code...</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="qmf" label="qmf" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>Here's a cheap and cheerful little script I threw together to automatically generate <a href="http://en.wikipedia.org/wiki/Markdown">Markdown</a>-formatted documentation for my QMF methods.  I used this to make the <a href="http://wallaby.freevariable.com/the-wallaby-api/">Wallaby API documentation</a>.</p>

<script src="http://gist.github.com/400583.js?file=qmf2markdown.py"></script><noscript>Please visit the site and enable Javascript to see the embedded code example.</noscript>]]>
        
    </content>
</entry>

<entry>
    <title>SPQR 0.3.0, now with event support</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2010/05/spqr-030-now-with-event-support.html" />
    <id>tag:chapeau.freevariable.com,2010://1.12</id>

    <published>2010-05-11T15:42:20Z</published>
    <updated>2010-05-11T15:56:29Z</updated>

    <summary>I&apos;m pleased to announce yesterday&apos;s release of SPQR 0.3.0, which is available as source, on github, or as a RubyGem. (SPQR is a library to make it painless to publish Ruby objects over the Qpid Management Framework; more details are...</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="qmf" label="qmf" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ruby" label="ruby" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="spqr" label="spqr" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>I'm pleased to announce yesterday's release of SPQR 0.3.0, which is available as <a href="http://git.fedorahosted.org/git/?p=grid/spqr.git">source</a>, on <a href="http://github.com/willb/spqr/">github</a>, or as a <a href="http://rubygems.org/gems/spqr">RubyGem</a>.  (SPQR is a library to make it painless to publish Ruby objects over the Qpid Management Framework; more details are available <a href="http://chapeau.freevariable.com/mt/mt-search.cgi?search=spqr&IncludeBlogs=1&limit=20">elsewhere on this site</a>.)</p>

<p>There are <a href="http://github.com/willb/spqr/blob/898072dd227c349bff02cd0c7501dd248aff3e9a/CHANGES">several new features and enhancements</a> in this release, including the ability to access the current Qpid user and context from within managed methods.  The most exciting new functionality, though, is support for QMF events.  In order to use QMF events, you'll need a fairly recent version of the Qpid and QMF libraries from their source repository (later than revision 929717 for nearly-complete support; revision 942861 fixes a minor bug that won't affect most users).  Once you have those installed, though, SPQR makes it characteristically easy to make QMF events; see the example below for details:</p>

<script src="http://gist.github.com/397424.js?file=logdaemon.rb"></script><noscript><p>If you're viewing this page in a feed reader or in another environment with JavaScript disabled, you'll need to click through to the post to see the embedded code example.</p></noscript>

<p>As usual, I welcome your feedback.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Notes on configuration</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2010/05/notes-on-configuration.html" />
    <id>tag:chapeau.freevariable.com,2010://1.11</id>

    <published>2010-05-03T19:45:55Z</published>
    <updated>2010-05-04T13:40:24Z</updated>

    <summary>As most readers of this site know, I&apos;ve been busy lately working on the Wallaby configuration service, which aims to make it painless to manage configurations for entire Condor pools. In this post, I&apos;m going to discuss some of the...</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="condor" label="condor" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="meta" label="meta" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>As most readers of this site know, I've been busy lately working on the <a href="http://getwallaby.com">Wallaby configuration service</a>, which aims to make it painless to manage configurations for entire Condor pools.  In this post, I'm going to discuss some of the issues of application configuration from the other side of the problem:  the semantics and interface to the configuration subsystem from within the application itself.  These issues and concerns are taken from Condor but are, I suspect, generally applicable to substantial configurable applications in general.  (I am currently collaborating with Pete Keller from Wisconsin on a redesign of Condor's configuration subsystem that should address these problems.)</p>

<p>Problems with application configuration generally fall into several categories:  value-gap problems, default value problems, type-safety problems for the configuration parameter values themselves, and type-safety problems of the programmatic interface to the configuration.  We'll discuss each of these in turn.</p>

<h3>Value-gap problems</h3>

<p><em>Truth-value gaps</em> are a problem of classical logic:  we would like some way to reason about propositions that are apparently neither true nor false (e.g. <a href="http://plato.stanford.edu/entries/aristotle-logic/#TimNecSea">Aristotle's example</a> that "there will be a sea battle tomorrow or there will not be a sea battle tomorrow" is true), but we cannot encode an unknown or indeterminate truth value as "true" or "false."  (The three-valued logic Ł<sub><small>3</small></sub> of <a href="http://en.wikipedia.org/wiki/Jan_Łukasiewicz">Jan Łukasiewicz</a> is one such system that addresses this problem.)</p>

<p>We can generalize the problem of truth-value gaps to many situations that come up in programming, for example:
<ul><li>Imagine a sparse array of Java-style references.  Does a <tt>null</tt> value correspond to an explicit <tt>null</tt> that we are interested in tracking, or merely to the absence of a value that we care about?</li><li>Consider C preprocessor macros:  many a novice C programmer has been frustrated by the distinction between <tt>#ifdef FOO</tt> and <tt>#if FOO</tt> --- but only after setting <tt>FOO</tt> to <tt>0</tt> fails to have the desired effect.</li><li>Similarly, applications that are configured through environment variables may act on the <em>mere existence of a variable</em> in the process's environment or on the <em>existence of a variable and some property of its actual value</em>.</ul></p>

<p>In Condor, these sorts of problems arising from the configuration subsystem are typically handled in an ad hoc manner.  In some places, the mere definition of a configuration parameter is enough to enable a feature; in others, the parameter must be defined and its string representation must include something that corresponds to "true" (one example is "the first character is either 't' or 'T'").  The current configuration API also makes it inconvenient (but not impossible) to determine if a parameter is undefined or set to false; in any case, the burden for sensibly treating value gaps falls to the programmer.  (I see an interface that does not depend on programmer discipline to be a win over one that does.)</p>

<h3>Default value problems</h3>

<p>Configuration parameters should have sensible defaults.  Unfortunately, the process of assigning default values may not be straightforward.  A default value may not merely be a value but it may be the result of evaluating a function at runtime.  Alternatively, defaults may depend on context:  parameter <tt>FOO</tt> may have one value in subsystem <em>X</em> on platform <em>Y</em>, but another in subsystem <em>Z</em> or on platform <em>W</em>.  (All but the last of these variable names have no deeper significance.)</p>

<p>In Condor, these defaults are handled in two ways:  for some parameters whose defaults that are consistent across subsystems and platforms, the default is specified in the generic configuration file shipped with Condor.  (About 275 parameters are given default values in this file.)  For other parameters that require context-sensitive defaults, the default values are supplied as an extra parameter to configuration API functions at each call site; these may also be conditionally compiled, so that, for example, whether thread-based parallelism is available is defined to be true within the <tt>condor_collector</tt> on all platforms except Windows, but false everywhere else.</p>

<p>A configuration subsystem that supported specifying rich defaults --- including immediate values as well as expressions that would evaluate to the correct default depending on the context in which they were evaluated --- would free application programmers from the tedious and error-prone work of encoding defaults in every call to <tt>param()</tt>.</p>

<h3>Type-safety problems</h3>

<p>Popular discussion of types and type safety is fraught with handwaving, imprecision, and nonsense (e.g. the ridiculous and contradictory appellation "<a href="http://web.willbenton.com/writing/2005/on-dynamic-typing">dynamically typed</a>," which is often applied to untyped languages).  For the remainder of this discussion, I will be using definitions adapted from Luca Cardelli's <a href="http://lucacardelli.name/Papers/TypeSystems.pdf">survey chapter on type systems</a>:  namely, a <em>type</em> is the upper bound on a range of values, and a <em>typed language</em> is one in which nontrivial types can be ascribed to variables.</p>

<p>It should be clear that imposing a sufficiently expressive type system on configuration variables is generally desirable.  A sufficiently expressive type system for an application like Condor would include not merely the classic types of low-level languages (e.g. <tt>unsigned int</tt>, boolean, character string, etc.), but also types that encode application-specific information (e.g. email addresses, hostnames, Pascal-style ranges, typed dictionaries).  However, since configuration variables in Condor may be defined in terms of macro-expanded values or (in the case of some parameters) as <a href="http://www.cs.wisc.edu/condor/classad/">ClassAd</a> expressions to be evaluated later, it may be difficult to typecheck configuration variables a priori.</p>

<p>Another type-safety problem deals with how (or how frequently) values are computed.  Some configuration parameters have fixed values for the life of a process, but others (e.g. "the current time" or "the result of taking a random element from this list") may change every time that they are evaluated.  The idea of using type systems to track <em>how</em> an expression is evaluated (and not merely the shape of its result) is not new:  Lucassen and Gifford proposed <em><a href="http://portal.acm.org/citation.cfm?id=73564">effect systems</a></em> for functional languages in 1988, and computer music languages like Max/MSP and <a href="http://www.eecs.berkeley.edu/~lazzaro/sa/book/tut/index.html#execution">SAOL</a> have long distinguished between expressions that are evaluated once and expressions whose values could change at various intervals (like control signals, which can change hundreds of times per second, or audio signals, which vary tens of thousands of time per second).  In the context of configuring Condor, it is sufficient to track whether a parameter's definition is to be evaluated (at least) once or every time its value is requested from the configuration subsystem.  The values of parameter definitions that need only be evaluated once can be memoized; currently, Condor's configuration subsystem doesn't support this sort of type information and any memoization is performed on an ad hoc basis in application code.</p>

<p>One of the main concerns behind thinking about improving Condor's configuration API is to reduce the potential avenues for error by developers.  Adding a typed interface to typed configuration data greatly simplifies application code that uses the configuration subsystem and eliminates ad hoc, per-call-site typechecking of configuration values.  (It shouldn't be acceptable to support a high-level configuration API in 2010 that might require clients to manually coerce a user-supplied string into a value of some other type!)  A typed interface could also automatically handle memoization of non-varying configuration variables, and provide methods to inspect <em>whether</em> and <em>where</em> parameters are defined, rather than merely a value (that might represent a value gap).</p>

<h3>Going forward</h3>

<p>As I mentioned earlier, these issues are the subject of active design and development.  Currently, some of our notes on our solution to these problems in Condor are <a href="https://condor-wiki.cs.wisc.edu/index.cgi/tktview?tn=988">in a ticket on the Condor wiki</a>; ideally, an implementation will be part of a developer release of Condor in the next few months.  Of course, I welcome feedback on these ideas and on the concerns that they are meant to address.</p>]]>
        
    </content>
</entry>

<entry>
    <title>At Condor Week</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2010/04/at-condor-week.html" />
    <id>tag:chapeau.freevariable.com,2010://1.10</id>

    <published>2010-04-15T17:27:40Z</published>
    <updated>2010-04-15T17:27:44Z</updated>

    <summary> Like many of my colleagues on the MRG Grid team, I&apos;ve been at Condor Week 2010 this week. Later today, I&apos;ll give a talk about some of the configuration management software we&apos;ve been developing; for more details, you can...</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="condor" label="condor" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="wallaby" label="wallaby" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p><a href="http://www.flickr.com/photos/willb/4519954186/" title="the team by willbenton, on Flickr"><img src="http://farm5.static.flickr.com/4021/4519954186_b0b5c934d5.jpg" width="500" height="500" alt="the team" /></a></p>

<p>Like many of my colleagues on the MRG Grid team, I've been at <a href="http://www.cs.wisc.edu/condor/CondorWeek2010/">Condor Week 2010</a> this week.  Later today, I'll give a talk about some of the configuration management software we've been developing; for more details, you can visit <a href="http://getwallaby.com">getwallaby.com</a>.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Introducing capricious</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2010/03/introducing-capricious.html" />
    <id>tag:chapeau.freevariable.com,2010://1.9</id>

    <published>2010-03-17T20:31:58Z</published>
    <updated>2010-03-17T20:32:49Z</updated>

    <summary>Last week I needed a good random number generator to make repeatable stress tests for a Ruby project. Ruby&apos;s standard library includes a good random number generator (the Mersenne Twister), but its implementation is unsuitable for use in simulations and...</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="poisson" label="poisson" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="prng" label="prng" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="random" label="random" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ruby" label="ruby" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="simulation" label="simulation" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>Last week I needed a good random number generator to make repeatable stress tests for a Ruby project.  Ruby's standard library includes a good random number generator (the <a href="http://en.wikipedia.org/wiki/Mersenne_twister">Mersenne Twister</a>), but its implementation is unsuitable for use in simulations and testing because the generator state is global to the program.  (For simulations, it is usually nice to have multiple independent generators, possibly seeded on different values, that coexist in the same program.)</p>

<p>I couldn't find one I liked, so I wrote my own.  I'm pleased to announce the immediate availablity of <em>capricious</em> (as <a href="http://github.com/willb/capricious/">source</a> or as a <a href="http://rubygems.org/gems/capricious/">RubyGem</a>).  capricious is a framework to manage randomness for simulations and tests; it includes an interface for pseudorandom number generators, a family of probability distribution simulators (currently <a href="http://github.com/willb/capricious/blob/master/lib/capricious/uniform.rb">uniform</a>, <a href="http://github.com/willb/capricious/blob/master/lib/capricious/normal.rb">normal</a>, <a href="http://github.com/willb/capricious/blob/master/lib/capricious/exponential.rb">exponential</a>, <a href="http://github.com/willb/capricious/blob/master/lib/capricious/erlang.rb">Erlang</a>, and <a href="http://github.com/willb/capricious/blob/master/lib/capricious/poisson.rb">Poisson</a>, but it is easy to add more), and <a href="http://github.com/willb/capricious/blob/master/lib/capricious/sample_sink.rb">a class that can track aggregate information</a> (e.g. min, max, mean and variance) about a stream of samples in constant space.  capricious also includes two pseudorandom number generators:  a simple <a href="http://github.com/willb/capricious/blob/master/lib/capricious/lfsr.rb">linear-feedback shift register</a> and one of George Marsaglia's <a href="http://github.com/willb/capricious/blob/master/lib/capricious/mwc5.rb">multiply-with-carry generators</a>.  Each of the distribution simulators is parameterized on a generator class as well as on a seed and any distribution parameters, so it is easy to evaluate new generators for different applications.</p>

<p>I will write more about some of the interesting technical details behind capricious soon; in the meantime, I welcome feedback, contributions, or bug reports.</p>]]>
        
    </content>
</entry>

<entry>
    <title>SPQR update</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2009/12/spqr-update.html" />
    <id>tag:chapeau.freevariable.com,2009://1.8</id>

    <published>2009-12-21T17:09:51Z</published>
    <updated>2009-12-21T17:10:26Z</updated>

    <summary>I released version 0.1.2 of SPQR this morning; it is available from gemcutter (as an installable gem package) or from fedorahosted.org (as source). This version contains many enhancements and fixes when compared to the versions described my previous SPQR posts....</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="qmf" label="qmf" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ruby" label="ruby" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="spqr" label="spqr" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>I released version 0.1.2 of SPQR this morning; it is available from <a href="http://www.gemcutter.org/gems/spqr">gemcutter</a> (as an installable gem package) or from <a href="http://git.fedorahosted.org/git/grid/spqr.git">fedorahosted.org</a> (as source).  This version contains many enhancements and fixes when compared to the versions described my previous SPQR posts.  I've noticed that people are still installing older versions of SPQR and would like to encourage everyone who's interested in using SPQR to adopt the most recent version.</p>

<p>The 0.1.x series and the 0.0.x series are not API-compatible, but the incompatibility is for a good reason:  it enables SPQR to expose normal Ruby methods (that is, those that don't use keyword arguments).  To see what I mean, compare <a href="http://github.com/willb/spqr/blob/v0.1.2/examples/hello.rb">the "Hello, world" example from v0.1.2</a> with <a href="http://github.com/willb/spqr/blob/v0.0.4/examples/hello.rb">its counterpart in v0.0.4</a>.  (The former is also embedded below, but you might have to click through to the post to see it if you're reading this in a syndication feed.)</p>

<p><script src="http://gist.github.com/261058.js"></script></p>

<p>Here are some other enhancements to the code since the last time I mentioned SPQR:</p>

<ul>
<li>Many fixes and enhancements to SPQR/Rhubarb (simple object-graph persistence) integration; most glue methods are now automatically generated at runtime.</li>
<li>Improved code generation from XML QMF schema files, including support for generating classes that are both exposed over QMF (with SPQR) and persistent (with Rhubarb).</li>
<li>A stable and mostly-repeatable test suite.  (I hope to write up the process of developing unit tests for QMF agents at some point in the near future.)</li>
<li>Enhancements to the app skeleton, which can now specify the broker that manages the QMF bus.</li>
<li>Many fixes and stability enhancements, most of which have come out of my experience with a substantial SPQR/Rhubarb application I'm developing.</li>
</ul>

<p>The full list <a href="http://github.com/willb/spqr/blob/v0.1.2/CHANGES">is here</a>.  Enjoy, and please don't hesitate to write with questions.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Two brief SPQR updates</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2009/11/two-brief-spqr-updates.html" />
    <id>tag:chapeau.freevariable.com,2009://1.7</id>

    <published>2009-11-26T06:16:22Z</published>
    <updated>2009-11-26T06:25:54Z</updated>

    <summary>Here are two quick notes (and a bonus meta-note) about the quickly-evolving SPQR project: SPQR now includes a gem target (courtesy of jeweler). Pull a recent version and sudo rake install to try it out. Once the project has stabilized...</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="amqp" label="amqp" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="qmf" label="qmf" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="qpid" label="qpid" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="spqr" label="spqr" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>Here are two quick notes (and a bonus meta-note) about the quickly-evolving <a href="http://chapeau.freevariable.com/2009/11/introducing-spqr.html">SPQR project</a>:</p>
<ol>
<li>SPQR now includes a gem target (courtesy of <a href="http://github.com/technicalpickles/jeweler">jeweler</a>).  Pull a recent version and <tt>sudo rake install</tt> to try it out.  Once the project has stabilized a little more, I will publish gems to gemcutter.</li>
<li>I'm mirroring the <a href="http://git.fedorahosted.org/git/grid/spqr.git">fedorahosted SPQR repository</a> on github; if you're already a github user, you might rather <a href="http://github.com/willb/spqr/">follow the repository there</a>.</li>
</ol>
<p>I'm pretty excited about SPQR, but this site won't become "all SPQR, all the time."  Since interested hackers can easily follow the day-to-day project status on github or fedorahosted, I will reserve future SPQR-related blog posts for substantial announcements.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Automatically generating QMF agents with spqr-gen</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2009/11/automatically-generating-qmf-agents-with-spqr-gen.html" />
    <id>tag:chapeau.freevariable.com,2009://1.6</id>

    <published>2009-11-24T16:34:23Z</published>
    <updated>2009-11-24T16:38:30Z</updated>

    <summary>In a previous post, I introduced SPQR and presented a couple of examples of how one could use SPQR to publish Ruby objects over QMF. Sometimes, though, you aren&apos;t starting from an application -- instead, you&apos;re starting from an XML...</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="metaprogramming" label="metaprogramming" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="qmf" label="qmf" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ruby" label="ruby" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="spqr" label="spqr" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>In a previous post, I <a href="http://chapeau.freevariable.com/2009/11/introducing-spqr.html">introduced SPQR</a> and presented a couple of examples of how one could use SPQR to publish Ruby objects over QMF.  Sometimes, though, you aren't starting from an application -- instead, you're starting from an XML QMF schema document.  SPQR includes <strong>spqr-gen</strong>, a tool designed to automatically generate a skeleton SPQR application from a QMF schema.  In this post, we'll see an example of <strong>spqr-gen</strong> in action.</p>

<p>First, let's look at a simple QMF schema for a class that exposes one method, <strong>echo</strong>, which returns its argument (note that the code examples may not show up if you're viewing this in a feed reader):</p>

<p><script src="http://gist.github.com/241988.js?file=codegen-example.xml"></script></p>

<p>Running <strong>spqr-gen</strong> on this example produces two files:  <strong>agent-app.rb</strong> and <strong>examples/codegen/EchoAgent.rb</strong>.  As you can see, these two files contain all of the boilerplate we need to start implementing these QMF methods --- and, by chance, the boilerplate methods actually have the behavior that our agent is meant to!</p>

<p><script src="http://gist.github.com/241988.js?file=agent-app.rb"></script></p>

<p><script src="http://gist.github.com/241988.js?file=EchoAgent.rb"></script></p>

<p><strong>spqr-gen</strong> is included in the <a href="http://git.fedorahosted.org/git/grid/spqr.git">SPQR repository</a>; the system as documented in the last two posts is tagged "<a href="http://git.fedorahosted.org/git/grid/spqr.git?p=grid/spqr.git;a=commit;h=2af82a3980d39fdc2e98fca85639b5410f5c1c69">introducing-spqr</a>".</p>]]>
        
    </content>
</entry>

<entry>
    <title>Introducing SPQR</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2009/11/introducing-spqr.html" />
    <id>tag:chapeau.freevariable.com,2009://1.5</id>

    <published>2009-11-21T08:09:32Z</published>
    <updated>2009-11-22T04:43:40Z</updated>

    <summary>SPQR is a framework to make it almost painless to create QMF agents in the Ruby language, and thus to write Ruby applications that can be managed remotely. I built it to serve as infrastructure for some new development at...</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="amqp" label="amqp" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="qmf" label="qmf" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="qpid" label="qpid" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="rpc" label="rpc" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="spqr" label="spqr" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>SPQR is a framework to make it almost painless to create QMF agents in the Ruby language, and thus to write Ruby applications that can be managed remotely.  I built it to serve as infrastructure for some new development at work, but am pleased to announce that it is now functional enough to be useful for a range of applications, and you can <a href="http://git.fedorahosted.org/git/grid/spqr.git">download it from its git repository on fedorahosted.org</a> and try it out.  If you know what a "QMF agent" is, then I hope you're already interested in learning more --- please skip ahead to <a href="#spqr-examples">the examples</a> to see it in action!  If you're confused, fear not and read on.</p>

<h2 id="spqr-background">Background</h2>

<p><a href="http://jira.amqp.org/confluence/display/AMQP/Advanced+Message+Queuing+Protocol">AMQP</a> is an open standard for interprocess messaging --- and an excellent basis for distributed applications with even particularly demanding requirements.  I'm most familiar with the <a href="http://qpid.apache.org/">Apache Qpid</a> implementation of AMQP, since many of my colleagues at Red Hat are Qpid committers.  Qpid is scalable, high-performance, and open-source --- it also features a variety of language bindings.</p>

<p>One great feature of Qpid that isn't in other AMQP implementations is the <a href="http://qpid.apache.org/qpid-management-framework.html">Qpid Management Framework</a>.  QMF is essentially a protocol so that applications can allow themselves to be managed remotely.  In this way, it is similar to familiar remote procedure call mechanisms:  a server application publishes an interface specification, and client programs are able to interact with that interface by invoking proxy methods that forward their arguments to the server machine and ferry return values back to the client.  Unlike RPC, however, QMF is built upon Qpid messaging, and so offers low-latency, high throughput, and great resiliency.</p>

<p>In the QMF world, "server" applications --- those that can be managed --- are called <em>agents</em>, and "client" applications are called <em>consoles</em>.  (Consoles and agents communicate by connecting to the same Qpid message broker.)  The interface to an agent is called a <em>schema</em>; while schemas are instantiated programmatically in the applications that use them, there is also a well-defined format for recording schema information in XML.</p>

<p>In older versions of Qpid, it was only possible to develop QMF agents in C++; with more recent versions (including the one packaged in Fedora 12), it is possible to use Ruby as well.  Since I am currently developing a rather substantial QMF agent application in Ruby, I wanted to have robust infrastructure that would allow me to avoid repeating myself, skip writing boilerplate as much as possible, and get on with the interesting work of my actual application.  SPQR is built on top of the existing Ruby QMF engine and allows developers to publish instances of standard Ruby classes (with minimal and unobtrusive annotation) over QMF.</p> 

<h2 id="spqr-examples">Examples</h2>

<p>The first example we'll run through is (of course) a very simple application that publishes one method, which merely greets the user.  Ours will be a little more interesting than classic "Hello, world!" programs, though, since we'll provide a personalized greeting (and publish our answer to another process).  Here's what our application would look like in plain Ruby:</p>

<div><script src="http://gist.github.com/240047.js?file=basic_hello.rb"></script></div>

<p>Note that we're using keyword-style arguments for the <strong>hello</strong> method, since we'd like to be able to support out-parameters (that is, not merely a single return value).  Otherwise, this is pretty straightforward.  Here's what it would look like if we used SPQR to publish <strong>Hello.hello</strong> over QMF:</p>

<div><script src="http://gist.github.com/240044.js?file=hello.rb"></script></div>

<p>The core of the class is basically the same (although we do collect statistics now, primarily to demonstrate SPQR's support for QMF statistics).  The only differences are in the annotations we've added in order to enable SPQR to manage this class (viz., mixing in the <strong>SPQR::Manageable</strong> module), and to tell SPQR which methods to expose over QMF (and the types of their arguments).  We've also added <strong>find</strong> and <strong>find_all</strong> methods to make it possible for QMF console applications to query for a particular <strong>Hello</strong> object (or for all of them).  (Since the <strong>Hello</strong> class has no state, we simply make it a singleton class and the find methods just return the sole instance.)</p>

<p>The second example is a little more interesting:  it shows the intersection of SPQR's capability to publish objects to QMF and my <a href="http://git.fedorahosted.org/git/grid/spqr.git?p=grid/spqr.git;a=tree;f=rhubarb">Rhubarb</a> library's capability to store specially-declared Ruby classes in SQLite databases.  (You'll need SQLite and its Ruby bindings installed to run this example.)  This example is a simple logging agent that exposes two classes:  LogService, which is a singleton class that can generate log records, and LogRecord, which is a class backed by a database table that models these records.</p>

<div><script src="http://gist.github.com/240051.js?file=logservice.rb"></script></div>

<h2>Conclusion</h2>

<p>SPQR is still under development, and is only available via git for the moment.  However, if you're interested in developing QMF agent applications in Ruby, it supports a useful subset of QMF and presents a clean, simple way to expose your applications over QMF.  I welcome comments, bug reports, feature requests, and patches.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Hiding template parameters with dynamic dispatch</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2009/07/hiding-template-parameters-with-dynamic-dispatch.html" />
    <id>tag:chapeau.freevariable.com,2009://1.4</id>

    <published>2009-07-01T20:08:57Z</published>
    <updated>2009-07-02T14:08:55Z</updated>

    <summary>In my last post, I mentioned a problem (choosing between one of several templated classes based on information that won&apos;t be available until runtime) and also mentioned a workaround involving virtual dispatch, in which the templated class extends a non-templated...</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="c" label="c++" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="dependenttypes" label="dependent types" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="templates" label="templates" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>In <a href="http://chapeau.freevariable.com/2009/06/a-problem-of-dependent-types.html">my last post</a>, I mentioned a problem (choosing between one of several templated classes based on information that won't be available until runtime) and also mentioned a workaround involving virtual dispatch, in which the templated class extends a non-templated class.  This doesn't address all of the concerns I set out with regard to other solutions, but it is rather cleaner than any of them since it makes conditional dispatch implicit.  Here's an example of this very simple workaround as applied to a trivial class:</p>

<p><script src="http://gist.github.com/139011.js"></script><noscript><em>Visit this post in a browser with Javascript support to see the <a href="http://gist.github.com/139011">code snippet</a>.</em></noscript></p>]]>
        
    </content>
</entry>

<entry>
    <title>A problem of dependent types</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2009/06/a-problem-of-dependent-types.html" />
    <id>tag:chapeau.freevariable.com,2009://1.3</id>

    <published>2009-06-24T16:05:19Z</published>
    <updated>2009-06-30T04:45:13Z</updated>

    <summary><![CDATA[Here&#8217;s an interesting problem involving C++ templates. Say you have a class that is parameterized on a term &#8212; we'll use std::bitset&lt;N&gt; as a running example &#8212; and you&#8217;d like to wrap this class in another class that hides the...]]></summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="c" label="c++" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="dependenttypes" label="dependent types" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="metaprogramming" label="metaprogramming" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="templates" label="templates" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>Here&#8217;s an interesting problem involving C++ templates.  Say you have a class that is parameterized on a term  &#8212; we'll use <tt>std::bitset&lt;N&gt;</tt> as a running example &#8212; and you&#8217;d like to wrap this class in another class that hides the value of <tt>N</tt> from its clients.</p>

	<p>Of course, it isn&#8217;t possible to instantiate a template based on a value that isn&#8217;t a compile-time constant, but it may be desirable to choose from one of several (statically-defined) values at run-time.  In the <tt>std::bitset</tt> case, we might define &#8220;small,&#8221; &#8220;medium,&#8221; and &#8220;large&#8221; sizes for a representation class, and have the constructor for wrapper class choose the representation that is large enough to hold the set of bits it is created with.  We&#8217;d like wrap <tt>bitset</tt> in such a way so that its size is not an explicit part of the type of the wrapper class (and thus clients can write code that handles wrapped-<tt>bitset</tt> objects of varying sizes without parameterizing their code).  This is a problem, because the size of <tt>bitset</tt> is part of its type.</p>

<p>In general, this problem manifests whenever a wrapper class can make a run-time decision about which of some  static set of template parameter values for its (hidden) representation class is most appropriate; or, still more generally, when it makes sense to choose a different type of representation based on a run-time value.  Note that this problem isn't confined to classes parameterized on terms; a similar problem could also appear with classes parameterized on types, like <span class="caps">STL</span> containers.   However, it is less immediately clear to me what a solution for classes parameterized on types would look like in the general case, since the type parameter is more likely to be exposed in the container's interface.  (There are special cases, like choosing different types of containers as an internal representation depending on the characteristics of different collections of homogeneous data, that might make sense.)</p>

	<p>There are a few approaches to wrapping a class in C++, but none of them are particularly suitable for solving this problem.  Here&#8217;s why:</p>


<ol>
	<li><em>Public inheritance</em> does not shield clients from the template value in the representation class, because it must be a template parameter to the wrapper class.  However, public inheritance frees the wrapper class implementor from implementing (potentially) many proxy methods that simply call out to to the representation class.</li>
	<li><em>Explicit delegation</em> requires the wrapper class implementor to write proxy methods for each operation of interest from the representation class.  However, the template parameter to the representation class is still part of its type.  Therefore, there must be several fields in the wrapper class that hold pointers to instances of different instantiations of the representation class template (e.g. <tt>std::bitset&lt;32&gt;</tt>, <tt>std::bitset&lt;128&gt;</tt>, and <tt>std::bitset&lt;2048&gt;</tt>).  In addition, each proxy method must include a conditional expression that determines which of these objects is the actual representation and a pointer dereference.  (Having the wrapper class include three <tt>std::bitset</tt> <em>values</em>, rather than pointers, would defeat the purpose of having &#8220;small,&#8221; &#8220;medium,&#8221; and &#8220;large&#8221; representations.)</li>
	<li><em>Private inheritance</em> combines the problems of the first two approaches with the advantages of neither.</li>
</ol>

	<p>A general solution to this problem at the type-system level might involve constrained template parameters and union types.  So you could say, e.g., <tt>std::bitset&lt;N in {32,128,2048}&gt; b = std::bitset&lt;32&gt;();</tt>  This solves our problem by encoding a range of possible sizes in the type of a <tt>bitset</tt>-valued variable rather than encoding a particular size.  (My gut feeling &#8212;  although I don&#8217;t have the turnstiles to prove it &#8212;  is that this feature might be difficult or impossible to include in a sound, statically-checked type system, let alone to implement in a production compiler.)  Sadly, extending the language is rarely a viable option for most software projects.</p>

     <p>There are, of course, ways to solve the problem of needing a set of bits large enough to hold <em>k</em> bits, where <em>k</em> isn't known until runtime: use <tt>std::bit_vector</tt> or use <tt>std::vector&lt;std::bitset&lt;32&gt; &gt;</tt>, to give two simple examples.  More generally, it would also be possible to use <tt>virtual</tt> functions in a base <tt>representation</tt> class that is extended by a templated class:  then <tt>derived&lt;32&gt;</tt> and <tt>derived&lt;128&gt;</tt> could both be pointed to by a <tt>representation*</tt>.  But I wonder, since I&#8217;m continually amazed by feats of template metaprogramming, what clean and efficient solutions to the general problem are possible?</p>]]>
        
    </content>
</entry>

<entry>
    <title>Virtualizing a physical Linux machine</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2009/03/virtualizing-a-physical-linux-machine.html" />
    <id>tag:chapeau.freevariable.com,2009://1.2</id>

    <published>2009-03-30T16:11:50Z</published>
    <updated>2009-03-30T21:51:26Z</updated>

    <summary>Due to some hardware trouble with my main work machine, I&apos;m presently working in a virtual machine on my personal computer. After a few dim trails, I found a pretty straightforward method to clone my work computer into a virtual...</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="virtualization" label="virtualization" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>Due to some hardware trouble with my main work machine, I'm presently working in a virtual machine on my personal computer.  After a few dim trails, I found a pretty straightforward method to clone my work computer into a virtual machine image, so that I am able to work in the exact same environment I would have on my physical work computer.  Here's how to do it:</p>

<ol>
<li>Clone the drive using <tt>dd</tt> (the following example assumes your drive is <tt>/dev/sda</tt> and you have an external drive mounted at <tt>/media/removable</tt>:<br/><script src="http://gist.github.com/86317.js"></script><noscript><em>Visit this post in a browser with Javascript support to see the <a href="http://gist.github.com/86317">example code</a>.</em></noscript></li>
<li>Use <tt>qemu-img</tt> to convert the raw bits of the drive to an image in the appropriate format for the virtual machine monitor you want to use (QEMU or VMWare):<br/><script src="http://gist.github.com/86330.js"></script><noscript><em>Visit this post in a browser with Javascript support to see the <a href="http://gist.github.com/86330">example code</a>.</em></noscript></li>
<li>Create a new virtual machine that uses this drive image, using the interface for your preferred virtual machine monitor.</li>
</ol>

<p>I was able to image and convert a 100 gb drive in around six hours.  My drive was an LVM volume and the home partition was encrypted with LUKS; I was delighted to see that <tt>qemu-img</tt> handled these oddball features of my drive flawlessly.  (I can't think of a technical reason why these wouldn't be supported, but I'm nonetheless inclined to be pleasantly surprised when things work as they should out of the box.)</p>]]>
        
    </content>
</entry>

<entry>
    <title>About the author</title>
    <link rel="alternate" type="text/html" href="http://chapeau.freevariable.com/2009/03/about-the-author.html" />
    <id>tag:chapeau.freevariable.com,2009://1.1</id>

    <published>2009-03-27T17:09:12Z</published>
    <updated>2009-03-27T19:44:02Z</updated>

    <summary>I&apos;m Will Benton and I&apos;ll be posting some short technical articles related to my work -- specifically, programming languages, broadly construed, and high-throughput, high-performance, and distributed computing....</summary>
    <author>
        <name>Will Benton</name>
        <uri>http://willbenton.com</uri>
    </author>
    
    <category term="meta" label="meta" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://chapeau.freevariable.com/">
        <![CDATA[<p>I'm Will Benton and I'll be posting some short technical articles related to my work -- specifically, programming languages, broadly construed, and high-throughput, high-performance, and distributed computing.</p>]]>
        
    </content>
</entry>

</feed>
