<?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"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Labix Blog &#187; Project</title>
	<atom:link href="http://blog.labix.org/tag/project/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.labix.org</link>
	<description>by Gustavo Niemeyer</description>
	<lastBuildDate>Mon, 16 Jan 2012 04:02:51 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Bazaar, the git way</title>
		<link>http://blog.labix.org/2012/01/16/bazaar-the-git-way</link>
		<comments>http://blog.labix.org/2012/01/16/bazaar-the-git-way#comments</comments>
		<pubDate>Mon, 16 Jan 2012 04:02:51 +0000</pubDate>
		<dc:creator>Gustavo Niemeyer</dc:creator>
				<category><![CDATA[Conference]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Project]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[RCS]]></category>

		<guid isPermaLink="false">http://blog.labix.org/?p=935</guid>
		<description><![CDATA[Back at the Ubuntu Platform Rally last week, I&#8217;ve pestered some of the Bazaar team with questions about co-location of branches in the same directory with Bazaar. The great news is that this seems to be really coming for the &#8230; <a href="http://blog.labix.org/2012/01/16/bazaar-the-git-way">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Back at the Ubuntu Platform Rally last week, I&#8217;ve pestered some of the Bazaar team with questions about co-location of branches in the same directory with Bazaar. The great news is that this seems to be really coming for the next release, with first-class integration of the feature in the command set. Unfortunately, though, it&#8217;s not quite yet ready for prime time, or even for <i>I&#8217;m-crazy-and-want-this-feature</i> time.</p>
<p>Some background on why this feature turns out to be quite important right now may be interesting, since life with Bazaar in the past years hasn&#8217;t really brought that up as a blocker. <span id="more-935"></span>The cause for the new interest lies in some recent changes in the toolset of the Go language. The new <i>go</i> tool not only makes building and interacting with Go packages a breeze, but it also solves a class of problems previously existent. For the <i>go</i> tool to work, though, it requires the use of $GOPATH consistently, and this means that the package has to live in a <i>well defined directory</i>. The traditional way that Bazaar manages branches into their own directories becomes a deal breaker then.</p>
<p>So, last week I had the chance to exchange some ideas with Jelmer Vernooij and Vincent Ladeuil (both Bazaar hackers) on these problems, and they introduced me to the approach of using lightweight checkouts to workaround some of the limitations. Lightweight checkouts in Bazaar makes the working tree resemble a little bit the old-style VCS tools, with the working tree being bound to another location that actually has the core content. The idea is great, and given how well lightweight checkouts work with Bazaar, building a full fledged solution shouldn&#8217;t be a lot of work really.</p>
<p>After that conversation, I&#8217;ve put a trivial hack together that would make bzr look like git from the outside, by wrapping the command line, and did a lightning talk demo. This got a few more people interested on the concept, which was enough motivation for me to move the idea forward onto a working implementation. Now I just needed the time to do it, but it wasn&#8217;t too hard to find it either.</p>
<p>I happen to be part of the unlucky group that too often takes more than 24 hours to get back home from these events. This is not entirely bad, though.. I also happen to be part of the lucky group that can code while flying and riding buses as means to relieve the boredom (reading helps too). This time around, <a href="http://labix.org/cobzr">cobzr</a> became the implementation of choice, and given ~10 hours of coding, we have a very neat and over-engineered wrapper for the bzr command.</p>
<p>The core of the implementation is the same as the original hack: wrap bzr and call it from outside to restructure the tree. That said, rather than being entirely lazy and hackish line parsing, it actually parses bzr&#8217;s &#8211;help output for commands to build a base of supported options, and parses the command line exactly like Bazaar itself would, validating options as it goes and distinguishing between flags with arguments from positional parameters. That enables the proxying to do much more interesting work on the intercepted arguments.</p>
<p>Here is a quick session that shows a branch being created with the tool. It should look fairly familiar for someone used to git:</p>
<p><code><br />
[~]% bzr branch lp:juju<br />
Branched 443 revisions.                                                                                                                       </p>
<p>[~]% cd juju<br />
[~/juju]% bzr branch<br />
* master</p>
<p>[~/juju]% bzr checkout -b new-feature<br />
Shared repository with trees (format: 2a)<br />
Location:<br />
  shared repository: .bzr/cobzr<br />
Branched 443 revisions.<br />
Branched 443 revisions.<br />
Tree is up to date at revision 443.<br />
Switched to branch: /home/niemeyer/juju/.bzr/cobzr/new-feature/</p>
<p>[~/juju]% bzr branch other-feature<br />
Branched 443 revisions.                                                                                                                       </p>
<p>[~/juju]% bzr branch<br />
&nbsp;&nbsp;master<br />
* new-feature<br />
&nbsp;&nbsp;other-feature<br />
</code></p>
<p>Note that cobzr will not reorganize the tree layout before the multiple branch support is required.</p>
<p>Even though the wrapping is taking place and bzr&#8217;s &#8211;help output is parsed, there&#8217;s pretty much no noticeable overhead given the use of Go for the implementation and also that the processed output of &#8211;help is cached (I <i>said</i> it was overengineered).</p>
<p>As an example, the first is the real bzr, while the second is a link to cobzr:</p>
<p><code><br />
[~/juju]% time /usr/bin/bzr status<br />
/usr/bin/bzr status  0.24s user 0.03s system 88% cpu 0.304 total</p>
<p>[~/juju]% time bzr status<br />
bzr status  0.19s user 0.08s system 88% cpu 0.307 total<br />
</code></p>
<p>This should be more than enough for surviving comfortably until bzr itself comes along with first class support for co-located branches in the next release.</p>
<p>In case you&#8217;re interested in using it or are just curious about the command set or other details, please check out the web page for the project:</p>
<ul>
<li><a href="http://labix.org/cobzr">http://labix.org/cobzr</a>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.labix.org/2012/01/16/bazaar-the-git-way/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Good concurrency changes the game</title>
		<link>http://blog.labix.org/2011/12/12/good-concurrency-changes-the-game</link>
		<comments>http://blog.labix.org/2011/12/12/good-concurrency-changes-the-game#comments</comments>
		<pubDate>Mon, 12 Dec 2011 17:52:47 +0000</pubDate>
		<dc:creator>Gustavo Niemeyer</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Project]]></category>
		<category><![CDATA[Snippet]]></category>

		<guid isPermaLink="false">http://blog.labix.org/?p=886</guid>
		<description><![CDATA[A long time before I seriously got into using distributed version control systems (DVCS) such as Bazaar and Git for developing software, it was already well known to me how the mechanics of these systems worked, and why people benefited &#8230; <a href="http://blog.labix.org/2011/12/12/good-concurrency-changes-the-game">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>A long time before I seriously got into using distributed version control systems (DVCS) such as Bazaar and Git for developing software, it was already well known to me how the mechanics of these systems worked, and why people benefited from them. That said, it wasn&#8217;t until I indeed started to use DVCS tools that I understood how much my daily workflow around code bases would be changed and improved.</p>
<p><span id="more-886"></span>This weekend, while flying home from <a href="http://www.10gen.com/events/mongosv-2011">MongoSV</a>, I could experience that same feeling in relation to first class concurrency support in programming languages. Everybody knows how the feature may be used, but I have the feeling that until one actually experiences it in practice, it&#8217;s very hard to really understand how much the relationship with ordering while developing software may be improved.</p>
<p>I was having some fun working on improvements to <a href="https://wiki.ubuntu.com/goetveld">Goetveld</a>. This package allows <a href="http://golang.org">Go</a> programs to communicate with <a href="https://codereview.appspot.com">Rietveld</a> servers to manipulate code review entries. The Rietveld API is a bit rough in a few places, and as a result some features of the package actually parse an HTML form to extract some data, before sending it back. You may have done something similar before while attempting to script a web site that wasn&#8217;t originally intended to be.</p>
<p>The interesting fact here is that this is an intrinsically serial procedure: load a form, change it, and send it back, right? Well, not really. As one might intuitively expect, establishing an SSL session and its underlying TCP connection are not instantaneous operations.</p>
<p>To give an idea, here is part of a dump of an SSL connection being <i>initiated</i> (that is, no HTTP data was sent yet) to codereview.appspot.com, originated from my home location:</p>
<pre>
# tcpdump -ttttt -i wlan0 'host codereview.appspot.com and port 443'
(...)
00:00:00.000000 IP (...)
00:00:00.000063 IP (...)
00:00:00.000562 IP (...)
00:00:00.341627 IP (...)
00:00:00.357009 IP (...)
00:00:00.357118 IP (...)
00:00:00.360362 IP (...)
00:00:00.360550 IP (...)
00:00:00.366011 IP (...)
00:00:00.689446 IP (...)
00:00:00.727693 IP (...)
</pre>
<p>That&#8217;s more than half a second before the application layer was even touched. So, turns out that to save that roundtrip time, we can start <i>both</i> the form loading and the form sending requests <i>at the same time</i>. By the time the form loading ends, processing the data locally is extremely fast, and we can complete the sending side by just providing the request body.</p>
<p>At this time you may be thinking something like <i>&#8220;Ugh, that&#8217;s too much trouble.. why bother?&#8221;</i>, and that highlights precisely the point I&#8217;d like to make: it is too much trouble because most people are used to languages that <i>turn</i> it into too much trouble, but the issue is not inherently complex. In fact, this is the entire implementation of this logic in Go:</p>
<pre>
func (r *Rietveld) UpdateIssue(issue *Issue) error {
        op := &#038;opInfo{r: r, issue: issue}
        errs := make(chan error)
        ch := make(chan map[string]string, 1)
        go func() {
                errs <- r.do(&#038;editLoadHandler{op: op, form: ch})
                close(ch)
        }()
        go func() {
                errs <- r.do(&#038;editHandler{op: op, form: ch})
        }()
        return firstError(2, errs)
}
</pre>
<p>I'm not cheating. The procedure was being done serially before, with very similar logic. Previously it had to take the form variable itself from the first request and manually provide it to the next one. Now, instead of providing the form, it's providing a channel that will be used to send the form across.  One might even argue that the channel makes the algorithm <i>more natural</i>, curiously.</p>
<p>This is the kind of procedure that becomes fun and natural to write, after having first class concurrency at hand for some time. But, as in the case of DVCS, it takes a while to get used to the idea that concurrency and simplicity are not necessarily at opposing ends.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.labix.org/2011/12/12/good-concurrency-changes-the-game/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Launchpad + Rietveld == HappyCodeReviews</title>
		<link>http://blog.labix.org/2011/11/17/launchpad-rietveld-happycodereviews</link>
		<comments>http://blog.labix.org/2011/11/17/launchpad-rietveld-happycodereviews#comments</comments>
		<pubDate>Fri, 18 Nov 2011 02:28:42 +0000</pubDate>
		<dc:creator>Gustavo Niemeyer</dc:creator>
				<category><![CDATA[Go]]></category>
		<category><![CDATA[Patch]]></category>
		<category><![CDATA[Project]]></category>
		<category><![CDATA[RCS]]></category>

		<guid isPermaLink="false">http://blog.labix.org/?p=849</guid>
		<description><![CDATA[In the past week, I&#8217;ve finally stopped to fix something that I&#8217;ve been wishing for years: inline code reviews in Launchpad. Well, I haven&#8217;t exactly managed fix it in Launchpad, but the integration with Rietveld feels nice enough to be &#8230; <a href="http://blog.labix.org/2011/11/17/launchpad-rietveld-happycodereviews">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In the past week, I&#8217;ve finally stopped to fix something that I&#8217;ve been wishing for years: inline code reviews in Launchpad. Well, I haven&#8217;t exactly managed fix it <i>in</i> Launchpad, but the integration with Rietveld feels nice enough to be relatively painless.</p>
<p>The integration is done using the <a href="https://launchpad.net/lbox">lbox</a> tool, that was developed in <a href="http://golang.org">Go</a> using the <a href="http://goneat.org/lp/lpad">lpad package</a> for the communication with Launchpad, and a newly written <a href="http://goneat.org/lp/goetveld/rietveld">rietveld package</a> for communication with Rietveld.</p>
<p>If you want to join me in my happines, here are the few steps to get that working for you as well.</p>
<p><span id="more-849"></span>First, install lbox from the Launchpad PPA. Since it&#8217;s written in Go, it has no dependencies.</p>
<pre>
$ sudo add-apt-repository ppa:gophers/go
$ sudo apt-get update
$ sudo apt-get install lbox
</pre>
<p>Now, as an example of using it, let&#8217;s suppose we want to perform a change in the lbox code itself. First, we take the branch out of Launchpad.</p>
<pre>
$ mkdir hacking
$ cd hacking
$ bzr branch lp:lbox
Branched 9 revision(s).
</pre>
<p>Then, let&#8217;s create a feature branch based on the original trunk, and perform a change.</p>
<pre>
$ bzr branch lbox my-nice-feature
Branched 9 revision(s).

$ cd my-nice-feature
$ echo # Yo >> Makefile
$ bzr commit -m "Yo-ified makefile"
Committing to: /home/user/hacking/my-nice-feature/
modified Makefile
Committed revision 10.
</pre>
<p>Ok, we&#8217;re ready for the magic step, which is actually pushing that branch and proposing the merge on the original branch on both Launchpad and Rietveld. It&#8217;s harder to explain than to do it:</p>
<pre>
$ lbox propose -cr
2011/11/17 23:29:49 Looking up branch information for "."...
2011/11/17 23:29:49 Looking up branch information for "hacking/lbox"...
2011/11/17 23:29:49 Found landing target: bzr+ssh://bazaar.../lbox/
(...)
</pre>
<p>This command will ask you for a few details interactively, like your authentication details in Launchpad and in Rietveld (your Google Account, details sent over SSL to Google itself; you may have to visit Rietveld first for that to work), and also the change description.</p>
<p>In case something fails, feel free to simply execute the command again, as many times as you want. The command is smart enough to figure that an existing merge proposal and change in Rietveld exist and will update the existing ones with the new details you provide, rather than duplicating work.</p>
<p>Once the command finishes, you can visit the URL for the merge proposal in Launchpad that was printed, and you should see something like this:</p>
<p><a href="http://blog.labix.org/wp-content/uploads/2011/11/lbox-lp-mp.jpg"><img src="http://blog.labix.org/wp-content/uploads/2011/11/lbox-lp-mp-1024x580.jpg" alt="" title="lbox-lp-mp" width="640" height="362" class="alignnone size-large wp-image-861"/></a></p>
<p>Note that the change description already includes a link onto the Rietveld issue at codereview.appspot.com. The issue on Rietveld will look something like this:</p>
<p><a href="http://blog.labix.org/wp-content/uploads/2011/11/lbox-rietveld.jpg"><img src="http://blog.labix.org/wp-content/uploads/2011/11/lbox-rietveld.jpg" alt="" title="lbox-rietveld" width="979" height="333" class="alignnone size-full wp-image-865" /></a></p>
<p>Observe how the issue has the same description as the merge proposal, but it links back onto the merge proposal. At the left-hand side, there&#8217;s also an interesting detail: the original merge proposal email has been added as the reviewer of this change. This means that any changes performed in Rietveld will be mailed back onto the merge proposal for its record.</p>
<p>In the center you can find the meat of the whole work: the actual change set that is being reviewed. Rietveld works with patch sets, so that you can not only see a given change, but you can also review the history of proposals that the proponent has made, and any inline comments performed in them.</p>
<p>Click on the side-by-side link next to Makefile to get an overview of the actual change, and to make comments on it just click on the desired line:</p>
<p><a href="http://blog.labix.org/wp-content/uploads/2011/11/lbox-rietveld-diff.jpg"><img src="http://blog.labix.org/wp-content/uploads/2011/11/lbox-rietveld-diff.jpg" alt="" title="lbox-rietveld-diff" width="986" height="628" class="alignnone size-full wp-image-867" /></a></p>
<p>Your comments won&#8217;t be sent immediately. Once you&#8217;re done making comments and want to deliver the review, click on the &#8220;Publish+Mail Comments&#8221; link at the top-right, which will take you onto a page that enables complementing with any heading details if desired.</p>
<p>Since the merge proposal is registered as the reviewer of the issue in Rietveld, publishing the review will deliver a message back onto the merge proposal itself, including context links that enable anyone to be taken to the precise review point back in Rietveld:</p>
<p><a href="http://blog.labix.org/wp-content/uploads/2011/11/lbox-lp-comment.jpg"><img src="http://blog.labix.org/wp-content/uploads/2011/11/lbox-lp-comment.jpg" alt="" title="lbox-lp-comment" width="776" height="275" class="alignnone size-full wp-image-870" /></a></p>
<p>Then, once you do make the suggested changes and want to publish a new version of the branch, simply repeat the original command: &#8220;lbox propose -cr&#8221;. This will push the new diff onto Rietveld and create a new patch set. You&#8217;ll also be given the chance to edit the previous description, and any changes there will take place both in the merge proposal and in the Rietveld issue.</p>
<p>lbox also has other useful command line options, such as -bug, -new-bug, to associate Launchpad bugs with the merge proposal and put them in progress, or -bp to associate a blueprint with the branch and bug (if provided) being handled.</p>
<p>This should turn your code reviews in Launchpad into significantly more pleasant tasks, and maybe even save some of your precious life time for more interesting activities.</p>
<p>Happy reviewing!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.labix.org/2011/11/17/launchpad-rietveld-happycodereviews/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Death of goroutines under control</title>
		<link>http://blog.labix.org/2011/10/09/death-of-goroutines-under-control</link>
		<comments>http://blog.labix.org/2011/10/09/death-of-goroutines-under-control#comments</comments>
		<pubDate>Sun, 09 Oct 2011 19:53:47 +0000</pubDate>
		<dc:creator>Gustavo Niemeyer</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Erlang]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Project]]></category>
		<category><![CDATA[Snippet]]></category>
		<category><![CDATA[Test]]></category>

		<guid isPermaLink="false">http://blog.labix.org/?p=717</guid>
		<description><![CDATA[Certainly one of the reasons why many people are attracted to the Go language is its first-class concurrency aspects. Features like communication channels, lightweight processes (goroutines), and proper scheduling of these are not only native to the language but are &#8230; <a href="http://blog.labix.org/2011/10/09/death-of-goroutines-under-control">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Certainly one of the reasons why many people are attracted to the <a href="http://golang.org">Go</a> language is its first-class concurrency aspects. Features like communication channels, lightweight processes (<i>goroutines</i>), and proper scheduling of these are not only native to the language but are integrated in a tasteful manner.</p>
<p><span id="more-717"></span>If you stay around listening to community conversations for a few days there&#8217;s a good chance you&#8217;ll hear someone proudly mentioning the tenet:</p>
<blockquote><p>Do not communicate by sharing memory; instead, share memory by communicating.</p></blockquote>
<p>There is a <a href="http://blog.golang.org/2010/07/share-memory-by-communicating.html">blog post</a> on the topic, and also a <a href="http://golang.org/doc/codewalk/sharemem/">code walk</a> covering it.</p>
<p>That model is very sensible, and being able to approach problems this way makes a significant difference when designing algorithms, but that&#8217;s not exactly news. What I address in this post is an open aspect we have today in Go related to this design: the <i>termination</i> of background activity.</p>
<p>As an example, let&#8217;s build a purposefully simplistic goroutine that sends lines across a channel:</p>
<pre>
type LineReader struct {
        Ch chan string
        r *bufio.Reader
}

func NewLineReader(r io.Reader) *LineReader {
        lr := &#038;LineReader{make(chan string), bufio.NewReader(r)}
        go lr.loop()
        return lr
}
</pre>
<p>The type has a channel where the client can consume lines from, and an internal buffer<br />
used to produce the lines efficiently. Then, we have a function that creates an initialized<br />
reader, fires the reading loop, and returns. Nothing surprising there.</p>
<p>Now, let&#8217;s look at the loop itself:</p>
<pre>
func (lr *LineReader) loop() {
        for {
                line, err := lr.r.ReadSlice('\n')
                if err != nil {
                        close(lr.Ch)
                        return
                }
                lr.Ch <- string(line)
        }
}
</pre>
<p>In the loop we'll grab a line from the buffer, close the channel in case of errors and stop, or otherwise send the line to the other side, perhaps blocking while the other side is busy with other activities. Should sound sane and familiar to Go developers.</p>
<p>There are two details related to the termination of this logic, though: first, the error information is being dropped, and then there's no way to interrupt the procedure from outside in a clean way. The error might be easily logged, of course, but what if we wanted to store it in a database, or send it over the wire, or even handle it taking in account its nature? Stopping cleanly is also a valuable feature in many circumstances, like when one is driving the logic from a test runner.</p>
<p>I'm not claiming this is something <i>difficult</i> to do, by any means.  What I'm saying is that there isn't today an <i>idiom</i> for handling these aspects in a simple and consistent way. Or maybe there wasn't. The <i>tomb</i> package for Go is an experiment I'm releasing today in an attempt to address this problem.</p>
<p>The model is simple: a <i>Tomb</i> tracks whether the goroutine is alive, dying, or dead, and the death reason.</p>
<p>To understand that model, let's see the concept being applied to the LineReader example. As a first step, creation is tweaked to introduce Tomb support:</p>
<pre>
type LineReader struct {
        Ch chan string
        r *bufio.Reader
        <span style="color: blue">*tomb.Tomb</span>
}

func NewLineReader(r io.Reader) *LineReader {
        lr := &#038;LineReader{
                make(chan string),
                bufio.NewReader(r),
                <span style="color: blue">tomb.New(),</span>
        }
        go lr.loop()
        return lr
}
</pre>
<p>Looks very similar. Just a new field in the struct and its respective initialization. We've used it as an embedded field just so we can use the Tomb methods directly in the <i>lr</i> variable.</p>
<p>Next, the loop function is modified to support tracking of errors and interruptions:</p>
<pre>
func (lr *LineReader) loop() {
        <span style="color: blue">defer lr.Done()</span>
        for {
                line, err := lr.r.ReadSlice('\n')
                if err != nil {
                        close(lr.Ch)
                        <span style="color: blue">lr.Fatal(err)</span>
                        return
                }
                select {
                case lr.Ch <- string(line):
                <span style="color: blue">case <-lr.Dying:</span>
                        close(lr.Ch)
                        return
                }
        }
}
</pre>
<p>Note a few interesting points here: first, <i>Done</i> is called to track the goroutine termination right before the loop function returns. Then, the previously loose error now goes into the <i>Fatal</i> Tomb method, flagging the goroutine as dying. Finally, the channel send was tweaked so that it doesn't block in case the goroutine is dying for whatever reason.</p>
<p>A Tomb has both <i>Dying</i> and <i>Dead</i> channels, which are closed when the Tomb state changes accordingly. These channels enable explicit blocking until the state changes, and also to selectively unblock select statements in those cases, as done above.</p>
<p>With the loop modified as above, a Stop method can trivially be introduced to request the clean termination of the goroutine synchronously from outside:</p>
<pre>
func (lr *LineReader) Stop() os.Error {
        <span style="color: blue">lr.Fatal(tomb.Stop)</span>
        return <span style="color: blue">lr.Wait()</span>
}
</pre>
<p>In this case the <i>Fatal</i> method will put the goroutine in a dying state from outside, and <i>Wait</i> will block until the goroutine terminates itself and notifies via the <i>Done</i> method as seen before. This procedure behaves correctly even if the goroutine was already dead or in a dying state due to internal errors, because only the first call to Fatal with an actual error is recorded as the cause for the goroutine death. The <i>tomb.Stop</i> value is used as a reason when terminating cleanly without an actual error, and it causes Wait to return nil once the goroutine terminates, flagging a clean stop per common Go idioms.</p>
<p>(<b>UPDATE:</b> there was <a href="http://groups.google.com/group/golang-nuts/browse_thread/thread/383f7cabbb174460">a minor simplification</a> in the API since this post was originally written, and the paragraph above was adapted to cover the new API)</p>
<p>This is pretty much all that there is to it. When I started developing in Go I wondered if coming up with a good convention for this sort of problem would require more support from the language, such as some kind of goroutine state tracking in a similar way to what <a href="http://www.erlang.org/doc/reference_manual/processes.html">Erlang does</a> with its lightweight processes, but it turns out this is mostly a matter of organizing the workflow with existing building blocks.</p>
<p>The tomb package and its Tomb type are a tangible representation of a good convention for goroutine termination, with familiar method names inspired in existing idioms. If you want to make use of it, goinstall the package with:</p>
<pre>
$ goinstall launchpad.net/tomb
</pre>
<p>The API documentation with details is available at:</p>
<p><span style="padding-left: 2em;"><a href="http://goneat.org/lp/tomb">http://goneat.org/lp/tomb</a></span></p>
<p>Have fun!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.labix.org/2011/10/09/death-of-goroutines-under-control/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Ensemble, Go, and MongoDB at Canonical</title>
		<link>http://blog.labix.org/2011/08/05/ensemble-go-and-mongodb-at-canonical</link>
		<comments>http://blog.labix.org/2011/08/05/ensemble-go-and-mongodb-at-canonical#comments</comments>
		<pubDate>Fri, 05 Aug 2011 03:49:14 +0000</pubDate>
		<dc:creator>Gustavo Niemeyer</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Project]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.labix.org/?p=706</guid>
		<description><![CDATA[About 1 year after development started in Ensemble, today the stars finally aligned just the right way (review queue mostly empty, no other pressing needs, etc) for me to start writing the specification about the repository system we&#8217;ve been jointly &#8230; <a href="http://blog.labix.org/2011/08/05/ensemble-go-and-mongodb-at-canonical">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>About 1 year after development started in <a href="https://ensemble.ubuntu.com">Ensemble</a>, today the stars finally aligned just the right way (review queue mostly empty, no other pressing needs, etc) for me to start writing the specification about the repository system we&#8217;ve been jointly planning for a long time. This is the system that the Ensemble client will communicate with for discovering which <a href="https://ensemble.ubuntu.com/docs/formula.html">formulas</a> are available, for publishing new formulas, for obtaining formula files for deployment, and so on.</p>
<p><span id="more-706"></span>We of course would have liked for this part of the project to have been specified and written a while ago, but unfortunately that wasn&#8217;t possible for several reasons. That said, there are also good sides of having an important piece flying around in minds and conversations for such a long time: sitting down to specify the system and describe the inner-working details has been a breeze. Even details such as the namespacing of formulas, which hasn&#8217;t been entirely clear in my mind, was just streamed into the document as the ideas we&#8217;ve been evolving finally got together in a written form. </p>
<p>One curious detail: this is the first long term project at <a href="https://www.canonical.com">Canonical</a> that will be developed in <a href="http://golang.org">Go</a>, rather than Python or C/C++, which are the most used languages for projects within Canonical. Not only that, but we&#8217;ll also be using <a href="http://www.mongodb.org">MongoDB</a> for a change, rather than the traditional <a href="http://www.postgresql.com">PostgreSQL</a>, and will also use (you guessed) the <a href="http://labix.org/mgo">mgo driver</a> which I&#8217;ve been pushing entirely as a personal project for about 8 months now.</p>
<p>Naturally, with so many moving parts that are new to the company culture, this is still being seen as a closely watched experiment. Still, this makes me highly excited, because when I started developing mgo, the MongoDB driver for Go, my hopes that the Go, MongoDB, and mgo trio would eventually be used at Canonical were very low, precisely because they were all alien to the culture. We only got here after quite a lot of internal debate, experiments, and trust too.</p>
<p>All of that means these are happy times. Important feature in Ensemble being specified and written, very exciting tools, home grown software being useful..</p>
<p>Awesomeness.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.labix.org/2011/08/05/ensemble-go-and-mongodb-at-canonical/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Vector clock support for Go</title>
		<link>http://blog.labix.org/2010/12/21/vector-clock-support-for-go</link>
		<comments>http://blog.labix.org/2010/12/21/vector-clock-support-for-go#comments</comments>
		<pubDate>Tue, 21 Dec 2010 18:03:47 +0000</pubDate>
		<dc:creator>Gustavo Niemeyer</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Project]]></category>
		<category><![CDATA[Snippet]]></category>

		<guid isPermaLink="false">http://blog.labix.org/?p=564</guid>
		<description><![CDATA[One more Go library oriented towards building distributed systems hot off the presses: govclock. This one offers full vector clock support for the Go language. Vector clocks allow recording and analyzing the inherent partial ordering of events in a distributed &#8230; <a href="http://blog.labix.org/2010/12/21/vector-clock-support-for-go">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>One more Go library oriented towards building distributed systems hot off the presses: <a href="http://labix.org/govclock">govclock</a>. This one offers full <a href="http://en.wikipedia.org/wiki/Vector_clock">vector clock</a> support for the <a href="http://golang.org">Go language</a>.  Vector clocks allow recording and analyzing the inherent partial ordering of events in a distributed system in a comfortable way.</p>
<p>The following features are offered by govclock, in addition to basic event tracking:</p>
<p><span id="more-564"></span>
<ul>
<li>Compact serialization and deserialization
<li>Flexible truncation (min/max entries, min/max update time)
<li>Unit-independent update times
<li>Traditional merging
<li>Fast and memory efficient
</ul>
<p>If you&#8217;d like to know more about vector clocks, the Basho guys did a great job in the following pair of blog posts:</p>
<ul>
<li><a href="http://blog.basho.com/2010/01/29/why-vector-clocks-are-easy/">Why vector clocks are easy</a>
<li><a href="http://blog.basho.com/2010/04/05/why-vector-clocks-are-hard/">Why vector clocks are hard</a>
</ul>
<p>The following sample program demonstrates some sequential and concurrent events, dumping and loading, as well as merging of clocks.  For more details, please look at the <a href="http://labix.org/govclock">web page</a>.  The project is available under a BSD license.</p>
<pre>

package main

import (
    "launchpad.net/govclock"
    "fmt"
)

func main() {
    vc1 := govclock.New()
    vc1.Update([]byte("A"), 1)

    vc2 := vc1.Copy()
    vc2.Update([]byte("B"), 0)

    fmt.Println(vc2.Compare(vc1, govclock.Ancestor))   // => true
    fmt.Println(vc1.Compare(vc2, govclock.Descendant)) // => true

    vc1.Update([]byte("C"), 5)

    fmt.Println(vc1.Compare(vc2, govclock.Descendant)) // => false
    fmt.Println(vc1.Compare(vc2, govclock.Concurrent)) // => true

    vc2.Merge(vc1)

    fmt.Println(vc1.Compare(vc2, govclock.Descendant)) // => true

    data := vc2.Bytes()
    fmt.Printf("%#v\n", string(data))
    // => "\x01\x01\x01\x01A\x01\x01\x01B\x01\x00\x01C"

    vc3, err := govclock.FromBytes(data)
    if err != nil { panic(err.String()) }

    fmt.Println(vc3.Compare(vc2, govclock.Equal))      // => true
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.labix.org/2010/12/21/vector-clock-support-for-go/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Integrating Go with C: the ZooKeeper binding experience</title>
		<link>http://blog.labix.org/2010/12/10/integrating-go-with-c-the-zookeeper-binding-experience</link>
		<comments>http://blog.labix.org/2010/12/10/integrating-go-with-c-the-zookeeper-binding-experience#comments</comments>
		<pubDate>Fri, 10 Dec 2010 16:17:16 +0000</pubDate>
		<dc:creator>Gustavo Niemeyer</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Article]]></category>
		<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Project]]></category>
		<category><![CDATA[Snippet]]></category>

		<guid isPermaLink="false">http://blog.labix.org/?p=534</guid>
		<description><![CDATA[ZooKeeper is a clever generic coordination server for distributed systems, and is one of the core softwares which facilitate the development of Ensemble (project for automagic IaaS deployments which we push at Canonical), so it was a natural choice to &#8230; <a href="http://blog.labix.org/2010/12/10/integrating-go-with-c-the-zookeeper-binding-experience">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://zookeeper.apache.org">ZooKeeper</a> is a clever generic coordination server for distributed systems, and is one of the core softwares which facilitate the development of Ensemble (project for automagic <a href="http://en.wikipedia.org/wiki/Cloud_computing">IaaS</a> deployments which we push at <a href="http://www.canonical.com">Canonical</a>), so it was a natural choice to experiment with.</p>
<p><a href="https://wiki.ubuntu.com/gozk">Gozk</a> is a complete binding for ZooKeeper which explores the native features of Go to facilitate the interaction with a ZooKeeper server.  To avoid reimplementing the well tested bits of the protocol in an unstable way, Gozk is built on top of the standard C ZooKeeper library.</p>
<p>The experience of integrating ZooKeeper with Go was certainly valuable on itself, and worked as a nice way to learn the details of integrating the Go language with a C library. If you&#8217;re interested in learning a bit about Go, ZooKeeper, or other details related to the creation of bindings and asynchronous programming, please fasten the seatbelt now.</p>
<p><span id="more-534"></span><b>Basics of C wrapping in Go</b></p>
<p>Creating the binding on itself was a pretty interesting experiment already.  I have worked on the creation of quite a few bindings and language bridges before, and must say I was pleasantly surprised with the experience of creating the Go binding.  With <i>Cgo</i>, the name given to the &#8220;<i>foreign function interface</i>&#8221; mechanism for C integration, one basically declares a special import statement which causes a pre-processor to look at the comment preceding it.  Something similar to this:</p>
<pre>
// #include &lt;zookeeper.h&gt;
import "C"
</pre>
<p>The comment doesn&#8217;t have to be restricted to a single line, or to <i>#include</i> statements even.  The C code contained in the comment will be transparently inserted into a helper C file which is compiled and linked with the final object file, and the given snippet will also be parsed and inclusions processed.  In the Go side, that &#8220;C&#8221; import is simulated as if it were a normal Go package so that the C functions, types, and values are all directly accessible.</p>
<p>As an example, a C function with this prototype:</p>
<pre>
int zoo_wexists(zhandle_t *zh, const char *path, watcher_fn watcher,
                void *context, struct Stat *stat);
</pre>
<p>In Go may be used as:</p>
<pre>
cstat := C.struct_Stat{}
rc, cerr := C.zoo_wexists(zk.handle, cpath, nil, nil, &#038;cstat)
</pre>
<p>When the C function is used in a context where two result values are requested, as done above, Cgo will save the well known <i>errno</i> variable after the function has finished executing and will return it wrapped into an <i>os.Errno</i> value.</p>
<p>Also, note how the C struct is defined in a way that can be passed straight to the C function.  Interestingly, the allocation of the memory backing the structure is going to be performed and tracked by the Go runtime, and will be garbage collected appropriately once no more references exist <i>within the Go runtime</i>. This fact has to be kept in mind since the application will crash if a value allocated normally within Go is saved with a foreign C function and maintained after all the Go references are gone.  The alternative in these cases is to call the usual C functions to get hold of memory for the involved values.  That memory won&#8217;t be touched by the garbage collector, and, of course, must be explicitly freed when no longer necessary.  Here is a simple example showing explicit allocation:</p>
<pre>
cbuffer := (*C.char)(C.malloc(bufferSize))
defer C.free(unsafe.Pointer(cbuffer))
</pre>
<p>Note the use of the <i>defer</i> statement above. Even when dealing with foreign functionality, it comes in handy. The above call will ensure that the buffer is deallocated right before the current function returns, for instance, so it&#8217;s a nice way to ensure no leaks happen, even if in the future the function suddenly gets a new exit point which didn&#8217;t consider the allocation of resources.</p>
<p>In terms of typing, Go is more strict than C, and Cgo-based logic will also ensure that the types returned and passed into the foreign C functions are correctly typed, in the same way done for the native types.  Note above, for instance, how the call to the <i>free()</i> function has to explicitly convert the value into an <i>unsafe.Pointer</i>, even though in C no casting would be necessary to pass a pointer into a <i>void *</i> parameter.</p>
<p>The <i>unsafe.Pointer</i> is in fact a very special type within Go. Using it, one can convert any pointer type into any other pointer type in an unsafe way (thus the package name), and also back and forth into a <i>uintptr</i> value with the address of the memory referenced by the pointer.  For every other type conversion, Go will ensure at compilation time that doing the conversion at runtime is a safe operation.</p>
<p>With all of these resources, including the ability to use common Go syntax and functionality even when dealing with foreign types, values, and function calls, the integration task turns out to be quite a pleasant experience.  That said, some of the things may still require some good thinking to get right, as we&#8217;ll see shortly.</p>
<p><b>Watch callbacks and channels</b></p>
<p>One of the most interesting (and slightly tricky) aspects of mapping the ZooKeeper concepts into Go was the &#8220;watch&#8221; functionality.  ZooKeeper allows one to attach a &#8220;watch&#8221; to a node so that the server will report back when changes happen to the given node.  In the C library, this functionality is exposed via a callback function which is executed once the monitored node aspect is modified.</p>
<p>It would certainly be possible to offer this functionality in Go using a similar mechanism, but <a href="http://golang.org/doc/go_spec.html#Channel_types">Go channels</a> provide a number of advantages for that kind of asynchronous notification: waiting for multiple events via the <a href="http://golang.org/doc/go_spec.html#Select_statements">select statement</a>, synchronous blocking until the event happens, testing if the event is already available, etc.</p>
<p>The tricky bit, though, isn&#8217;t the use of channels.  That part is quite simple.  The tricky detail is that the C callback function execution happens in a C thread started by the ZooKeeper library, and happens asynchronously, while the Go application is doing its business elsewhere.  Right now, there&#8217;s no straightforward way to transfer the execution of this asynchronous C function back into the Go land.  The solution for this problem was found with some help from the folks at the <a href="">golang-nuts</a> mailing list, and luckily it&#8217;s not that hard to support or understand.  That said, this is a good opportunity to get some coffee or your preferred focus-enhancing drink.</p>
<p>The solution works like this: when the ZooKeeper C library gets a watch notification, it executes a C callback function which is inside a Gozk helper file. Rather than transferring control to Go right away, this C function simply appends data about the event onto a queue, and signals a pthread condition variable to notify that an event is available.  Then, on the Go side, once the first ZooKeeper connection is initialized, a new goroutine is fired and loops waiting for events to be available.  The interesting detail about this loop, is that it blocks <i>within a foreign C function</i> waiting for an event to be available, through the signaling of the shared pthread condition variable.  In the Go side, that&#8217;s how the call looks like, just to give a more practical feeling:</p>
<pre>
// This will block until there's a watch available.
data := C.wait_for_watch()
</pre>
<p>Then, on the C side, here is the function definition:</p>
<pre>
watch_data *wait_for_watch() {
    watch_data *data = NULL;
    pthread_mutex_lock(&#038;watch_mutex);
    if (first_watch == NULL)
        pthread_cond_wait(&#038;watch_available, &#038;watch_mutex);
    data = first_watch;
    first_watch = first_watch->next;
    pthread_mutex_unlock(&#038;watch_mutex);
    return data;
}
</pre>
<p>As you can see, not really a big deal.  When that kind of blocking occurs inside a foreign C function, the Go runtime will correctly continue the execution of other goroutines within other operating system threads.</p>
<p>The result of this mechanism is a nice to use interface based on channels, which may be explored in different ways depending on the application needs.  Here is a simple example blocking on the event synchronously, for instance:</p>
<pre>
stat, watch, err := zk.ExistsW("/some/path")
if stat == nil &#038;&#038; err == nil {
    event := <-watch
    // Use event ...
}
</pre>
<p><b>Concluding</b></p>
<p>Those were some of the interesting aspects of implementing the ZooKeeper binding.  I would like to speak about some additional details, but this post is rather long already, so I'll keep that for a future opportunity.  The code is available under the LGPL, so if you're curious about some other aspect, or would like to use ZooKeeper with Go, please move on and <a href="https://wiki.ubuntu.com/gozk">check it out</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.labix.org/2010/12/10/integrating-go-with-c-the-zookeeper-binding-experience/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Gocheck: A rich testing library for Go</title>
		<link>http://blog.labix.org/2010/11/06/gocheck-a-rich-testing-library-for-go</link>
		<comments>http://blog.labix.org/2010/11/06/gocheck-a-rich-testing-library-for-go#comments</comments>
		<pubDate>Sat, 06 Nov 2010 23:31:59 +0000</pubDate>
		<dc:creator>Gustavo Niemeyer</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Project]]></category>
		<category><![CDATA[Test]]></category>

		<guid isPermaLink="false">http://blog.labix.org/?p=433</guid>
		<description><![CDATA[It&#8217;s time to release my &#8220;side project&#8221; which has been evolving over the last several months: Gocheck. I&#8217;ve been watching Go for some time, and have been getting more and more interested in the language. My first attempt to write &#8230; <a href="http://blog.labix.org/2010/11/06/gocheck-a-rich-testing-library-for-go">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s time to release my &#8220;side project&#8221; which has been evolving over the last several months: <a href="http://j.mp/dcKGmQ" _href="http://labix.org/gocheck">Gocheck</a>. I&#8217;ve been watching Go for some time, and have been getting more and more interested in the language.  My first attempt to write something interesting in it made it obvious that there would be benefit in having a richer testing platform than what is <a href="http://golang.org/pkg/testing/">available in the standard library</a>.  That said, I do understand why the standard one is slim: it&#8217;s pretty minimalist, because it&#8217;s used by itself to test the rest of the platform.  With Gocheck, though, I don&#8217;t have that requirement.  I&#8217;m able to trust that the standard library works well, and focus on having features which will make me more productive while writing tests, including features such as:</p>
<p><span id="more-433"></span>
<ul>
<li>Better error reporting
<li> Richer test helpers: assertions which interrupt the test immediately, deep multi-type comparisons, string matching, etc
<li> Suite-based grouping of tests
<li> Fixtures: per suite and/or per test set up and tear down
<li> Management of temporary directories
<li> Panic-catching logic, with proper error reporting
<li> Proper counting of successes, failures, panics, missed tests, skips, etc
<li> Support for expected failures
<li> Fully tested (yes, it manages to test itself reliably!)
</ul>
<p>That last point was actually quite fun to get right.  It&#8217;s the first time I wrote a testing framework from the ground up, and of course I wanted to have it fully tested by itself, but I didn&#8217;t want to simply use a foreign testing framework to test it.  So what it does is basically to have a &#8220;bootstrapping&#8221; phase, which ensures that the very basic parts of the library work, without trusting on pretty much any internal functionality (e.g. it verifies the number of executed functions, and works with low-level panics). Then, once the lower layers are trusted, tests for higher functionality was introduced by building on the trusted bits.</p>
<p>Gocheck is actually <i>mostly</i> ready for some time now, but I&#8217;ve been polishing edges with some real world usage before releasing it.  Since both the real world usage and Gocheck itself are side projects, you can imagine that took a bit of time.  Today, though, I&#8217;ve managed to fix the last few things which were bothering me, so it&#8217;s up for world consumption.</p>
<p>I hope you enjoy it, and make some good use of it so that we can all have more reliable software. <img src='http://blog.labix.org/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.labix.org/2010/11/06/gocheck-a-rich-testing-library-for-go/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Mocker 1.0 for Python released!</title>
		<link>http://blog.labix.org/2010/06/20/mocker-1-0-for-python-released</link>
		<comments>http://blog.labix.org/2010/06/20/mocker-1-0-for-python-released#comments</comments>
		<pubDate>Mon, 21 Jun 2010 00:09:02 +0000</pubDate>
		<dc:creator>Gustavo Niemeyer</dc:creator>
				<category><![CDATA[Project]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Test]]></category>

		<guid isPermaLink="false">http://blog.labix.org/?p=323</guid>
		<description><![CDATA[After a few years in development, version 1.0 of Mocker is now available! Check out the changes since 0.10.1, the supported features, or go straight to the download page.]]></description>
			<content:encoded><![CDATA[<p>After a few years in development, version 1.0 of <a href="http://bit.ly/dm0GGy" _href="http://labix.org/mocker">Mocker</a> is now <a href="http://bit.ly/dez9jQ" _href="https://launchpad.net/mocker/trunk/1.0">available</a>!  Check out the <a href="http://bit.ly/czhiru " _href="http://bazaar.launchpad.net/~niemeyer/mocker/trunk/annotate/head:/NEWS">changes since 0.10.1</a>, the <a href="http://bit.ly/dm0GGy" _href="http://labix.org/mocker">supported features</a>, or go straight to the <a href="http://bit.ly/9Wszmp" _href="https://launchpad.net/mocker/+download">download page</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.labix.org/2010/06/20/mocker-1-0-for-python-released/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Integrating IRC with LDAP and two-way SMSing</title>
		<link>http://blog.labix.org/2010/06/19/integrating-irc-with-ldap-and-two-way-smsing</link>
		<comments>http://blog.labix.org/2010/06/19/integrating-irc-with-ldap-and-two-way-smsing#comments</comments>
		<pubDate>Sat, 19 Jun 2010 21:56:07 +0000</pubDate>
		<dc:creator>Gustavo Niemeyer</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Erlang]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Project]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.labix.org/?p=296</guid>
		<description><![CDATA[A bit of history I don&#8217;t know exactly why, but I&#8217;ve always enjoyed IRC bots. Perhaps it&#8217;s the fact that it emulates a person in an easy-to-program way, or maybe it&#8217;s about having a flexible and shared &#8220;command line&#8221; tool, &#8230; <a href="http://blog.labix.org/2010/06/19/integrating-irc-with-ldap-and-two-way-smsing">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><b>A bit of history</b></p>
<p>I don&#8217;t know exactly why, but I&#8217;ve always enjoyed IRC bots.  Perhaps it&#8217;s the fact that it emulates a person in an easy-to-program way, or maybe it&#8217;s about having a flexible and shared &#8220;command line&#8221; tool, or maybe it&#8217;s just the fact that it helps people perceive things in an asynchronous way without much effort.  Probably a bit of everything, actually.</p>
<p><span id="more-296"></span></p>
<p>My bot programming started with <a href="http://labix.org/pybot">pybot</a> many years ago, when I was still working at <a href="http://www.conectiva.com.br">Conectiva</a>.  Besides having many interesting features, this bot eventually got in an abandonware state, since <a href="http://www.canonical.com">Canonical</a> already had pretty much equivalent features available when I joined, and I had other interests which got in the way.  The code was a bit messy as well.. it was a time when I wasn&#8217;t very used to testing software properly (a friend has a great excuse for that kind of messy software: <i>&#8220;I was young, and needed the money!&#8221;</i>).</p>
<p>Then, a couple of years ago, while working in the <a href="http://landscape.canonical.com">Landscape</a> project, there was an opportunity of getting some information more visible to the team.  Coincidently, it was also a time when I wanted to get some practice with the concepts of <a href="http://erlang.org">Erlang</a>, so I decided to write a bot from scratch with some nice support for plugins, just to get a feeling of how the promised stability of Erlang actually took place for real.  This bot is called <a href="https://launchpad.net/mup">mup</a> (Mup Pet, more formally), and its code is available publicly through <a href="https://launchpad.net/mup">Launchpad</a>.</p>
<p>This was a nice experiment indeed, and I did learn quite a bit about the ins and outs of Erlang with it.  Somewhat unexpected, though, was the fact that the bot grew up a few extra features which multiple teams in Canonical started to appreciate.  This was of course very nice, but it also made it more obvious that the egocentric reason for having a bot written in Erlang would now hurt, because most of Canonical&#8217;s own coding is done in Python, and that&#8217;s what internal tools should generally be written in for everyone to contribute and help maintaining the code.</p>
<p>That&#8217;s where the desire of migrating mup into a Python-based brain again came from, and having a new feature to write was the perfect motivator for this.</p>
<p><b>LDAP and two-way SMSing over IRC</b></p>
<p>Canonical is a <i>very</i> distributed company.  Employees are distributed over dozens of countries, literally.  Not only that, but most people also work from their homes, rather than in an office.  Many different countries also means many different timezones, and working from home with people from different timezones means flexible timing.  All of that means communication gets&#8230; well.. interesting.</p>
<p>How do we reach someone that should be in an online meeting and is not?  Or someone that is traveling to get to a sprint?  Or how can someone that has no network connectivity reach an IRC channel to talk to the team?  There are probably several answers to this question, but one of them is of course SMS.  It&#8217;s not exactly cheap if we consider the cost of the data being transfered, but pretty much everyone has a mobile phone which can do SMS, and the model is not that far away from IRC, which is the main communication system used by the company.</p>
<p>So, the itch was itching.  Let&#8217;s scratch it!</p>
<p>Getting the mobile phone of employees was already a solved problem for mup, because it had a plugin which could interact with the LDAP directory, allowing people to do something like this:</p>
<blockquote><p>
&lt;joe&gt; mup: poke gustavo<br />
&lt;mup&gt; joe: niemeyer is Gustavo Niemeyer &lt;&#8230;@canonical.com&gt; &lt;time:&#8230;&gt; &lt;mobile:&#8230;&gt;
</p></blockquote>
<p>This just had to be migrated from Erlang into a Python-based brain for the reasons stated above. This time, though, there was no reason to write something from scratch.  I could even have used pybot itself, but there was also <a href="http://sourceforge.net/projects/supybot/">supybot</a>, an IRC bot which started around the same time I wrote the first version of pybot, and unlike the latter, supybot&#8217;s author was much more diligent in evolving it.  There is quite a comprehensive list of plugins for supybot nowadays, and it includes means for testing plugins and so on.  The choice of using it was straighforward, and getting &#8220;<i>poke</i>&#8221; support ported into a plugin wasn&#8217;t hard at all.</p>
<p>So, on to SMSing.  Canonical already had a contract with an SMS gateway company which we established to test-drive some ideas on <a href="https://landscape.canonical.com">Landscape</a>. With the mobile phone numbers coming out of the LDAP directory in hands and an SMS contract established, all that was needed was a plugin for the bot to talk to the SMS gateway.  That &#8220;conversation&#8221; with the SMS gateway allows not only sending messages, but also receiving SMS messages which were sent to a specific number.</p>
<p>In practice, this means that people which are connected to IRC can very easily deliver an SMS to someone using their nicks.  Something like this:</p>
<blockquote><p>
&lt;joe&gt; @sms niemeyer Where are you?  We&#8217;re waiting!
</p></blockquote>
<p>And this would show up in the mobile screen as:</p>
<blockquote><p>
joe&gt; Where are you?  We&#8217;re waiting!
</p></blockquote>
<p>In addition to this, people which have <i>no connectivity</i> can also contact individuals and channels on IRC, with mup working as a middle man.  The message would show up on IRC in a similar way to:</p>
<blockquote><p>
&lt;mup&gt; [SMS] &lt;niemeyer&gt; Sorry, the flight was delayed. Will be there in 5.
</p></blockquote>
<p>The communication from the bot to the gateway happens via plain HTTPS.  The communication back is a bit more complex, though.  There is a small proxy service deployed in <a href="http://code.google.com/appengine">Google App Engine</a> to receive messages from the SMS gateway.  This was done to avoid losing messages when the bot itself is taken down for maintenance.  The SMS gateway doesn&#8217;t handle this case very well, so it&#8217;s better to have something which will be up most of the time buffering messages.</p>
<p>A picture is worth 2<sup>10</sup> words, so here is a simple diagram explaining how things got linked together:</p>
<p><a href="http://blog.labix.org/wp-content/uploads/2010/06/mup-sms.png"><img src="http://blog.labix.org/wp-content/uploads/2010/06/mup-sms.png" alt="" title="SMS integration diagram" width="449" height="255" class="aligncenter size-full wp-image-308" /></a></p>
<p>This is now up for experimentation, and so far it&#8217;s working nicely.  I&#8217;m hoping that in the next few weeks we&#8217;ll manage to port the rest of mup into the supybot-based brain.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.labix.org/2010/06/19/integrating-irc-with-ldap-and-two-way-smsing/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

