<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>LShift Ltd.</title>
	<atom:link href="http://www.lshift.net/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.lshift.net/blog</link>
	<description>What happens at LShift</description>
	<pubDate>Fri, 05 Mar 2010 16:21:36 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>Publishing your mercurial-server repositories to the Web</title>
		<link>http://www.lshift.net/blog/2010/03/05/publishing-your-mercurial-server-repositories-to-the-web</link>
		<comments>http://www.lshift.net/blog/2010/03/05/publishing-your-mercurial-server-repositories-to-the-web#comments</comments>
		<pubDate>Fri, 05 Mar 2010 16:11:32 +0000</pubDate>
		<dc:creator>Paul Crowley</dc:creator>
		
		<category><![CDATA[Howto]]></category>

		<category><![CDATA[mercurial-server]]></category>

		<guid isPermaLink="false">http://www.lshift.net/blog/?p=483</guid>
		<description><![CDATA[I got a couple of queries recently on how to make your mercurial-server repositories publically readable over HTTP.  Happily this isn&#8217;t hard to do, and doesn&#8217;t really touch on mercurial-server itself.  Here&#8217;s how we do it on our Debian systems; in what follows I assume that you have installed mercurial-server on hg.example.com, and [...]]]></description>
			<content:encoded><![CDATA[<p>I got a couple of queries recently on how to make your <a href="http://www.lshift.net/mercurial-server.html">mercurial-server</a> repositories publically readable over HTTP.  Happily this isn&#8217;t hard to do, and doesn&#8217;t really touch on mercurial-server itself.  Here&#8217;s how we do it on our Debian systems; in what follows I assume that you have installed mercurial-server on hg.example.com, and that you&#8217;re not already using that machine as a web server for anything else.  First install these packages; note that they tend to have a lot of stuff you don&#8217;t need marked as recommended, so don&#8217;t install those things:</p>

<pre>
apt-get --no-install-recommends install apache2 libapache2-mod-fcgid python-flup
</pre>

<p>Create the following four files:</p>

<p>/etc/mercurial-server/hgweb.config:</p>

<pre>
[collections]
/var/lib/mercurial-server/repos = /var/lib/mercurial-server/repos
</pre>

<p>/etc/mercurial-server/hgweb.hgrc:</p>

<pre>
[web]
style = gitweb
allow_archive = bz2 gz zip
baseurl = http://hg.example.com/
maxchanges = 200
</pre>

<p>/etc/mercurial-server/hgwebdir.fcgi:</p>

<pre>
#!/usr/bin/env python

from mercurial import demandimport; demandimport.enable()

import os
os.environ["HGENCODING"] = &#8220;UTF-8&#8243;
os.environ["HGRCPATH"] = &#8220;/etc/mercurial-server/hgweb.hgrc&#8221;

from mercurial.hgweb.hgwebdir_mod import hgwebdir
from mercurial.hgweb.request import wsgiapplication
from flup.server.fcgi import WSGIServer

def make_web_app():
    return hgwebdir(&#8221;/etc/mercurial-server/hgweb.config&#8221;)

WSGIServer(wsgiapplication(make_web_app)).run()
</pre>

<p>/etc/apache2/sites-available/hg:</p>

<pre>
&lt;VirtualHost *>
    ServerName hg.example.com
    AddHandler fcgid-script .fcgi
    ScriptAlias / /etc/mercurial-server/hgwebdir.fcgi/
    ErrorLog /var/log/apache2/hg/error.log
    LogLevel warn
    CustomLog /var/log/apache2/hg/access.log combined
&lt;/VirtualHost>
</pre>

<p>Finally run these commands as root:</p>

<pre>
chmod +x /etc/mercurial-server/hgwebdir.fcgi
mkdir -p /var/log/apache2/hg
cd /etc/apache2/sites-enabled
rm 000-default
ln -s ../sites-available/hg
/etc/init.d/apache2 reload
</pre>

<p>Your files should now be served at http://hg.example.com/ .  Sadly because of a design flaw in hgwebdir, there&#8217;s no easy way to get Apache to handle the static files it needs, but these are pretty small so there&#8217;s no harm in letting hgwebdir handle them.  The &#8220;rm 000-default&#8221; thing seems pretty undesirable, but without it I can&#8217;t seem to get this recipe to work.</p>

<p>I&#8217;ve chosen FastCGI as the connector.  This has the advantage that<ul>
<li>unlike CGI, it doesn&#8217;t fork a new handler on every request
<li>unlike mod_python, it keeps your Mercurial handler separate from your web server
<li>unlike SCGI, it will automatically start the service for you if it&#8217;s not already running, which is a massive convenience
</ul>
I&#8217;m not aware of any other way of working that offers all three advantages.</p>

<p>As soon as a version of <a href="http://www.lighttpd.net/">lighttpd</a> with <a href="http://redmine.lighttpd.net/issues/show/729">this bug fixed</a> makes it into Debian, I&#8217;ll add my recipe for that.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lshift.net/blog/2010/03/05/publishing-your-mercurial-server-repositories-to-the-web/feed</wfw:commentRss>
		</item>
		<item>
		<title>Installing Visual Studio AddIns for All Users</title>
		<link>http://www.lshift.net/blog/2010/03/05/installing-visual-studio-addins-for-all-users</link>
		<comments>http://www.lshift.net/blog/2010/03/05/installing-visual-studio-addins-for-all-users#comments</comments>
		<pubDate>Fri, 05 Mar 2010 08:41:48 +0000</pubDate>
		<dc:creator>paulj</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Technology]]></category>

		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://www.lshift.net/blog/?p=484</guid>
		<description><![CDATA[Whilst writing the installer for WebGAC, I was faced with some challenges trying to make the Add-In install for all users on the system. The MSDN documentation for Add-In registration generally recommends placing the files into the user&#8217;s My Documents directory. It&#8217;s All Users solution is to place it into the Shared Documents directory. The [...]]]></description>
			<content:encoded><![CDATA[<p>Whilst writing the installer for <a href="http://github.com/paulj/webgac">WebGAC</a>, I was faced with some challenges trying to make the Add-In install for all users on the system. The <a href="http://msdn.microsoft.com/en-us/library/19dax6cz.aspx">MSDN documentation</a> for Add-In registration generally recommends placing the files into the user&#8217;s My Documents directory. It&#8217;s All Users solution is to place it into the Shared Documents directory. The problem I faced was that that directory has moved drastically on Windows 7 - to the point where as far as I can tell, Visual Studio (2008 at least) is no longer searching there by default.</p>

<p>It turns out, though, that there is an easy solution.</p>

<p><span id="more-484"></span></p>

<p>Using some other Add-Ins as examples (such as JetBrain&#8217;s <a href="http://www.jetbrains.com/resharper">ReSharper</a>) the simplest strategy seems to be:</p>

<ol>
<li>Install your AddIn into a standard application install directory (eg, the &#8220;Application Folder&#8221; pointed at [TARGETDIR] in your Visual Studio Setup project, or C:\Program Files\AppName if doing this manually)</li>
<li>Create a string value in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\AutomationOptions\LookInFolders in the registry, with key [TARGETDIR] and value being something descriptive for your application. Note that [TARGETDIR] is a special substituted variable in Visual Studio Setup projects - if you&#8217;re doing this manually, you should instead use the actual path to the directory containing your .addin file (eg  C:\Program Files\AppName)</li>
</ol>

<p>When you start Visual Studio, your AddIn should be loaded. You can also verify this path by opening Tools -> Options, and looking at the list in Environment -> Add-in/Macros Security.</p>

<p>This solution also has the advantage of not placing application files in user directories - hence preventing the user accidentally removing them, and allowing Windows to apply normal Program File protections to the files too.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lshift.net/blog/2010/03/05/installing-visual-studio-addins-for-all-users/feed</wfw:commentRss>
		</item>
		<item>
		<title>Memory matters - even in Erlang</title>
		<link>http://www.lshift.net/blog/2010/02/28/memory-matters-even-in-erlang</link>
		<comments>http://www.lshift.net/blog/2010/02/28/memory-matters-even-in-erlang#comments</comments>
		<pubDate>Sun, 28 Feb 2010 21:42:43 +0000</pubDate>
		<dc:creator>marek</dc:creator>
		
		<category><![CDATA[Erlang]]></category>

		<category><![CDATA[RabbitMQ]]></category>

		<category><![CDATA[Reflection]]></category>

		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://www.lshift.net/blog/?p=481</guid>
		<description><![CDATA[
Some time ago we got an interesting bug report for RabbitMQ. Surprisingly, unlike other complex bugs, this one is easy to describe:&#160;
At some point basic.get suddenly starts being very slow - about 9 times slower!


Basic.get doesn&#8217;t do anything complex - it just pops a message from a queue. This behaviour was quite unexpected. Our initial [...]]]></description>
			<content:encoded><![CDATA[<p>
Some time ago we got an interesting bug report for <a href="http://www.rabbitmq.com/" id="y62y" title="RabbitMQ">RabbitMQ</a>. Surprisingly, unlike other complex bugs, this one is easy to describe:&nbsp;<br />
<p><i>At some point basic.get suddenly starts being very slow - about 9 times slower!</i></p>
<span id="more-481"></span>

<p><i><span class="Apple-style-span" style="font-style:normal"><span class="Apple-style-span" style="font-style:normal">Basic.get doesn&#8217;t do anything complex - it just pops a message from a queue. This behaviour was quite unexpected. Our initial tests confirmed that we have a problem when a queue contains thousands of elements:</span></span></i></p>
<pre>queue_length: 90001  basic_get 3333 times took: 1421.250ms
queue_length: 83335  basic_get 3333 times took: 1576.664ms
queue_length: 60004  basic_get 3333 times took: 1403.086ms
queue_length: 53338  basic_get 3333 times took: 9659.434ms [ look at that! ]
queue_length: 50005  basic_get 3333 times took: 9885.598ms
queue_length: 46672  basic_get 3333 times took: 8562.136ms</pre>
<p>
Let me repeat that. Usually popping a message from a queue takes Xms. At some point, it slows down to 9*Xms.
</p>

<p>It turned out that the problem is with the <i><a href="http://ftp.sunet.se/pub/lang/erlang/doc/man/queue.html#len-1" id="d89l" title="queue:length()">queue:len()</a></i> function, which is executed during the <i>basic.get</i>. Actually, <i>queue:len()</i> calls only <i><a href="http://www.erlang.org/doc/man/erlang.html#length-1" id="somh" title="erlang:length()">erlang:length()</a></i> builtin. At some point it switches to the &#8220;slow&#8221; mode.&nbsp;</p>

<p><i>Erlang:length()</i> is a builtin that iterates through a linked list and counts it&#8217;s length. It&#8217;s complexity is&nbsp;<i>O(N)</i>, where N is the length of the list. This function is implemented in the VM so it&#8217;s expected to be very, very fast.</p>

<p>The problem is not with <i>erlang:length()</i> being slow. It&#8217;s about being unpredictably slow. Let&#8217;s take a look at Erlang interpreter source code (<a href="http://github.com/yrashk/erlang/blob/master/erts/emulator/beam/erl_bif_guard.c#L328" id="ii56" title="erl_bif_guard.c:erts_gc_length_1">erl_bif_guard.c:erts_gc_length_1</a>). Here&#8217;s the main loop for <i>erlang:length()</i>:</div>
<p><pre>i=0
while (is_list(list)) {
    i++;
    list = CDR(list_val(list));
}</pre>

<p>It does nothing unusual - it just iterates through <a href="http://en.wikipedia.org/wiki/Cons" id="ag6g" title="Cons">list elements</a>. However, recompiling Erlang with some debugging information confirms that the problem is indeed here:</p>
<pre>clock_gettime(CLOCK_REALTIME, &amp;t0);
while (is_list(list)) {
    i++;
    list = CDR(list_val(list));
}
clock_gettime(CLOCK_REALTIME, &amp;t1);
td_ms = TIMESPEC_NSEC_SUBTRACT(t1, t0) / 1000000.0;
if (i &gt; 200000 || td_ms &gt; 2.0) {
    fprintf(stderr, "gc_length_1(%p)=%i %.3fms\n\r", reg[live], i, td_ms);
}</pre>

<pre>gc_length_1(0x7f4dbfa7fc19)=499999 2.221ms
gc_length_1(0x7f4dbfa7fc19)=499999 2.197ms
gc_length_1(0x7f4dbfa7fc19)=499999 2.208ms
(hibernation)
gc_length_1(0x7f4db0572049)=499999 13.793ms
gc_length_1(0x7f4db0572049)=499999 12.806ms
gc_length_1(0x7f4db0572049)=499999 12.531ms</pre><p>
This confirms Matthias&#8217; initial guess - the slowdown starts after Erlang process hibernation.
</p>

<p>For those who aren&#8217;t Erlang experts:&nbsp;<a href="http://www.erlang.org/doc/man/erlang.html#hibernate-3" id="g:63" style="color:#551a8b" title="Hibernation">Hibernation</a>&nbsp;is an operation that compacts an Erlang process. It does aggressive garbage collection and reduces the memory footprint of a process to absolute minimum.</p>

<p>The intended result of hibernation is recovering free memory from the process. However its side effect is a new memory layout of objects allocated on the heap.</p>

<p>Ah, how could I have forgotten! The <a href="http://norvig.com/21-days.html#Answers" id="uk7i" title="memory access is slow">memory is nowadays slow</a>! What happens, is that before hibernation list elements are aligned differently, more dense. Whereas after hibernation they are sparse. It&#8217;s easy to test it - let&#8217;s count the average distance between pointers to list elements:</p>
<pre>gc_length_1(0x7f5c626fbc19)=499999 2.229ms avg=16.000 dev=0.023
gc_length_1(0x7f5c626fbc19)=499999 3.349ms avg=16.000 dev=0.023
gc_length_1(0x7f5c626fbc19)=499999 3.345ms avg=16.000 dev=0.023
(hibernation)
gc_length_1(0x7f5c61f7d049)=499999 13.800ms avg=136.000 dev=0.266
gc_length_1(0x7f5c61f7d049)=499999 12.726ms avg=136.000 dev=0.266
gc_length_1(0x7f5c61f7d049)=499999 12.367ms avg=136.000 dev=0.266
</pre>
<p>
<div>Confirmed! Standard deviation is surprisingly small, so we can read the numbers as:</div>
<ul><li>Before hibernation list elements are aligned exactly one after another, values are somewhere else.</li>
<li>After hibernation list elements are interleaved with values.&nbsp;</li></ul>
</p>

<p>This behavior does make sense. In most cases when you traverse the list, you actually do something with the values. After hibernation, when you access list item, the value will be already loaded to the CPU cache.</p>

<p>Knowing the mechanism, it&#8217;s easy to write a <a href="http://ai.pjwstk.edu.pl/~majek/dump/erlang-prefetch-length-test.erl" id="cb:0" title="test case that reproduces this behavior">test case that reproduces the problem</a>.</p>

<p>The average distance between pointers in my case is constant - the standard deviation is negligible. This information has a practical implication - we can &#8220;predict&#8221; where the next pointer will be. Let&#8217;s use that information to &#8220;fix&#8221; the Erlang VM by <a href="http://gcc.gnu.org/projects/prefetch.html" id="wv5_" title="prefetching memory">prefetching memory</a>!</p>

<pre>while (is_list(list)) {
    i++;
    list2 = CDR(list_val(list));
    __builtin_prefetch((char*)list2 + 128*((long)list2-(long)list));
    list = list2;
}
</pre>
<div>Test script running on original Erlang VM:</div>
<pre>length: 300001  avg:0.888792ms dev:0.061587ms
length: 300001  avg:0.881030ms dev:0.040961ms
length: 300001  avg:0.875158ms dev:0.019436ms
hibernate
length: 300001  avg:14.861762ms dev:0.150635ms
length: 300001  avg:14.833733ms dev:0.017405ms
length: 300001  avg:14.884861ms dev:0.220119ms
</pre>
<div><a href="http://ai.pjwstk.edu.pl/~majek/dump/erlang-R13B04-prefetch-length.diff" id="n_0l" title="Patched">Patched</a> Erlang VM:</div>
<pre>length: 300001  avg:0.742822ms dev:0.029322ms
length: 300001  avg:0.739149ms dev:0.012897ms
length: 300001  avg:0.739465ms dev:0.014417ms
hibernate
length: 300001  avg:7.543693ms dev:0.284355ms
length: 300001  avg:7.342802ms dev:0.330158ms
length: 300001  avg:7.265960ms dev:0.053176ms
</pre>
<p>
The test runs only a tiny bit faster for the &#8220;fast&#8221; case (dense <a href="http://en.wikipedia.org/wiki/Cons" id="khsh" title="conses">conses</a>) and twice as fast for the &#8220;slow&#8221; case (sparse conses).</p>

<p>Should this patch be merged into mainline Erlang? Not really. I have set the prefetch multiplier value to 128 and I don&#8217;t even know if it&#8217;s optimal. This was only an experiment. But it was fun to see how low-level system architecture can affect high-level applications.</p>
</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lshift.net/blog/2010/02/28/memory-matters-even-in-erlang/feed</wfw:commentRss>
		</item>
		<item>
		<title>WebGAC: Minding your .NET Dependencies</title>
		<link>http://www.lshift.net/blog/2010/02/27/webgac-minding-your-net-dependencies</link>
		<comments>http://www.lshift.net/blog/2010/02/27/webgac-minding-your-net-dependencies#comments</comments>
		<pubDate>Sat, 27 Feb 2010 18:30:12 +0000</pubDate>
		<dc:creator>paulj</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://www.lshift.net/blog/?p=480</guid>
		<description><![CDATA[Managing binary dependencies in .NET can be a complicated task. For  small projects, checking the dependencies into source control tends to work just fine.  So does requesting that all developers have various binaries available in their GAC. Grow much bigger, or add more projects, and managing that starts to get very difficult.

The Java [...]]]></description>
			<content:encoded><![CDATA[<p>Managing binary dependencies in .NET can be a complicated task. For  small projects, checking the dependencies into source control tends to work just fine.  So does requesting that all developers have various binaries available in their GAC. Grow much bigger, or add more projects, and managing that starts to get very difficult.</p>

<p>The Java world has had a solution to this problem for a long time, in the form of <a href="http://maven.apache.org">Maven</a> and <a href="http://ant.apache.org/ivy">Ivy</a>. Remote servers store the binaries, and the build tool automatically downloads them on demand. WebGAC adds the core of this functionality to .NET, but without requiring you to switch build tools, or maintain a separate configuration file. Dependencies are specified just the same way as normal, but if you don&#8217;t have them when building your project, WebGAC will fetch  them for you automatically.</p>

<p>WebGAC is available at <a href="http://github.com/paulj/webgac">http://github.com/paulj/webgac</a>. Browse over there for more information and installation instructions, or continue reading here for more details.</p>

<p><span id="more-480"></span></p>

<h2>The Remote Server</h2>

<p>A WebGAC remote server is as simple as an Apache HTTP server running the DAV extensions. The DAV extensions provide the ability to query (in a structured form) for directory lists, and to upload new files remotely.</p>

<h2>WebGAC in MSBuild and Visual Studio</h2>

<p>To do its thing, WebGAC requires that a custom Import of targets is added to each project. This is as simple as adding the following block:</p>

<pre>&lt;Import Project="$(MSBuildExtensionsPath)\WebGAC\WebGAC.targets" /></pre>

<p>This import adds all the necessary hooks for doing remote dependency resolution using your project&#8217;s normal references. Any missing assemblies will be automatically downloaded and inserted into your build.</p>

<p>The WebGAC Visual Studio add-in provides mechanisms for configuring the WebGAC extension (eg, setting up remote servers), browsing the remote servers and uploading binaries to the remote servers. </p>

<p>The imported MSBuild targets file also includes targets that allow the assembly produced by the current project to be uploaded to a WebGAC - thus allowing for the release of binaries either from developer machines or from a continuous integration environment. </p>

<h2>The Gory Details</h2>

<p>This section discusses how WebGAC actually does what it does. If you&#8217;re just interested in using WebGAC, feel free to skip it.</p>

<p>As a standard property within the MSBuild environment for a .NET project, the AssemblySearchPaths property is defined as:</p>

<pre>
 &lt;AssemblySearchPaths>
      {CandidateAssemblyFiles};
      $(ReferencePath);
      {HintPathFromItem};
      {TargetFrameworkDirectory};
      {Registry:$(FrameworkRegistryBase),$(TargetFrameworkVersion),$(AssemblyFoldersSuffix)$(AssemblyFoldersExConditions)};
      {AssemblyFolders};
      {GAC};
      {RawFileName};
      $(OutputPath)
    &lt;/AssemblySearchPaths> </pre>

<p>The WebGAC targets import overrides this, by inserting a {WebGAC} target after the {GAC} element. It also overrides the ResolveAssemblyReferencesDependsOn variable (which defines the standard set of tasks to execute when preparing Assembly Resolution) to execute the target AddWebGACAssemblySearchPaths. This target will query it&#8217;s own cache (and any configured remote web servers) for the project&#8217;s references. If they are available via the WebGAC, it will download the files and insert the local cache directories into the search paths. MSBuild and Visual Studio will treat these new paths as if they came from any other standard part of the build system, and incorporate them transparently into the build. Visual Studio will even treat the assemblies as if they came from the GAC!</p>

<p>If WebGAC sounds like it could be useful to you on your .NET project, head over to <a href="http://github.com/paulj/webgac">http://github.com/paulj/webgac</a>. There is even a pre-built installer to get you going quickly!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lshift.net/blog/2010/02/27/webgac-minding-your-net-dependencies/feed</wfw:commentRss>
		</item>
		<item>
		<title>A simple web application in Clojure using ring and enlive</title>
		<link>http://www.lshift.net/blog/2010/02/27/a-simple-web-application-in-clojure-using-ring-and-enlive</link>
		<comments>http://www.lshift.net/blog/2010/02/27/a-simple-web-application-in-clojure-using-ring-and-enlive#comments</comments>
		<pubDate>Sat, 27 Feb 2010 15:31:53 +0000</pubDate>
		<dc:creator>tim</dc:creator>
		
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://www.lshift.net/blog/?p=479</guid>
		<description><![CDATA[This post walks through the steps for using Clojure to write an extremely simple web application. The web application will use the Ring and Enlive libraries.

Firstly install Leiningen, this is a simple build tool for Clojure, follow the instructions on the web page and place the lein somewhere on your executable path.



Now use leiningen to [...]]]></description>
			<content:encoded><![CDATA[<p>This post walks through the steps for using Clojure to write an extremely simple web application. The web application will use the <a href="http://github.com/mmcgrana/ring">Ring</a> and <a href="http://github.com/cgrand/enlive">Enlive</a> libraries.</p>

<p>Firstly install <a href="http://github.com/technomancy/leiningen">Leiningen</a>, this is a simple build tool for Clojure, follow the instructions on the web page and place the <code>lein</code> somewhere on your executable path.</p>

<p><span id="more-479"></span></p>

<p>Now use leiningen to create a new clojure project; I always name my projects after vegetables so we will call this one sprout. Execute this command at the command line:</p>

<pre>% lein new sprout</pre>

This will create a directory called sprout. Change into the newly created directory and issue the following commands:

<pre>
sprout% lein deps
sprout% lein test
</pre>

<p>The first command will download some dependent libraries and the second command will run a default unit test that should fail like this:</p>

<pre>
     [null] Testing sprout.core-test
     [null] FAIL in (replace-me) (core_test.clj:6)
     [null] expected: false
     [null]   actual: false
     [null] Ran 1 tests containing 1 assertions.
     [null] 1 failures, 0 errors.
     [null] &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;
     [null] Total:
     [null] Ran 1 tests containing 1 assertions.
     [null] 1 failures, 0 errors.
</pre>

<p>If this all goes successfully we have a project ready to work with. Working with Clojure is made a lot easier if you have a working REPL to interact with, create a file called <code>clj</code> in the project directory containing a script like this:</p>

<pre>
#!/bin/bash
    LIBS=`printf "%s:" lib/*.jar | sed s/:$//`
    if [ $# -eq 0 ]; then
         java -cp $LIBS:src clojure.main
    else
         java -cp $LIBS:src clojure.main $1 &#8212; $@
    fi
</pre>

<p>Make sure this script is executable and check that it works from the command line like this:</p>

<pre>
sprout%./clj
Clojure 1.1.0
user=> (+ 2 3)
5
user=> ^C
sprout%
</pre>

<p>Now edit the project.clj file to add dependencies for the Ring and Enlive libraries, the file should look like this:</p>

<pre>
(defproject sprout &quot;1.0.0-SNAPSHOT&quot;
  :description &quot;Simple program to play with ring and enlive&quot;
  :dependencies [[org.clojure/clojure &quot;1.1.0&quot;]
                 [org.clojure/clojure-contrib &quot;1.1.0&quot;]
                 [ring &quot;0.1.1-SNAPSHOT&quot;]
                 [enlive &quot;1.0.0-SNAPSHOT&quot;]])
</pre>

<p>Now use leiningen to download the dependencies:</p>

<pre>
sprout% lein deps
</pre>

<p>Now let us create a basic application that will serve some web pages, edit the file <code>src/sprout/core.clj</code> to look like this:</p>

<pre>
(ns sprout.core)

(defn router [req]
  (condp = (:uri req)
    &quot;/error&quot;
      {:status 404
       :headers {&quot;Content-Type&quot; &quot;text/html&quot;}
       :body    (str &quot;Error&quot;)}
    &quot;/info&quot;
      {:status 200
       :headers {&quot;Content-Type&quot; &quot;text/html&quot;}
       :body    (str &quot;This is Ring on &quot; (:server-name req))
      }
    {:status 200
     :headers {&quot;Content-Type&quot; &quot;text/html&quot;}
     :body    (str &quot;Welcome&quot;)}))

(defn app [req]
  (router req))
</pre>

<p>This contains two functions, the router function generates different pages dependent on the requested uri and the app function that forwards a request to the router. We can test this code with a unit test, edit the file <code>test/sprout/core_test.clj</code> and make it look like this:</p>

<pre>
(ns sprout.core-test
  (:use [sprout.core] :reload-all)
  (:use [clojure.test]))

(deftest not-found-error
  (let [req {:uri &quot;/error&quot;}
        resp (app req)]
    (is (= 404 (:status resp)))))

(deftest default-page
  (let [req {:uri &quot;/index.html&quot;}
        resp (app req)]
    (is (= 200 (:status resp)))))

(deftest info-page
  (let [req {:uri &quot;/info&quot;
             :server-name &quot;test&quot;}
        resp (app req)]
    (testing &quot;Info page shown&quot;
      (is (= 200 (:status resp)))
      (is (= &quot;This is Ring on test&quot; (:body resp))))))
</pre>

<p>You can run this test with <code>lein test</code> at the command line.</p>

<p>So far this is pure functional Clojure with no real web pages in site, just a map being passed into a function and a different map being returned, the maps happen to be keyed with keys that look a bit like http requests and responses. The Ring library wraps these functions with adapters that talk to real web containers we will use Jetty to demonstrate real web pages.</p>

<p>Create a new file in <code>src/sprout</code> called <code>run.clj</code> and edit it to appear like this:</p>

<pre>
(ns sprout.run
  (use [ring.adapter.jetty])
  (use [sprout.core]))

(run-jetty app {:port 8080})
</pre>

<p>Now from the command line do this:</p>

<pre>
sprout%./clj src/sprout/run.clj
2010-02-27 14:08:03.602::INFO:  Logging to STDERR via org.mortbay.log.StdErrLog
2010-02-27 14:08:03.604::INFO:  jetty-6.1.14
2010-02-27 14:08:03.727::INFO:  Started SocketConnector@0.0.0.0:8080
</pre>

<p>Using a browser visit the urls <a href="http://localhost:8080">http://localhost:8080</a>, <a href="http://localhost:8080/info">http://localhost:8080/info</a> and <a href="http://localhost:8080/error">http://localhost:8080/error</a>. All being well you should see a welcome page, an info page and a 404 error.</p>

<p>Ring provides a further level of wrapper functions that enable html processing pipelines to be built using simple functions written in Clojure. The pages you have seen so far haven&#8217;t looked very impressive, they are not even valid HTML! We could embed the HTML in the code or write a library to generate HTML in Clojure but instead we will use Enlive.</p>

<p>Enlive is a selector based templating library, this differs from templating languages such as JSP or ASP in that the raw html remains untouched, functions are written that use css selectors to replace and augment the existing html. Create a file in the <code>src/sprout</code> directory called <code>enlive.clj</code> and edit it to appear like this:</p>

<pre>
(ns sprout.enlive
  (:use [net.cgrand.enlive-html]))

(deftemplate t1 &quot;templates/t1.html&quot; []
  [:h1]   (content &quot;heading&quot;))

(defn enlive-template []
  (apply str(t1)))
</pre>

<p>The <code>deftemplate</code> declaration creates a template called t1, that takes no parameters and substitutes the content of any h1 tags with the word heading. The function enlive-template just applies the template to generate HTML.</p>

<p>Now add a new mapping to the router defined in <code>src/sprout/core.clj</code> to use this function, the file should now look like this:</p>

<pre>
(ns sprout.core
  (:use sprout.enlive))

(defn router [req]
  (condp = (:uri req)
    &quot;/error&quot;
      {:status 404
       :headers {&quot;Content-Type&quot; &quot;text/html&quot;}
       :body    (str &quot;Error&quot;)}
    &quot;/info&quot;
      {:status 200
       :headers {&quot;Content-Type&quot; &quot;text/html&quot;}
       :body    (str &quot;This is Ring on &quot; (:server-name req))
      }
    &quot;/enlive&quot;
      {:status 200
       :headers {&quot;Content-Type&quot; &quot;text/html&quot;}
       :body (enlive-template)
      }
    {:status 200
     :headers {&quot;Content-Type&quot; &quot;text/html&quot;}
     :body    (str &quot;Welcome&quot;)}))

(defn app [req]
  (router req))
</pre>

<p>Running the run script again:</p>

<pre>
prout%./clj src/sprout/run.clj
2010-02-27 15:10:35.476::INFO:  Logging to STDERR via org.mortbay.log.StdErrLog
2010-02-27 15:10:35.479::INFO:  jetty-6.1.14
2010-02-27 15:10:35.528::INFO:  Started SocketConnector@0.0.0.0:8080
</pre>

<p>Now go to <a href="http://localhost:8080/enlive">http://localhost:8080/enlive</a> and an HTML page should be visible.</p>

<p>This has been an extremely basic introduction to using Ring and Enlive with Clojure to serve up web pages. I&#8217;ll be expanding on this example at a later date to dive deeper into the functionality of Ring, Enlive and Clojure.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lshift.net/blog/2010/02/27/a-simple-web-application-in-clojure-using-ring-and-enlive/feed</wfw:commentRss>
		</item>
		<item>
		<title>RabbitMQ-shovel: Message Relocation Equipment</title>
		<link>http://www.lshift.net/blog/2010/02/01/rabbitmq-shovel-message-relocation-equipment</link>
		<comments>http://www.lshift.net/blog/2010/02/01/rabbitmq-shovel-message-relocation-equipment#comments</comments>
		<pubDate>Mon, 01 Feb 2010 12:13:52 +0000</pubDate>
		<dc:creator>matthew</dc:creator>
		
		<category><![CDATA[Erlang]]></category>

		<category><![CDATA[RabbitMQ]]></category>

		<category><![CDATA[Technology]]></category>

		<category><![CDATA[plugin]]></category>

		<category><![CDATA[shovel]]></category>

		<guid isPermaLink="false">http://www.lshift.net/blog/?p=478</guid>
		<description><![CDATA[In several applications, it&#8217;s very useful to be able to take messages out of one RabbitMQ broker, and insert them into another. Many people on our mailing list have being asking for such a shovel, and we&#8217;ve recently been able to devote some time to writing one. This takes the form of a plugin for [...]]]></description>
			<content:encoded><![CDATA[<p>In several applications, it&#8217;s very useful to be able to take messages out of one RabbitMQ broker, and insert them into another. Many people on our mailing list have being asking for such a shovel, and we&#8217;ve recently been able to devote some time to writing one. This takes the form of a plugin for Rabbit, and whilst it hasn&#8217;t been through QA just yet, we&#8217;re announcing it so people who would like to play and even suggest further features for inclusion can do so sooner rather than later.</p>

<p>The shovel is written on top of the Erlang client. It supports both direct and network connections to nodes, SSL support, the ability to declare resources on nodes it connects to, basic round-<del datetime="2010-02-01T11:10:34+00:00">robin</del>rabbit balancing of both source and destination nodes, and allows you to configure many parameters controlling how messages are consumed from the source, and how they&#8217;re published to the destination. Multiple shovels can be specified, their statuses queried, and shovels can repeatedly reconnect to nodes in the event of failure.</p>

<p>The plugin is available from <a href="http://hg.rabbitmq.com/rabbitmq-shovel/">http://hg.rabbitmq.com/rabbitmq-shovel/</a>, and is released under the MPL v1.1. There is a README included which contains full documentation. This is replicated below.<span id="more-478"></span></p>

<h1>RabbitMQ-shovel</h1>

<h2>Introduction</h2>

<p>This is a plug-in for RabbitMQ that shovels messages from a queue on
one broker to an exchange on another broker. The two brokers may be
the same. The plug-in allows several shovels to be specified at the
same time. Each shovel may have a number of source and destination
brokers specified, and one of each is chosen whenever the shovel
attempts to make a connection: this permits simple round-rabbit load
balancing.</p>

<p>Resources can be declared upon connection to both the source and
destination brokers, and parameters can be specified for both the
reception and publishing of messages.</p>

<h2>Requirements</h2>

<p>Currently, you must build the server from source, under branch
bug16653. You must also have checked out the rabbitmq-public-umbrella
hg repository, and have the rabbitmq-erlang-client built. From
scratch, the following commands should build RabbitMQ with the shovel
plug-in:</p>

<pre>
hg clone http://hg.rabbitmq.com/rabbitmq-public-umbrella
cd rabbitmq-public-umbrella
hg clone http://hg.rabbitmq.com/rabbitmq-codegen
hg clone http://hg.rabbitmq.com/rabbitmq-erlang-client
hg clone http://hg.rabbitmq.com/rabbitmq-server
hg clone http://hg.rabbitmq.com/rabbitmq-shovel
cd rabbitmq-server
hg up -C bug16653
make -j
mkdir -p plugins
cd plugins
ln -s ../../rabbitmq-erlang-client
ln -s ../../rabbitmq-shovel
cd ../../rabbitmq-erlang-client
make
cd ../rabbitmq-shovel
make
cd ../rabbitmq-server
./scripts/rabbitmq-activate-plugins
make cleandb run
</pre>

<h2>Configuration</h2>

<p>The RabbitMQ configuration file specifies the shovel
configurations. This exists by default, in
<code>/etc/rabbitmq/rabbitmq.config</code> under Linux systems,
<code>%RABBITMQ_BASE%\rabbitmq.config</code> under Windows or somewhere else under
OS X. This file configures both RabbitMQ-server and all the plugins
installed in it. It is an Erlang-syntax file of the form:</p>

<pre>
[{section1, [section1-config]},
 {section2, [section2-config]},
 &#8230;
 {sectionN, [sectionN-config]}
].
</pre>

<p>thus a list of tuples, where the left element of each tuple names the
applications being configured. Don&#8217;t forget the last element of the
list doesn&#8217;t have a trailing comma, and don&#8217;t forget the full-stop is
needed after closing the list. Hence if you configure RabbitMQ-server
and the RabbitMQ-shovel, then the configuration file may have a
structure like this:</p>

<pre>
[{rabbit,        [configuration-for-RabbitMQ-server]},
 {rabbit-shovel, [configuration-for-RabbitMQ-shovel]}
].
</pre>

<p>A full example of the shovel configuration is:</p>

<pre>
{rabbit_shovel,
  [{shovels,
    [{my_first_shovel,
      [{sources,      [{brokers,
                          ["amqp://fred:secret@host1.domain/my_vhost",
                           "amqp://john:secret@host2.domain/my_vhost"
                          ]},
                       {declarations,
                          ['queue.declare',
                           {'queue.bind',
                                  [{exchange, <<"my_exchange">>},
                                   {queue,    <<>>}]}
                          ]}]},
       {destinations, [{broker, "amqp://"},
                       {declarations,
                          [{'exchange.declare',
                                  [{exchange, <<"my_exchange">>},
                                   {type, <<"direct">>},
                                   durable]}
                          ]}]},
       {queue, <<>>},
       {qos, 10},
       {auto_ack, false},
       {tx_size, 0},
       {delivery_mode, keep},
       {publish_fields, [{exchange, <<"my_exchange">>},
                         {routing_key, <<"from_shovel">>}]},
       {reconnect, 5}
      ]}
     ]
   }]
}
</pre>

<p>Firstly, all shovels are named. Here we have one shovel, called
&#8216;my_first_shovel&#8217;. We can have multiple shovels if you wish. Every
shovel must have all sub-fields specified: sources, destinations, qos,
auto_ack, delivery_mode, publish_fields, reconnect.</p>

<h2>Sources and Destinations</h2>

<p>Sources and destinations specify respectively where messages are
fetched from and delivered too. One of &#8216;broker&#8217; and &#8216;brokers&#8217; must be
specified, and &#8216;broker&#8217; is simply shorthand for when only one broker
needs specifying. Using &#8216;brokers&#8217; allows a list of brokers to be
specified: whenever the connection to a broker is lost, another one is
chosen at random from the list and a connection attempt is made to
that. The syntax for broker URIs is:</p>

<p><code>amqp://username:password@host:port/vhost</code></p>

<p>If username or password are omitted, the default values of guest and
guest are used. If the vhost is omitted, the default value of / is
used. If the host is omitted, then the plugin uses the &#8220;direct&#8221;
connection internally rather than a network connection: this means it
connects to the RabbitMQ-server node on which it is running without
going through the network stack. This is much more efficient. If port
is omitted then the default value is used (5672 or 5671 if SSL is
used).</p>

<p>SSL is implemented, for which additional parameters are needed:</p>

<p><code>amqps://username:password@host:port/vhost?cacertfile=/path/to/cacert.pem&amp;certfile=/path/to/certfile.pem&amp;keyfile=/path/to/keyfile.pem&amp;verify=verifyOption&amp;fail_if_no_peer_cert=failOption</code></p>

<p>(note, this is a single line)</p>

<p>All five parameters (3 paths: cacertfile, certfile and keyfile; 2
options: verify, fail_if_no_peer_cert) must be specified. See the SSL
guide at http://www.rabbitmq.com/ssl.html#configure-erlang for details
of SSL in RabbitMQ in general and specifically for the Erlang client
(on which the shovel is built).</p>

<p>Note that SSL cannot be used with the direct connection (i.e. a host
must be specified when using SSL), and that it is preferable to use
the non-SSL direct connection when connecting to the same node that&#8217;s
running the shovel.</p>

<h2>Resource Declarations</h2>

<p>Both sources and destinations can have an optional &#8216;declarations&#8217;
clause. The value of this is a list, consisting of AMQP Methods. If
default values are sufficient, then the method name alone can be
specified - e.g. &#8216;queue.declare&#8217;. If parameters need to be set then
the method should be given as a tuple, with the right hand side a
proplist specifying which fields need altering from their default
values. E.g:</p>

<pre>
    {'exchange.declare',[{exchange, <<"my_exchange">>},
                         {type, <<"direct">>},
                         durable]},
</pre>

<p>One very useful feature here is the Most-Recently-Declared-Queue
feature, in which RabbitMQ remembers the name of the most recently
declared queue. This means that you can declare a private queue, and
then bind it to exchanges without ever needing to know its name.</p>

<h2>queue :: binary</h2>

<p>This parameter specifies the name of the queue on the source brokers
to consume from. This queue must exist. Use the resource declarations
to create the queue (or ensure it exists) first. Note again that the
Most-Recently-Declared-Queue feature can be used here, thus an
anonymous queue can be used: use &lt;&lt;>> to indicate the
Most-Recently-Declared-Queue.</p>

<h2>qos :: non-negative-integer</h2>

<p>The shovel consumes from a queue. The QoS controls how many messages
are sent to the shovel in advance of the message the shovel is
currently processing.</p>

<h2>auto_ack :: boolean</h2>

<p>Setting this to &#8216;true&#8217; turns on the no_ack flag when subscribing to
the source queue.</p>

<h2>tx_size :: non-negative-integer</h2>

<p>When set to 0, transactions are not used. Other values make publishes
transactional, with a commit every N messages. In lieu of the auto-ack
option, when transactions are not used, messages are acknowledged to
the source immediately after every publish. When transactions are
used, acks are only issued to the source on receipt of the commit-ok
message from the destination. This can thus be used to guarantee that
messages are only acknowledged (and thus forgotten about by the source
broker) when they are guaranteed to have been received by the
destination broker.</p>

<h2>delivery_mode :: &#8216;keep&#8217; | 0 | 2</h2>

<p>This affects the delivery_mode field when publishing to the
destination. A value of &#8216;keep&#8217; means that the same delivery_mode
should be used as when the message was originally published to the
source broker. 0 and 2 override the original setting.</p>

<h2>publish_fields</h2>

<p>This is a list of tuples which override fields in the publish method
when publishing to the destination. This can be used to direct
messages to a particular exchange on the destination, for example, or
change the routing key. By default, the routing key of the message as
it is received by the shovel is passed through, but this can be
overridden as necessary.</p>

<h2>reconnect :: non-negative-integer</h2>

<p>When an error occurs, the shovel will disconnect from both the source
and destination broker immediately. This will force uncommitted
transactions at the destination to be rolled back, and delivered but
unacknowledged messages from the source to be requeued. The shovel
will then try connecting again. If this is unsuccessful, then it&#8217;s not
a good idea for the shovel to very quickly and repeatedly try to
reconnect. The value specified here is the number of seconds to wait
between each connection attempt.</p>

<p>Note that if set to 0, the shovel will never try to reconnect: it&#8217;ll
stop after the first error.</p>

<h2>Obtaining shovel statuses</h2>

<p>From the broker Erlang prompt, call
<code>rabbit_shovel_status:status().</code> This will return a list, with one row
for each configured shovel. Each row has three fields: the shovel
name, the shovel status, and the timestamp (a local calendar time of
<code>{{YYYY,MM,DD},{HH,MM,SS}}</code>). There are 3 possible statuses:</p>

<ul>
<li><p>&#8217;starting&#8217;: The shovel is starting up, connecting and creating
resources.</p></li>
<li><p>&#8216;running&#8217;: The shovel is up and running, shovelling messages.</p></li>
<li><p>{&#8217;terminated&#8217;, Reason}: Something&#8217;s gone wrong. The Reason should give
a further indication of where the fault lies.</p></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.lshift.net/blog/2010/02/01/rabbitmq-shovel-message-relocation-equipment/feed</wfw:commentRss>
		</item>
		<item>
		<title>Validating whole forms with WPF Data Binding</title>
		<link>http://www.lshift.net/blog/2010/01/31/validating-whole-forms-with-wpf-data-binding</link>
		<comments>http://www.lshift.net/blog/2010/01/31/validating-whole-forms-with-wpf-data-binding#comments</comments>
		<pubDate>Sun, 31 Jan 2010 10:38:09 +0000</pubDate>
		<dc:creator>tim</dc:creator>
		
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://www.lshift.net/blog/?p=477</guid>
		<description><![CDATA[Microsoft WPF includes a data binding framework that provides a simple declarative mechanism to associate  and validate data with UI components - read some good tips and tricks here.

This works well very well for simple form validation but sometimes you may want to perform a more complex series of validations and reflect the failures [...]]]></description>
			<content:encoded><![CDATA[<p>Microsoft WPF includes a data binding framework that provides a simple declarative mechanism to associate  and validate data with UI components - <a href="http://stackoverflow.com/questions/63646/wpf-data-binding-and-validation-rules-best-practices">read some good tips and tricks here</a>.</p>

<p>This works well very well for simple form validation but sometimes you may want to perform a more complex series of validations and reflect the failures back to the user in a similar manner to the field level validation. For example, a particular combination of fields may result in breaking a business rule for that particular user and the client has asked you to highlight all of these fields with a similar message. In this situation additional validation when the form is submitted may be the simplest solution, so we need to carry out some process like this:</p>

<ol>
    <li>Perform validation of business object obtained from data binding.</li>
    <li>Interpret validation results.</li>
    <li>Flag multiple fields as being incorrect.</li>
</ol>

<p>To perform the last step you need to know how to programmatically force binding errors. I googled  and binged for ages trying to find this information so here is the simple recipe.</p>

<ol>
    <li>Make sure the fields that the fields that need to show binding errors have a mode of TwoWay or OneWayToSource in their binding expression.</li>
    <li>Make sure the fields that need to show binding errors have the ValidatesOnDataErrors set to true in their binding expressions.</li>
    <li>Force the validation errors when the form is submitted like this</li>
</ol>

<pre>
ValidationError validationError = new ValidationError(emptyValidationRule,
         textBox.GetBindingExpression(TextBox.TextProperty), "Error message", null);
Validation.MarkInvalid(textBox.GetBindingExpression(TextBox.TextProperty), validationError);
</pre>

<p>I am using an <em>emptyValidationRule</em> just to satisfy the type signature here. It is never actually used because my business validation is carried out elsewhere. The <em>emptyValidationRule</em> is a simple implementation of a ValidationRule that always fails. </p>

<p>To remove a validation error from a field</p>

<pre>
Validation.ClearInvalid(textBox.GetBindingExpression(TextBox.TextProperty));
</pre>

<p>This approach can also help if you need to validate that a ComboBox value is actually selected when no default value has been provided. Validation rules only fire automatically if data binding actually occurs, that means the ComboBox must actually be used. You could force databinding to occur like this:</p>

<pre>
comboBox.GetBindingExpression(ComboBox.SelectedItemProperty).UpdateTarget();
</pre>

<p>when the ComboBox loses focus. However, if the user just uses the mouse to press the form submit button, the combobox will never gain or lose focus so no validation will take place. To work around this you can validate in the way I have shown above or perform UpdateTarget operations on all of the ComboBox controls in the form when submit is pressed.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lshift.net/blog/2010/01/31/validating-whole-forms-with-wpf-data-binding/feed</wfw:commentRss>
		</item>
		<item>
		<title>Plugin exchange types for RabbitMQ</title>
		<link>http://www.lshift.net/blog/2010/01/22/plugin-exchange-types-for-rabbitmq</link>
		<comments>http://www.lshift.net/blog/2010/01/22/plugin-exchange-types-for-rabbitmq#comments</comments>
		<pubDate>Fri, 22 Jan 2010 14:38:54 +0000</pubDate>
		<dc:creator>mikeb</dc:creator>
		
		<category><![CDATA[Erlang]]></category>

		<category><![CDATA[RabbitMQ]]></category>

		<category><![CDATA[rabbitmq erlang]]></category>

		<guid isPermaLink="false">http://www.lshift.net/blog/?p=473</guid>
		<description><![CDATA[An obvious extension point for an AMQP broker is the addition of new types of exchange.  An exchange type essentially represents an algorithm for dispatching messages to queues, usually based on the message's routing key, given how the queues are bound to the exchange -- it's a routing algorithm.  RabbitMQ now supports plugin exchange types, currently on an experimental branch.]]></description>
			<content:encoded><![CDATA[<p>An obvious extension point for an AMQP broker is the addition of new types of exchange.  An exchange type essentially represents an algorithm for dispatching messages to queues, usually based on the message&#8217;s routing key, given how the queues are bound to the exchange &#8212; it&#8217;s a message routing algorithm.</p>

<p>At a minimum, supporting new exchange types requires only some scaffolding to plug in to (an exchange type registry) and a hook for routing messages.  However, this wouldn&#8217;t support some more interesting use cases, and in particular it didn&#8217;t support our <a href="http://oceanobservatories.org/spaces/download/attachments/19432960/ooi-amqp-api-20091228.pdf?version=1">motivating use case</a>.  Exchange types that want to keep their own state need to be initialised, and be notified about other lifecycle events.
<span id="more-473"></span></p>

<p>The <del datetime="2010-03-04T16:21:12+00:00">branch bug22169</del> default branch of RabbitMQ supports plugin exchange types, by providing a behaviour for exchange type modules to implement, and an exchange type registry to map a module to a type (i.e., what the client supplies in the type field of exchange.declare).</p>

<p>The behaviour requires exported hooks for validating exchange declarations, creating exchanges, recovering durable exchanges, publishing to an exchange (this is where the routing comes in), maintaining bindings, and deleting an exchange.  RabbitMQ continues to maintain the database of exchanges and bindings, and calls the hooks after it&#8217;s done its own bookkeeping.</p>

<p>For simplicity, the hooks are not called atomically with the bookkeeping; so, it is possible for instance to publish to a new exchange for which the hook has not completed.  However, provided there are no asynchronous operations in the hook implementation, the hook will have completed by the time the OK message is sent to the client.  This is no more racey than AMQP itself, with consistency at the channel level where operations follow a single thread of control.</p>

<p>Here&#8217;s an example that simply <code>io:format</code>s things as they happen:</p>

<pre><code>-module(rabbit_exchange_type_debug).
-include("rabbit.hrl").

-behaviour(rabbit_exchange_type).

-export([description/0, publish/2]).
-export([validate/1, create/1, recover/2, delete/2, add_binding/2, remove_bindings/2]).
-export([register_debug_types/0]).
-include(&#8221;rabbit_exchange_type_spec.hrl&#8221;).

-rabbit_boot_step({debug_exchange_types, 
                   [{description, "debugging exchange types"},
                    {mfa, {?MODULE, register_debug_types, []}},
                    {requires, rabbit_exchange_type_registry},
                    {enables, exchange_recovery}]}).

description() -&gt;
    [{name, &lt;&lt;"debug"&gt;&gt;},
     {description, &lt;&lt;"Debugging exchange"&gt;&gt;}].

backing_module(#exchange{ type = Type }) -&gt;
    %% Presume that Type is EITHER one of the standard types &#8211;
    %% i.e,. that we have been registered this module as direct,
    %% topic, fanout or match &#8212; or, for testing purposes, it&#8217;s
    %% registered (as in the boot steps above) as debug_direct, etc.
    Type1 = case atom_to_list(Type) of
                &#8220;x-debug-&#8221; ++ T -&gt; T; 
                              T -&gt; T
            end,
    list_to_existing_atom(&#8221;rabbit_exchange_type_&#8221; ++ Type1).

publish(Exchange, Delivery) -&gt;
    io:format(&#8221;Publish ~p to ~p~n&#8221;, [Delivery, Exchange]),
    Module = backing_module(Exchange),
    Module:publish(Exchange, Delivery).

validate(X) -&gt;
    io:format(&#8221;Validate ~p~n&#8221;, [X]),
    (backing_module(X)):validate(X).

create(X) -&gt;
    io:format(&#8221;Create ~p~n&#8221;, [X]),
    (backing_module(X)):create(X).

recover(X, Bs) -&gt;
    io:format(&#8221;Recover ~p with bindings ~p~n&#8221;, [X, Bs]),
    (backing_module(X)):recover(X, Bs).

delete(X, Bs) -&gt;
    io:format(&#8221;Delete ~p with bindings ~p~n&#8221;, [X, Bs]),
    (backing_module(X)):delete(X, Bs).

add_binding(X, B) -&gt;
    io:format(&#8221;Add binding ~p to ~p~n&#8221;, [B, X]),
    (backing_module(X)):add_binding(X, B).

remove_bindings(X, Bs) -&gt;
    io:format(&#8221;Delete bindings ~p from ~p~n&#8221;, [Bs, X]),
    (backing_module(X)):remove_bindings(X, B).

register_debug_types() -&gt;
    lists:foreach(
      fun (T) -&gt;
              rabbit_exchange_type_registry:register(T, ?MODULE)
      end,
      [&lt;&lt;"x-debug-direct"&gt;&gt;,
       &lt;&lt;"x-debug-topic"&gt;&gt;,
       &lt;&lt;"x-debug-fanout"&gt;&gt;,
       &lt;&lt;"x-debug-headers"&gt;&gt;]).
</code></pre>

<p>Bit by important bit:</p>

<pre><code>-behaviour(rabbit_exchange_type).
-export([description/0, publish/2]).
-export([validate/1, create/1, recover/2, delete/2, add_binding/2, remove_bindings/2]).
</code></pre>

<p><code>rabbit_exchange_type</code> specifies these exported callbacks.</p>

<pre><code>-include("rabbit_exchange_type_spec.hrl").
</code></pre>

<p>This include has the specs for each of the exported functions, if you&#8217;re using specs.</p>

<pre><code>-rabbit_boot_step({debug_exchange_types, 
                   [{description, "debugging exchange types"},
                    {mfa, {?MODULE, register_debug_types, []}},
                    {requires, rabbit_exchange_type_registry},
                    {enables, exchange_recovery}]}).
</code></pre>

<p>This uses the new boot sequence mechanism to register the exchange type during boot.  The &#8220;enables&#8221; and &#8220;requires&#8221; say that the function given as mfa above must be run after the exchange type registry is available, but before any exchanges are recovered.</p>

<pre><code>publish(Exchange, Delivery) -&gt;
    io:format("Publish ~p to ~p~n", [Delivery, Exchange]),
    Module = backing_module(Exchange),
    Module:publish(Exchange, Delivery).
</code></pre>

<p>This exchange type simply delegates to a &#8220;backing&#8221; exchange type.</p>

<pre><code>register_debug_types() -&gt;
    lists:foreach(
      fun (T) -&gt;
              rabbit_exchange_type:register(T, ?MODULE)
      end,
      [&lt;&lt;"x-debug-direct"&gt;&gt;,
       &lt;&lt;"x-debug-topic"&gt;&gt;,
       &lt;&lt;"x-debug-fanout"&gt;&gt;,
       &lt;&lt;"x-debug-headers"&gt;&gt;]).
</code></pre>

<p><code>rabbit_exchange_type_registry</code> maintains a registry of type to module; because of this indirection, we can register this module as many different types, then check the declared type of the exchange in our hook to see which type we&#8217;re expected to be.  Note that the AMQP specification requires the &#8220;x-&#8221; prefix for non-standard exchange types.</p>

<p><del datetime="2010-03-04T16:21:12+00:00">This should reach default branch soon after RabbitMQ 1.7.1 is
released.</del> This is in RabbitMQ&#8217;s default branch, and should be in the next release (1.7.2).</p>

<p>You can drop modules straight into <code>src</code>, but they are better packaged
as plugins &#8212; follow the drill at <a href="http://www.rabbitmq.com/plugin-development.html](http://www.rabbitmq.com/plugin-development.html">the plugin development
guide</a>
(and note that your plugin may only need to be a library application).</p>

<p>[EDITS: Updated sample code to keep up with name changes, and correct use of list_to_atom to list_to_existing_atom]
[Further EDITS: slight API change, now in default branch]</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lshift.net/blog/2010/01/22/plugin-exchange-types-for-rabbitmq/feed</wfw:commentRss>
		</item>
		<item>
		<title>Upgrading your disk with LVM</title>
		<link>http://www.lshift.net/blog/2010/01/15/upgrading-your-disk-with-lvm</link>
		<comments>http://www.lshift.net/blog/2010/01/15/upgrading-your-disk-with-lvm#comments</comments>
		<pubDate>Fri, 15 Jan 2010 17:35:51 +0000</pubDate>
		<dc:creator>Paul Crowley</dc:creator>
		
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://www.lshift.net/blog/?p=472</guid>
		<description><![CDATA[I&#8217;ve just had my most pleasant move from a smaller to a larger disk ever thanks to LVM, with vastly reduced downtime, and I thought I&#8217;d share my happy experience.

LVM is Linux&#8217;s &#8220;Logical Volume Manager&#8221;. You take a bunch of physical disks and partitions - the &#8220;physical volumes&#8221; - and bundle them together to make [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just had my most pleasant move from a smaller to a larger disk ever thanks to LVM, with vastly reduced downtime, and I thought I&#8217;d share my happy experience.<span id="more-472"></span></p>

<p>LVM is Linux&#8217;s &#8220;Logical Volume Manager&#8221;. You take a bunch of physical disks and partitions - the &#8220;physical volumes&#8221; - and bundle them together to make a &#8220;volume group&#8221;.  Then you split up the &#8220;volume group&#8221; into partitions - or &#8220;logical volumes&#8221; again in whatever way you like.  It works by breaking the disk up into 4MB chunks called &#8220;extents&#8221;, and maintaining a map between the logical and physical indexes of extents.   The advantage is that you don&#8217;t have to care about the physical layout when you create the logical layout - you can stick together several physical disks into one big virtual disk, for example, or grow whatever logical volume you like without worrying about what might be using the disk sectors in front of it.  You can also do things like move a logical volume from one disk to another <em>while it&#8217;s still in use</em>, which is the very exciting subject of this post.</p>

<p>I&#8217;ve been setting up LVM on every machine I&#8217;ve installed Linux on for a while now, on the assumption that this sort of flexibility would come in handy one day, but I&#8217;ve never actually used it until now.  At install time,  I set up a 100MB physical partition at the start of the disk for the &#8220;/boot&#8221; directory - I&#8217;ll talk about this later when I discuss GRUB - then dedicate the rest of the disk to LVM.  You can do all this in the Ubuntu installer.  When I needed to extend my disk space, here&#8217;s what I did:</p>

<ul>
<li>switched my machine off (not sure if I have SATA hot-swap, and thought it best not to find out the hard way)</li>
<li>fitted the new disk</li>
<li>brought it back up; the new disk arrived as /dev/sdb.</li>
<li>Applied the same partitioning to the new disk - /dev/sdb1 is 100MB and /dev/sdb5 is the rest of the disk.</li>
<li>&#8220;pvcreate /dev/sdb5&#8243; makes (most of) the disk into a &#8220;physical partition&#8221; that LVM can use</li>
<li>&#8220;vgextend lvmvolume /dev/sdb5&#8243; adds the new physical partition to the volume group.  Now my volume group is three times bigger!</li>
<li>I needed to make use of some of that extra space right away to get some work done, so next came &#8220;lvextend -L +50G /dev/lvmvolume/root&#8221; to give my root partition an extra 50 gig.</li>
<li>Now the partition is bigger than the filesystem, so I tell the filesystem to make use of the extra space: &#8220;resize2fs /dev/lvmvolume/root&#8221;. &#8220;resize2fs&#8221; is happy to make the filesystem bigger even while it&#8217;s mounted and in use, but you have to unmount it to make it smaller, so I tend to resize upwards in small increments as the extra space is needed.</li>
<li>And that&#8217;s it, I had the space I needed.  I started to use it right away.</li>
<li>But, I want to take the old disk out otherwise they will start to pile up, so there&#8217;s more to do.  To tell LVM to stop using the old disk, I issued &#8220;pvmove /dev/sda1&#8243;.  Over the course of several hours, this copied my root filesystem - which, in case I hadn&#8217;t mentioned this enough, was mounted and in use - from the old disk to the new.</li>
<li>I was disturbed to see that pvmove finshed with an error; I&#8217;m afraid I didn&#8217;t keep a copy of the error.  However, issuing it a second time said there was no work to do, and &#8220;pvdisplay&#8221; showed that /dev/sda1 was no longer in use.</li>
<li>&#8220;vgreduce -a&#8221; removed /dev/sda1 from the list of physical volumes in the volume group, and</li>
<li>&#8220;pvremove&#8221; marked it as no longer a physical volume.</li>
</ul>

<p>These days I call my volume group &#8220;vg&#8221; rather than &#8220;lvmvolume&#8221;.  I suspect that the system that needs more than one volume group is rare, so a short name is handy.</p>

<p>That&#8217;s the LVM part of things moved.  However, there&#8217;s still &#8220;/boot&#8221; to take care of.  To explain what&#8217;s going on there, I need to talk a little about how a modern Linux system boots; I got this from <a href="http://lists.gnu.org/archive/html/grub-devel/2009-12/msg00266.html">this mailing list post</a> and discussions on the #grub IRC channel.</p>

<p>If the BIOS decides that it&#8217;s going to boot from a hard drive, it loads a very small program from the very first sector of the disk (known as the MBR).  That program then loads the next things it needs &#8220;core.img&#8221; which is in sectors 1 to 62 (which are always unused).  It finds two things in there:</p>

<ul>
<li>GRUB modules - these tell it how to do things like read partition tables, or read Linux filesystems</li>
<li>basic config information - which tells it where &#8220;/boot&#8221; may be found</li>
</ul>

<p>In other words &#8220;core.img&#8221; contains exactly enough for GRUB to find and read the filesystem with &#8220;/boot&#8221; in it.  From there, it can read any other modules it may need.  It can also find the &#8220;grub.cfg&#8221; configuration file that tells it what to do next.  &#8220;grub.cfg&#8221; will usually instruct it to display a menu; when you select a system to boot, &#8220;grub.cfg&#8221; will tell it where to find the kernel image it&#8217;s going to boot.  It loads that image into memory and runs it, with parameters from &#8220;grub.cfg&#8221; that tell it where to look for the root filesystem it&#8217;s eventually going to use.</p>

<p>What I&#8217;ve described here is GRUB 2, and as it happens GRUB 2 is happy to read /boot from an LVM-based filesystem, given the right modules.  However, the old GRUB couldn&#8217;t do that, and since Ubuntu still prefers to use the old GRUB at install time and upgrade later, I prefer to put it on a separate filesystem.  Possibly I could have changed that while moving to the new disk, but I didn&#8217;t want to change too much at once, and it only takes up 0.1% of the disk.</p>

<p>So, after this transition I&#8217;ve got most of my filesystem onto the new disk, but the boot process still relies on the old disk - only the old disk has the MBR, or core.img, or the /boot partition.  Copying over /boot is easy - &#8220;mkfs.ext3 /dev/sdb1&#8243; to create it, then mount it and copy over the files, after which I unmounted both, changed &#8220;/etc/fstab&#8221; to point at the new drive (to avoid problems when devices move about, /etc/fstab names the partition by UUID - you can get the UUID of all your partitions with &#8220;blkid&#8221;) and re-mounted it now using the new one.</p>

<p>After this, I went wrong.  I had hoped that &#8220;grub-install &#8211;recheck /dev/sdb&#8221; would be enough to get the new drive booting OK, but it turns out that this doesn&#8217;t re-write &#8220;grub.cfg&#8221;, and that file still contained references to an old UUID.  I&#8217;m not sure what the Right Way to fix this file was; I just used &#8220;grub-mkconfig > /boot/grub/grub.cfg&#8221; to rewrite it, but I suspect there&#8217;s some higher-level tool I should have called.</p>

<p>That&#8217;s it - with that done, I could remove the drive from the machine.  However, I plugged it in one last time - in order to zero it out.  Not so much for security, though this is also a consideration, since though there is some theoretical possibility of recovering data from such a drive, in practice zeroing will make recovering any data vastly more expensive.  But the main reason for zeroing the drive is to unambiguously mark the drive as not in use, so that neither I nor anyone else hesitates to use the drive for another purpose.  Otherwise, it&#8217;s easy to acquire stacks of &#8220;limbo&#8221; drives which have been replaced, but which you&#8217;re keeping because you can&#8217;t quite remember if there&#8217;s anything on them you might want.  Zeroing the drive out eliminates that concern.</p>

<p>This could have been easier - the LVM stage was as straightforward as I could ask, but the GRUB side of things was harder, at least in part thanks to a lack of documentation.  Still, I&#8217;m now happily using my new disk, and I was very happy not to have to leave the machine out of use while it copied half a gigabyte of data from the old drive to the new.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lshift.net/blog/2010/01/15/upgrading-your-disk-with-lvm/feed</wfw:commentRss>
		</item>
		<item>
		<title>Network server programming with SML/NJ and CML</title>
		<link>http://www.lshift.net/blog/2010/01/01/network-server-programming-with-smlnj-and-cml</link>
		<comments>http://www.lshift.net/blog/2010/01/01/network-server-programming-with-smlnj-and-cml#comments</comments>
		<pubDate>Fri, 01 Jan 2010 15:30:32 +0000</pubDate>
		<dc:creator>tonyg</dc:creator>
		
		<category><![CDATA[Howto]]></category>

		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://www.lshift.net/blog/?p=471</guid>
		<description><![CDATA[My experience with <a href="http://www.smlnj.org/">SML/NJ</a> has been almost uniformly positive, over the years. We used it extensively in a previous project to write a compiler (targeting the .NET CLR) for a pi-calculus-based language, and it was fantastic. One drawback with it, though, is the lack of documentation. Finding out how to (a) compile for and (b) use <a href="http://cml.cs.uchicago.edu/">CML</a> takes real stamina. I've only just now, after several hours poring over webpages, mailing lists, and library source code, gotten to the point where I have a running socket server.

Read on for a full, commented, example.]]></description>
			<content:encoded><![CDATA[<p>My experience with <a href="http://www.smlnj.org/">SML/NJ</a> has been almost uniformly positive, over the years. We used it extensively in a previous project to write a compiler (targeting the .NET CLR) for a pi-calculus-based language, and it was fantastic. One drawback with it, though, is the lack of documentation. Finding out how to (a) compile for and (b) use <a href="http://cml.cs.uchicago.edu/">CML</a> takes real stamina. I&#8217;ve only just now, after several hours poring over webpages, mailing lists, and library source code, gotten to the point where I have a running socket server.</p>

<h2>Download source code, building, and running</h2>

<p>The following example is comprised of a <code>.cm</code> file for building the program, and the <code>.sml</code> file itself. The complete sources:</p>

<ul>
<li><a href="http://dev.lshift.net/tonyg/test.cm"><code>test.cm</code></a></li>
<li><a href="http://dev.lshift.net/tonyg/test.sml"><code>test.sml</code></a></li>
</ul>

<p>Running the following command compiles the project:</p>

<pre><code>ml-build test.cm Testprog.main
</code></pre>

<p>The <code>ml-build</code> output is a heap file, with a file extension dependent on your architecture and operating system. For me, right now, it produces <code>test.x86-darwin</code>. To run the program:</p>

<pre><code>sml @SMLload=test.x86-darwin
</code></pre>

<p>substituting the name of your <code>ml-build</code>-produced heap file as necessary.</p>

<p>On Ubuntu, you will need to have run <code>apt-get install smlnj libcml-smlnj libcmlutil-smlnj</code> to ensure both SML/NJ and CML are present on your system.</p>

<h2>The build control file</h2>

<p>The <a href="http://dev.lshift.net/tonyg/test.cm"><code>test.cm</code></a> file contains</p>

<pre><code>Group is
    $cml/basis.cm
    $cml/cml.cm
    $cml-lib/smlnj-lib.cm
    test.sml
</code></pre>

<p>which instructs the build system to use the CML variants of the basis and the standard SML/NJ library, as well as the core CML library itself and the source code of our program. For more information about the SML CM build control system, see <a href="http://www.smlnj.org/doc/CM/index.html">here</a>.</p>

<h2>The example source code</h2>

<p>Turning to <a href="http://dev.lshift.net/tonyg/test.sml"><code>test.sml</code></a> now, we first declare the ML structure (module) we&#8217;ll be constructing. The structure name is also part of one of the command-line arguments to <code>ml-build</code> above, telling it which function to use as the main function for the program.</p>

<pre><code>structure Testprog = struct
</code></pre>

<p>Next, we bring the contents of the <code>TextIO</code> module into scope. This is necessary in order to use the <code>print</code> function with CML; if we use the standard version of <code>print</code>, the output is unreliable. The special CML variant is needed. We also declare a local alias <code>SU</code> for the global <code>SockUtil</code> structure.</p>

<pre><code>open TextIO
structure SU = SockUtil
</code></pre>

<p>ML programs end up being written upside down, in a sense, because function definitions need to precede their use (unless mutually-recursive definitions are used). For this reason, the next chunk is <code>connMain</code>, the function called in a new lightweight thread when an inbound TCP connection has been accepted. Here, it simply prints out a countdown from 10 over the course of the next five seconds or so, before closing the socket. Multiple connections end up running connMain in independent threads of control, leading automatically to the natural and obvious interleaving of outputs on concurrent connections.</p>

<pre><code>fun connMain s =
    let fun count 0 = SU.sendStr (s, "Bye!\r\n")
          | count n = (SU.sendStr (s, "Hello " ^ (Int.toString n) ^ "\r\n");
                       CML.sync (CML.timeOutEvt (Time.fromReal 0.5));
                       count (n - 1))
    in
        count 10;
        print "Closing the connection.\n";
        Socket.close s
    end
</code></pre>

<p>The function that depends on <code>connMain</code> is the accept loop, which repeatedly accepts a connection and spawns a connection thread for it.</p>

<pre><code>fun acceptLoop server_sock =
    let val (s, _) = Socket.accept server_sock
    in
        print "Accepted a connection.\n";
        CML.spawn (fn () =&gt; connMain(s));
        acceptLoop server_sock
    end
</code></pre>

<p>The next function is the primordial CML thread, responsible for creating the TCP server socket and entering the accept loop. We set <code>SO_REUSEADDR</code> on the socket, listen on port 8989 with a connection backlog of 5, and enter the accept loop.</p>

<pre><code>fun cml_main (program_name, arglist) =
    let val s = INetSock.TCP.socket()
    in
        Socket.Ctl.setREUSEADDR (s, true);
        Socket.bind(s, INetSock.any 8989);
        Socket.listen(s, 5);
        print "Entering accept loop...\n";
        acceptLoop s
    end
</code></pre>

<p>Finally, the function we told <code>ml-build</code> to use as the main entry point of the program. The only thing we do here is disable SIGPIPE (otherwise we get rudely killed if a remote client&#8217;s socket closes!) and start CML&#8217;s scheduler running with a primordial thread function. When the scheduler decides that everything is over and the program is complete, it returns control to us. (The lone <code>end</code> closes the <code>struct</code> definition way back at the top of the file.)</p>

<pre><code>fun main (program_name, arglist) =
    (UnixSignals.setHandler (UnixSignals.sigPIPE, UnixSignals.IGNORE);
     RunCML.doit (fn () =&gt; cml_main(program_name, arglist), NONE);
     OS.Process.success)

end
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.lshift.net/blog/2010/01/01/network-server-programming-with-smlnj-and-cml/feed</wfw:commentRss>
		</item>
	</channel>
</rss>
