<?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 Feb 2010 18:08:26 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<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.</p>

<p>The branch bug22169 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, delete_binding/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).

delete_binding(X, B) -&gt;
    io:format(&#8221;Delete binding ~p from ~p~n&#8221;, [B, X]),
    (backing_module(X)):delete_binding(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, delete_binding/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>This should reach default branch soon after RabbitMQ 1.7.1 is
released.  Until then, if you want to play, you&#8217;ll have to</p>

<pre><code>rabbitmq-server$ hg update -C bug22169
</code></pre>

<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]</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>
		<item>
		<title>Snarl: A Growl-like notification system for Squeak Smalltalk</title>
		<link>http://www.lshift.net/blog/2009/12/24/snarl-a-growl-like-notification-system-for-squeak-smalltalk</link>
		<comments>http://www.lshift.net/blog/2009/12/24/snarl-a-growl-like-notification-system-for-squeak-smalltalk#comments</comments>
		<pubDate>Thu, 24 Dec 2009 10:00:27 +0000</pubDate>
		<dc:creator>tonyg</dc:creator>
		
		<category><![CDATA[Our Software]]></category>

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

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

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

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

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

		<guid isPermaLink="false">http://www.lshift.net/blog/?p=470</guid>
		<description><![CDATA[I&#8217;ve just released Snarl, a Growl-like notification system for Squeak. To use it,

Snarl label: 'Something happened'
      body: 'What could it have been?'


I&#8217;ve recorded a quick demo:



(It&#8217;s pretty blurry, so I&#8217;ve uploaded it to vimeo too, but it&#8217;s still in the queue for conversion; when it&#8217;s converted, it&#8217;ll be here.)

The code [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just released <a href="http://www.squeaksource.com/Snarl.html">Snarl</a>, a Growl-like notification system for <a href="http://www.squeak.org/">Squeak</a>. To use it,</p>

<pre><code>Snarl label: 'Something happened'
      body: 'What could it have been?'
</code></pre>

<p>I&#8217;ve recorded a quick <a href="http://www.youtube.com/watch?v=xg-XJ0zvZAg">demo</a>:</p>

<p><object width="560" height="340"><param name="movie" value="http://www.youtube.com/v/xg-XJ0zvZAg&amp;hl=en_GB&amp;fs=1&amp;rel=0"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/xg-XJ0zvZAg&amp;hl=en_GB&amp;fs=1&amp;rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="560" height="340"></embed></object></p>

<p>(It&#8217;s pretty blurry, so I&#8217;ve uploaded it to vimeo too, but it&#8217;s still in the queue for conversion; when it&#8217;s converted, it&#8217;ll be <a href="http://vimeo.com/8366252">here</a>.)</p>

<p>The code is three classes: one tiny convenience class, Snarl; one TextMorph subclass, which does almost all the work; and one helper TextAttribute subclass, for fading out coloured text along with the rest of each notification. In total, it&#8217;s 205 lines of text, including documentation.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lshift.net/blog/2009/12/24/snarl-a-growl-like-notification-system-for-squeak-smalltalk/feed</wfw:commentRss>
		</item>
		<item>
		<title>Technology that solves the world&#8217;s climate problems?</title>
		<link>http://www.lshift.net/blog/2009/12/22/technology-that-solves-the-worlds-climate-problems</link>
		<comments>http://www.lshift.net/blog/2009/12/22/technology-that-solves-the-worlds-climate-problems#comments</comments>
		<pubDate>Tue, 22 Dec 2009 18:37:25 +0000</pubDate>
		<dc:creator>mike</dc:creator>
		
		<category><![CDATA[Politics]]></category>

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

		<category><![CDATA[Water cooler]]></category>

		<guid isPermaLink="false">http://www.lshift.net/blog/?p=469</guid>
		<description><![CDATA[Those guys at Arup are taking this seriously and unlike many others who postulate in this area they have the clout and the commercial imperative to influence decisions and make changes. Interesting times ahead&#8230;
]]></description>
			<content:encoded><![CDATA[<p>Those guys at Arup are <a href="http://www.arup.com/Blogs.aspx?post=A+new+era+in+information+management&amp;blog=COP15&amp;edit=true">taking this seriously</a> and unlike many others who postulate in this area they have the clout and the commercial imperative to influence decisions and make changes. Interesting times ahead&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lshift.net/blog/2009/12/22/technology-that-solves-the-worlds-climate-problems/feed</wfw:commentRss>
		</item>
		<item>
		<title>Merry Christmas: Toke &#8212; Tokyo Cabinet driver for Erlang</title>
		<link>http://www.lshift.net/blog/2009/12/21/merry-christmas-toke-tokyo-cabinet-driver-for-erlang</link>
		<comments>http://www.lshift.net/blog/2009/12/21/merry-christmas-toke-tokyo-cabinet-driver-for-erlang#comments</comments>
		<pubDate>Mon, 21 Dec 2009 17:01:01 +0000</pubDate>
		<dc:creator>matthew</dc:creator>
		
		<category><![CDATA[Erlang]]></category>

		<category><![CDATA[Our Software]]></category>

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

		<category><![CDATA[open source]]></category>

		<category><![CDATA[tokyo cabinet]]></category>

		<guid isPermaLink="false">http://www.lshift.net/blog/?p=468</guid>
		<description><![CDATA[Tokyo Cabinet is a rather excellent key-value store, with the ability to write to disk in a sane way (i.e. not just repeatedly dumping the same data over and over again), operate in bounded memory, and go really fast. I like it a lot, and there&#8217;s a likelihood that there&#8217;ll be a RabbitMQ plugin fairly [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://1978th.net/tokyocabinet/">Tokyo Cabinet</a> is a rather excellent key-value store, with the ability to write to disk in a sane way (i.e. not just repeatedly dumping the same data over and over again), operate in bounded memory, and go <em>really</em> fast. I like it a lot, and there&#8217;s a likelihood that there&#8217;ll be a RabbitMQ plugin fairly soon that&#8217;ll use Tokyo Cabinet to improve the new persister yet further. <a href="http://hg.opensource.lshift.net/toke/">Toke</a> is an Erlang linked-in driver that allows you to use Tokyo Cabinet from Erlang.<span id="more-468"></span></p>

<p>There is already a Tokyo Cabinet driver for Erlang, <a href="http://code.google.com/p/tcerl/">tcerl</a>, however, I couldn&#8217;t make it work: even after fixing the C so that it compiles (I hit <a href="http://code.google.com/p/tcerl/issues/detail?id=5">this bug</a>), I still couldn&#8217;t make it work. Inspecting the code, I get the feeling it&#8217;s bit-rotted - the Tokyo Cabinet API has moved on, and tcerl hasn&#8217;t kept up.</p>

<p>The other issue with tcerl is that it&#8217;s not a <em>linked-in driver</em>. Erlang allows two different types of drivers: the first are external C programs &#8212; these have a <code>main()</code> and run in their own process. Communication is done by stdin/stdout. These are a bit safer because if they crash they don&#8217;t take out the Erlang VM, but they&#8217;re never going to be blazingly fast. Toke, on the other hand, is a fully linked-in driver. It dynamically links with the Erlang VM, exists in the same address space and goes as fast as it possibly can (using the Erlang driver callbacks which avoid all copying of data passed from the Erlang). My tests show it&#8217;s about three times slower driving Tokyo Cabinet from Erlang via Toke, than driving it natively through C (which is quite good: some googling suggests both the Ruby and Python bindings to Tokyo Cabinet are rather slower). Toke is also about twice as slow as the Erlang <a href="http://erlang.org/doc/man/ets.html">ets</a> module, which is in-memory only.</p>

<p>Toke only implements the Tokyo Cabinet hash table (tchdb*) functions, and doesn&#8217;t even support all of those: I only wrapped exactly what I needed. You&#8217;ll want to read the <a href="http://1978th.net/tokyocabinet/spex-en.html#tchdbapi">documentation</a> for Tokyo Cabinet for these. The functions implemented are as follows (refer to the Tokyo Cabinet documentation to explain these further):</p>

<ul>
<li>toke_drv:new/1 &#8212; Set up the driver with a new TCHDB object.</li>
<li>toke_drv:delete/1 &#8212; Destroy the driver&#8217;s TCHDB object.</li>
<li>toke_drv:tune/5 &#8212; Tune the driver&#8217;s TCHDB Object.</li>
<li>toke_drv:set_cache/2 &#8212; Set the number of records to cache.</li>
<li>toke_drv:set_xm_size/2 &#8212; Set the extra amount of memory mapped in.</li>
<li>toke_drv:set_df_unit/2 &#8212; Set the steps between auto defrag.</li>
<li>toke_drv:open/3 &#8212; Open a db.</li>
<li>toke_drv:close/1 &#8212; Close an open db.</li>
<li>toke_drv:insert/3 &#8212; Insert. If the key already exists, value is updated.</li>
<li>toke_drv:insert_new/3 &#8212; Insert new. If the key already exists, the old value is silently kept.</li>
<li>toke_drv:insert_concat/3 &#8212; Concatenate the supplied value with an existing value for this key.</li>
<li>toke_drv:insert_async/3 &#8212; Asynchronously insert. If the key already exists, value is updated.</li>
<li>toke_drv:delete/2 &#8212; Delete a key from the db.</li>
<li>toke_drv:get/2 &#8212;  Fetch a key from the db. Returns &#8216;not_found&#8217; on occasion.</li>
<li>toke_drv:fold/3 &#8212; Fold over every value in the db. This internally uses the iteration functions. It&#8217;s just wrapped up as a fold to make it appear more functional.</li>
<li>toke_drv:stop/1 &#8212; Stop the driver and close the port.</li>
</ul>

<p>You should be able to use Mercurial to clone it:</p>

<pre># hg clone http://hg.opensource.lshift.net/toke/</pre>
Make sure you have Tokyo Cabinet installed (ideally from source. If you&#8217;re using a package, make sure you have the development headers available. If you do compile from source, make sure you <code>ldconfig</code> to make your system pick up the new library once it&#8217;s installed.). Then it should just be a case of <code>make</code>. There&#8217;s also a <code>make run</code> target that starts up an Erlang shell with the paths set up correctly for testing Toke:

<pre>toke# make run
erl -pa ebin +K true +A30
Erlang R13B03 (erts-5.7.4) [source] [64-bit] [smp:4:4] [rq:4] [async-threads:30] [hipe] [kernel-poll:true]

Eshell V5.7.4  (abort with ^G)
1> toke_test:test().
passed
2>
</pre>

<p>Toke is licensed under the MPL. As ever, feedback is very welcome, as are patches!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lshift.net/blog/2009/12/21/merry-christmas-toke-tokyo-cabinet-driver-for-erlang/feed</wfw:commentRss>
		</item>
		<item>
		<title>RabbitMQ at the Skills Matter Functional Programming Exchange</title>
		<link>http://www.lshift.net/blog/2009/12/07/rabbitmq-at-the-skills-matter-functional-programming-exchange</link>
		<comments>http://www.lshift.net/blog/2009/12/07/rabbitmq-at-the-skills-matter-functional-programming-exchange#comments</comments>
		<pubDate>Mon, 07 Dec 2009 18:37:30 +0000</pubDate>
		<dc:creator>matthew</dc:creator>
		
		<category><![CDATA[Erlang]]></category>

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

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

		<guid isPermaLink="false">http://www.lshift.net/blog/?p=466</guid>
		<description><![CDATA[Today I was lucky enough to give a talk at the Skills Matter Functional Programming Exchange. I talked about resource management in RabbitMQ and how we&#8217;re improving this in upcoming versions of RabbitMQ. All the sessions were videotaped and it would seem that a podcast will be going up shortly. In the mean time you [...]]]></description>
			<content:encoded><![CDATA[<p>Today I was lucky enough to give a talk at the <a href="http://skillsmatter.com/event/cloud-grid/functional-programming-exchange-2009">Skills Matter Functional Programming Exchange</a>. I talked about resource management in RabbitMQ and how we&#8217;re improving this in upcoming versions of RabbitMQ. All the sessions were videotaped and it would seem that a podcast will be <a href="http://skillsmatter.com/podcast/cloud-grid/supercharged-rabbit-resource-management-at-high-speed-in-erlang">going up shortly</a>. In the mean time <a href='http://www.lshift.net/blog/wp-content/uploads/2009/12/slides.pdf'>you can have a look at the slides</a> if you want to.</p>

<p>The attendance was really good and the talks well received. There was a good range of talks, from some very practical and pragmatic such as my own, to slightly more theoretical talks. It was great to see Haskell, Erlang and F# being discussed outside of a purely academic setting and great to see so many companies and organisations getting really interested in functional programming and coming along to see how other people were making the most of it.</p>

<p>The <a href="http://skillsmatter.com/podcast/cloud-grid/parkbench-panel-discussion-1118">Park Bench</a> session was also good fun, with a good range of questions and experience being demonstrated by all. A good, fun atmosphere, and I&#8217;m sure all enjoyed the day.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lshift.net/blog/2009/12/07/rabbitmq-at-the-skills-matter-functional-programming-exchange/feed</wfw:commentRss>
		</item>
		<item>
		<title>Testing Times in Java</title>
		<link>http://www.lshift.net/blog/2009/12/06/testing-times-in-java</link>
		<comments>http://www.lshift.net/blog/2009/12/06/testing-times-in-java#comments</comments>
		<pubDate>Sun, 06 Dec 2009 11:57:44 +0000</pubDate>
		<dc:creator>lee</dc:creator>
		
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://www.lshift.net/blog/?p=464</guid>
		<description><![CDATA[How do you test a Java application that uses the current date or time as the basis for a calculation? I&#8217;ve seen a couple of ways:


    Make sure all date/time operations use a service class to get the current date, which is then mocked
    Adjust the system clock


Option 1) [...]]]></description>
			<content:encoded><![CDATA[<p>How do you test a Java application that uses the current date or time as the basis for a calculation? I&#8217;ve seen a couple of ways:</p>

<ol>
    <li>Make sure all date/time operations use a service class to get the current date, which is then mocked</li>
    <li>Adjust the system clock</li>
</ol>

<p>Option 1) is a PITA for an existing codebase, or if any 3rd party libraries do date processing. Option 2) rules out any sensible automation, especially on a machine used for anything else.</p>

<p>Another option is to mock system date related classes. <a href="https://jmockit.dev.java.net/">JMockit</a> is a mock testing framework that uses Java 5 instrumentation to allow bytecode to be modified at runtime. Using this, known date values can be inserted into tests with no interference with production code or rewriting of legacy code. If Java 6 is available, it is possible to go further and mock the <code>System</code> class itself.</p>

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

<p>We have an example application that performs the onerous task of checking whether a supplied date is the future or not:</p>

<pre>public class App {
    public static boolean isInFuture(Date date) {
        return new Date().after(date);
    }
}</pre>
To test this under Java 5, we need to mock out the <code>java.util.Date</code> class. First of all, we need to configure JMockit. The project (attached at the bottom of this post) uses <a href="http://maven.apache.org/">Maven</a> for building and testing. The POM is pretty much the standard archetype with the following modifications:
<br/>
1. JMockit lives at java.net, so their repo needs to be added:
<pre>  &lt;repositories&gt;
    &lt;repository&gt;
      &lt;id&gt;download.java.net&lt;/id&gt;
      &lt;url&gt;http://download.java.net/maven/2&lt;/url&gt;
    &lt;/repository&gt;
  &lt;/repositories&gt;</pre>
2. The library needs to be added as a dependency for testing:
<pre>    &lt;dependency&gt;
      &lt;groupId&gt;mockit&lt;/groupId&gt;
      &lt;artifactId&gt;jmockit&lt;/artifactId&gt;
      &lt;version&gt;0.993&lt;/version&gt;
      &lt;scope&gt;test&lt;/scope&gt;
    &lt;/dependency&gt;</pre>
3. Finally, the JMockit JAR needs to be set as the Java agent in order to hook into the instrumentation API. This is done in the Surefire plugin configuration by passing the correct argument to the JVM.
<pre>    &lt;plugin&gt;
        &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
        &lt;artifactId&gt;maven-surefire-plugin&lt;/artifactId&gt;
        &lt;configuration&gt;
            &lt;argLine&gt;-javaagent:"${settings.localRepository}/mockit/jmockit/0.993/jmockit-0.993.jar"&lt;/argLine&gt;
        &lt;/configuration&gt;
    &lt;/plugin&gt;</pre>
With JMockit configured, a mock for the <code>java.util.Date</code> class can be created:
<pre>1.   @MockClass(realClass = Date.class)
     public class MockDate {
         private Calendar now = null;
         public Date it;

         public MockDate(Calendar now) {
             this.now = now;
         }

2.       @Mock
3.       public void $init() throws Exception {
4.           Field field = Date.class.getDeclaredField("fastTime");
             field.setAccessible(true);
             field.set(it, now.getTimeInMillis());
         }
     }</pre>
<ol>
    <li>The <code>MockClass</code> annotation declares the class as containing mock methods or constructors</li>
    <li>The <code>Mock</code> annotation declares the following method / constructor as a replacement for that in the real class</li>
    <li>The special <code>$init()</code> method overrides the default constructor in the real class</li>
    <li>The private field <code>fastTime</code> holds the underlying date represented by a <code>Date</code> object, and so this is set to be the date passed to the mock</li>
</ol>
The mock object can now be initialised and used in a JUnit test class:

<pre>   public class AppTest extends TestCase {
        private static Calendar TODAY = new GregorianCalendar(2009, JANUARY, 5);
        private static Calendar YESTERDAY = new GregorianCalendar(2009, JANUARY, 4);
        private static Calendar TOMORROW = new GregorianCalendar(2009, JANUARY, 6);

        ...

        @Override
        protected void setUp() {
1.          mockit.Mockit.setUpMocks(new MockDate(TODAY));
        }

        @Override
        protected void tearDown() {
2.          mockit.Mockit.restoreOriginalDefinition(Date.class);
        }

        public void testDateInFuture() {
            assertTrue(App.isInFuture(TOMORROW.getTime()));
        }

        public void testDateInPast() {
            assertFalse(App.isInFuture(YESTERDAY.getTime()));
        }
   }
</pre>

<ol>
    <li>Tells JMockit which classes are to be mocked</li>
    <li>Restores mocked classes to the original versions. Failure to do this can lead to interesting and often subtle errors in subsequent tests</li>
</ol>

<p>The same approach can be taken for the <code>java.util.Calendar</code> class.</p>

<p>Java 6 allows the instrumentation of native methods which means that the <code>System.currentTimeMillis()</code> method can be mocked. This is used in both the <code>java.util.Date</code> or <code>java.util.Calendar</code> classes and so is the simplest way of covering all bases if using Java 6:</p>

<pre>@MockClass(realClass = System.class)
public class MockSystem {
    private Calendar now = null;

    public MockSystem(Calendar now) {
        this.now = now;
    }

    @Mock
    public long currentTimeMillis() {
        return now.getTimeInMillis();
    }
}
</pre>

<p>An example project containing the code can be found <a href='http://www.lshift.net/blog/wp-content/uploads/2009/12/testing-datetime.zip'>here</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.lshift.net/blog/2009/12/06/testing-times-in-java/feed</wfw:commentRss>
		</item>
	</channel>
</rss>
