<?xml version="1.0"?>
<rss version="2.0">

<channel>
	<title>Planet Trapexit - Erlang/OTP News</title>
	<link>http://planet.trapexit.org</link>
	<language>en</language>
	<description>Planet Trapexit - Erlang/OTP News - http://planet.trapexit.org</description>

<item>
	<title>REALITY.SYS: Stierkampf mal anders.</title>
	<guid>http://www.brakmic.de/?p=468</guid>
	<link>http://www.brakmic.de/index.php/2011/06/04/stierkampf-mal-anders/</link>
	<description>&lt;p&gt;Wie so viele andere schwachsinnige Rituale ist auch der sogenannte &amp;#8220;Stierkampf&amp;#8221; (besser: &lt;em&gt;langsames Stiereschlachten&lt;/em&gt;) eine &amp;#8220;Tradition&amp;#8221;. Das Bemerkenswerte daran ist aber vor allem die Tatsache, dass angeblich aufgeklärte Westler wohl keine Probleme damit haben, dieser morbiden Veranstaltung beizuwohnen. Menschen (fast) wie du und ich sitzen schön brav in der Menge, oft von ihren minderjährigen Kindern flankiert, und schauen zu, wie ein Stier langsam zu Tode gequält wird, während mehrere Zirkusfritzen, sog. &amp;#8220;Torreros&amp;#8221;, in ihren glitzernden Schlachterkostümen um ihn herum tänzeln.&lt;/p&gt;
&lt;p&gt;Ich könnte jetzt mehrere Millionen Gründe aufzählen, warum der sog. &amp;#8220;Stierkampf&amp;#8221; eine Tierquälerei ist. Dies wäre aber nicht so &amp;#8220;ökonomisch&amp;#8221; und schon gar nicht effektiv, wie wenn ich einfach einige Videos anführe, wo das Tier gewinnt.&lt;/p&gt;
&lt;p&gt;Solche Videos zeigen den einzig wahren Stierkampf!&lt;/p&gt;
&lt;p&gt;Und ich muss zugeben, dass ich es als &lt;em&gt;sehr angenehm&lt;/em&gt; empfinde, zu sehen, &lt;em&gt;wenn das Tier gewinnt&lt;/em&gt;. Jedem Besucher, jedem &amp;#8220;Torrero&amp;#8221; und vor allem den Vollhonks, die hinter den Stieren her laufen, kann ich nur die Bekanntschaft mit dem Stierhorn wünschen. &lt;span&gt;Manchmal kann die Vernunft einfach nicht anders vermittelt werden&lt;/span&gt;. 200 Jahre Aufklärung sind für einige von uns eben nicht ausreiched.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.brakmic.de/index.php/2011/06/04/stierkampf-mal-anders/&quot;&gt;&lt;em&gt;Click here to view the embedded video.&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.brakmic.de/index.php/2011/06/04/stierkampf-mal-anders/&quot;&gt;&lt;em&gt;Click here to view the embedded video.&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.brakmic.de/index.php/2011/06/04/stierkampf-mal-anders/&quot;&gt;&lt;em&gt;Click here to view the embedded video.&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.brakmic.de/index.php/2011/06/04/stierkampf-mal-anders/&quot;&gt;&lt;em&gt;Click here to view the embedded video.&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.brakmic.de/index.php/2011/06/04/stierkampf-mal-anders/&quot;&gt;&lt;em&gt;Click here to view the embedded video.&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.brakmic.de/index.php/2011/06/04/stierkampf-mal-anders/&quot;&gt;&lt;em&gt;Click here to view the embedded video.&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.brakmic.de/index.php/2011/06/04/stierkampf-mal-anders/&quot;&gt;&lt;em&gt;Click here to view the embedded video.&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
	<pubDate>Sat, 04 Jun 2011 19:27:58 +0000</pubDate>
</item>
<item>
	<title>REALITY.SYS: Immer dieses Händewaschen…</title>
	<guid>http://www.brakmic.de/?p=459</guid>
	<link>http://www.brakmic.de/index.php/2011/06/04/immer-dieses-handewaschen/</link>
	<description>&lt;p&gt;Angesichts der, ähnlich SARS und Schweinepest, herbeigetrommelten Seuche &amp;#8220;EHEC&amp;#8221;, muss man sich ernsthaft die Frage stellen, ob wir in Sachen Hygiene nicht immer noch im Mittelalter stecken.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hallo Leute&lt;/strong&gt;! Sich die Hände richtig zu waschen ist eine Sache, die man normalerweise als Kleinkind gelernt haben muss!&lt;/p&gt;
&lt;p&gt;Und die Betonung, dass man nach einem Toilettenbesuch die Hände waschen sollte, ist mehr als lächerlich. Es ist erschreckend, traurig und zeugt nur von unserer sterilen Lebensweise in dieser angeblich fortschrittlichen Welt. Ja, sterile Lebensweise, als Bezeichnung für unser Abgekoppelt-Sein von elementarsten menschlichen Ritualformen wie richtiges Waschen des eigenen Körpers, richtiger Umgang mit fremden Sachen (z.B. indem wir ausgestellte Waren nicht ohne Weiteres betatschen sollten!) etc.&lt;/p&gt;
&lt;p&gt;Wie blamabel muss es denn für uns sein, wenn man uns über die Medien darum bitten muss, sich die Hände richtig zu wachen und das Gemüse bzw. Fleisch vor dem Verzehr ebenfalls gewaschen zu haben.&lt;/p&gt;
&lt;p&gt;Aber nein, am leichtesten ist es doch, diesen &lt;em&gt;blöden Südeuropäern&lt;/em&gt; alles in die Schuhe zu schieben.&lt;span&gt; Ja, genau, die Spanier waren&amp;#8217;s&lt;/span&gt;, diese gemeinen Kerle. Sie haben uns all das eingebrockt und siehe da: wir müssen uns jetzt die Hände waschen!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
	<pubDate>Sat, 04 Jun 2011 08:23:13 +0000</pubDate>
</item>
<item>
	<title>ejabberd@jabber.ru: ejabberd 2.1.8 - Fix PubSub</title>
	<guid>http://www.ejabberd.im/4740 at http://www.ejabberd.im</guid>
	<link>http://www.ejabberd.im/ejabberd-2.1.8</link>
	<description>&lt;p&gt;The &lt;a href=&quot;http://www.ejabberd.im/ejabberd-2.1.7&quot;&gt;ejabberd 2.1.7&lt;/a&gt; released yesterday contains a bug that breaks PubSub.&lt;/p&gt;
&lt;p&gt;If you use ejabberd 2.1.7 and PubSub, you can find the patch and the fixed mod_pubsub.beam in the page &lt;a href=&quot;https://support.process-one.net/browse/EJAB-1457&quot;&gt;EJAB-1457&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Updated binary installers will be available next monday in &lt;a href=&quot;http://www.process-one.net/en/ejabberd/downloads&quot; title=&quot;http://www.process-one.net/en/ejabberd/downloads&quot;&gt;http://www.process-one.net/en/ejabberd/downloads&lt;/a&gt;&lt;/p&gt;</description>
	<pubDate>Fri, 03 Jun 2011 11:39:09 +0000</pubDate>
</item>
<item>
	<title>Process-one Blogs: “Google Social”: A paradox of its own</title>
	<guid>http://www.process-one.net/en/blogs/article/google_social_a_paradox_of_its_own/</guid>
	<link>http://www.process-one.net/en/blogs/article/google_social_a_paradox_of_its_own/</link>
	<description>&lt;p&gt;Yesterday was a sad day for the Internet, as an open and decentralized content repository.&lt;/p&gt; &lt;p align=&quot;center&quot;&gt;&lt;img alt=&quot;image&quot; height=&quot;375&quot; src=&quot;http://www.process-one.net/images/uploads/internet_open.jpg&quot; width=&quot;500&quot; /&gt;&lt;/p&gt;
&lt;p&gt;At the same moment, Twitter launch its follow button and Google extend its +1 button for websites. They both are attempting to catch up with Facebook success with the &quot;like button&quot;.&lt;/p&gt;
&lt;p&gt;Of course, it feels ridiculous for content producers and consumers to expect to place more buttons on their pages in the hope to attract more traffic. The escalation in the battle for embedding buttons in web pages and the battle to get the users clicks is leading nowhere.&lt;/p&gt;
&lt;p&gt;I would rather however focus on Google move, the paradox and possibly the trap it could become for the company. I have read numerous times that Google initiative in &quot;social&quot; area had always been a failure. Even &lt;a href=&quot;http://www.guardian.co.uk/technology/2011/jun/01/google-missed-out-on-the-friends-thing-eric-chmidt&quot;&gt;Eric Schmidt admitted at D9 conference that he had messed up on Google Social initiative&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In my opinion, the main reason for failure is because social, as defined by today's market, is the complete opposite of Google model and view of the online world.&lt;/p&gt;
&lt;p&gt;&quot;Like buttons&quot; are replacements for the HTML links that authors used to place on their webpage to talk about topics they liked and point to relevant content. But as HTML links were purely open and available for search engine web spiders, the end result of the &quot;like button&quot; action is closed and proprietary. Facebook and Twitter are one of the biggest threat for Google: they are cutting Google supply of their raw material: the data to analyze, both content and relations (links).&lt;/p&gt;
&lt;p&gt;Google reactions yesterday has been to launch its own initiative, its own &quot;like button&quot; to gather its own data. However, doing so Google enter the trap of the closed Internet, in which they cannot prosper.&lt;/p&gt;
&lt;p&gt;Google's model has been to compete on algorithm, not data. They have beaten all other search engine using the same data set than anyone could use. They hire smart scientists to produce clever mathematical solution to the world data analysis problem. Algorithm competition is their reason to exist: organizing the world data, not owning it.&lt;/p&gt;
&lt;p&gt;Launching a &quot;like button&quot; is admitting that they were wrong in their core vision. Can the world be organized automatically by algorithm, from news to search ? It is an impossible equation to solve for them without deeper changes in Google's vision.&amp;nbsp;In other words, the social graph that Facebook wants to build is actually what the web is about, and should be at the heart of the open web. Copying that closed vision of the web is a mistake.&lt;/p&gt;
&lt;p&gt;What happen today looks like Yahoo!'s revenge (even if Yahoo! company is now out of the game): curation is the return of directories of content, with a larger number of curators and ranking depending on the proximity of the curators to yourself.&lt;/p&gt;
&lt;p&gt;Google simply cannot win with this definition of the &quot;social web&quot;. If social is about building competing subsets of Internet, defined by their user base, Google will decline on search, their core business. They cannot remain the entry point on the Internet for a large number of users, because they could not be able to bring them on every place you might want to go on the web.&lt;/p&gt;
&lt;p&gt;The solution for Google requires to change the view of the social web, not to build their own clone of social network. Google social should be about putting people at the heart of an open Internet, where companies keeps on competing on algorithms. They already have valuable tools to rely on: google reader can share publicly what you like to read, blogger to publish your thought. They can build &quot;Google People&quot; around them.&lt;/p&gt;
&lt;p&gt;I think that Google should keep on producing tools to make easy to share publicly what people would like to share, from status, to picture, though and links. This should be published in a well defined and documented way that will lead to a more open web. To be frank, such standards are emerging in many initiatives  (webfinger, salmon, foaf, ostatus, opensocial and many others). Google promotes or even design several of those web protocols.&lt;/p&gt;
&lt;p&gt;However, Google +1, until it leads to publicly available data on user profile, is a move in the wrong direction for Google. Let's hope for the Internet that their next move will open the data and bring the competition back to algorithms.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Credits: Photo by &lt;a href=&quot;http://www.flickr.com/photos/balleyne/&quot;&gt;Blaise Alleyne&lt;/a&gt;&lt;/p&gt;</description>
	<pubDate>Thu, 02 Jun 2011 12:59:07 +0000</pubDate>
</item>
<item>
	<title>ejabberd@jabber.ru: ejabberd 2.1.7, 3.0.0-alpha-3 and exmpp 0.9.7 -- security release</title>
	<guid>http://www.ejabberd.im/4731 at http://www.ejabberd.im</guid>
	<link>http://www.ejabberd.im/ejabberd-2.1.7</link>
	<description>&lt;p&gt;ejabberd 2.1.7, and ejabberd 3.0.0-alpha-3, and exmpp 0.9.7 have been released, after a few months of development. They contain a lot of bugfixes, improvements and some new features.&lt;/p&gt;
&lt;p&gt;If you have ejabberd running in a public server, please &lt;strong&gt;update it immediately&lt;/strong&gt;: those releases contain a security fix that disables entity expansion completely to prevent billion laughs DoS attack (CVE-2011-1753).&lt;/p&gt;
&lt;h2&gt;ejabberd 2.1.7&lt;/h2&gt;
&lt;p&gt;This release contains many bugfixes, improvements and a few new features.&lt;/p&gt;
&lt;p&gt;A short list of changes:&lt;/p&gt;
&lt;ul&gt;
&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;http://www.ejabberd.im/ejabberd-2.1.7&quot; target=&quot;_blank&quot;&gt;read more&lt;/a&gt;&lt;/p&gt;</description>
	<pubDate>Wed, 01 Jun 2011 17:05:55 +0000</pubDate>
</item>
<item>
	<title>erlang.org RSS Feed: R14B03 released</title>
	<guid>http://www.erlang.org/news/18</guid>
	<link>http://www.erlang.org/news/18</link>
	<description>&lt;p&gt;&lt;p&gt;
	&lt;b&gt;Erlang/OTP R14B03&lt;/b&gt; has been released as planned on May 25:th 2011. It is the third R14 service release.&lt;/p&gt;
&lt;p&gt;
	See the release notes in the &lt;a href=&quot;http://www.erlang.org/download/otp_src_R14B03.readme&quot;&gt;readme file&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
	Download the new release from the &lt;a href=&quot;http://www.erlang.org/download.html&quot;&gt;download page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
	&lt;strong&gt;Highlights:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;
		Diameter is a brand new application in this release. The application support the diameter protocol specified in RFC 3588 and is intended to provide an Authentication, Authorization and Accounting (AAA) framework for applications.&amp;nbsp;&lt;/li&gt;
	&lt;li&gt;
		The documentation for stdlib and kernel now uses type specifications from the source modules which should guarantee that the documentation and code are consistent with regard to the type information.&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;</description>
	<pubDate>Wed, 25 May 2011 16:00:00 +0000</pubDate>
</item>
<item>
	<title>Erlang Factory News: Countdown to the Erlang Factory London!</title>
	<guid>http://www.erlang-factory.com/news/list#60</guid>
	<link>http://www.erlang-factory.com/news/list#60</link>
	<description>&lt;p&gt;There are&lt;span&gt; only two weeks left&lt;/span&gt; to the Erlang Factory London. If you haven't registered yet, you can still do this by clicking &lt;a href=&quot;https://www.erlang-factory.com/conference/London2011/register&quot;&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;We have confirmed speakers including &lt;span&gt;Robert Virding and Mike Williams &lt;/span&gt;(Inventors of Erlang),&lt;span&gt; Tony Falco&lt;/span&gt; (COO of Basho Technologies), &lt;span&gt;John Hughes&lt;/span&gt; (Inventor of QuickCheck) and &lt;span&gt;Eric Merritt&lt;/span&gt; (Author of Erlang and OTP in Action). Many more are listed on the &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/speakers&quot;&gt;Speakers Page&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;You are welcome to follow &lt;a href=&quot;http://twitter.com/erlangfactory&quot;&gt;@erlangfactory&lt;/a&gt; on Twitter.&lt;/p&gt;</description>
	<pubDate>Wed, 25 May 2011 09:01:32 +0000</pubDate>
</item>
<item>
	<title>Programming in the 21st Century: Constantly Create</title>
	<guid>http://prog21.dadgum.com/99.html</guid>
	<link>http://prog21.dadgum.com/99.html</link>
	<description>When I wrote &lt;a href=&quot;http://prog21.dadgum.com/58.html&quot;&gt;Flickr as a Business Simulator&lt;/a&gt;, I was thinking purely about making a product--photos--and getting immediate feedback from a real audience. Seeing how much effort it takes to build-up a following. Learning if what you think people will like and what they actually like are the same thing.
&lt;br /&gt;&lt;br /&gt;It works just as well for learning what it's like to be in any kind of creative profession, such as an author of fiction or a recording artist.
&lt;br /&gt;&lt;br /&gt;Go look at music reviews on Amazon, and you'll see people puzzling over why a band's latest release doesn't have the spark of their earlier material, pointing out filler songs on albums, complaining about inconsistency between tracks. Sometimes the criticisms are empty, but there's often a ring of truth. There's an underlying question of &lt;i&gt;why&lt;/i&gt;. How could a songwriter or band release material that isn't always at the pinnacle of perfection?
&lt;br /&gt;&lt;br /&gt;After years of posting photos to Flickr, I get it. I'm just going along, taking my odd photographs, when all of a sudden one resonates and breaks through and I watch the view numbers jump way up. Then I've got pressure: How can I follow that up? Sometimes I do, with a couple of winners in a row, but inevitably I can't stay at that level. Sometimes I take a break, not posting shots for a month or more, and then I lose all momentum.
&lt;br /&gt;&lt;br /&gt;When I'm at a low point, when I devolve into taking pictures of mundane subjects, pictures I know aren't good, I think about how I'm ever going to get out of that rut. Inevitably I do, though it's often a surprise when I go from a forgettable photo one day to something inspired the next.
&lt;br /&gt;&lt;br /&gt;The key for me is to keep going, to keep taking and posting photos. If I get all perfectionist then there's too much pressure, and I start second-guessing myself. If I give up when my quality drops off, then that's not solving anything. The steady progress of continual output, whether good or bad output, is part of the overall creative process.</description>
	<pubDate>Sun, 22 May 2011 06:00:00 +0000</pubDate>
</item>
<item>
	<title>Damien Katz: I'm in Boston next week for a Couchbase Meetup</title>
	<guid>tag:damienkatz.net,2011://1.595</guid>
	<link>http://damienkatz.net/2011/05/im_in_boston_next_week_for_a_c.html</link>
	<description>&lt;p&gt;Get yo couch on! Sign up here: &lt;a href=&quot;http://www.meetup.com/Boston-CouchDB/events/17374461/&quot;&gt;http://www.meetup.com/Boston-CouchDB/events/17374461/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;damien@couchbase.com&lt;/p&gt;</description>
	<pubDate>Thu, 19 May 2011 19:03:26 +0000</pubDate>
</item>
<item>
	<title>Erlang Training and Consulting &lt;br/&gt;- News: 18 May 2011: Radio-Electronics publishes an article on Open Telecommunications Platform, OTP for Open Communications by Francesco Cesarini</title>
	<guid>http://www.erlang-solutions.com/news/1/entry/1242</guid>
	<link>http://www.erlang-solutions.com/news/1/entry/1242</link>
	<description>&lt;p&gt;Francesco Cesarini, Technical Director of &lt;a href=&quot;http://www.erlang-solutions.com&quot; target=&quot;_blank&quot;&gt;Erlang Solutions&lt;/a&gt;, discusses the benefits of the Erlang Open Telecom Platform and how it can be used in product development for writing software for telecommunications systems.&lt;/p&gt;
&lt;p&gt;In the article he looks at Erlang as a programming language, what exactly is OTP, OTP as more than a telecoms platform, and the benefits of OTP. This is an article you can't afford to miss. For the full article check out the Radio-Electronics &lt;a href=&quot;http://www.radio-electronics.com/articles/telecoms-networks/open-telecommunications-platform-otp-for-open-17&quot; target=&quot;_blank&quot;&gt;website&lt;/a&gt;.&lt;/p&gt;</description>
	<pubDate>Wed, 18 May 2011 16:17:43 +0000</pubDate>
</item>
<item>
	<title>Erlang Factory News: Early Bird Rate - Book before 22 May to save £100</title>
	<guid>http://www.erlang-factory.com/news/list#59</guid>
	<link>http://www.erlang-factory.com/news/list#59</link>
	<description>&lt;p&gt;&lt;a href=&quot;https://www.erlang-factory.com/conference/London2011/register&quot;&gt;Book&lt;/a&gt; your place now at the &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011&quot;&gt;Erlang Factory London 2011&lt;/a&gt; at the Early Bird Rate of &amp;pound;495 for the conference and &amp;pound;1295 for the &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/university&quot;&gt;University&lt;/a&gt; and conference. This is a saving of &amp;pound;100 off the standard price of the conference!Only valid until the 22 May!&lt;/p&gt;
&lt;p&gt;Speakers so far include , &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/speakers/KostisSagonas&quot;&gt;Kostis Sagonas&lt;/a&gt;, the leader of the HIPE Team at Uppsala University, &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/speakers/MarkusKern&quot;&gt;Marcus Kern&lt;/a&gt;, CTO at MIG, &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/speakers/SteveVinoski&quot;&gt;Steve Vinosk&lt;/a&gt;i, distributed systems expert and &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/speakers/ScottLystigFritchie&quot;&gt;Scott Lystig Fritchie&lt;/a&gt;, senior software engineer at Basho Technologies. Many more speakers are still to be announced.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.erlang-factory.com/conference/London2011/register&quot;&gt;Book now to secure this fantastic rate!&lt;/a&gt;&lt;/p&gt;</description>
	<pubDate>Wed, 18 May 2011 09:16:37 +0000</pubDate>
</item>
<item>
	<title>Trapexit's Erlang Blog Filter: More Erlang Web Server Benchmarking</title>
	<guid>http://steve.vinoski.net/blog/?p=832</guid>
	<link>http://steve.vinoski.net/blog/2011/05/18/more-erlang-web-server-benchmarking/</link>
	<description>&lt;p&gt;In my &lt;a rel=&quot;nofollow&quot;&gt;previous blog entry&lt;/a&gt; I questioned the value of most web server benchmarking, particularly as related to Erlang. Typical benchmarks are misleading, inaccurate, and poorly executed. Perhaps worse, the intent of publishing them seems to be to assert that the &lt;em&gt;fastest&lt;/em&gt; web server (at least according to the tests performed) is of course also the &lt;em&gt;best&lt;/em&gt; web server. You&amp;#8217;d think the flaws of this fallacy would be so obvious that nobody would fall for it, but think again: watching the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.delicious.com/tag/erlang&quot;&gt;delicious &amp;#8220;erlang&amp;#8221; tag&lt;/a&gt; over the past few days revealed the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.ostinelli.net/a-comparison-between-misultin-mochiweb-cowboy-nodejs-and-tornadoweb/&quot;&gt;benchmarks my blog post referred to&lt;/a&gt; to be one of the most bookmarked Erlang-related pages during that timeframe.&lt;/p&gt;
&lt;p&gt;Not surprisingly, though, it looks like I&amp;#8217;m not the only one bothered by poor benchmarking practices. Over on his blog, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.mnot.net/&quot;&gt;Mark Nottingham&lt;/a&gt; just published &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.mnot.net/blog/2011/05/18/http_benchmark_rules&quot;&gt;a brilliant set of rules for HTTP load testing&lt;/a&gt;. It&amp;#8217;s quite instructive to take your favorite set of published web server benchmarks and see just how many of Mark&amp;#8217;s rules they violate.&lt;/p&gt;
&lt;p&gt;Like I hinted last time, if you want benchmarks, you are best off by far if you run them yourself. That way, their relevance to the problems you&amp;#8217;re addressing will be much more likely, and you can run them in a similar, or even the same, environment on which you plan to deploy. You can also gear the benchmarks to much more closely resemble your applications and the loads you require them to handle. Doing the benchmarking work yourself will give you valuable hands-on experience with the servers and frameworks you&amp;#8217;re considering, allowing you to get a feel for important factors such as feature completeness and correctness, ease of development, flexibility, and ease of deployment and runtime management/monitoring, none of which can be gauged by someone else&amp;#8217;s performance benchmarks. Finally, by doing your own benchmarking you can also help ensure the validity and usefulness of your results by following Mark&amp;#8217;s load testing rules.&lt;/p&gt;</description>
	<pubDate>Wed, 18 May 2011 05:54:45 +0000</pubDate>
</item>
<item>
	<title>Erlang Inside: Motivated Reasoning and Erlang vs Python vs Node</title>
	<guid>http://erlanginside.com/?p=280</guid>
	<link>http://erlanginside.com/motivated-reasoning-and-erlang-vs-python-vs-node-280</link>
	<description>A comparison between Misultin, Mochiweb, Cowboy, Node.JS, and Tornado. Tests such as this one tend to focus on either raw parsing speed or total number of concurrent connections, and which is more important depends on the ultimate application. Or they perfectly tune the tester&amp;#8217;s favorite framework and use a stock configuration for the other competitors. [...]</description>
	<pubDate>Mon, 16 May 2011 15:51:08 +0000</pubDate>
</item>
<item>
	<title>Erlang Inside: Erlang in Haskell</title>
	<guid>http://erlanginside.com/?p=275</guid>
	<link>http://erlanginside.com/erlang-in-haskell-275</link>
	<description>Haskellers who want to experiment with the concepts of Erlang in Haskell can now do so with an experimental Erlang-like distributed computing framework called &amp;#8216;remote&amp;#8217;. It&amp;#8217;s quite basic but covers concurrency, selective receive of messages, local and global registration of processes, and trapping exits. Related Microsoft Research Paper.</description>
	<pubDate>Mon, 16 May 2011 03:49:18 +0000</pubDate>
</item>
<item>
	<title>Erlang Training and Consulting &lt;br/&gt;- News: 11 May 2011: Juan Puig has been invited to talk at The University of Coruña's Computer Science faculties 25th Anniversary celebrations!</title>
	<guid>http://www.erlang-solutions.com/news/1/entry/1240</guid>
	<link>http://www.erlang-solutions.com/news/1/entry/1240</link>
	<description>&lt;p&gt;The University of Coru&amp;ntilde;a's Computer Science faculty is turning 25 years, and in order to celebrate such an important event, this Thursday, 12th May 2011, talks, workshops and expositions will be run in Palexco, the main auditorium in A Coru&amp;ntilde;a. We here at Erlang Solutions are proud that Juan Puig has been invited to talk at this event as one of the graduates from The University of Coru&amp;ntilde;a. He will then give a more technical lecture on the Friday at the Computer Science department.&lt;/p&gt;
&lt;p&gt;Location: Palexco auditorium, A Coru&amp;ntilde;a, Spain&lt;br /&gt;Time: 12th May, 12:30h&lt;br /&gt;&lt;a href=&quot;http://www.fic.udc.es/files/25028/25028Programa_INF11.pdf&quot;&gt;Program&lt;/a&gt; (in Spanish)&lt;/p&gt;
&lt;p&gt;Juan's talk will be:&lt;br /&gt;Title: Building fault-tolerant systems.&lt;br /&gt;Summary: An introduction to the current software and fault-tolerant systems will be held, followed by how Erlang/OTP does provide with the right built-in features to build large and scalable fault-tolerant systems.&lt;br /&gt;&lt;br /&gt;Friday 13,&lt;br /&gt;Juan will be giving a lecture within the Computer Science faculty, more technical, within the slot of a Software Design course of the Computer Engineering degree.&lt;br /&gt;Location: Room 3.3, Faculty of Computer Science, University of A Coru&amp;ntilde;a, Spain&lt;br /&gt;Time: 13th May, 11:30h&lt;br /&gt;Title: &quot;Design of abstract models with Erlang&quot;&lt;br /&gt;Summary: Introduction to Erlang followed by a quick OTP and its behaviours showing how to design large applications. Second part of the talk will be oriented to property based-testing design.&lt;/p&gt;</description>
	<pubDate>Wed, 11 May 2011 17:32:43 +0000</pubDate>
</item>
<item>
	<title>Scattered Thoughts: mist</title>
	<guid>http://scattered-thoughts.net/one/1305/106859/184342</guid>
	<link>http://scattered-thoughts.net/one/1305/106859/184342</link>
	<description>&lt;p&gt;I have a new secret project. It's called Mist. The goal is to make it easy to build, use, distribute and maintain small-scale p2p apps. By small-scale I mean apps where each invocation has at most a few dozen users. You would use Mist to build the next etherpad, not the next bittorrent.
&lt;/p&gt;
&lt;p&gt;The main inspiration behind Mist is &lt;a href=&quot;http://one.laptop.org/about/software&quot;&gt;Sugar&lt;/a&gt;. Sugar supports seamless sharing of activities (applications) across local mesh networks or the internet, even if some of the peers don't even have the activity installed. Where Sugar is focused on providing a working system here and now, I am more interested in how distributed programming can be made easier in the future. I also want to build applications that I can use myself so my initial target is Ubuntu/Gnome.
&lt;/p&gt;
&lt;p&gt;Starting from September, I'm going to be doing just enough freelance work to support full time work on Mist. I'm aware that this is a huge project and probably doomed to failure so there a few key principles that I hope will keep me on track. Wherever possible I will reuse existing code and protocols. Mist will be built out of small components each of which are useful by themselves. Where practical Mist will be compatible with Sugar, so that any improvements can be folded back into the Sugar codebase. Finally, Mist is a prototype. The goal will be to get something up and running to experiment with different ways of building distributed apps.
&lt;/p&gt;
&lt;p&gt;So without further ado here is a misty outline of what Mist might one day look like:
&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Seamless connectivity, serverless presence and activity discovery
    &lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;Mostly borrowed from Sugar
        &lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Apps communicate over &lt;a href=&quot;http://telepathy.freedesktop.org/wiki/&quot;&gt;Telepathy&lt;/a&gt; tubes
        &lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Use Sugar &lt;a href=&quot;http://wiki.laptop.org/go/Presence_Service&quot;&gt;presence service&lt;/a&gt; for activity discovery
        &lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;LAN / ad-hoc networks supported by &lt;a href=&quot;http://wiki.laptop.org/go/Telepathy_Salut&quot;&gt;Telepathy Salut&lt;/a&gt; and &lt;a href=&quot;http://en.wikipedia.org/wiki/Avahi&quot;&gt;Avahi&lt;/a&gt;
        &lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Centralized communication supported using &lt;a href=&quot;http://wiki.laptop.org/go/Telepathy_Gabble&quot;&gt;Telepathy Gabble&lt;/a&gt; to talk to Jabber servers
        &lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Decentralized communication supported using a Telepathy plugin for &lt;a href=&quot;https://github.com/jamii/erl-telehash&quot;&gt;erl-telehash&lt;/a&gt;
        &lt;/p&gt;
        &lt;ul&gt;
          &lt;li&gt;
            &lt;p&gt;Use telehash peers for &lt;a href=&quot;http://en.wikipedia.org/wiki/Interactive_Connectivity_Establishment&quot;&gt;ICE&lt;/a&gt;
            &lt;/p&gt;
          &lt;/li&gt;
          &lt;li&gt;
            &lt;p&gt;Use link-local XMMP to talk
            &lt;/p&gt;
          &lt;/li&gt;
          &lt;li&gt;
            &lt;p&gt;Use telehash taps to implement Avahi compatible mDNS
            &lt;/p&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Use pgp for authentication and end-to-end encryption
        &lt;/p&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Securely portable applications
    &lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;Use an existing system. Some options which will need to be researched:
        &lt;/p&gt;
        &lt;ul&gt;
          &lt;li&gt;
            &lt;p&gt;&lt;a href=&quot;http://wiki.laptop.org/go/Bitfrost&quot;&gt;Bitfrost&lt;/a&gt; is specific to the XO laptop and probably too hard to port
            &lt;/p&gt;
          &lt;/li&gt;
          &lt;li&gt;
            &lt;p&gt;Browsers provide well-tested sandboxes and mobile code but limit access to hardware. Perhaps ChromeOS or Firefox Chromeless?
            &lt;/p&gt;
          &lt;/li&gt;
          &lt;li&gt;
            &lt;p&gt;Java apps can possibly be installed securely. Looking at the Android source may be instructive.
            &lt;/p&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Development tools for distributed apps
    &lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;Want to experiment with &lt;a href=&quot;http://www.bloom-lang.net/&quot;&gt;Bloom&lt;/a&gt;. I have some ideas for static analysis of bloom programs that might be fun.
        &lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Expose libraries/APIs for common patterns eg leader election, operational transform
        &lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Support serverless syncing of contacts, bookmarks, mail etc using DHT with enforced reciprocal storage (pretty sure I've read a paper on this somewhere)
        &lt;/p&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The immediate plan for the next few months (during which I'm still working full time) is:
&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Get erl-telehash working (currently has no test suite and doesn't support taps, _ring/_line or rate limiting)
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Get ICE working between telehash peers
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Write a Telepathy backend using erl-telehash and link-local XMPP
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Extend Empathy to use the telehash Telepathy backend
    &lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you are wondering where Mist gets its name from - it's not the cloud.
&lt;/p&gt;</description>
	<pubDate>Wed, 11 May 2011 09:40:59 +0000</pubDate>
</item>
<item>
	<title>Trapexit's Erlang Blog Filter: Erlang Web Server Benchmarking</title>
	<guid>http://steve.vinoski.net/blog/?p=780</guid>
	<link>http://steve.vinoski.net/blog/2011/05/09/erlang-web-server-benchmarking/</link>
	<description>&lt;p&gt;Over on his blog, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.ostinelli.net/&quot;&gt;Roberto Ostinelli&lt;/a&gt; published &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.ostinelli.net/a-comparison-between-misultin-mochiweb-cowboy-nodejs-and-tornadoweb/&quot;&gt;&amp;#8220;A comparison between Misultin, Mochiweb, Cowboy, NodeJS and Tornadoweb.&amp;#8221;&lt;/a&gt; I was going to write a reply comment there, but it got pretty long so I decided to publish it here instead. I&amp;#8217;m going to ignore the non-Erlang web servers it discusses and focus entirely on Erlang. I&amp;#8217;m not trying to really pick specifically on Roberto here, but rather I decided to finally write something I&amp;#8217;ve been meaning to write for awhile now about Erlang web servers and benchmarking.&lt;/p&gt;
&lt;p&gt;First, I second the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.ostinelli.net/a-comparison-between-misultin-mochiweb-cowboy-nodejs-and-tornadoweb/#comment-32413&quot;&gt;request made by one commenter&lt;/a&gt; for including &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/klacke/yaws&quot;&gt;Yaws&lt;/a&gt; in the measurements. Roberto, if you need help with the code or setup, just let me know. If one insists on writing these kinds of benchmarks, which as you&amp;#8217;ll learn if you read this whole entry is something I question, the least he or she could do is include Yaws since it&amp;#8217;s the granddaddy of all Erlang web servers.&lt;/p&gt;
&lt;p&gt;Based on the benchmark code Roberto published, I wrote the following simple Yaws module to conform to the problem statement and registered it in my Yaws configuration as a &amp;#8220;/&amp;#8221; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://yaws.hyber.org/appmods.yaws&quot;&gt;appmod&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;
&lt;pre&gt;-module(yaws_bench).
-export([out/1]). out(Arg) -&amp;gt; [{status, 200}, {content, &quot;text/xml&quot;, case yaws_api:queryvar(Arg, &quot;value&quot;) of {ok, Value} -&amp;gt; [&quot;&amp;lt;http_test&amp;gt;&amp;lt;value&amp;gt;&quot;, Value, &quot;&amp;lt;/value&amp;gt;&amp;lt;/http_test&amp;gt;&quot;]; _ -&amp;gt; &quot;&amp;lt;http_test&amp;gt;&amp;lt;error&amp;gt;no value specified&amp;lt;/error&amp;gt;&amp;lt;/http_test&amp;gt;&quot; end}].&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;I then measured it on my Ubuntu 10.10 two-core system using Roberto&amp;#8217;s published &lt;code&gt;httperf&lt;/code&gt; command against the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/ostinelli/misultin&quot;&gt;misultin&lt;/a&gt; and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/mochi/mochiweb&quot;&gt;Mochiweb&lt;/a&gt; code he published, and found that Yaws definitely holds its own, even though it&amp;#8217;s a full-featured web server and does not claim to be just a lightweight library offering (sometimes partial) HTTP support as some frameworks do. For some tests Yaws outperforms misultin, and for others it doesn&amp;#8217;t. This is interesting, considering that neither Klacke nor I have made any attempts at performance improvements in Yaws recently.&lt;/p&gt;
&lt;p&gt;Second, the benchmarks do not compare apples to apples. Both Mochiweb and Yaws, for example, produce replies that are larger in size than misultin&amp;#8217;s replies, primarily because they both include &lt;code&gt;Server&lt;/code&gt; and &lt;code&gt;Date&lt;/code&gt; headers. As I&amp;#8217;ve learned from years of helping maintain Yaws, date calculations can noticeably and surprisingly impact Erlang web server performance, yet simply leaving &lt;code&gt;Date&lt;/code&gt; headers out isn&amp;#8217;t an option for real-world apps since HTTP 1.1 pretty much requires them (&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.2.3&quot;&gt;section 13.2.3&lt;/a&gt; of &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.w3.org/Protocols/rfc2616/rfc2616.html&quot;&gt;RFC 2616&lt;/a&gt; states, &lt;em&gt;&amp;#8220;HTTP/1.1 requires origin servers to send a Date header, if possible, with every response, giving the time at which the response was generated&amp;#8230;&amp;#8221;&lt;/em&gt;). Caches use &lt;code&gt;Date&lt;/code&gt; headers for several reasons, for example in the absence of cache-control headers to help heuristically calculate content expiration. Even ignoring the date calculation requirements, just creating and delivering larger replies due to the presence of the &lt;code&gt;Server&lt;/code&gt; header will negatively impact any comparisons based on request/second measurements.&lt;/p&gt;
&lt;p&gt;Third, the benchmarking approach includes no application &amp;#8220;think time.&amp;#8221; How many real-world apps just blast request after request down a connection without any intervening time to handle replies? If the goal is to measure something akin to real-world apps, then the benchmarks should at least be using something like httperf&amp;#8217;s &lt;code&gt;--wsess&lt;/code&gt; option to simulate client think time. And unfortunately doing that is hard to get right for generic benchmarks, since different client apps will have different think times.&lt;/p&gt;
&lt;p&gt;On a related note, what exactly &lt;em&gt;is&lt;/em&gt; the goal of these benchmarks? To imply that faster is better? That&amp;#8217;s unfortunately a commonly-held fallacy. Given that the blog entry states that the target is dynamic applications, then consider the fact that the performance of a real-world dynamic application is often dominated by something other than the web server &amp;mdash; perhaps some back-end service from which page data is being fetched, for example. A real-world setup greatly concerned with performance is likely to have &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://nginx.net/&quot;&gt;nginx&lt;/a&gt; out in front, probably with a local cache, to handle fast-path requests, shunting only those requests it can&amp;#8217;t fulfill off to the slower back-end server. Such benchmarking games are therefore often misguided as far as real-world dynamic apps are concerned because they end up measuring something that isn&amp;#8217;t even in the critical path in a real setup.&lt;/p&gt;
&lt;p&gt;I don&amp;#8217;t agree with &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.ostinelli.net/a-comparison-between-misultin-mochiweb-cowboy-nodejs-and-tornadoweb/#comment-32432&quot;&gt;Kyle Drake&amp;#8217;s comment&lt;/a&gt; on Roberto&amp;#8217;s blog about code ugliness, since the Erlang code posted there is very clear and would look like &amp;#8220;garbage&amp;#8221; only to someone who doesn&amp;#8217;t know the language. But I do agree with the sentiment, which is that for dynamic apps, what often matters is what kind of code, and how much, you have to write and maintain to support your app. Given that Erlang web servers tend to make use of the underlying Erlang/OTP facilities for &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://erlang.org/doc/man/erlang.html#decode_packet-3&quot;&gt;HTTP parsing&lt;/a&gt; and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://erlang.org/doc/man/gen_tcp.html&quot;&gt;socket handling&lt;/a&gt;, then all things considered you&amp;#8217;re just not going to get a huge variation in performance among them, assuming they&amp;#8217;re written halfway decently. What matters for dynamic apps are the stability of the web server/library and the programming model it offers. These are what Roberto should really be benchmarking, but of course that&amp;#8217;s basically impossible since stability would take a long time to prove, and programming model is a matter of taste that can&amp;#8217;t be conveniently measured using artificial benchmarking tools. This reminds me of one of my old columns on this very issue as applied to enterprise middleware, entitled &amp;#8220;&lt;a rel=&quot;nofollow&quot;&gt;The Performance Presumption&lt;/a&gt;&amp;#8221; (PDF); the short version is that people often measure performance simply because performance is relatively easy to measure. The lesson is that you shouldn&amp;#8217;t rely on generic benchmarks, but rather you should take the time to create specific benchmarks that mimic the app you want to develop, and base your decisions on the results of that exercise.&lt;/p&gt;
&lt;p&gt;On top of all that, I don&amp;#8217;t really understand the desire to keep writing new Erlang web frameworks for performance reasons. As I stated earlier, if a framework uses Erlang&amp;#8217;s built-in packet decoding and socket handling, it won&amp;#8217;t perform a great deal better than any other Erlang web framework. OTOH, if someone writes a new framework with the hope of providing a really nice new programming model &amp;mdash; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/basho/webmachine&quot;&gt;webmachine&lt;/a&gt; is a fantastic example of this &amp;mdash; then they shouldn&amp;#8217;t be &amp;#8220;proving&amp;#8221; how good the programming model is by trying to show how fast it is. Ever seen webmachine being advertised via performance benchmarks? Neither have I.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s face it, the Erlang web development community isn&amp;#8217;t large enough to support numerous web servers and frameworks. I&amp;#8217;m sure some will disagree, but publishing artificial benchmarks designed to &amp;#8220;prove&amp;#8221; which is best IMO results mostly in just fragmenting the community. If you really have an itch to write a fast Erlang web server, you&amp;#8217;d help the community much more by contributing to an existing one, including the Erlang &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://erlang.org/doc/man/inets.html&quot;&gt;inets&lt;/a&gt; web server included in Erlang/OTP and now powering &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://erlang.org/&quot;&gt;the Erlang website&lt;/a&gt;. For Yaws, Klacke and I often take patches and suggestions from our users, and we gladly welcome solid contributions intended to improve Yaws performance. If you&amp;#8217;re just dying to show off your chops, note that improving performance in a long-lived and highly stable codebase like Yaws without breaking anyone&amp;#8217;s code is far more challenging than writing another new server that basically doesn&amp;#8217;t differ much from what already exists.&lt;/p&gt;
&lt;p&gt;Or perhaps better yet, contribute to the Erlang core. IMO the next major performance improvements in Erlang web servers will come not from minor tweaks in handling binaries or such things, but rather via radical improvements in the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/erlang/otp/blob/dev/erts/emulator/drivers/common/inet_drv.c&quot;&gt;Erlang TCP driver&lt;/a&gt; or even from developing a whole new HTTP-specific driver. Unlike a war of artificial benchmarks among Erlang web servers, these approaches have a great chance to improve the lot of all Erlang web systems.&lt;/p&gt;</description>
	<pubDate>Tue, 10 May 2011 02:01:01 +0000</pubDate>
</item>
<item>
	<title>erlang.org RSS Feed: ACM SIGPLAN Erlang Workshop in Tokyo on September 23, 2011</title>
	<guid>http://www.erlang.org/news/17</guid>
	<link>http://www.erlang.org/news/17</link>
	<description>&lt;p&gt;&lt;p&gt;
	&lt;strong&gt;ACM SIGPLAN Erlang Workshop &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
	The Tenth ACM SIGPLAN Erlang Workshop will take place in Tokyo, Japan, on September 23, 2011. Please see the call for papers &lt;a href=&quot;http://www.erlang.org/workshop/2011/&quot;&gt;here&lt;/a&gt; .&lt;/p&gt;
&lt;/p&gt;</description>
	<pubDate>Fri, 06 May 2011 23:08:27 +0000</pubDate>
</item>
<item>
	<title>Erlang Factory News: Book your place at the Erlang Factory London Now and save £100!</title>
	<guid>http://www.erlang-factory.com/news/list#58</guid>
	<link>http://www.erlang-factory.com/news/list#58</link>
	<description>&lt;p&gt;&lt;a href=&quot;https://www.erlang-factory.com/conference/London2011/register&quot;&gt;Book&lt;/a&gt; your place now at the &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011&quot;&gt;Erlang Factory London 2011&lt;/a&gt; at the Early Bird Rate of &amp;pound;495 for the conference and &amp;pound;1295 for the &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/university&quot;&gt;University&lt;/a&gt; and conference. This is a saving of &amp;pound;100 off the standard price of the conference! This is only available for a limited time!&lt;/p&gt;
&lt;p&gt;Speakers so far include , &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/speakers/KostisSagonas&quot;&gt;Kostis Sagonas&lt;/a&gt;, the leader of the HIPE Team at Uppsala University, &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/speakers/MarkusKern&quot;&gt;Marcus Kern&lt;/a&gt;, CTO at MIG, &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/speakers/SteveVinoski&quot;&gt;Steve Vinosk&lt;/a&gt;i, distributed systems expert and &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/speakers/ScottLystigFritchie&quot;&gt;Scott Lystig Fritchie&lt;/a&gt;, senior software engineer at Basho Technologies. Many more speakers are still to be announced.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.erlang-factory.com/conference/London2011/register&quot;&gt;Book now to secure this fantastic rate!&lt;/a&gt;&lt;/p&gt;</description>
	<pubDate>Wed, 04 May 2011 10:31:39 +0000</pubDate>
</item>
<item>
	<title>Anders Conbere's Journal: Learning to Program is Easy</title>
	<guid>tag:anders.conbere.org,2011-05-03:1304473332.0</guid>
	<link>http://anders.conbere.org/blog/2011/05/03/learning_to_program_is_easy</link>
	<description>&lt;p&gt;Years ago I spent a summer teaching science classes to kids aged 6 to 12 at the Oregon Museum of Science and Industry. This program wasn't particularly well managed, mostly a disaster, but quite a bit of fun. The most fun I had was helping teach a class on game programming to 5th and 6th graders. The class used a pretty nice implementation of Logo called MicroWorlds which benefited from having a simple GUI and IDE for the kids to use. Maybe today we'd use something like &lt;a href=&quot;http://scratch.mit.edu/&quot;&gt;Scratch&lt;/a&gt; or &lt;a href=&quot;http://www.squeakland.org/&quot;&gt;EToys&lt;/a&gt;. Either way the class began with a simple introduction to making things happen in this virtual world, and some of the basics of the command structure. And within minutes there was a volley of hands that shot into the air each with it's very own bug.&lt;/p&gt;
&lt;p&gt;That might not sounds like much, but by the time you've engaged someone to the point that they've typed in some commands and arrived at an unexpected occurrence... you've basically got them hook line and sinker. So that day and some of the next was often spent detailing the use of variables, the intricacies of syntax, and what rules exist and why they make their life easier. By the end of the week we would have flies narrowly dodging venus fly traps, and robots that had to defeat monsters.&lt;/p&gt;
&lt;p&gt;I'm not saying every kid produced a work of genius, and some had more difficulties than others. But the nature of programming does not have to be a complex and difficult venture. Simply mapping input to a behavior gets you pretty far. This is a big part of the idea of Scheme. How do we build a language that is simple enough that our english majors can accomplish something in it, but powerful enough that our computer science students can develop complex ideas with it. The point is that most people can be taught to create at least rudimentary programs in just a few hours of tutorial.&lt;/p&gt;
&lt;p&gt;And this really brings me to the reason I'm writing this post. And that is, that while programming might be easy, making applications, architecting large projects, putting all the various pieces together in a way that gives you the flexibility to accomplish what you &lt;em&gt;might&lt;/em&gt; need to, but the structure to finishing what you &lt;em&gt;have&lt;/em&gt; to, is amazingly difficult. And two different skills. You can teach someone to use python like a calculator, and to write functions that help them manage their bills. But the ability to take that knowledge and expand upon it to write a personal finance applications is much more difficult to teach.&lt;/p&gt;
&lt;p&gt;Some of this is abstraction. Abstraction is difficult for humans, and I say this knowing that of all the creatures we've ever encountered we're likely the most capable abstractors in existence. But while that might be true, or brains are wired to work inside a rather constrained and physical world. There's a test that's often mentioned in literature where they ask the participants to accomplish a mathematical task using variable names, and then ask it again relating it to cards. In the first case most participants answer incorrectly, while in the next they do it with ease. The great difficult of mathematics as well as programming arrises from the depths of abstraction.&lt;/p&gt;
&lt;p&gt;Just like Mathematics might be the deep study one abstract layer after another, complex application design mirrors this. While in mathematics at the bottom might be something like Category Theory from which derives Algebra from which derive the infinity of number systems from which derive Real and Complex numbers from which derive Real Analysis and then the Calculuses and on down the chain. A Complex application might have a User Interface which abstracts a Programable Interface which calls down into a Data Layer that then talks to a Persistence Layer that talks to the Operating System on down to the bare metal. Most of the extremely competent application architects I know might be considered a software version of a &quot;tall, thin man&quot;. Someone who is familiar with all the ramifications of his design from the top layers to the cost at the bottom layers.&lt;/p&gt;
&lt;p&gt;What I'm trying to say is that Programming might be easy. But the understanding of both the ramifications of the current environment (what can be done with the current language and tools) and the cost of the various layers below it, is hard. And that teaching THAT is much more difficult task than teaching someone how to use a fancy calculator. Books like SICP attempt to accomplish this task by dealing with abstraction in it's own right, by merging programing and mathematics and enabling a kind of cross pollination there of. But even that can leave a student with little understanding of how to put all the pieces together. I write this because my focus since college has been into the art of programming. And I'm beginning to understand where the limitations of my studies have been, and where I'm headed. And my new goal of trying to find more people to look at my code and find new ways of expressing those problems.&lt;/p&gt;</description>
	<pubDate>Wed, 04 May 2011 01:42:12 +0000</pubDate>
</item>
<item>
	<title>Erlang Factory News: Only 5 Places left at the Erlang Factory London!</title>
	<guid>http://www.erlang-factory.com/news/list#57</guid>
	<link>http://www.erlang-factory.com/news/list#57</link>
	<description>&lt;p&gt;There are only 5 chances left to &lt;a href=&quot;https://www.erlang-factory.com/conference/London2011/register&quot;&gt;book&lt;/a&gt; your place at the &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011&quot;&gt;Erlang Factory London 2011&lt;/a&gt; at the Very Early Bird Rate of &amp;pound;395 for the conference and &amp;pound;1195 for the &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/university&quot;&gt;University&lt;/a&gt; and conference. This is a saving of &amp;pound;200 off the standard price of the conference!When they are gone, they are gone!&lt;/p&gt;
&lt;p&gt;Speakers so far include , &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/speakers/KostisSagonas&quot;&gt;Kostis Sagonas&lt;/a&gt;, the leader of the HIPE Team at Uppsala University, &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/speakers/MarkusKern&quot;&gt;Marcus Kern&lt;/a&gt;, CTO at MIG, &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/speakers/SteveVinoski&quot;&gt;Steve Vinosk&lt;/a&gt;i, distributed systems expert and &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/speakers/ScottLystigFritchie&quot;&gt;Scott Lystig Fritchie&lt;/a&gt;, senior software engineer at Basho Technologies. Many more speakers are still to be announced.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.erlang-factory.com/conference/London2011/register&quot;&gt;Book now to secure this fantastic rate!&lt;/a&gt;&lt;/p&gt;</description>
	<pubDate>Tue, 03 May 2011 15:02:00 +0000</pubDate>
</item>
<item>
	<title>erlang.org RSS Feed: The Erlang Factory London is back!</title>
	<guid>http://www.erlang.org/news/16</guid>
	<link>http://www.erlang.org/news/16</link>
	<description>&lt;p&gt;&lt;p&gt;
	The Erlang Factory London is back! The dates you need for your diary are 6th, 7th and 8th June for the Erlang University courses and 9th and 10th June for the Erlang Factory Conference.&lt;br /&gt;
	&lt;br /&gt;
	There are 10 places left at the very Early bird rate of &amp;pound;395 which is a saving of &amp;pound;200! &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011&quot;&gt;Book now&amp;nbsp;&lt;/a&gt; to get your place!&lt;br /&gt;
	&lt;br /&gt;
	&amp;nbsp;&lt;/p&gt;
&lt;/p&gt;</description>
	<pubDate>Tue, 03 May 2011 09:10:31 +0000</pubDate>
</item>
<item>
	<title>Programming in the 21st Century: Impressed by Slow Code</title>
	<guid>http://prog21.dadgum.com/98.html</guid>
	<link>http://prog21.dadgum.com/98.html</link>
	<description>At one time I was interested in--even enthralled by--low-level optimization.
&lt;br /&gt;&lt;br /&gt;Beautiful and clever tricks abound. Got a function call followed by a return statement? Replace the pair with a single jump instruction. Once you've realized that &quot;load effective address&quot; operations are actually doing math, then they can subsume short sequences of adds and shifts. On processors with fast &quot;count leading zero bits&quot; instructions, entire loops can be replaced with a couple of lines of linear code.
&lt;br /&gt;&lt;br /&gt;I spent a long time doing that before I realized it was a mechanical process.
&lt;br /&gt;&lt;br /&gt;I don't necessarily mean mechanical in the &quot;a good compiler can do the same thing&quot; sense, but that it's a raw engineering problem to take a function and make it faster. Take a simple routine that potentially loops through a lot of data, like a case insensitive string comparison. The first step is to get as many instructions out of the loop as possible. See if what remains can be rephrased using fewer or more efficient instructions. Can any of the calculations be replaced with a small table? Is there a way to process multiple elements at the same time using vector instructions?
&lt;br /&gt;&lt;br /&gt;The truth is that there's no magic in taking a well-understood, working function, analyzing it, and rewriting it in a way that involves doing slightly or even dramatically less work at run-time. If I ended up with a routine that was a bottleneck, I know I could take the time to make it faster. Or someone else could. Or if it was small enough I could post it to an assembly language programming forum and come back in a couple of days when the dust settled.
&lt;br /&gt;&lt;br /&gt;What's much more interesting is speeding up something complex, a program where all the time isn't going into a couple of obvious hotspots. 
&lt;br /&gt;&lt;br /&gt;All of a sudden, that view through the low-level magnifying glass is misleading. Yes, that's clearly an N-squared algorithm right there, but it may not matter at all. (It might only get called with with low values of N, for example.) This loop here contains many extraneous instructions, but that's hardly a big picture view. None of this helps with understanding the overall data flow, how much computation is really being done, and where the potential for simplification lies.
&lt;br /&gt;&lt;br /&gt;Working at that level, it makes sense to use a language that keeps you from thinking about exactly how your code maps to the underlying hardware. It can take a bit of faith to set aside deeply ingrained instincts about performance and concerns with low-level benchmarks, but I've seen Python programs that ended up faster than C. I've seen complex programs running under the Erlang virtual machine that are done executing before my finger is off the return key.
&lt;br /&gt;&lt;br /&gt;And that's what's impressive: code that is so easy to label as slow upon first glance, code containing functions that can--in isolation--be definitively proven to be dozens or hundreds of times slower than what's possible on a given CPU, and yet the overall program is decidedly one of high performance.
&lt;br /&gt;&lt;br /&gt;(If you liked this, you might enjoy &lt;a href=&quot;http://prog21.dadgum.com/35.html&quot;&gt;Timidity Does Not Convince&lt;/a&gt;.)</description>
	<pubDate>Sat, 30 Apr 2011 06:00:00 +0000</pubDate>
</item>
<item>
	<title>Learn You Some Erlang: Building an Application With OTP</title>
	<guid>http://learnyousomeerlang.com/building-applications-with-otp</guid>
	<link>http://learnyousomeerlang.com/building-applications-with-otp</link>
	<description>This chapter lets us make practical use of the OTP behaviours seen so far. We do this by writing a process pool application that will let us handle resources and tasks. We explore ideas behind process trees, onion layer theories for processes and general views of how OTP can be used to write software.</description>
	<pubDate>Fri, 29 Apr 2011 12:00:00 +0000</pubDate>
</item>
<item>
	<title>Erlang Training and Consulting &lt;br/&gt;- News: 20 April 2011: Registration is now open for the Erlang Factory London - Early Bird Rate Available</title>
	<guid>http://www.erlang-solutions.com/news/1/entry/1238</guid>
	<link>http://www.erlang-solutions.com/news/1/entry/1238</link>
	<description>&lt;p align=&quot;center&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.erlang-factory.com&quot;&gt;&lt;img title=&quot;Erlang Factory London&quot; src=&quot;http://erlang-factory.com//upload/item/43/LondonBanner2011.jpg&quot; alt=&quot;Erlang Factory&quot; width=&quot;554&quot; height=&quot;85&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p align=&quot;center&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The registration for the &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011&quot;&gt;Erlang Factory London 2011&lt;/a&gt; is now open! Register now and you will &lt;strong&gt;save &amp;pound;100&lt;/strong&gt; by taking advantage of the Early-Bird offer. So far each Erlang   Factory has been met with great interest so don't waste time. &lt;a href=&quot;https://www.erlang-factory.com/conference/London2011/register&quot;&gt;Register before it sells out!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011&quot;&gt;Erlang Factory London&lt;/a&gt; is the best place to exchange knowledge, experience and the vision for   the future of Erlang. We have great speakers who will share all that   with &lt;strong&gt;YOU.&lt;/strong&gt; This conference has become one of the best Erlang networking events in Europe.&lt;/p&gt;
&lt;p&gt;Among our first confirmed speakers for the Erlang Factory London are: &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/speakers/KostisSagonas&quot;&gt;Kostis Sagonas&lt;/a&gt;, the leader of the HIPE Team at Uppsala University, &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/speakers/MarkusKern&quot;&gt;Marcus Kern&lt;/a&gt;, CTO at MIG, &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/speakers/SteveVinoski&quot;&gt;Steve Vinosk&lt;/a&gt;i, distributed systems expert and &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/speakers/ScottLystigFritchie&quot;&gt;Scott Lystig Fritchie&lt;/a&gt;, senior software engineer at Basho Technologies with many more still to be announced.&lt;/p&gt;
&lt;p&gt;The list of speakers is available &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/speakers&quot;&gt;here&lt;/a&gt;, with many more to be announced.&lt;/p&gt;
&lt;p&gt;In addition to the conference, there will be a three day &lt;a href=&quot;http://www.erlang-factory.com/conference/London2010/university&quot;&gt;Erlang University&lt;/a&gt;, allowing you to learn Erlang from the experts. You can choose from the following courses: &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/university/ErlangExpress&quot;&gt;Erlang Express&lt;/a&gt;, &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/university/optexpress&quot;&gt;OTP Express&lt;/a&gt;, &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/university/ErlangandTestDrivenDevelopment&quot;&gt;Erlang and Test Driven Development&lt;/a&gt; or &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/university/QuickCheck&quot;&gt;Quick Check for Erlang Developers&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The Erlang University training courses will take place on &lt;strong&gt;the 6th, 7th and 8th June &lt;/strong&gt;and the &lt;strong&gt;Erlang Factory conference on&lt;/strong&gt; &lt;strong&gt;9th and 10th June. &lt;/strong&gt;Don't miss out - &lt;a href=&quot;https://www.erlang-factory.com/conference/London2011/register&quot;&gt;register now.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We will also be offering certification at Foundation and Intermediate   level. You can register for this when you book your place at the   Factory. Pricing for each exam is &amp;pound;195, or you can sit both for &amp;pound;345.   For more information on Certification please visit the &lt;a href=&quot;http://www.erlang-solutions.com/section/14/certification&quot;&gt;website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
	<pubDate>Wed, 20 Apr 2011 11:18:12 +0000</pubDate>
</item>
<item>
	<title>Erlang Factory News: Erlang Factory London Open for Registration - Save £200</title>
	<guid>http://www.erlang-factory.com/news/list#56</guid>
	<link>http://www.erlang-factory.com/news/list#56</link>
	<description>&lt;p&gt;Be one of the first 50 people to &lt;a href=&quot;https://www.erlang-factory.com/conference/London2011/register&quot;&gt;book&lt;/a&gt; your place at the &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011&quot;&gt;Erlang Factory London 2011&lt;/a&gt; at the Very Early Bird Rate of &amp;pound;395 for the conference and &amp;pound;1195 for the &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/university&quot;&gt;University&lt;/a&gt; and conference. This is a saving of &amp;pound;200 off the standard price of the conference!&lt;/p&gt;
&lt;p&gt;Speakers so far include , &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/speakers/KostisSagonas&quot;&gt;Kostis Sagonas&lt;/a&gt;, the leader of the HIPE Team at Uppsala University, &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/speakers/MarkusKern&quot;&gt;Marcus Kern&lt;/a&gt;, CTO at MIG, &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/speakers/SteveVinoski&quot;&gt;Steve Vinosk&lt;/a&gt;i, distributed systems expert and &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/speakers/ScottLystigFritchie&quot;&gt;Scott Lystig Fritchie&lt;/a&gt;, senior software engineer at Basho Technologies. Many more speakers are still to be announced.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.erlang-factory.com/conference/London2011/register&quot;&gt;Book now to secure this fantastic rate!&lt;/a&gt;&lt;/p&gt;</description>
	<pubDate>Wed, 20 Apr 2011 09:16:52 +0000</pubDate>
</item>
<item>
	<title>Programming in the 21st Century: Follow the Vibrancy</title>
	<guid>http://prog21.dadgum.com/97.html</guid>
	<link>http://prog21.dadgum.com/97.html</link>
	<description>Back in 1999 or 2000, I started reading a now-defunct Linux game news site. I thought the combination of enthusiastic people wanting to write video games and the excitement surrounding both Linux and open source would result in a vibrant, creative community.
&lt;br /&gt;&lt;br /&gt;Instead there were endless emulators and uninspired rewrites of stale old games.
&lt;br /&gt;&lt;br /&gt;I could theorize about why there was such a lack of spark, a lack of motivation to create anything distinctive and exciting. Perhaps most of the projects were intended to fulfill coding itches, not personal visions. I don't know. But I lost interest, and I stopped following that site
&lt;br /&gt;&lt;br /&gt;When I wanted to &lt;a href=&quot;http://prog21.dadgum.com/22.html&quot;&gt;modernize my programming skills&lt;/a&gt;, I took a long look at Lisp. It's a beautiful and powerful language, but I was put off by the community. It was a justifiably smug community, yes, but it was an empty smugness. Where were the people using this amazing technology to build impressive applications? Why was everyone so touchy and defensive? That doesn't directly point at the language being flawed--not by any means--but it seemed an indication that &lt;i&gt;something&lt;/i&gt; wasn't right, that maybe there was a reason that people driven to push boundaries and create new experiences weren't drawn to the tremendous purported advantages of Lisp. So I moved on.
&lt;br /&gt;&lt;br /&gt;Vibrancy is an indicator of worthwhile technology. If people are excited, if there's a community of developers more concerned with building things than advocating or justifying, then that's a good place to be. &quot;Worthwhile&quot; may not mean the best or fastest, but I'll take enthusiasm and creativity over either of those.
&lt;br /&gt;&lt;br /&gt;(If you liked this, you might enjoy &lt;a href=&quot;http://prog21.dadgum.com/46.html&quot;&gt;The Pure Tech Side is the Dark Side&lt;/a&gt;.)</description>
	<pubDate>Wed, 20 Apr 2011 06:00:00 +0000</pubDate>
</item>
<item>
	<title>Scattered Thoughts: telehash: router</title>
	<guid>http://scattered-thoughts.net/one/1303/237475/636804</guid>
	<link>http://scattered-thoughts.net/one/1303/237475/636804</link>
	<description>&lt;p&gt;Now that we have all the necessary datastructures we can build the router itself. Most of the routing table logic is handled by the bit_tree and bucket modules. The router just ties these together and handles I/O.
&lt;/p&gt;
&lt;p&gt;Before actually running the routing table the router has to find out its own address, as it is seen from the outside world. It does this by sending +end signals to a list of known telehash nodes (eg telehash.org:42424).
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;record(bootstrap, { % the state of the router when bootstrapping
          timeout, % give up if no address received before this time
          addresses % list of addresses contacted to find out our address
         }).

bootstrap(Addresses, Timeout) -&amp;gt;
    ?INFO([bootstrapping]),
    State = #bootstrap{timeout=Timeout, addresses=Addresses},
    {ok, _Pid} = gen_server:start_link(?MODULE, State, []).
                          
init(State) -&amp;gt;
    switch:listen(),
    case State of
        #bootstrap{timeout=Timeout, addresses=Addresses} -&amp;gt;
            Telex = telex:end_signal(util:random_end()),
            lists:foreach(fun (Address) -&amp;gt; switch:send(Address, Telex) end, Addresses),
            erlang:send_after(Timeout, self(), giveup);
        #state{} -&amp;gt;
            ok
    end,
    {ok, State}.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we listen until we either get a reply with a _to field or run out of time.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;handle_info({switch, {recv, From, Telex}}, #bootstrap{addresses=Addresses}=Bootstrap) -&amp;gt;
    % bootstrapping, waiting to receive a message telling us our own address
    case {lists:member(From, Addresses), telex:get(Telex, '_to')} of
        {true, {ok, Binary}} -&amp;gt;
            try util:to_end(util:binary_to_address(Binary)) of
                End -&amp;gt;
                    Self = util:to_bits(End),
                    Table = touched(From, Self, empty_table(Self)),
                    dialer:dial(End, [From], ?ROUTER_DIAL_TIMEOUT),
                    refresh(Self, Table),
                    ?INFO([bootstrap, finished, {self, Binary}, {from, From}]),
                    {noreply, #state{self=Self, pinged=sets:new(), table=Table}}
            catch
                _ -&amp;gt;
                    ?WARN([bootstrap, bad_self, {self, Binary}, {from, From}]),
                    {noreply, Bootstrap}
            end;
        _ -&amp;gt;
            {noreply, Bootstrap}
    end;

handle_info(giveup, #bootstrap{}=Bootstrap) -&amp;gt;
    % failed to bootstrap, die
    ?INFO([giveup, {state, Bootstrap}]),
    {stop, {shutdown, gaveup}, Bootstrap};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once we know our own address we can fill in the state record and start managing the routing table.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;-record(state, { % the state of the router in normal operation
          self, % the bits of the routers own end
          pinged, % set of addresses which have been pinged and not yet replied/timedout
          table % the routing table, a bit_tree containing buckets of nodes
         }).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One of the jobs of the router is to remove unresponsive nodes from the routing table. To check if a node is responsive we just a random +end signal and wait for a reply. If the node is unresponsive it gets marked as stale and we try to find a suitable replacement. The node won't actually be dropped from the table until a replacement is found - this prevents the table from getting flushed if our network connection goes down.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ping(To) -&amp;gt;
    Telex = telex:end_signal(util:random_end()),
    % do this in a message to self to avoid some awkward control flow
    self() ! {pinging, To},
    switch:send(To, Telex),
    erlang:send_after(?ROUTER_PING_TIMEOUT, self(), {timeout, Address}).

timedout(Address, Self, Table) -&amp;gt;
    bit_tree:update(
      fun (_Suffix, _Depth, _Gap, Bucket) -&amp;gt;
              case bucket:timedout(Address, Bucket) of
                  {node, Node, Update} -&amp;gt;
                      % try to touch this node, might be suitable replacement
                      ping(Node),
                      Update;
                  Update -&amp;gt;
                      Update
              end
      end,
      util:to_bits(Address),
      Self,
      Table
     ).

handle_info({pinging, Address}, #state{pinged=Pinged}=State) -&amp;gt;
    % do this in a message to self to avoid some awkward control flow
    ?INFO([recording_ping, {address, Address}]),
    Pinged2 = sets:add_element(Address, Pinged),
    {noreply, State#state{pinged=Pinged2}};
handle_info({timeout, Address}, #state{self=Self, pinged=Pinged, table=Table}=State) -&amp;gt;
    case lists:member(Address, Pinged) of
        true -&amp;gt;
            % ping timedout
            ?INFO([timeout, {address, Address}]),
            Table2 = timedout(Address, Self, Table),
            {ok, State#state{table=Table2}};
        false -&amp;gt;
            % address already replied
            {ok, State}
    end;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One of the rules of the router is that it should never pass on information about a node that it hasn't personally confirmed to exist. Once we receive a message from a node we know that it exists (later we will implement _ring/_line to protect against address spoofing):
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;touched(Address, Self, Table) -&amp;gt;
    bit_tree:update(
      fun (Suffix, _Depth, Gap, Bucket) -&amp;gt;
              May_split = (Gap &amp;lt; ?K), % !!! or (Depth &amp;lt; ?ROUTER_TABLE_EXPANSION)
              bucket:touched(Address, Suffix, now(), Bucket, May_split)
      end,
      util:to_bits(Address),
      Self,
      Table
     ).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On receiving a .see command we record all the contained addresses as potential nodes and ping them to try to confirm their existence.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;seen(Address, Self, Table) -&amp;gt;
    bit_tree:update(
      fun (Suffix, _Depth, _Gap, Bucket) -&amp;gt;
              case bucket:seen(Address, Suffix, now(), Bucket) of
                  {node, Node, Update} -&amp;gt;
                      % check if this node is stale
                      ping(Node),
                      Update;
                  Update -&amp;gt;
                      Update
              end
      end,
      util:to_bits(Address),
      Self,
      Table
     ).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On receiving a +end signal we reply with a .see command containing the nearest K addresses which we have confirmed to exist.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;see(To, End, Table) -&amp;gt;
    Telex = telex:see_command(nearest(?K, End, Table)),
    switch:send(To, Telex).

nearest(N, End, Table) when N&amp;gt;=0 -&amp;gt;
    Bits = util:to_bits(End),
    iter:take(
      N,
      iter:flatten(
        iter:map(
          fun ({_Prefix, Bucket}) -&amp;gt; bucket:by_dist(End, Bucket) end,
          bit_tree:iter(Bits, Table)))).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On receiving a message we have handle the above three cases, which gets a little ugly.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;handle_info({switch, {recv, From, Telex}}, #state{self=Self, pinged=Pinged, table=Table}=State) -&amp;gt;
    % this counts as a reply
    Pinged2 = sets:del_element(From, Pinged),
    % touched the sender
    % !!! eventually will check _line here
    ?INFO([touched, {node, From}]),
    Table2 = touched(From, Self, Table),
    % maybe seen some nodes
    Table3 =
        case telex:get(Telex, '.see') of
            {ok, Binaries} -&amp;gt;
                try [util:binary_to_address(Bin) || Bin &amp;lt;- Binaries] of
                    Addresses -&amp;gt;
                        ?INFO([seen, {nodes, Addresses}, {from, From}]),
                        lists:foldl(fun (Address, Table_acc) -&amp;gt; seen(Address, Self, Table_acc) end, Table2, Addresses)
                catch
                    _ -&amp;gt;
                        ?INFO([bad_seen, {nodes, Binaries}, {from, From}]),
                        Table2
                end;
            _ -&amp;gt;
                Table2
        end,
    % maybe send some nodes back
    case telex:get(Telex, '+end') of
        {ok, Hex} -&amp;gt;
            try util:hex_to_end(Hex) of
                End -&amp;gt;
                    ?INFO([see, {'end', End}, {from, From}]),
                    see(From, End, Table3)
            catch
                _ -&amp;gt;
                    ?WARN([bad_see, {'end', Hex}, {from, From}])
            end;
        _ -&amp;gt;
            ok
    end,
    {noreply, State#state{pinged=Pinged2, table=Table2}};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The last responsibility of the router is to periodically refresh buckets which haven't recently seen any activity.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;handle_info(refresh, #state{self=Self, table=Table}=State) -&amp;gt;
    ?INFO([refreshing_table]),
    refresh(Self, Table),
    {noreply, State};
handle_info({dialed, _, _}, State) -&amp;gt;
    % response from a bucket refresh, we don't care
    {noreply, State};

dialed(Address, Self, Table) -&amp;gt;
    bit_tree:update(
      fun (_Suffix, _Depth, _Gap, Bucket) -&amp;gt;
              bucket:dialed(now(), Bucket)
      end,
      util:to_bits(Address),
      Self,
      Table
     ).

needs_refresh(Bucket, Now) -&amp;gt;
    case bucket:last_dialed(Bucket) of
        never -&amp;gt;
            true;
        Last -&amp;gt;
            (timer:now_diff(Now, Last) div 1000) &amp;lt; ?ROUTER_REFRESH_TIME
    end.

refresh(Self, Table) -&amp;gt;
    Now = now(),
    iter:foreach(
      fun ({Prefix, Bucket}) -&amp;gt;
              case needs_refresh(Bucket, Now) of
                  true -&amp;gt;
                      ?INFO([refreshing_bucket, {prefix, Prefix}, {bucket, Bucket}]),
                      To = util:random_end(Prefix),
                      From = nearest(?K, To, Table),
                      dialer:dial(To, From, ?ROUTER_DIAL_TIMEOUT);
                  false -&amp;gt;
                      ok
              end
      end,
      bit_tree:iter(Self, Table)
     ),
    erlang:send_after(?ROUTER_REFRESH_TIME, self(), refresh),
    ok.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That's it. As usual the (untested) code is in the &lt;a href=&quot;https://github.com/jamii/erl-telehash&quot;&gt;repo&lt;/a&gt;. The next post will probably deal with taps.
&lt;/p&gt;</description>
	<pubDate>Tue, 19 Apr 2011 18:24:35 +0000</pubDate>
</item>
<item>
	<title>Scattered Thoughts: telehash: gen_event woes</title>
	<guid>http://scattered-thoughts.net/one/1303/234437/654230</guid>
	<link>http://scattered-thoughts.net/one/1303/234437/654230</link>
	<description>&lt;p&gt;I ran into some tricky bugs caused by a misconception I had about gen_event. Since this is not explicitly stated in the gen_event documentation I will say it here: gen_event does NOT spawn individual processes for each handler. Each handler is run sequentially in the event manager process.
&lt;/p&gt;
&lt;p&gt;Now obviously the documentation is not at fault here. I assumed that each handler got its own process solely because the callbacks resembled gen_server. However, a little googling reveals that several other people made the same mistake so I thought it was worth mentioning.
&lt;/p&gt;
&lt;p&gt;Here is how I found this out. I was working on the router implementation for telehash. When I tested the bootstrapping algorithm everything looked fine until the first dial, after which nothing else happened. Straight away I suspected a bug in the dialer, but repeating the exact same call in the console worked fine. After a few deadends I opened pman to look for anything suspicious but couldn't find the dialer process (because it doesn't exist, it's an event handler). I assumed that it was somehow crashing silently and wasted an hour or so reading and rereading the code and stepping through various calls in the debugger. No matter what I tried the dialer worked absolutely perfectly unless it was called by the router.
&lt;/p&gt;
&lt;p&gt;Eventually I noticed that the switch_event process was blocking inside a receive and the whole thing unravelled. The dialer is an event handler so when started it calls:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;gen_event:add_handler(switch_event, dialer, State)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which is a synchronous call to the switch_event process. The router event handler is running inside the switch_event process so when the router tries to dial it deadlocks.
&lt;/p&gt;
&lt;p&gt;The moral of this story is &lt;b&gt;RTFM&lt;/b&gt;.
&lt;/p&gt;
&lt;p&gt;This is easily fixed by changing
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;dialer:dial(End, [Address])
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;spawn(fun () -&amp;gt; dialer:dial(End, [Address]) end)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but there were more problems. Most of the event handlers used erlang:send_after to handle timeouts but since they all run in the same process they all receive each others timeouts. Also, every event handler is run sequentially so the switch_event process becomes a huge bottleneck.
&lt;/p&gt;
&lt;p&gt;The solution I settled on was to change each event handler into a gen_server and write a simple event handler that just forwards events to its owner. By using gen_event:add_sup_handler and listening for event handler exits we can keep the two in sync.
&lt;/p&gt;</description>
	<pubDate>Tue, 19 Apr 2011 17:33:57 +0000</pubDate>
</item>
<item>
	<title>Erlang Factory News: Erlang Factory SF Bay Area 2011 - A Great Success</title>
	<guid>http://www.erlang-factory.com/news/list#55</guid>
	<link>http://www.erlang-factory.com/news/list#55</link>
	<description>&lt;p&gt;On the 24th - 25th March 2011, over 170 people gathered in the SF Bay Area for the 3rd Erlang Factory. With two Keynotes this year delivered by, Kostis Sagonas and Dan Ingalls, 10 extra talks compared to last year and a record-breaking number of delegates, this year's conference was nothing short of a tremendous success. &lt;br /&gt;&lt;br /&gt;We would like to thank everyone that attended and keep your eyes out for the videos that will be released soon!&lt;/p&gt;</description>
	<pubDate>Tue, 19 Apr 2011 14:01:55 +0000</pubDate>
</item>
<item>
	<title>Erlang Factory News: Only 5 Places left at the Erlang Factory SF Bay Area!</title>
	<guid>http://www.erlang-factory.com/news/list#54</guid>
	<link>http://www.erlang-factory.com/news/list#54</link>
	<description>&lt;p&gt;We only have 5 places left at the Erlang Factory SF Bay Area so if you haven't booked yet, don't miss out and &lt;a href=&quot;https://www.erlang-factory.com/conference/SFBay2011/register&quot;&gt;book now!&lt;/a&gt; The OTP Express course has now sold out but there are a few places left on the other courses at the &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/university&quot;&gt;University&lt;/a&gt;.&lt;/p&gt;</description>
	<pubDate>Tue, 19 Apr 2011 14:01:55 +0000</pubDate>
</item>
<item>
	<title>Erlang Factory News: Erlang Factory London 2011 - Talk Submission Open!</title>
	<guid>http://www.erlang-factory.com/news/list#53</guid>
	<link>http://www.erlang-factory.com/news/list#53</link>
	<description>&lt;p&gt;Do you have  something you want to share with the programming world? A  great  project, something new or innovative then we want to hear from  you. If  you want to give a presentation at the Erlang Factory, you can  find  more information how to do that, &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/submit_talk&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The submission deadline is the 11th April 2011.&lt;/p&gt;</description>
	<pubDate>Tue, 19 Apr 2011 14:01:55 +0000</pubDate>
</item>
<item>
	<title>Erlang Factory News: Early Bird Rate - 1 Week left to save over $200!</title>
	<guid>http://www.erlang-factory.com/news/list#52</guid>
	<link>http://www.erlang-factory.com/news/list#52</link>
	<description>&lt;div&gt;There is only 1 week left to book your place at the Early Bird Rate of $690 so don't miss out!&lt;br /&gt;
&lt;p&gt;You will get the chance to, see some &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers&quot;&gt;fantastic names&lt;/a&gt; from the Erlang world including, Joe Armstrong, Kostis Sagonas, Damien   Katz, and Dan Ingalls, network with your fellow programmers and find  out  what&amp;rsquo;s new not only in the world of Erlang but in the world of   programming.&lt;/p&gt;
&lt;p&gt;Register now to receive the Early Bird Rate and save over $200!&lt;/p&gt;
&lt;/div&gt;</description>
	<pubDate>Tue, 19 Apr 2011 14:01:55 +0000</pubDate>
</item>
<item>
	<title>Erlang Factory News: Erlang Factory SF Bay Area - Save over $200</title>
	<guid>http://www.erlang-factory.com/news/list#51</guid>
	<link>http://www.erlang-factory.com/news/list#51</link>
	<description>&lt;div&gt;We are offering a fantastic saving of over $200 when you register for the conference before the 1st of March 2011.
&lt;p&gt;You will get the chance to, see some &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers&quot;&gt;fantastic names&lt;/a&gt; from the Erlang world including, Joe Armstrong, Kostis Sagonas, Damien  Katz, and Dan Ingalls, network with your fellow programmers and find out  what&amp;rsquo;s new not only in the world of Erlang but in the world of  programming.&lt;/p&gt;
&lt;p&gt;Register now to receive the Early Bird Rate and save over $200!&lt;/p&gt;
&lt;/div&gt;</description>
	<pubDate>Tue, 19 Apr 2011 14:01:55 +0000</pubDate>
</item>
<item>
	<title>Programming in the 21st Century: Revisiting &quot;Tricky When You Least Expect It&quot;</title>
	<guid>http://prog21.dadgum.com/96.html</guid>
	<link>http://prog21.dadgum.com/96.html</link>
	<description>Since writing &lt;a href=&quot;http://prog21.dadgum.com/71.html&quot;&gt;Tricky When You Least Expect It&lt;/a&gt; in June 2010, I've gotten a number of responses offering better solutions to the &lt;tt&gt;angle_diff&lt;/tt&gt; problem. The final version I presented in the original article was this:
&lt;pre&gt;angle_diff(Begin, End) -&amp;gt;
   D = End - Begin,
   DA = abs(D),
   case {DA &amp;gt; 180, D &amp;gt; 0} of
      {true, true} -&amp;gt; DA - 360;
      {true, _}    -&amp;gt; 360 - DA;
      _ -&amp;gt; D
   end.
&lt;/pre&gt;But, maybe surprisingly, this function can be written in two lines:
&lt;pre&gt;angle_diff(Begin, End) -&amp;gt;
   (End - Begin + 540) rem 360 - 180.
&lt;/pre&gt;The key is to shift the difference into the range -180 to 180 before the modulo operation. The &quot;- 180&quot; at the end adjusts it back. One quirk of Erlang is that the modulo operator (rem) gives a negative result if the first value is negative. That's easily fixed by adding 360 to the difference (180 + 360 = 540) to ensure that it's always positive. (Remember that adding 360 to an angle gives the same angle.)
&lt;br /&gt;&lt;br /&gt;So how did I miss this simpler solution? I got off track by by thinking I needed an absolute value, and things went downhill from there. I'd like to think if I could rewind and re-attempt the problem from scratch, then I'd see the error of my ways, but I suspect I'd miss it the second time, too. And that's what I was getting at when I wrote &quot;Tricky When You Least Expect It&quot;: that you never know when it will take some real thought to solve a seemingly simple problem.
&lt;br /&gt;&lt;br /&gt;(Thanks to Samuel Tardieu, Benjamin Newman, and Greg Rosenblatt, who all sent almost identical solutions.)</description>
	<pubDate>Fri, 15 Apr 2011 06:00:00 +0000</pubDate>
</item>
<item>
	<title>Erlang Training and Consulting &lt;br/&gt;- News: 13 April 2011: Ulf Wiger and Robert Virding to be on the judging panel at Spawnfest  - 9 - 10 July 2011</title>
	<guid>http://www.erlang-solutions.com/news/1/entry/1236</guid>
	<link>http://www.erlang-solutions.com/news/1/entry/1236</link>
	<description>&lt;p&gt;We are happy to announce that our CTO, Ulf Wiger and Robert Virding will be on the panel of judges at this years Spawnfest. Spawnfest is an annual &lt;em&gt;48 hour development competition&lt;/em&gt; in which teams of skilled application developers get exactly one weekend to develop the best &lt;a href=&quot;http://erlang.org/&quot;&gt;Erlang&lt;/a&gt; applications that they can. First contest is scheduled for July 9th and 10th. Please follow &lt;a href=&quot;http://twitter.com/spawnfest&quot;&gt;them on twitter&lt;/a&gt; to stay updated.&lt;/p&gt;
&lt;p&gt;The judging panel also includes Bob Ippolito, Co-Founder/CTO of &lt;a href=&quot;http://www.mochimedia.com/&quot;&gt;Mochi Media&lt;/a&gt;, Inc.&lt;/p&gt;
&lt;p&gt;For more information on the event please see our &lt;a href=&quot;http://www.erlang-solutions.com/events/2/entry/1234&quot;&gt;events page&lt;/a&gt;.&lt;/p&gt;</description>
	<pubDate>Wed, 13 Apr 2011 15:02:44 +0000</pubDate>
</item>
<item>
	<title>Erlang Inside: Memory Models in Erlang vs Java</title>
	<guid>http://erlanginside.com/?p=272</guid>
	<link>http://erlanginside.com/erlang-vs-java-memory-model-272</link>
	<description>A view of Erlang (focused on the memory model) from a &amp;#8220;Java Code Geek&amp;#8221; &amp;#8211; http://www.javacodegeeks.com/2011/04/erlang-vs-java-memory-architecture.html</description>
	<pubDate>Wed, 13 Apr 2011 11:58:36 +0000</pubDate>
</item>
<item>
	<title>Programming in the 21st Century: Caught-Up with 20 Years of UI Criticism</title>
	<guid>http://prog21.dadgum.com/95.html</guid>
	<link>http://prog21.dadgum.com/95.html</link>
	<description>Interaction designers have leveled some harsh criticisms at the GUI status-quo over the last 20+ years. The mouse is an inefficient input device. The desktop metaphor is awkward and misguided. Users shouldn't be exposed to low-level details like the raw file-system and having to save their work.
&lt;br /&gt;&lt;br /&gt;And they were right.
&lt;br /&gt;&lt;br /&gt;But instead of better human/computer interaction, we got faster processors and hotter processors and multiple processors and entire processors devoted to 3D graphics. None of which are bad, mind you, but it was always odd to see such tremendous advances in hardware while the researchers promoting more pleasant user experiences wrote books that were eagerly read by people who enjoyed smirking at the wrong-headedness of an entire industry--yet who weren't motivated enough to do anything about it. Or so it seemed.
&lt;br /&gt;&lt;br /&gt;It's miraculous that in 2011, the biggest selling computers are mouse-free, run programs that take over the entire screen without the noise of a faux-desktop, and the entire concept of &quot;saving&quot; has been rendered obsolete.
&lt;br /&gt;&lt;br /&gt;Clearly, someone listened.
&lt;br /&gt;&lt;br /&gt;(If you liked this, you might enjoy &lt;a href=&quot;http://prog21.dadgum.com/74.html&quot;&gt;Free Your Technical Aesthetic from the 1970s&lt;/a&gt;.)</description>
	<pubDate>Mon, 11 Apr 2011 06:00:00 +0000</pubDate>
</item>
<item>
	<title>Functional Jobs: Programmer - Lisp and other languages at Streamtech bv (Full-time)</title>
	<guid>urn:uuid:2470eb22-dac5-5688-2f80-7c417e3a39e8</guid>
	<link>http://functionaljobs.com/jobs/68/programmer-lisp-and-other-languages-at-streamtech-bv</link>
	<description>&lt;p&gt;&lt;em&gt;Streamtech is a small Dutch company specialized in the development of high quality custom (web) applications.
We are looking for programmers who like to write pragmatic but elegant code.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;who we&amp;#039;re looking for&lt;/h3&gt;

&lt;p&gt;Elegant code makes you happy.&lt;/p&gt;

&lt;p&gt;To you, programming is not just a job but a hobby. You&amp;#039;ve been programming for fun for years.&lt;/p&gt;

&lt;p&gt;You&amp;#039;re not blind to practical demands, but you relish doing things the right way. When something seems to work but you&amp;#039;re not sure how or why, you bang your head against it until you understand.&lt;/p&gt;

&lt;p&gt;You like the net.&lt;/p&gt;

&lt;p&gt;You love exploring interesting new languages, concepts and approaches.&lt;/p&gt;

&lt;p&gt;Having played with Lisp, Haskell, Erlang, Prolog, Smalltalk, or other non-mainstream languages gets you bonus points.
The same goes for language/compiler implementation, kernel hacking, cryptography, etc. Impress us with your need to learn cool stuff.&lt;/p&gt;

&lt;p&gt;Because of the unfortunately strict immigration laws, already having permission to work in the Netherlands is also a plus.&lt;/p&gt;

&lt;h3&gt;the job&lt;/h3&gt;

&lt;p&gt;You&amp;#039;ll be working on the development of our diverse web based projects &amp;ndash; in streaming video, lawful interception, narrowcasting, and many other topics &amp;ndash; together with the rest of the programming team, from our office in The Hague.&lt;/p&gt;

&lt;p&gt;Together with the rest of the team, you&amp;#039;ll make applications that are technically elegant and pleasant to work with, using whatever language and technologies suit the project best.&lt;/p&gt;

&lt;p&gt;You will be involved in projects from A to Z &amp;ndash; including finding out what exactly the customer needs, choosing the best approach for the job, and then making it so.&lt;/p&gt;

&lt;h3&gt;what we use&lt;/h3&gt;

&lt;p&gt;In a perfect world, we&amp;#039;d be Lisping all day long. In the real world, the needs of our clients don&amp;#039;t always allow this, so there&amp;#039;s also quite a lot of Python, and even some C and PHP.&lt;/p&gt;

&lt;p&gt;We don&amp;#039;t expect you to have experience with all the languages we use, but we do expect you to be able to learn new things and enjoy doing it.&lt;/p&gt;

&lt;h3&gt;what we offer&lt;/h3&gt;

&lt;p&gt;A challenging, fun job in a small but professional team that does not think Java, MVC and SOAP are the answer to every question.&lt;/p&gt;</description>
	<pubDate>Sun, 10 Apr 2011 20:42:51 +0000</pubDate>
</item>
<item>
	<title>REALITY.SYS: Adlige Posse</title>
	<guid>http://www.brakmic.de/?p=450</guid>
	<link>http://www.brakmic.de/index.php/2011/04/10/adlige-posse/</link>
	<description>&lt;p&gt;&lt;a href=&quot;http://www.spiegel.de/flash/flash-25408.html&quot; target=&quot;_blank&quot;&gt;Eigentlich ist Guttenberg ist Sachen Öffentlichkeit sehr konsequent&lt;/a&gt;: immer wenn es darum ging, sich in Pose zu setzen, waren die Kameras willkommen (selbst eine Talk-Show aus Afghanistan durfte sich das &lt;em&gt;gemeine Volk&lt;/em&gt; antun). Später aber, als es darum ging, für eigene Fehler gerade zu stehen, wurde zensiert was das Zeug hält. Zuerst versuchte er, vor &amp;#8220;ausgewählten&amp;#8221; Presse-Vertretern seine erste Stellungnahme zu den Plagiatsvorwürfen zu geben, während zur gleichen Zeit eine Bundespresse-Konferenz abgehalten wurde. Danach verbot er die Live-Übertragung seines Rücktritts aus dem Bundesverteidigungsministerium, so dass das &lt;em&gt;gemeine Volk&lt;/em&gt; nur durch das zwischengeschaltete Handy einer NTV-Reporterin die &amp;#8220;live Stimme&amp;#8221; des ehemaligen Dr./Ministers hören konnte. Und jetzt erleben wir einen &lt;a href=&quot;http://www.spiegel.de/politik/deutschland/0,1518,756126,00.html&quot; target=&quot;_blank&quot;&gt;weiteren Zensurversuch&lt;/a&gt;. &lt;em&gt;Typisch adliges&lt;/em&gt; aber sicherlich nicht &amp;#8220;edles&amp;#8221; Verhalten: immer schöne Posen halten, aber kaum Leistung erbringen. Dass solche &amp;#8220;erlauchten&amp;#8221; Kreise wenig von&lt;a href=&quot;http://de.guttenplag.wikia.com/wiki/GuttenPlag_Wiki&quot; target=&quot;_blank&quot;&gt; Fleißarbeit, Mühsal und Ehrlichkeit&lt;/a&gt; halten, dasselbe aber ihren Wählern einbläuen, muss hier nicht ausführlich erörtert werden. ABER: so hat es vielleicht in den Jahrhunderten zuvor funktioniert. In dieser Zeit, und das hat mittlerweile auch ein Herr KTG begriffen, reicht eine bloße Pose nicht mehr aus, um die Massen zu begeistern. Nicht einmal die Royal-versessenen Briten erlauben ihren blaublütigen Posern mehr zu sein, als Yellow-Press-Volontäre! Herr KTG ist nur ein typisches Beispiel für die Oberflächlichkeit der ehemaligen Herrschenden dieses Landes, die wohl immer noch davon träumen, durch bloßes Posing und &amp;#8220;gute&amp;#8221; Manieren das Volk zu steuern. Diese Zeiten sind für den größten Teil Deutschlands aber schon längst vorbei. Die feudale Matrix funktioniert nicht mehr. KTG, du bist raus!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://deinweckruf.files.wordpress.com/2011/03/guttenberg-der-blender.jpg&quot; alt=&quot;&quot; width=&quot;614&quot; height=&quot;451&quot; /&gt;&lt;/p&gt;</description>
	<pubDate>Sun, 10 Apr 2011 17:03:14 +0000</pubDate>
</item>
<item>
	<title>Process-one Blogs: Sea Beyond 2011 Talk 7: Jukka Alakontiola on Nokia Push Notifications</title>
	<guid>http://www.process-one.net/en/blogs/article/sea_beyond_2011_talk_7_jukka_alakontiola_on_nokia_push_notifications/</guid>
	<link>http://www.process-one.net/en/blogs/article/sea_beyond_2011_talk_7_jukka_alakontiola_on_nokia_push_notifications/</link>
	<description>&lt;p&gt;Nokia Push Notification system has been developed by Nokia to send notifications on mobile directly.&lt;/p&gt; &lt;p&gt;Jukka Alakontiola presents the architecture of Nokia push and speaks about mobile related XMPP optimisations.&lt;/p&gt;
&lt;p&gt;Do not miss this video, it features lots of great insights on mobile realtime services.&lt;/p&gt;
&lt;p&gt;Here is the video of his presentation:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;You can see the slides here:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Do not miss the&amp;nbsp;&lt;a href=&quot;http://www.process-one.net/en/blogs/article/sea_beyond_2011_video_summary/&quot;&gt;event summary and the other videos from Sea Beyond event&lt;/a&gt;.&lt;/p&gt;</description>
	<pubDate>Thu, 07 Apr 2011 12:53:26 +0000</pubDate>
</item>
<item>
	<title>Erlang Training and Consulting &lt;br/&gt;- Jobs: Erlang Developer, Mountain View, CA, USA</title>
	<guid>http://www.erlang-solutions.com/jobs/detail/39/</guid>
	<link>http://www.erlang-solutions.com/jobs/detail/39/</link>
	<description>&lt;p&gt;&lt;strong&gt;Erlang Developer (Mountain View, CA)&lt;/strong&gt;&lt;br /&gt;As a software engineer with experience in Erlang and call processing, you would be responsible for evolving the key call processing and event distribution systems at the heart of the platform. Your responsibilities will include designing and developing new features and capabilities in the Erlang based components.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Key Responsibilities&lt;/strong&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;bull;&amp;nbsp;&amp;nbsp; &amp;nbsp;Design and develop key features and capabilities in the Erlang based systems&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;bull;&amp;nbsp;&amp;nbsp; &amp;nbsp;Maintain and evolve the call processing and event distribution components&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Requirements&lt;/strong&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;bull;&amp;nbsp;&amp;nbsp; &amp;nbsp;Bachelors Degree or 5+ years of comparable experience in architecture and development using Erlang and OTP&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;bull;&amp;nbsp;&amp;nbsp; &amp;nbsp;Experience in eunit and quickcheck&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;bull;&amp;nbsp;&amp;nbsp; &amp;nbsp;Experience in developing call processing software, telephony systems&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;bull;&amp;nbsp;&amp;nbsp; &amp;nbsp;Experience working in an agile environment (Scrum, Kanban or both)&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Desired Skills&lt;/strong&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;bull;&amp;nbsp;&amp;nbsp; &amp;nbsp;Experience in Python, Perl, Java, Javascript&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;bull;&amp;nbsp;&amp;nbsp; &amp;nbsp;Knowledge of telephony protocols (SIP, RTP, RTMP, etc.)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;bull;&amp;nbsp;&amp;nbsp; &amp;nbsp;Experience with Jira, Perforce&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;bull;&amp;nbsp;&amp;nbsp; &amp;nbsp;Experience with AGILE development&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;bull;&amp;nbsp;&amp;nbsp; &amp;nbsp;Experience with Test Driven Development&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;bull;&amp;nbsp;&amp;nbsp; &amp;nbsp;Must be team-oriented, possess a positive attitude and work well with others&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;bull;&amp;nbsp;&amp;nbsp; &amp;nbsp;Must be flexible and able to work accurately in a fast-paced environment&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;bull;&amp;nbsp;&amp;nbsp; &amp;nbsp;Ability to work independently and deliver on schedule with little supervision&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;bull;&amp;nbsp;&amp;nbsp; &amp;nbsp;Ability to quickly understand and articulate interactions in a complex technical environment&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;bull;&amp;nbsp;&amp;nbsp; &amp;nbsp;Able to plan and execute own tasks in timely manner&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;bull;&amp;nbsp;&amp;nbsp; &amp;nbsp;Passionate about software development, willing to learn new technology, self-motivated with high technical competency&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Please send your CV and a cover letter when applying.&lt;/p&gt;</description>
	<pubDate>Wed, 06 Apr 2011 14:00:56 +0000</pubDate>
</item>
<item>
	<title>Scattered Thoughts: telehash: buckets</title>
	<guid>http://scattered-thoughts.net/one/1301/514243/595154</guid>
	<link>http://scattered-thoughts.net/one/1301/514243/595154</link>
	<description>&lt;p&gt;The other half of the routing table is the buckets which store node addresses.
&lt;/p&gt;
&lt;p&gt;Usual disclaimer: none of this is properly tested yet.
&lt;/p&gt;
&lt;p&gt;The Kademlia paper has much to say on the issue of routing, most of it contradictory. My takeaway from many readings and from browsing the source code of various different implementations is that the following points are the most important:
&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;each bucket should contain at most &lt;b&gt;K&lt;/b&gt; nodes
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;we should only ever report node addresses which we have personally confirmed exist
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;responsive nodes should never be removed from buckets
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;nodes should never be removed from buckets unless a suitable replacement exists
    &lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The first three points make the routing table very resistant to flooding and spoofing. In particular, they prevent a common attack for p2p networks where some bad guy floods the routing tables of all the other nodes so that all traffic is routed through nodes controlled by the bad guy. The last point prevents nodes from flushing their routing tables if their own network connection goes down.
&lt;/p&gt;
&lt;p&gt;I think the implementation I have come up with is fairly clean, if a little lengthy. Like the bit_tree I want the bucket to be completely pure. All side effects will be handled by the router itself. The main data structures are explained pretty well by the comments:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;-define(K, ?DIAL_DEPTH).

-record(node, {
          address, % node #address{} record
          'end', % node end
          suffix, % the remaining bits of the nodes end left over from the bit_tree
          status, % one of [live, stale, cache]
          last_seen % for live/stale nodes, the time of the last received message. for cache nodes the time of the last .see reference to the node
         }).

-record(bucket, {
          nodes, % gb_tree mapping addresses to {Status, Last_seen}
          % remaining fields are pq's of nodes sorted by their last_seen field
          live, % nodes currently expected to be alive
          stale, % nodes which have not replied recently
          cache % potential nodes which we have not yet verified
         }). % invariant: pq_maps:size(live) + pq_maps:size(stale) &amp;lt;= ?K
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The bucket is a two-stage data structure. This allows us the keep nodes of different statuses sorted by the last_seen time but still be able to get/delete nodes just knowing the address. The &lt;b&gt;get_node&lt;/b&gt; function should make it clear how this works:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;get_node(Address,
         #bucket{nodes=Nodes, live=Live, stale=Stale, cache=Cache}) -&amp;gt;
    case gb_trees:lookup(Address, Nodes) of
        {value, {Status, Last_seen}} -&amp;gt;
            case Status of
                live -&amp;gt;
                    {ok, pq_maps:get({Last_seen, Address}, Live)};
                stale -&amp;gt;
                    {ok, pq_maps:get({Last_seen, Address}, Stale)};
                cache -&amp;gt;
                    {ok, pq_maps:get({Last_seen, Address}, Cache)}
            end;
        none -&amp;gt;
            none
    end.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is only long because records are purely a compile time structure ie we can't write &lt;b&gt;Bucket#bucket.Status&lt;/b&gt; so we have to pattern match on &lt;b&gt;Status&lt;/b&gt; instead. We also define &lt;b&gt;add_node/2&lt;/b&gt;, &lt;b&gt;del_node/2&lt;/b&gt; and &lt;b&gt;update_node/2&lt;/b&gt;, which look pretty similar, as well as &lt;b&gt;to_list/1&lt;/b&gt;, &lt;b&gt;from_list/1&lt;/b&gt; and &lt;b&gt;sizes/1&lt;/b&gt;.
&lt;/p&gt;
&lt;p&gt;The router is going to react to various events by calling the appropriate bucket functions and possibly sending out messages based on the result. The first event it has to handle is a node becoming unresponsive. The bucket will mark this node as stale and return a cache node which the router can attempt to verify.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;% this address failed to reply in a timely manner
timedout(Address, Bucket) -&amp;gt;
    log:info([?MODULE, timing_out, Address, Bucket]),
    case get_node(Address, Bucket) of
        {ok, Node} -&amp;gt;
            case Node#node.status of
                live -&amp;gt;
                    % mark as stale, return a cache node that might be a suitable replacement
                    Bucket2 = update_node(Node#node{status=stale}, Bucket),
                    pop_cache_hi(Bucket2);
                _ -&amp;gt;
                    % if cache or stale already we don't care
                    ok(Bucket)
            end;
        none -&amp;gt;
            % wtf? we don't even know this node?
            % one way this could happen:
            % send N1, sendN1, timedout N1, add N2 (pushing N1 out of stale), timedout N1
            log:warning([?MODULE, unknown_node_timedout, Address, Bucket]),
            ok(Bucket)
    end.

% return most recently seen cache node, if any exist
pop_cache_hi(#bucket{cache=Cache}=Bucket) -&amp;gt;
    case pq_maps:pop_hi(Cache) of
        {_Key, Node, Cache2} -&amp;gt;
            {node, Node, ok(Bucket#bucket{cache=Cache2})};
        false -&amp;gt;
            ok(Bucket)
    end.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The next event is receiving a &lt;b&gt;.see&lt;/b&gt; command. This may be as a result of a &lt;b&gt;+end&lt;/b&gt; sent by the router but is more likely to be part of a dialing process happening elsewhere. The beauty of Kademlia is that the router can populate the routing table just by listening in on dialing attempts.
&lt;/p&gt;
&lt;p&gt;For each node listed in the &lt;b&gt;.see&lt;/b&gt; command the router will call &lt;b&gt;seen&lt;/b&gt;. This adds the node to the cache and returns the least recently seen live node so the router can check that it is still responsive.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;% this address has been reported to exist by another node
seen(Address, Time, Suffix, Bucket) -&amp;gt;
    log:info([?MODULE, seeing, Address, Bucket]),
    case get_node(Address, Bucket) of
        {ok, Node} -&amp;gt;
            case Node#node.status of
                cache -&amp;gt;
                    % for cache nodes being in a .see is good enough
                    ok(update_node(Node#node{last_seen=Time}, Bucket));
                _ -&amp;gt;
                    % for live/stale nodes we require direct contact so ignore this
                    ok(Bucket)
            end;
        none -&amp;gt;
            % put node in cache, return a live node to ping
            Node = #node{
              address = Address,
              'end' = util:to_end(Address),
              suffix = Suffix,
              status = cache,
              last_seen = Time
             },
            Bucket2 = add_node(Node, Bucket),
            case peek_live_lo(Bucket) of
                none -&amp;gt; ok(Bucket2);
                {ok, Live_node} -&amp;gt; {node, Live_node, ok(Bucket2)}
            end
    end.

% return the oldest live node
peek_live_lo(#bucket{live=Live}) -&amp;gt;
    case pq_maps:peek_lo(Live) of
        none -&amp;gt; none;
        {_, Node} -&amp;gt; {ok, Node}
    end.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Any time we receive a message we learn that the node sending it exists (or not - we'll deal with address spoofing in a later post) so we can potentially mark it as a live node. The &lt;b&gt;touched&lt;/b&gt; function checks if the node is already in the bucket or if it needs to be added.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;% this address has been verified as actually existing
touched(Address, Suffix, Time, Bucket, May_split) -&amp;gt;
    log:info([?MODULE, touching, Address, Bucket]),
    case get_node(Address, Bucket) of
        {ok, Node} -&amp;gt;
            case Node#node.status of
                live -&amp;gt;
                    % update last_seen time
                    ok(update_node(Node#node{last_seen=Time}, Bucket));
                stale -&amp;gt;
                    % update last_seen time and promote to live
                    ok(update_node(Node#node{last_seen=Time, status=live}, Bucket));
                cache -&amp;gt;
                    % potentially promote the node to live
                    Bucket2 = del_node(Node, Bucket),
                    new_node(Address, Suffix, Time, Bucket2, May_split)
            end;
        none -&amp;gt;
            % potentially add the node to live
            new_node(Address, Suffix, Time, Bucket, May_split)
    end.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the node needs to be added then &lt;b&gt;touched&lt;/b&gt; calls &lt;b&gt;new_node&lt;/b&gt; which decides if there is space in the bucket and, if so, adds the new node. If the bucket is full and &lt;b&gt;May_split&lt;/b&gt; is true then &lt;b&gt;new_node&lt;/b&gt; will split the bucket before adding the new node. Deciding whether or not splitting is allowed is the routers job.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;% assumes Address is not already in Bucket, otherwise crashes
new_node(Address, Suffix, Time, Bucket, May_split) -&amp;gt;
    Node = #node{
      address = Address,
      'end' = util:to_end(Address),
      suffix = Suffix,
      status = undefined,
      last_seen = Time
     },
    {Lives, Stales, _} = sizes(Bucket),
    if
        Lives + Stales &amp;lt; ?K -&amp;gt;
            % space left in live
            log:info([?MODULE, adding, Node, Bucket]),
            ok(add_node(Node#node{status=live}, Bucket));
        (Lives &amp;lt; ?K) and (Stales &amp;gt; 0) -&amp;gt;
            % space left in live if we push something out of stale
            log:info([?MODULE, adding, Node, Bucket]),
            Bucket2 = drop_stale(Bucket),
            ok(add_node(Node#node{status=live}, Bucket2));
        May_split and (Suffix /= []) -&amp;gt;
            % allowed to split the bucket to make space
            log:info([?MODULE, splitting, Node, Bucket]),
            {split, BucketF, BucketT} = split(Bucket),
            [Bit | Suffix2] = Suffix,
            case Bit of
                false -&amp;gt;
                    BucketF2 = new_node(Address, Suffix2, Time, BucketF, May_split),
                    {split, BucketF2, BucketT};
                true -&amp;gt;
                    BucketT2 = new_node(Address, Suffix2, Time, BucketT, May_split),
                    {split, BucketF, BucketT2}
            end;
        true -&amp;gt;
            % not allowed to split, will have to go in the cache
            log:info([?MODULE, caching, Node, Bucket]),
            ok(add_node(Node#node{status=cache}, bucket))
    end.

% drop the oldest stale node, crashes if none exist
drop_stale(#bucket{stale=Stale}=Bucket) -&amp;gt;
    {_Key, _Node, Stale2} = pq_maps:pop_one_hi(Stale),
    Bucket#bucket{stale=Stale2}.

split(Bucket) -&amp;gt;
    Nodes = to_list(Bucket),
    NodesF = [Node#node{suffix=Suffix2} || #node{suffix=[false|Suffix2]}=Node &amp;lt;- Nodes],
    NodesT = [Node#node{suffix=Suffix2} || #node{suffix=[true|Suffix2]}=Node &amp;lt;- Nodes],
    {split, from_list(NodesF), from_list(NodesT)}.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, upon receiving a &lt;b&gt;+end&lt;/b&gt; signal the router needs to reply with a &lt;b&gt;.see&lt;/b&gt; command listing the &lt;b&gt;K&lt;/b&gt; nearest nodes to the specified end. This will be done using a combination of &lt;b&gt;bit_tree:iter&lt;/b&gt; and &lt;b&gt;bucket:nearest&lt;/b&gt;.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;nearest(N, End, #bucket{live=Live, stale=Stale}) -&amp;gt;
    Nodes = pq_maps:to_list(Live) ++ pq_maps:to_list(Stale),
    Num_nodes = pq_maps:size(Live) + pq_maps:size(Stale),
    if
        Num_nodes =&amp;lt; N -&amp;gt;
            [Node#node.address || {_Key, Node} &amp;lt;- Nodes];
        true -&amp;gt;
            % !!! maybe should prefer to return live nodes even if further away
            Nodes_by_dist = [{util:distance(End, Node#node.'end'), Node} || {_Key, Node} &amp;lt;- pq_maps:to_list(Live)],
            {Closest, _} = lists:split(N, lists:sort(Nodes_by_dist)),
            [Node#node.address || {_Dist, Node} &amp;lt;- Closest]
    end.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As usual all the code is sitting in the &lt;a href=&quot;https://github.com/jamii/erl-telehash&quot;&gt;repo&lt;/a&gt;.
&lt;/p&gt;</description>
	<pubDate>Wed, 30 Mar 2011 19:44:03 +0000</pubDate>
</item>
<item>
	<title>Process-one Blogs: Sea Beyond 2011 Talk 6: Diana Cheng on OneSocialWeb</title>
	<guid>http://www.process-one.net/en/blogs/article/sea_beyond_2011_talk_6_diana_cheng_on_onesocialweb/</guid>
	<link>http://www.process-one.net/en/blogs/article/sea_beyond_2011_talk_6_diana_cheng_on_onesocialweb/</link>
	<description>&lt;p&gt;Diana Cheng, from Vodafone, introduces OneSocialWeb project.&lt;/p&gt; &lt;p&gt;Diana Cheng presents OneSocialWeb distributed social web initiative, primarily based on XMPP and Activitystreams standards.&lt;/p&gt;
&lt;p&gt;Here is the video of her presentation:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;You can see the slides here:&lt;/p&gt;
&lt;p&gt;








&lt;/p&gt;
&lt;p&gt;Do not miss the &lt;a href=&quot;http://www.process-one.net/en/blogs/article/sea_beyond_2011_video_summary/&quot;&gt;event summary and the other videos from Sea Beyond event&lt;/a&gt;.&lt;/p&gt;</description>
	<pubDate>Tue, 29 Mar 2011 11:45:05 +0000</pubDate>
</item>
<item>
	<title>Erlang Factory News: Erlang Factory SF Bay Area 2011 - A Great Success</title>
	<guid>http://erlang-factory.com/news/rss/c6d8ecd4513002716858b76e2d848abd</guid>
	<link></link>
	<description>&lt;p&gt;On the 24th - 25th March 2011, over 170 people gathered in the SF Bay Area for the 3rd Erlang Factory. With two Keynotes this year delivered by, Kostis Sagonas and Dan Ingalls, 10 extra talks compared to last year and a record-breaking number of delegates, this year's conference was nothing short of a tremendous success. &lt;br /&gt;&lt;br /&gt;We would like to thank everyone that attended and keep your eyes out for the videos that will be released soon!&lt;/p&gt;</description>
	<pubDate>Tue, 29 Mar 2011 11:34:01 +0000</pubDate>
</item>
<item>
	<title>Trapexit's Erlang Blog Filter: London Erlang User Group Slides</title>
	<guid>http://steve.vinoski.net/blog/?p=762</guid>
	<link>http://steve.vinoski.net/blog/2011/03/28/london-erlang-user-group-slides/</link>
	<description>&lt;p&gt;While attending &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://qconlondon.com/&quot;&gt;QCon&lt;/a&gt; recently I also spoke at the &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.erlang-solutions.com/etc/usergroup/london&quot;&gt;London Erlang User Group&lt;/a&gt; meeting. I gave a quick talk about &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.erlang.org/doc/tutorial/nif.html&quot;&gt;Erlang Native Implemented Functions&lt;/a&gt; (NIFs) as used in my little &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/vinoski/erlsha2&quot;&gt;erlsha2&lt;/a&gt; implementation. Slides are &lt;a rel=&quot;nofollow&quot;&gt;here&lt;/a&gt; (pdf).&lt;/p&gt;</description>
	<pubDate>Mon, 28 Mar 2011 18:00:22 +0000</pubDate>
</item>
<item>
	<title>Programming in the 21st Century: If You're Not Gonna Use It, Why Are You Building It?</title>
	<guid>http://prog21.dadgum.com/94.html</guid>
	<link>http://prog21.dadgum.com/94.html</link>
	<description>Just about every image editing or photo editing program I've tried has a big collection of visual filters. There's one to make an image look like a mosaic, one to make it look like watercolors, and so on. Except for few of the most fundamental image adjustments, like saturation and sharpness, I never use any of them.
&lt;br /&gt;&lt;br /&gt;I have this suspicion that the programmers of these tools got hold of some image processing textbooks and implemented everything in them. If an algorithm had any tweakable parameters, then those were exposed to the user as sliders.
&lt;br /&gt;&lt;br /&gt;Honestly, that sounds like something I might have done in the past. The process of implementing those filters is purely technical--almost mechanical--yet it makes the feature list longer and more impressive. And they could be fun to code up. But no consideration is given to if those filters have any practical value.
&lt;br /&gt;&lt;br /&gt;Contrast this with apps like &lt;a href=&quot;http://instagr.am/&quot;&gt;Instagram&lt;/a&gt; and &lt;a href=&quot;http://hipstamaticapp.com/&quot;&gt;Hipstamatic&lt;/a&gt;. Those programs use your phone's camera to grab images, then apply built-in filters to them. They're fully automatic; you can't make any manual adjustments. And yet unlike all of those filter-laden photo editors I've used in the past, I'm completely hooked on Hipstamatic. It rekindled my interest in photography, and I can't thank the authors enough.
&lt;br /&gt;&lt;br /&gt;What's the difference between those apps and old-fashioned photo editors?
&lt;br /&gt;&lt;br /&gt;The Hipstamatic and Instagram filters were designed with clear goals in mind: to emulate certain retro-camera aesthetics, to serve as starting points and inspirations for photographs. Or more succinctly: they were built to be used.
&lt;br /&gt;&lt;br /&gt;If you find yourself creating something, and you don't understand how it will be used, and you don't plan on using it yourself, then it's time to take a few steps back and reevaluate what you're doing.
&lt;br /&gt;&lt;br /&gt;(If you liked this, you might like &lt;a href=&quot;http://prog21.dadgum.com/80.html&quot;&gt;Advice to Aimless, Excited Programmers&lt;/a&gt;.)</description>
	<pubDate>Sat, 26 Mar 2011 06:00:00 +0000</pubDate>
</item>
<item>
	<title>RJ's Blog: Erlang rebar tutorial: generating releases and upgrades</title>
	<guid>http://www.metabrew.com/article/erlang-rebar-tutorial-generating-releases-upgrades</guid>
	<link>http://www.metabrew.com/article/erlang-rebar-tutorial-generating-releases-upgrades</link>
	<description>&lt;p&gt;During my experiments with rebar, I made a simple example app for testing upgrades and releases. This article will walk you through using rebar to create an application, lay it out properly, package and deploy it, and create and install new versions without downtime.&lt;/p&gt;

&lt;p&gt;The code accompanying this article is in various branches of &lt;a href=&quot;https://github.com/RJ/erlang_rebar_example_project&quot;&gt;github.com/RJ/erlang_rebar_example_project&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;N.B.&lt;/strong&gt; The &lt;a href=&quot;http://www.erlang.org/doc/design_principles/des_princ.html&quot;&gt;OTP
Design Principles&lt;/a&gt; docs are a good place to start if you want an overview of the OTP approach to Erlang apps and releases. However, rebar isn&amp;#8217;t (yet) part of OTP, so consider that background reading. Rebar makes things much easier.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;creating_the_project&quot;&gt;Creating the project&lt;/h2&gt;

&lt;p&gt;Build rebar:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/src
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; git clone https://github.com/basho/rebar.git
&lt;span class=&quot;go&quot;&gt;Initialized empty Git repository in /tmp/rebar/.git/&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;remote: Counting objects: 2651, done.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;remote: Compressing objects: 100% (1344/1344), done.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;remote: Total 2651 (delta 1540), reused 2227 (delta 1174)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Receiving objects: 100% (2651/2651), 622.99 KiB | 495 KiB/s, done.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Resolving deltas: 100% (1540/1540), done.&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;rebar &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; make
&lt;span class=&quot;go&quot;&gt;...snip....&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;==&amp;gt; rebar (compile)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Congratulations! You now have a self-contained script called &amp;quot;rebar&amp;quot; in&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;your current working directory. Place this script anywhere in your path&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;and you can use rebar to build OTP-compliant apps.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now we&amp;#8217;ll make a project directory called &amp;#8220;dummy_proj&amp;#8221;, copy rebar into it, and use rebar to generate a skeleton application:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; mkdir -p ~/src/dummy_proj/apps
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/src/dummy_proj/
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; cp ../rebar/rebar .
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;apps
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; ../rebar create-app &lt;span class=&quot;nv&quot;&gt;appid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;dummy_proj
&lt;span class=&quot;go&quot;&gt;==&amp;gt; dummy_proj (create-app)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Writing src/dummy_proj.app.src&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Writing src/dummy_proj_app.erl&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Writing src/dummy_proj_sup.erl&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;To the skeleton, I added a basic gen_server called dummy_proj_server, which just keeps track of the number of times it was poked, i.e. it holds some state, for demonstration purposes.&lt;/p&gt;

&lt;p&gt;I also renamed dummy_proj_app.erl to just dummy_proj.erl, and added a start/0 function, which is useful when starting the application during developement, when not running from a generated release.&lt;/p&gt;

&lt;h3 id=&quot;compiling_with_rebar&quot;&gt;Compiling with rebar&lt;/h3&gt;

&lt;p&gt;You need a rebar.conf, place this in the top-level project directory:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;erlang&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sub_dirs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&amp;quot;apps/dummy_proj&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&amp;quot;rel&amp;quot;&lt;/span&gt;
           &lt;span class=&quot;p&quot;&gt;]}.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;erl_opts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;debug_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fail_on_warning&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]}.&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;require_otp_vsn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;R14&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And now to compile, you do:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; ./rebar compile
&lt;span class=&quot;go&quot;&gt;==&amp;gt; dummy_proj (compile)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Compiled src/dummy_proj_sup.erl&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Compiled src/dummy_proj.erl&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Compiled src/dummy_proj_server.erl&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;==&amp;gt; rel (compile)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;==&amp;gt; dummy_proj (compile)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Note that you now have .beam files in apps/dummy_proj/ebin/, and the .app.src generated apps/dummy_proj/ebin/dummy_proj.app for you, with a complete modules list.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;N.B.&lt;/strong&gt; I made a simple Makefile that calls &amp;#8216;rebar compile&amp;#8217;, because I&amp;#8217;m too used to typing make. Find it in the git repo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;running_your_app_development&quot;&gt;Running your app (development)&lt;/h3&gt;

&lt;p&gt;Here&amp;#8217;s how you can start the application (and sasl, for nice error reporting):&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; erl -pa apps/*/ebin -boot start_sasl -s dummy_proj
&lt;span class=&quot;go&quot;&gt;...snip...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;=INFO REPORT==== 16-Mar-2011::14:17:04 ===&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Starting dummy_proj application...&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;=PROGRESS REPORT==== 16-Mar-2011::14:17:04 ===&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;          supervisor: {local,dummy_proj_sup}&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;             started: [{pid,&amp;lt;0.45.0&amp;gt;},&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;                       {name,dummy_proj_server},&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;                       {mfargs,{dummy_proj_server,start_link,[]} },&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;                       {restart_type,permanent},&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;                       {shutdown,5000},&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;                       {child_type,worker}]&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;=PROGRESS REPORT==== 16-Mar-2011::14:17:04 ===&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;         application: dummy_proj&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;          started_at: nonode@nohost&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Eshell V5.8.1  (abort with ^G)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1&amp;gt; dummy_proj_server:num_pokes().&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;2&amp;gt; dummy_proj_server:poke().     &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{ok,1}&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;3&amp;gt; dummy_proj_server:poke().&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{ok,2}&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;4&amp;gt; dummy_proj_server:num_pokes().&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;5&amp;gt;  &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now you have a nice sensibly structured Erlang project that you can compile with rebar. Exit the VM with q(). and let&amp;#8217;s use rebar to package it up, so you can deploy it on a production box.&lt;/p&gt;

&lt;h2 id=&quot;generating_your_first_release&quot;&gt;Generating your first release&lt;/h2&gt;

&lt;p&gt;When you generate a release with rebar, and indeed if you use the erlang tools manually (not recommended, just use rebar), you end up with the whole Erlang VM and required libraries packaged up under one directory.&lt;/p&gt;

&lt;p&gt;This means you have a self-contained environment containing Erlang, the OTP libraries you need, and all your application code and dependencies. You can just tar it up, ship it over to another machine (of the same architecture, eg GNU/Linux 64-bit), and run it there.&lt;/p&gt;

&lt;h3 id=&quot;creating_a_node_config&quot;&gt;Creating a node config&lt;/h3&gt;

&lt;p&gt;Use rebar to create a default node configuration in a rel subdirectory:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; mkdir rel
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;rel/
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; ../rebar create-node &lt;span class=&quot;nv&quot;&gt;nodeid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;dummynode
&lt;span class=&quot;go&quot;&gt;==&amp;gt; rel (create-node)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Writing reltool.config&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Writing files/erl&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Writing files/nodetool&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Writing files/dummynode&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Writing files/app.config&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Writing files/vm.args&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You need to edit reltool.config a little; point to to your apps directory, and make sure the version number matches your .app.src file. You should also add dummy_app to the list of applications that are started as part of the release. Here&amp;#8217;s &lt;a href=&quot;https://github.com/RJ/erlang_rebar_example_project/blob/v1/rel/reltool.config&quot; target=&quot;v1rel&quot;&gt;reltool.conf from my v1 tag&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;generating_the_release&quot;&gt;Generating the release&lt;/h3&gt;

&lt;p&gt;Back in the top level directory, just run:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; ./rebar generate
&lt;span class=&quot;go&quot;&gt;==&amp;gt; rel (generate)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now have a look in rel/dummynode. This is the release directory containing everything you need to run your application.&lt;/p&gt;

&lt;p&gt;We are going to be creating more releases later, so rename rel/dummynode to rel/dummynode_first, and then launch it using the handy script that rebar created for us:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;rel/dummynode_first
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; ./bin/dummynode console
&lt;span class=&quot;go&quot;&gt;...snip...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Erlang R14B (erts-5.8.1) [source] [64-bit] [smp:8:8] [rq:8] [async-threads:5] [hipe] [kernel-poll:true&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;=INFO REPORT==== 16-Mar-2011::13:29:59 ===&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Starting dummy_proj application...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Eshell V5.8.1  (abort with ^G)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(dummynode@127.0.0.1)1&amp;gt; &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(dummynode@127.0.0.1)1&amp;gt; dummy_proj_server:num_pokes().&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(dummynode@127.0.0.1)2&amp;gt; dummy_proj_server:poke().     &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{ok,1}&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(dummynode@127.0.0.1)3&amp;gt; dummy_proj_server:poke().&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{ok,2}&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(dummynode@127.0.0.1)4&amp;gt; dummy_proj_server:num_pokes().&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(dummynode@127.0.0.1)5&amp;gt; &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now the release is running, we never want to have to restart it ever again, so open up another console because we want to leave that running whilst we work on version 2.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;N.B.&lt;/strong&gt; In a production environment, you would start with &amp;#8220;./bin/dummynode start&amp;#8221; so it runs in the background, and use &amp;#8220;dummynode attach&amp;#8221; to get a console.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Check the &lt;a href=&quot;https://github.com/RJ/erlang_rebar_example_project/blob/v1/&quot;&gt;'v1 branch'&lt;/a&gt; on github for code up to this point.&lt;/p&gt;

&lt;h2 id=&quot;upgrading_to_version_2&quot;&gt;Upgrading to Version 2&lt;/h2&gt;

&lt;p&gt;Add the poke_twice() function to dummy_proj_server.&lt;/p&gt;

&lt;p&gt;Change the version from &amp;#8220;1&amp;#8221; to &amp;#8220;2&amp;#8221;, in both apps/dummy_proj.app.src and rel/reltool.conf.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s the github &lt;a href=&quot;https://github.com/RJ/erlang_rebar_example_project/compare/v1...v2#diff-3&quot;&gt;diff between v1...v2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Erlang application version numbers can be any string - I tend to use a date format with letter: &amp;#8220;20110316a&amp;#8221;, but you can use any scheme you want. I tag releases in git with the same version as the erlang application. We&amp;#8217;ll just use &amp;#8220;1&amp;#8221;, &amp;#8220;2&amp;#8221;, &amp;#8220;3&amp;#8221; here for simplicity.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;N.B.&lt;/strong&gt; If you use &lt;code&gt;{vsn, git}&lt;/code&gt; as the version in your .app.src, rebar will get the version string from the closest git tag.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now build the new version:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; ./rebar compile
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; ./rebar generate
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;So now you have rel/dummy_proj, containing a full release (VM included) of version 2. If you don&amp;#8217;t care about online-upgrades, you could just kill your version 1 VM, and start version 2 from this new release directory.&lt;/p&gt;

&lt;h3 id=&quot;writing_the_appup_upgrade_instructions&quot;&gt;Writing the .appup upgrade instructions&lt;/h3&gt;

&lt;p&gt;In order to make an upgrade, you must have a valid .appup file. This tells the erlang release_handler how to upgrade and downgrade between specific versions of your application.&lt;/p&gt;

&lt;p&gt;Rebar has a (relatively new) command called &amp;#8216;generate-appups&amp;#8217;. I&amp;#8217;ll show how it works, but ultimately we&amp;#8217;ll write our .appup manually, and keep it in our project directory (in git).&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; ./rebar generate-appups &lt;span class=&quot;nv&quot;&gt;previous_release&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;dummynode_first
&lt;span class=&quot;go&quot;&gt;==&amp;gt; rel (generate-appups)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Generated appup for dummy_proj&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Appup generation complete&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; cat ./rel/dummynode/lib/dummy_proj-2/ebin/dummy_proj.appup
&lt;span class=&quot;gp&quot;&gt;%&lt;/span&gt;% appup generated &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;dummy_proj by rebar &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;2011/03/16 13:37:43&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;¬                                   
&lt;span class=&quot;go&quot;&gt;{&amp;quot;2&amp;quot;, [{&amp;quot;1&amp;quot;, [{update,dummy_proj_server,{advanced,[]}}]}], [{&amp;quot;1&amp;quot;, []}]}.¬&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Get rid of the autogenerated one, and create the appup file manually, in apps/dummy_proj/ebin/dummy_proj.appup:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;erlang&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;2&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;c&quot;&gt;%% Upgrade instructions from 1 to 2&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;load_module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dummy_proj_server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;    
    &lt;span class=&quot;p&quot;&gt;]}],&lt;/span&gt; 
    &lt;span class=&quot;c&quot;&gt;%% Downgrade instructions from 2 to 1&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,[&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;load_module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dummy_proj_server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;    
    &lt;span class=&quot;p&quot;&gt;]}]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This .appup contains instructions for upgrading and downgrading between versions &amp;#8220;2&amp;#8221; and &amp;#8220;1&amp;#8221;. Typically the downgrade instructions are the reverse of the upgrade instructions. Since we just added a function to our server process, without changing any internal state, we can just use load_module instructions. The Appup Cookbook explains the various upgrade instructions in depth.&lt;/p&gt;

&lt;p&gt;Now generate again, overwriting the previous version 2. This will just make sure the .appup is part of the release directory:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; ./rebar generate -f
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And now, create the upgrade package:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; ./rebar generate-upgrade &lt;span class=&quot;nv&quot;&gt;previous_release&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;dummynode_first
&lt;span class=&quot;go&quot;&gt;==&amp;gt; rel (generate-upgrade)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;dummynode_2 upgrade package created&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The generate-upgrade command will look for rel/dummynode as the current version, and rel/dummynode_first as the previous version. It should have created the upgrade .tar.gz in rel:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; ls -lh rel/
&lt;span class=&quot;go&quot;&gt;total 15M&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;drwxr-xr-x 8 rj rj 4.0K 2011-03-16 13:42 dummynode&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;drwxr-xr-x 8 rj rj 4.0K 2011-03-16 13:29 dummynode_first&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-rw-r--r-- 1 rj rj  14M 2011-03-16 13:45 dummynode_2.tar.gz&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;drwxr-xr-x 2 rj rj 4.0K 2011-03-16 13:11 files&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-rw-r--r-- 1 rj rj  922 2011-03-16 13:36 reltool.config&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id=&quot;installing_the_upgrade_package&quot;&gt;Installing the upgrade package&lt;/h3&gt;

&lt;p&gt;You should still have the VM running from dummynode_first. Make sure you called poke(), so the internal state is something other than the default. This will help illustrate that the upgrade worked seamlessly.&lt;/p&gt;

&lt;p&gt;Copy the upgrade package to the releases directory of the running release:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; cp rel/dummynode_2.tar.gz rel/dummynode_first/releases
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now, at the Erlang console where version 1 is running, we use release_handler to check which releases are currently available, and install our new one:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;(dummynode@127.0.0.1)5&amp;gt; release_handler:which_releases().&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[{&amp;quot;dummynode&amp;quot;,&amp;quot;1&amp;quot;,[],permanent}]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(dummynode@127.0.0.1)6&amp;gt; release_handler:unpack_release(&amp;quot;dummynode_2&amp;quot;).&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{ok,&amp;quot;2&amp;quot;}&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(dummynode@127.0.0.1)7&amp;gt; release_handler:install_release(&amp;quot;2&amp;quot;).&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{ok,&amp;quot;1&amp;quot;,[]}   &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(dummynode@127.0.0.1)8&amp;gt; dummy_proj_server:num_pokes().&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(dummynode@127.0.0.1)9&amp;gt; dummy_proj_server:poke_twice().&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{ok,4}&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(dummynode@127.0.0.1)10&amp;gt; dummy_proj_server:num_pokes(). &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(dummynode@127.0.0.1)11&amp;gt; release_handler:which_releases().&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[{&amp;quot;dummynode&amp;quot;,&amp;quot;2&amp;quot;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  [&amp;quot;kernel-2.14.1&amp;quot;,&amp;quot;stdlib-1.17.1&amp;quot;,&amp;quot;dummy_proj-2&amp;quot;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;   &amp;quot;sasl-2.1.9.2&amp;quot;,&amp;quot;compiler-4.7.1&amp;quot;,&amp;quot;crypto-2.0.1&amp;quot;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;   &amp;quot;syntax_tools-1.6.6&amp;quot;,&amp;quot;edoc-0.7.6.7&amp;quot;,&amp;quot;et-1.4.1&amp;quot;,&amp;quot;gs-1.5.13&amp;quot;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;   &amp;quot;hipe-3.7.7&amp;quot;,&amp;quot;inets-5.5&amp;quot;,&amp;quot;mnesia-4.4.15&amp;quot;,&amp;quot;observer-0.9.8.3&amp;quot;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;   &amp;quot;public_key-0.8&amp;quot;,&amp;quot;runtime_tools-1.8.4.1&amp;quot;,&amp;quot;ssl-4.0.1&amp;quot;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;   &amp;quot;tools-2.6.6.1&amp;quot;,&amp;quot;webtool-0.8.7&amp;quot;,&amp;quot;wx-0.98.7&amp;quot;,&amp;quot;xmerl-1.2.6&amp;quot;],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  current},&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; {&amp;quot;dummynode&amp;quot;,&amp;quot;1&amp;quot;,[],permanent}]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The upgrade worked; you can see that the num_pokes() was preserved, and that the new poke_twice() function is available.&lt;/p&gt;

&lt;p&gt;release_handler shows our version 2 as &amp;#8220;current&amp;#8221;, and the original version 1 as &amp;#8220;permanent&amp;#8221;. This means that although version 2 is running right now, if you restart the VM, version &amp;#8220;1&amp;#8221; will be booted up.&lt;/p&gt;

&lt;p&gt;If you are happy with the upgrade, make it permanent, meaning it will boot instead of version 1 if you restart the VM:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;(dummynode@127.0.0.1)12&amp;gt; release_handler:make_permanent(&amp;quot;2&amp;quot;).&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Check the &lt;a href=&quot;https://github.com/RJ/erlang_rebar_example_project/blob/v2/&quot;&gt;'v2 branch'&lt;/a&gt; on github for code up to this point.&lt;/p&gt;

&lt;h2 id=&quot;version_3_and_beyond&quot;&gt;Version 3 and beyond&lt;/h2&gt;

&lt;p&gt;The upgrade from v1 to v2 was simple: we just added a fun without changing the internal #state{} record.&lt;/p&gt;

&lt;p&gt;Erlang .appup files can do all sorts of clever stuff, allowing you to rewire your running applications during the upgrade process.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://www.erlang.org/doc/design_principles/appup_cookbook.html&quot;&gt;Appup
Cookbook&lt;/a&gt; details the various commands you can put in your .appup.&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s do an upgrade with a more complex appup - we&amp;#8217;ll change the #state record in the dummy_proj_server process.&lt;/p&gt;

&lt;p&gt;For version 3, we&amp;#8217;ll track prods as well as pokes, which will require another field in the state record.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s the github &lt;a href=&quot;https://github.com/RJ/erlang_rebar_example_project/compare/v2...v3#diff-2&quot;&gt;diff between v2...v3&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Check out the addition to .appup for this release:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;erlang&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;3&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;c&quot;&gt;%% Upgrade instructions&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;2&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dummy_app_server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;advanced&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from2to3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]}}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;]}],&lt;/span&gt; 
    &lt;span class=&quot;c&quot;&gt;%% Downgrade instructions&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;2&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,[&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dummy_app_server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;advanced&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from3to2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]}}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;]}]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This {update..} directive will result in the code_change function being called on the dummy_app_server. The purpose of code_change is to change the State from the old (v2) format, to the new (v3) format.&lt;/p&gt;

&lt;p&gt;Although it&amp;#8217;s not strictly necessary, I pass &amp;#8216;from2to3&amp;#8217; as the &amp;#8216;Extra&amp;#8217; field in the code_change call. This can be pattern matched on, and makes it clear in your code_change code exactly what version upgrade is expected.&lt;/p&gt;

&lt;h3 id=&quot;packaging_and_upgrading_to_v3&quot;&gt;Packaging and upgrading to v3&lt;/h3&gt;

&lt;p&gt;Move the generated release dir for v2:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; mv rel/dummynode rel/dummynode_2
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Compile and generate for v3, then create the upgrade package:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; ./rebar compile
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; ./rebar generate
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; ./rebar generate-upgrade &lt;span class=&quot;nv&quot;&gt;previous_release&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;dummynode_2
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;N.B.&lt;/strong&gt; You need to provide the full, standalone generated release dir as the previous_release, you can&amp;#8217;t use dummynode_first, even though that contains version 2 of your release.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As before, copy the upgrade package to the releases directory of the running release:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; cp rel/dummynode_3.tar.gz rel/dummynode_first/releases
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now, at the Erlang console where you upgraded v1 to v2:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;(dummynode@127.0.0.1)12&amp;gt; release_handler:unpack_release(&amp;quot;dummynode_3&amp;quot;).&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{ok,&amp;quot;3&amp;quot;}&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(dummynode@127.0.0.1)13&amp;gt; release_handler:install_release(&amp;quot;3&amp;quot;).&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{ok,&amp;quot;2&amp;quot;,[]}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id=&quot;congratulations&quot;&gt;Congratulations&lt;/h3&gt;

&lt;p&gt;Now you can deploy hot-code-upgrades the proper OTP way. Ideal for complex or large upgrades that change internal state or do require special upgrade hooks. Read the Appup Cookbook a few times, and &lt;strong&gt;test your upgrade packages in a staging environment before deploying&lt;/strong&gt;. You can just tar up and copy the live environment to your staging box, to get an exact clone of the production system to test upgrades against.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Warning: a current issue with downgrades&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To downgrade, you just install a previous release. However, there is currently a bug where release_handler chokes during downgrades to the first version, because of a discrepancy in the naming of .boot files in the release. release_handler has start.boot hardcoded, but rebar will generate appname.boot, with start.boot as a symlink. If you need to do downgrades, test this carefully before deploying; you may need to manually rename the boot file.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;cowboying_out_quick_fixes&quot;&gt;Cowboying out quick fixes&lt;/h2&gt;

&lt;p&gt;Appup files and generating releases is rather heavyweight. Here&amp;#8217;s an overview of the process I&amp;#8217;m using on &lt;a href=&quot;https://www.irccloud.com/&quot;&gt;IRCCloud&lt;/a&gt; at the moment&lt;/p&gt;

&lt;h4 id=&quot;complex_upgrades_are_proper_releases_with_appup&quot;&gt;Complex upgrades are proper releases, with .appup&lt;/h4&gt;

&lt;p&gt;No way around it; bit of a pain to create and test, but glorious when you pull off a complex upgrade with zero downtime. Releases are tagged in git with the datetime and letter version, eg: v20110324a. If I do a second release that day, v20110324b.&lt;/p&gt;

&lt;h4 id=&quot;hotfixes_preserve_my_sanity&quot;&gt;&amp;#8216;Hotfixes&amp;#8217; preserve my sanity&lt;/h4&gt;

&lt;p&gt;If I make a quick fix that simply requires reloading a module with no risk of instability, I do the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reset code to currently deployed tag, egv 20110324a&lt;/li&gt;

&lt;li&gt;Write the fix&lt;/li&gt;

&lt;li&gt;Commit as v200110324a-hotfix1&lt;/li&gt;

&lt;li&gt;Build this version of the specific module that&amp;#8217;s changed, and copy it into the production environment, eg to: /somewhere/dummyapp/lib/dummyapp-20110324a/ebin/&lt;/li&gt;

&lt;li&gt;Reload the module, eg by using l(module_name). at the shell.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It&amp;#8217;s of vital importance to have a repeatable process, so you know exactly which version of code (ie, the git tag) is currently running in production. If you can&amp;#8217;t be sure, then it&amp;#8217;s much harder to write successful upgrade code later on.&lt;/p&gt;

&lt;p&gt;This process gives a reasonable balance between periodic &amp;#8216;proper&amp;#8217; releases, during which any complex changes are made that rewire internal state, and quick fixes that just require a module reload.&lt;/p&gt;

&lt;h2 id=&quot;pitfalls_to_avoid&quot;&gt;Pitfalls to avoid&lt;/h2&gt;

&lt;p&gt;In the IRCCloud app, there&amp;#8217;s one place that I don&amp;#8217;t use a supervisor, but wish I had; the user process acts as a sort of supervisor for connection processes, because I needed exponential backoff / more control over restarting crashed children.&lt;/p&gt;

&lt;p&gt;Don&amp;#8217;t do that. release_handler isn&amp;#8217;t aware of the child processes I spawn myself, so I can&amp;#8217;t use the normal appup process to call code_change.&lt;/p&gt;</description>
	<pubDate>Sat, 26 Mar 2011 00:00:00 +0000</pubDate>
	<author>rj@metabrew.com (Richard Jones)</author>
</item>
<item>
	<title>erlang.org RSS Feed: Mailing Lists Operating</title>
	<guid>http://www.erlang.org/news/15</guid>
	<link>http://www.erlang.org/news/15</link>
	<description>&lt;p&gt;&lt;p&gt;
	The mailing lists at erlang.org are now back online after fixing a subtle Python &amp;quot;gotcha&amp;quot; configuration error.&lt;/p&gt;
&lt;p&gt;
	Please report any posts that you feel slipped into the void, or double posts or whatnot!&lt;/p&gt;
&lt;/p&gt;</description>
	<pubDate>Fri, 25 Mar 2011 18:52:58 +0000</pubDate>
</item>
<item>
	<title>Scattered Thoughts: telehash: bit_trees revisited</title>
	<guid>http://scattered-thoughts.net/one/1301/8124/662205</guid>
	<link>http://scattered-thoughts.net/one/1301/8124/662205</link>
	<description>&lt;p&gt;It has been suggested that the bit_trees presented in the last post are overly complicated. Indeed, in the cold light of the morning there is absolutely no need for that zipper. Without further ado, here is the much simpler version.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;% implements the tree part of kademlias k-buckets
% a bit_tree maps ends (lists of bits) to buckets
% as far as the bit_tree is concerned the buckets are completely opaque
% the bit_tree also calculates various numbers needed for splitting decisions

-module(bit_tree).

-include(&quot;conf.hrl&quot;).

-export([empty/2, update/4, iter/2]).

% a bit_tree is either a leaf or a branch
-record(leaf, {
          size, % size of bucket
          bucket % some opaque bucket of stuff
         }).
-record(branch, {
          size, % size(childF) + size(childT)
          childF, % tree containing nodes whose next bit is false
          childT % tree containing nodes whose next bit is true
         }).

% --- api ---

empty(Size, Bucket) -&amp;gt;
    #leaf{size=Size, bucket=Bucket}.
                
update(Fun, Bits, Self, Tree) when is_function(Fun), is_list(Bits), is_list(Self) -&amp;gt;
    update(Fun, Bits, {self, Self}, 0, Tree).

update(Fun, Bits, Gap, Depth, #leaf{bucket=Bucket}) -&amp;gt;
    Gap_size =
        case Gap of
            {gap, G} -&amp;gt; G;
            {self, _} -&amp;gt; 0
        end,
    bucket_update_to_tree(Fun(Bits, Depth, Gap_size, Bucket));
update(Fun, Bits, Self, Depth, #branch{childF=ChildF, childT=ChildT}) -&amp;gt;
    [Next|Bits2] = Bits,
    Self2 =
        case Self of
            {gap, _} -&amp;gt; Self;
            {self, [Next|Rest]} -&amp;gt; {self, Rest};
            {self, [false|_]} -&amp;gt; {gap, tree_size(ChildF)};
            {self, [true|_]} -&amp;gt; {gap, tree_size(ChildT)}
        end,
    Depth2 = Depth+1,
    case Next of
        true -&amp;gt;
            ChildT2 = update(Fun, Bits2, Self2, Depth2, ChildT),
            Size = tree_size(ChildF) + tree_size(ChildT2),
            #branch{size=Size, childF=ChildF, childT=ChildT2};
        false -&amp;gt;
            ChildF2 = update(Fun, Bits2, Self2, Depth2, ChildF),
            Size = tree_size(ChildF2) + tree_size(ChildT),
            #branch{size=Size, childF=ChildF2, childT=ChildT}
    end.

% iterate through buckets in ascending order of xor distance to Bits
iter(Bits, Tree) -&amp;gt;
    iter(Bits, Tree, fun() -&amp;gt; done end).
                             
iter(_Bits, #leaf{bucket=Bucket}, Iter) -&amp;gt;
    fun () -&amp;gt;
            {Bucket, Iter}
    end;
iter([Bit|Bits], #branch{childF=ChildF, childT=ChildT}, Iter) -&amp;gt;
    case Bit of
        true -&amp;gt;
            iter(Bits, ChildT, iter(Bits, ChildF, Iter));
        false -&amp;gt;
            iter(Bits, ChildF, iter(Bits, ChildT, Iter))
    end.

% --- internal functions ---

tree_size(#leaf{size=Size}) -&amp;gt;
    Size;
tree_size(#branch{size=Size}) -&amp;gt;
    Size.

bucket_update_to_tree({ok, Size, Bucket}) -&amp;gt;
    #leaf{size=Size, bucket=Bucket};
bucket_update_to_tree({split, SplitF, SplitT}) -&amp;gt;
    ChildF = bucket_update_to_tree(SplitF),
    ChildT = bucket_update_to_tree(SplitT),
    #branch{size=tree_size(ChildF)+tree_size(ChildT), childF=ChildF, childT=ChildT}.

% --- end ---
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the corresponding test code.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;% simple buckets used for testing bit_tree

-module(test_bucket).

-include(&quot;conf.hrl&quot;).

-export([bits/1, add/3, split/1, add_to_tree/2, make_tree/1, distance/2, list_from/2]).

-define(MAX_SIZE, 3).
-define(BITS, ?END_BITS).

bits(Int) -&amp;gt;
    util:to_bits(&amp;lt;&amp;lt;Int:?BITS&amp;gt;&amp;gt;).

add(Suffix, Int, Bucket) -&amp;gt;
    split([{Suffix, Int} | Bucket]).

split(Bucket) -&amp;gt;
    if
        length(Bucket) &amp;gt; ?MAX_SIZE -&amp;gt;
            BucketF = [{Suffix2, Int2} || {[false | Suffix2], Int2} &amp;lt;- Bucket],
            BucketT = [{Suffix2, Int2} || {[true | Suffix2], Int2} &amp;lt;- Bucket],
            {split, split(BucketF), split(BucketT)};
        true -&amp;gt;
            {ok, length(Bucket), Bucket}
    end.

add_to_tree(Int, Tree) -&amp;gt;
    bit_tree:update(
      fun (Suffix, _Depth, _Gap_size, Bucket) -&amp;gt;
              add(Suffix, Int, Bucket)
      end,
      bits(Int),
      bits(Int), % dont care about gap for now
      Tree).

make_tree(Ints) -&amp;gt;
    Tree = bit_tree:empty(0, []),
    lists:foldl(fun add_to_tree/2, Tree, Ints).

distance(IntA, IntB) -&amp;gt;
    util:distance({'end', &amp;lt;&amp;lt;IntA:?BITS&amp;gt;&amp;gt;}, {'end', &amp;lt;&amp;lt;IntB:?BITS&amp;gt;&amp;gt;}).

% output *should* be in ascending order
list_from(Int, Tree) -&amp;gt;
    List = util:iter_to_list(bit_tree:iter(bits(Int), Tree)),
    lists:map(
      fun (Bucket) -&amp;gt;
              lists:sort([{distance(Int, Elem), Elem} || {_,Elem} &amp;lt;- Bucket])
      end,
      List).
&lt;/code&gt;&lt;/pre&gt;</description>
	<pubDate>Thu, 24 Mar 2011 23:08:44 +0000</pubDate>
</item>
<item>
	<title>Scattered Thoughts: telehash: bit_trees</title>
	<guid>http://scattered-thoughts.net/one/1300/995285/442278</guid>
	<link>http://scattered-thoughts.net/one/1300/995285/442278</link>
	<description>&lt;p&gt;The next step in building a switch is managing a routing table. Actually, the next step is handling sessions via _ring/_line but I'm still mulling over the protocol so we'll skip to the routing table.
&lt;/p&gt;
&lt;p&gt;I'll add the usual 'I don't understand Kademlia and I don't test my code' disclaimer in here.
&lt;/p&gt;
&lt;p&gt;Routing in the Kademlia paper is described using what can best be called the 'mash everything together and be vague about the details' pattern. I want my switch to be a bit cleaner than that so I've split it into three modules. The first of these is the bit_tree.
&lt;/p&gt;
&lt;p&gt;The bit_tree is a suffix tree which maps ends (lists of bits) to buckets. The bit_tree neither knows nor cares what a bucket is and for now you don't either. The utility of this tree comes down to one important property: the floor of the log (base 2) of the XOR distance between two ends is the height of the smallest sub-tree which contains both of them. Got that? For example, if log(distance(EndA,EndB)) == 7.234... then the height of the smallest sub-tree containing both EndA and EndB is 7 nodes. This makes it easy to locate the nearest known nodes to a specified end, something we are supposed to do in response to a &lt;b&gt;.see&lt;/b&gt; command.
&lt;/p&gt;
&lt;p&gt;So here is a bog-standard binary suffix tree:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;% a bit_tree is either a leaf or a branch
-record(leaf, {
          size, % size of bucket
          bucket % some opaque bucket of stuff
         }).
-record(branch, {
          size, % size(childF) + size(childT)
          childF, % tree containing nodes whose next bit is false
          childT % % tree containing nodes whose next bit is true
         }).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When adding nodes to a bucket we need to keep track of certain numbers which will be used by the router to decide when to split buckets. Some of these are quite complicated so to make this easier we will work with a zipper-like structure instead of using &lt;b&gt;leaf&lt;/b&gt; and &lt;b&gt;branch&lt;/b&gt; directly. If you know what a zipper is the code in this post will make sense. If you don't know what a zipper is, go find out. When you come back the code in this post will make sense.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;% zipper-esque structure marking a position in a bit_tree
-record(finger, {
          sizer, % a size function for buckets
          tree, % current sub-tree
          self, % the path *to* self (the nodes own end). either {down, Down_bits} or {up, Up_bits, Down_bits, Gap}
                % where Gap is the size of the largest tree containing self but not touching this finger
          depth, % the number of bits away from the root tree
          zipper % a list of {Bit, Tree} pairs marking branches NOT taken
         }).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The finger keeps track of where the nodes own end is located in the tree in order to calculate something I have termed the gap - the size of the largest sub-tree containing the nodes own end but not touching the finger.
&lt;/p&gt;
&lt;p&gt;The empty bit_tree is easy to define:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;empty(Self, Bucket, Sizer) -&amp;gt;
    #finger{
       sizer = Sizer,
       tree = #leaf{size=Sizer(Bucket), bucket=Bucket},
       self = {down, Self},
       depth = 0,
       zipper = []
      }.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Moving around within the tree is a little more complicated but if you already went away and read about zippers it should feel familiar. Most of the work is in keeping track of the gap.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;extend(Bits, #finger{tree=#leaf{}}=Finger) -&amp;gt; % must always end on a leaf
    {Bits, Finger};
extend([Next | Bits],
       #finger{
         tree = #branch{childF=ChildF, childT=ChildT},
         self = Self,
         depth = Depth,
         zipper = Zipper
        }=Finger) -&amp;gt;
    {Branch_taken, Branch_missed} =
        case Next of
            false -&amp;gt; {ChildF, ChildT};
            true -&amp;gt; {ChildT, ChildF}
        end,
    Self2 =
        case Self of
            {up, Up, Down, Gap} -&amp;gt;
                % already stepped out of gap
                {up, [not(Next)|Up], Down, Gap};
            {down, [Bit|Down]} when Bit == Next -&amp;gt;
                % still in the gap
                {down, Down};
            {down, [Bit|Down]} when Bit /= Next -&amp;gt;
                % leaving gap, check its size
                {up, [not(Next)], [Bit|Down], tree_size(Branch_missed)}
        end,
    Depth2 = Depth+1,
    Zipper2 = [{not(Next), Branch_missed} | Zipper],
    Finger2 = Finger#finger{
      tree = Branch_taken,
      self = Self2,
      depth = Depth2,
      zipper = Zipper2
     },
    extend(Bits, Finger2).
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;retract(0, Finger) -&amp;gt;
    Finger;
retract(N,
        #finger{
          tree = Tree,
          self = Self,
          depth = Depth,
          zipper = [{Last,Branch}|Zipper]
         }=Finger) when N&amp;gt;0 -&amp;gt;
    Size = tree_size(Tree) + tree_size(Branch),
    Tree2 =
        case Last of
            false -&amp;gt; #branch{size=Size, childF=Branch, childT=Tree};
            true -&amp;gt; #branch{size=Size, childF=Tree, childT=Branch}
        end,
    Self2 =
        case Self of
            {down, Down} -&amp;gt;
                % already in gap
                {down, [Last|Down]};
            {up, [], Down, _Gap} -&amp;gt;
                % just entered gap
                {down, [Last|Down]};
            {up, [Bit|Up], Down, Gap} -&amp;gt;
                % still outside gap
                true = (Bit==Last), % assert
                {up, Up, Down, Gap}
        end,
    Depth2 = Depth-1,
    Finger2 =
        Finger#finger{
          tree=Tree2,
          self=Self2,
          depth=Depth2,
          zipper=Zipper
         },
    retract(N-1, Finger2).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;b&gt;extend&lt;/b&gt; and &lt;b&gt;retract&lt;/b&gt; functions are only used internally. We export a much simpler function, &lt;b&gt;move_to&lt;/b&gt;, which moves the finger to point at the bucket corresponding to the specified end.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;move_to(Bits, #finger{depth=Depth}=Finger) when length(Bits) == ?END_BITS -&amp;gt;
    % !!! naive version
    extend(Bits, retract(Depth, Finger)).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We could make this more efficient by only retracting until the finger meets &lt;b&gt;Bits&lt;/b&gt; partway up. For now I don't expect performance of the bit_tree to be an issue.
&lt;/p&gt;
&lt;p&gt;Now that we can find buckets we can modify them. Deciding when to split buckets is not the concern of the bit_tree so we delegate it to the caller.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;update(Fun,
       #finger{
         sizer=Sizer,
         tree=#leaf{bucket=Bucket}
        }=Finger) -&amp;gt;
    Tree = bucket_update_to_tree(Sizer, Fun(Bucket)),
    Finger#finger{tree=Tree}.

bucket_update_to_tree(Sizer, {ok, Bucket}) -&amp;gt;
    #leaf{size=Sizer(Bucket), bucket=Bucket};
bucket_update_to_tree(Sizer, {split, SplitF, SplitT}) -&amp;gt;
    ChildF = bucket_update_to_tree(Sizer, SplitF),
    ChildT = bucket_update_to_tree(Sizer, SplitT),
    #branch{size=tree_size(ChildF)+tree_size(ChildT), childF=ChildF, childT=ChildT}.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In order to handle &lt;b&gt;.see&lt;/b&gt; commands the &lt;b&gt;iter&lt;/b&gt; function is used to return buckets in order of distance from the specified end. Here we are making use of the aforementioned nice properties of the bit_tree in order to efficiently return the buckets in order.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;% iterate through buckets in ascending order of xor distance to (current position ++ Suffix)
iter(Suffix, #finger{tree=Tree, zipper=Zipper}) -&amp;gt;
    iter_buckets(Tree, Suffix, iter_zipper(Zipper, Suffix)).

% iterate through buckets in ascending order of xor distance to (current position ++ Suffix)
iter_zipper([], _Suffix) -&amp;gt;
    fun () -&amp;gt;
            done
    end;
iter_zipper([{Bit, Tree} | Zipper], Suffix) -&amp;gt;
    iter_buckets(Tree, Suffix, iter_zipper(Zipper, [not(Bit)|Suffix])).

% iterate through buckets in ascending order of xor distance to Bits, then hand over to Iter
iter_buckets(#leaf{bucket=Bucket}, _Bits, Iter) -&amp;gt;
    fun () -&amp;gt;
            {Bucket, Iter}
    end;
iter_buckets(#branch{childF=ChildF, childT=ChildT}, [Bit|Bits], Iter) -&amp;gt;
    case Bit of
        true -&amp;gt;
            iter_buckets(ChildT, Bits, iter_buckets(ChildF, Bits, Iter));
        false -&amp;gt;
            iter_buckets(ChildF, Bits, iter_buckets(ChildT, Bits, Iter))
    end.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It will typically be called like this:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{Suffix, Tree2} = bit_tree:move_to(util:to_bits(End), Tree),
bit_tree:iter(Suffix, Tree2)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Splitting the routing table into separate structures like this makes for easier testing. The bit_tree can be tested independently using really simple buckets where the elements are just integers and the buckets split when they reach more than three elements.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;% simple buckets used for testing bit_tree

-module(test_bucket).

-include(&quot;conf.hrl&quot;).

-export([bits/1, add/3, split/1, move_to/2, add_to_tree/2, make_tree/2, distance/2, move_list_from/2, list_from/3]).

-define(MAX_SIZE, 3).
-define(BITS, ?END_BITS).

bits(Int) -&amp;gt;
    util:to_bits(&amp;lt;&amp;lt;Int:?BITS&amp;gt;&amp;gt;).

add(Suffix, Int, Bucket) -&amp;gt;
    split([{Suffix, Int} | Bucket]).

split(Bucket) -&amp;gt;
    if
        length(Bucket) &amp;gt; ?MAX_SIZE -&amp;gt;
            BucketF = [{Suffix2, Int2} || {[false | Suffix2], Int2} &amp;lt;- Bucket],
            BucketT = [{Suffix2, Int2} || {[true | Suffix2], Int2} &amp;lt;- Bucket],
            {split, split(BucketF), split(BucketT)};
        true -&amp;gt;
            {ok, Bucket}
    end.

move_to(Int, Tree) -&amp;gt;
    bit_tree:move_to(bits(Int), Tree).

add_to_tree(Int, Tree) -&amp;gt;
    {Suffix, Tree2} = move_to(Int, Tree),
    bit_tree:update(fun (Bucket) -&amp;gt; add(Suffix, Int, Bucket) end, Tree2).

make_tree(Int, Ints) -&amp;gt;
    Tree = bit_tree:empty(bits(Int), [], fun (Bucket) -&amp;gt; length(Bucket) end),
    lists:foldl(fun add_to_tree/2, Tree, Ints).

distance(IntA, IntB) -&amp;gt;
    util:distance({'end', &amp;lt;&amp;lt;IntA:?BITS&amp;gt;&amp;gt;}, {'end', &amp;lt;&amp;lt;IntB:?BITS&amp;gt;&amp;gt;}).

% output *should* be in ascending order
move_list_from(Int, Tree) -&amp;gt;
    {Suffix, Tree2} = bit_tree:move_to(bits(Int), Tree),
    list_from(Int, Suffix, Tree2).

list_from(Int, Suffix, Tree) -&amp;gt;
    List = util:iter_to_list(bit_tree:iter(Suffix, Tree)),
    lists:map(
      fun (Bucket) -&amp;gt;
              lists:sort([{distance(Int, Elem), Elem} || {_,Elem} &amp;lt;- Bucket])
      end,
      List).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can play around with the test buckets a bit:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;25&amp;gt; Tree = test_bucket:make_tree(47, lists:seq(1,1000)).
{finger,#Fun&amp;lt;test_bucket.1.121651971&amp;gt;,
        {leaf,1,[{[false,false,false],1000}]},
        {up,[false,true,false,false,false,false,false,true,true,
             true,true,true,true,true,true,true,true,true,true,true,true,
             true,true|...],
            [true,true,true,true,true,true,true,true,true,true,true,
             true,true,true,true,true,true,true,true,true,true,true|...],
            0},
        157,
        [{false,{branch,8,
                        {branch,4,
                                {leaf,2,[{[true],993},{[false],992}]},
                                {leaf,2,[{[true],995},{[false],994}]}},
                        {branch,4,
                                {leaf,2,[{[true],997},{[false],996}]},
                                {leaf,2,[{[true],999},{[false],998}]}}}},
         {true,{leaf,0,[]}},
         {false,{branch,32,
                        {branch,16,
                                {branch,8,
                                        {branch,4,
                                                {leaf,2,[{[true],961},{[...],...}]},
                                                {leaf,2,[{[...],...},{...}]}},
                                        {branch,4,
                                                {leaf,2,[{[...],...},{...}]},
                                                {leaf,2,[{...}|...]}}},
                                {branch,8,
                                        {branch,4,{leaf,2,[{[...],...},{...}]},{leaf,2,[{...}|...]}},
                                        {branch,4,{leaf,2,[{...}|...]},{leaf,2,[...]}}}},
                        {branch,16,
                                {branch,8,
                                        {branch,4,{leaf,2,[{[...],...},{...}]},{leaf,2,[{...}|...]}},
                                        {branch,4,{leaf,2,[{...}|...]},{leaf,2,[...]}}},
                                {branch,8,
                                        {branch,4,{leaf,2,[{...}|...]},{leaf,2,[...]}},
                                        {branch,4,{leaf,2,[...]},{leaf,2,...}}}}}},
         {false,{branch,64,
                        {branch,32,
                                {branch,16,
                                        {branch,8,
                                                {branch,4,{leaf,2,...},{leaf,...}},
                                                {branch,4,{leaf,...},{...}}},
                                        {branch,8,{branch,4,{leaf,...},{...}},{branch,4,{...},...}}},
                                {branch,16,
                                        {branch,8,{branch,4,{leaf,...},{...}},{branch,4,{...},...}},
                                        {branch,8,{branch,4,{...},...},{branch,4,...}}}},
                        {branch,32,
                                {branch,16,
                                        {branch,8,{branch,4,{leaf,...},{...}},{branch,4,{...},...}},
                                        {branch,8,{branch,4,{...},...},{branch,4,...}}},
                                {branch,16,
                                        {branch,8,{branch,4,{...},...},{branch,4,...}},
                                        {branch,8,{branch,4,...},{branch,...}}}}}},
         {false,{branch,128,
                        {branch,64,
                                {branch,32,
                                        {branch,16,
                                                {branch,8,{branch,...},{...}},
                                                {branch,8,{...},...}},
                                        {branch,16,{branch,8,{...},...},{branch,8,...}}},
                                {branch,32,
                                        {branch,16,{branch,8,{...},...},{branch,8,...}},
                                        {branch,16,{branch,8,...},{branch,...}}}},
                        {branch,64,
                                {branch,32,
                                        {branch,16,{branch,8,{...},...},{branch,8,...}},
                                        {branch,16,{branch,8,...},{branch,...}}},
                                {branch,32,
                                        {branch,16,{branch,8,...},{branch,...}},
                                        {branch,16,{branch,...},{...}}}}}},
         {false,{branch,256,
                        {branch,128,
                                {branch,64,
                                        {branch,32,{branch,16,{...},...},{branch,16,...}},
                                        {branch,32,{branch,16,...},{branch,...}}},
                                {branch,64,
                                        {branch,32,{branch,16,...},{branch,...}},
                                        {branch,32,{branch,...},{...}}}},
                        {branch,128,
                                {branch,64,
                                        {branch,32,{branch,16,...},{branch,...}},
                                        {branch,32,{branch,...},{...}}},
                                {branch,64,
                                        {branch,32,{branch,...},{...}},
                                        {branch,32,{...},...}}}}},
         {false,{branch,511,
                        {branch,255,
                                {branch,127,
                                        {branch,63,{branch,31,...},{branch,...}},
                                        {branch,64,{branch,...},{...}}},
                                {branch,128,
                                        {branch,64,{branch,...},{...}},
                                        {branch,64,{...},...}}},
                        {branch,256,
                                {branch,128,
                                        {branch,64,{branch,...},{...}},
                                        {branch,64,{...},...}},
                                {branch,128,{branch,64,{...},...},{branch,64,...}}}}},
         {true,{leaf,0,[]}},
         {true,{leaf,0,[]}},
         {true,{leaf,0,[]}},
         {true,{leaf,0,[]}},
         {true,{leaf,0,[]}},
         {true,{leaf,0,[]}},
         {true,{leaf,0,[]}},
         {true,{leaf,0,[]}},
         {true,{leaf,0,[]}},
         {true,{leaf,0,[]}},
         {true,{leaf,0,[]}},
         {true,{leaf,0,...}},
         {true,{leaf,...}},
         {true,{...}},
         {true,...},
         {...}|...]}
26&amp;gt; List = test_bucket:move_list_from(657, Tree).
[[{0,657},{1,656}],
 [{2,659},{3,658}],
 [{4,661},{5,660}],
 [{6,663},{7,662}],
 [{8,665},{9,664}],
 [{10,667},{11,666}],
 [{12,669},{13,668}],
 [{14,671},{15,670}],
 [{16,641},{17,640}],
 [{18,643},{19,642}],
 [{20,645},{21,644}],
 [{22,647},{23,646}],
 [{24,649},{25,648}],
 [{26,651},{27,650}],
 [{28,653},{29,652}],
 [{30,655},{31,654}],
 [{32,689},{33,688}],
 [{34,691},{35,690}],
 [{36,693},{37,692}],
 [{38,695},{39,694}],
 [{40,697},{41,696}],
 [{42,699},{43,698}],
 [{44,701},{45,700}],
 [{46,703},{47,702}],
 [{48,673},{49,672}],
 [{50,675},{51,...}],
 [{52,...},{...}],
 [{...}|...],
 [...]|...]
27&amp;gt; lists:flatten(List) == lists:sort(lists:flatten(List)).
true
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As usual the full code is in the &lt;a href=&quot;http://github.com/jamii/erl-telehash&quot;&gt;repo&lt;/a&gt;.
&lt;/p&gt;</description>
	<pubDate>Thu, 24 Mar 2011 19:34:45 +0000</pubDate>
</item>
<item>
	<title>erlang.org RSS Feed: New Site Look</title>
	<guid>http://www.erlang.org/news/14</guid>
	<link>http://www.erlang.org/news/14</link>
	<description>&lt;p&gt;&lt;p&gt;
	Our demo site has now been launched as the regular erlang.org. We hope you like it. Report any problems.&lt;/p&gt;
&lt;/p&gt;</description>
	<pubDate>Thu, 24 Mar 2011 18:11:55 +0000</pubDate>
</item>
<item>
	<title>Erlang Training and Consulting &lt;br/&gt;- News: 24 March 2011: Erlang Solutions partners with Travelping to provide next generation AAA Solutions to telecom operators</title>
	<guid>http://www.erlang-solutions.com/news/1/entry/1229</guid>
	<link>http://www.erlang-solutions.com/news/1/entry/1229</link>
	<description>&lt;p&gt;Erlang Solutions (ESL), the driver behind the worldwide uptake of the   Erlang development environment, today announced its partnership with   Travelping, a Germany based software vendor offering solutions for   network operators to build, manage and charge their broadband services   securely and efficiently.&amp;nbsp; Together, the two companies will offer   operators highly scalable, robust and distributed, control plane   solutions to build AAA and session control systems for their next   generation networks (NGN).&lt;/p&gt;
&lt;p&gt;For more information please see the &lt;a href=&quot;http://www.erlang-solutions.com/press-releases/3/entry/1228&quot;&gt;press release.&lt;/a&gt;&lt;/p&gt;</description>
	<pubDate>Thu, 24 Mar 2011 17:17:22 +0000</pubDate>
</item>
<item>
	<title>Trapexit's Erlang Blog Filter: Don&amp;#8217;t Lose Your ets Tables</title>
	<guid>http://steve.vinoski.net/blog/?p=722</guid>
	<link>http://steve.vinoski.net/blog/2011/03/23/dont-lose-your-ets-tables/</link>
	<description>&lt;p&gt;In my &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://qconlondon.com/london-2011/file?path=/qcon-london-2011/slides/SteveVinoski_LetItCrashExceptWhenYouShouldnt.pdf&quot;&gt;recent QCon talk&lt;/a&gt; I talked about accidentally crashing an Erlang process on a customer&amp;#8217;s subscription streaming video website running live in production. The code involved had not been used in production before, and the customer had decided somewhat unexpectedly to turn on a new feature that required it. The developer who wrote it had not tested it and had long since left the company.&lt;/p&gt;
&lt;p&gt;The purpose of the code was to monitor bandwidth and session usage for each video subscriber to make sure they weren&amp;#8217;t streaming more than they&amp;#8217;d paid for. Concerned about the viability of the code, a colleague and I logged into the customer site (with their permission, of course), chose a subscriber at random, and, in an Erlang shell, I interactively invoked a function in the code in question to check that subscriber&amp;#8217;s current bandwidth and session count. After a second check, we saw the numbers dropping, potentially indicating the subscriber was logging out, and we wanted to make sure all went well when the subscriber completely stopped streaming. After waiting a bit, I interactively called the function again, and &amp;mdash; &lt;strong&gt;BAM!&lt;/strong&gt; &amp;mdash; the process holding session state for all paying customers crashed.&lt;/p&gt;
&lt;p&gt;The original developer had used an Erlang &lt;code&gt;ets&lt;/code&gt; table, an in-memory data store, to hold the subscriber data, and wrote something like this for lookups:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[SubscriberData] = ets:lookup(Table, Subscriber),&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;My interactive call from the shell looked up a nonexistent subscriber, so the result was the empty list &lt;code&gt;[]&lt;/code&gt; rather than &lt;code&gt;[SubscriberData]&lt;/code&gt;, which caused a pattern mismatch and a &lt;code&gt;badmatch&lt;/code&gt; exception. Uncaught, the exception crashed the process. Since the process owned the &lt;code&gt;ets&lt;/code&gt; table, when it went down it took the &lt;code&gt;ets&lt;/code&gt; table and all subscriber session data with it. It wasn&amp;#8217;t so bad, since all it meant was that for a few hours a few subscribers potentially got a bit more video than they&amp;#8217;d paid for, but still, it&amp;#8217;s not at all the kind of design Erlang&amp;#8217;s &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.erlang.org/download/armstrong_thesis_2003.pdf&quot;&gt;&amp;#8220;Let It Crash&amp;#8221; philosophy&lt;/a&gt; actually encourages. Crashing a process when something unexpected occurs is perfectly fine, since coding defensively introduces problems of its own, but you can still avoid losing your &lt;code&gt;ets&lt;/code&gt; tables like this relatively easily.&lt;/p&gt;
&lt;h3&gt;Name an Heir&lt;/h3&gt;
&lt;p&gt;When you create an &lt;code&gt;ets&lt;/code&gt; table you can also name a process to inherit the table should the creating process die:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;TableId = ets:new(my_table, [{heir, SomeOtherProcess, HeirData}]),&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the creating process dies, the process &lt;code&gt;SomeOtherProcess&lt;/code&gt; will receive a message of the form&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{'ETS-TRANSFER', TableId, OldOwner, HeirData}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where &lt;code&gt;TableId&lt;/code&gt; is the table identifier returned from &lt;code&gt;ets:new&lt;/code&gt;, &lt;code&gt;OldOwner&lt;/code&gt; is the pid of the process that owned the table, and &lt;code&gt;HeirData&lt;/code&gt; is the data provided with the &lt;code&gt;heir&lt;/code&gt; option passed to &lt;code&gt;ets:new&lt;/code&gt;. Once it receives this message, &lt;code&gt;SomeOtherProcess&lt;/code&gt; owns the table.&lt;/p&gt;
&lt;h3&gt;Give It Away&lt;/h3&gt;
&lt;p&gt;Alternatively, you can create an &lt;code&gt;ets&lt;/code&gt; table and then give it to some other process to keep it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;TableId = ets:new(my_table, []),
ets:give_away(TableId, SomeOtherProcess, GiftData),&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;If the creating process dies, the process &lt;code&gt;SomeOtherProcess&lt;/code&gt; will receive a message of the form&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{'ETS-TRANSFER', TableId, OldOwner, GiftData}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where &lt;code&gt;TableId&lt;/code&gt; is the table identifier returned from &lt;code&gt;ets:new&lt;/code&gt;, &lt;code&gt;OldOwner&lt;/code&gt; is the pid of the process that owned the table, and &lt;code&gt;GiftData&lt;/code&gt; is the data provided in the &lt;code&gt;ets:give_away&lt;/code&gt; call. Once it receives this message, &lt;code&gt;SomeOtherProcess&lt;/code&gt; owns the table.&lt;/p&gt;
&lt;h3&gt;Table Manager&lt;/h3&gt;
&lt;p&gt;Instead of naming an heir or giving a table away, you can just have your Erlang &lt;code&gt;supervisor&lt;/code&gt; process create a child process whose sole task is to own the table. This process creates the table as a named public table, thus allowing other processes to know its name and read/write it directly, with &lt;code&gt;ets&lt;/code&gt; built-in concurrency protection dealing with any concurrency issues. Since the owner process does nothing more than create the table and then wait to be told to shut down, the likelihood of it crashing and taking the table with it is practically nil. The drawback here, though, is that the process actually using the table may have to coordinate with the owner process to ensure the table is available, and worse, it ends up using what is essentially a global variable &amp;mdash; the table name &amp;mdash; which can make code harder to read and maintain.&lt;/p&gt;
&lt;h3&gt;A Combination Approach&lt;/h3&gt;
&lt;p&gt;A nice way of managing &lt;code&gt;ets&lt;/code&gt; tables, though, is to use a combination of the three previous techniques:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The Erlang &lt;code&gt;supervisor&lt;/code&gt; creates a table manager process. Since all this process does is manage the table, the likelihood of it crashing is very low.&lt;/li&gt;
&lt;li&gt;The table manager links itself to the table user process and traps exits, allowing it to receive an &lt;code&gt;EXIT&lt;/code&gt; message if the table user process dies unexpectedly.&lt;/li&gt;
&lt;li&gt;The table manager creates a table, names itself (&lt;code&gt;self()&lt;/code&gt;) as the heir, and then gives it away to the table user process.&lt;/li&gt;
&lt;li&gt;If the table user process dies, the table manager is informed of the process death and also inherits the table back.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Once it inherits the table, the table manager can then for example wait until the &lt;code&gt;supervisor&lt;/code&gt; recreates the table user process, and then repeat the steps above to give the table to the new table user process. Other variations on this approach, like maybe a small pool of child process clones that cooperate to transfer the table between them in case of error, are of course also possible. Even though there are still process coordination issues here (but nothing difficult), I like this approach because it avoids global named tables and takes advantage of Erlang's supervision hierarchy.&lt;/p&gt;
&lt;p&gt;The title of my QCon talk was &quot;Let It Crash...Except When You Shouldn't.&quot; This scenario is an example of &quot;when you shouldn't&quot; &amp;mdash; losing &lt;code&gt;ets&lt;/code&gt; data due to a process crash is easily avoided.&lt;/p&gt;</description>
	<pubDate>Wed, 23 Mar 2011 15:01:51 +0000</pubDate>
</item>
<item>
	<title>Damien Katz: Couchbase SF Training Was Awesome</title>
	<guid>tag:damienkatz.net,2011://1.594</guid>
	<link>http://damienkatz.net/2011/03/couchbase_sf_training_was_awes.html</link>
	<description>&lt;p&gt;I had a blast teaching the first Couchbase CouchDB Training with training pro Alan McKean last week. 2 intensive days of hands on teaching and talking about Apache CouchDB to enthusiastic and excited people. It was actually a learning experience for me too, there's a lot in CouchDB I haven't had a chance to use yet :)&lt;/p&gt;

&lt;p&gt;It's not too late to sign up for the remaining 3 cities on the Couchbase Training World Tour:  &lt;a href=&quot;http://austincouchdbtraining.eventbrite.com/&quot;&gt;Austin&lt;/a&gt;, &lt;a href=&quot;http://londoncouchdbtraining.eventbrite.com&quot;&gt;London&lt;/a&gt; and &lt;a href=&quot;http://berlincouchdbtraining.eventbrite.com&quot;&gt;Berlin&lt;/a&gt;.&lt;/p&gt;</description>
	<pubDate>Mon, 21 Mar 2011 22:49:00 +0000</pubDate>
</item>
<item>
	<title>Scattered Thoughts: telehash: dialing</title>
	<guid>http://scattered-thoughts.net/one/1300/720479/161992</guid>
	<link>http://scattered-thoughts.net/one/1300/720479/161992</link>
	<description>&lt;p&gt;The next step in building a telehash switch is being able to dial.
&lt;/p&gt;
&lt;p&gt;First a disclaimer: this post reflects my current understanding of TeleHash and Kademlia and is highly likely to be wrong. This code has only received minimal testing. Properly testing a p2p network is not something I'm entirely sure how to do yet. Expect to see more on that in later posts.
&lt;/p&gt;
&lt;p&gt;Each TeleHash node and each key in the DHT is identified by a 160 bit sha1 hash (aka end). In the original Kademlia paper the node ids are selected at random but in TeleHash they are the hashed address (IP:port) of the node. This means that malicious nodes don't get to choose where they are inserted in the DHT.
&lt;/p&gt;
&lt;p&gt;Kademlia routing is based on the XOR distance between ends. This forms a metric space over the set of ends.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;distance(A, B) -&amp;gt;
    {'end', EndA} = to_end(A),
    {'end', EndB} = to_end(B),
    Bytes = lists:zip(binary_to_list(EndA), binary_to_list(EndB)),
    Xor = list_to_binary([ByteA bxor ByteB || {ByteA, ByteB} &amp;lt;- Bytes]),
    &amp;lt;&amp;lt;Dist:?END_BITS&amp;gt;&amp;gt; = Xor,
    Dist.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The Kademlia paper defines two constants, &lt;b&gt;K&lt;/b&gt; and &lt;b&gt;A&lt;/b&gt;. &lt;b&gt;K&lt;/b&gt; controls the amount of redundant storage in the DHT and &lt;b&gt;A&lt;/b&gt; controls the number of parallel requests issued by each node. To insert a key into the DHT a node must be able to locate the &lt;b&gt;K&lt;/b&gt; nodes whose IDs are closest to the key. This process is called dialing.
&lt;/p&gt;
&lt;p&gt;Dialing works roughly as follows. Each node keeps track of all the other nodes it has seen. Upon receiving a &lt;b&gt;+end&lt;/b&gt; signal a node will reply with a &lt;b&gt;.see&lt;/b&gt; command containing the &lt;b&gt;K&lt;/b&gt; nodes it is aware of which are closest to the specified end. To dial an end we send a &lt;b&gt;+end&lt;/b&gt; signal to each of the &lt;b&gt;K&lt;/b&gt; closest nodes we are aware of. Then to each node contained in the &lt;b&gt;.see&lt;/b&gt; replies we send &lt;b&gt;+end&lt;/b&gt; signals, and so on until we run out of nodes to contact.
&lt;/p&gt;
&lt;p&gt;Now this is nice and simple and will work but it generates a huge amount of load on the network. To reduce this Kademlia introduces two additional rules. First, we only send up to &lt;b&gt;A&lt;/b&gt; signals at a time and don't send any new signals until previous signals have either generated a reply or timed out. Second, we finish early if at any point we have received replies from &lt;b&gt;K&lt;/b&gt; nodes which are closer to the end than all the nodes we are waiting to contact. The Kademlia paper proves that under reasonable assumptions about the knowledge of each node this still has a very high chance to return the correct results.
&lt;/p&gt;
&lt;p&gt;The dialer process is an event handler which has two important data structures. The first stores the dialer configuration:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;-record(conf, {
          target, % the end to dial
          timeout, % the timeout for the entire dialing process
          ref, caller % reply details
         }).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The second record stores the state of the dialing process. The principle around which the dialer is designed is that the state record is a reflection of the outside world and the sole job of the dialer is to keep this record up to date while maintaining the invariants in the comments. This is often the way that I write code and I feel that it needs it's own post once I can articulate it properly. It's certainly heavily informed both by the designs in Okasaki's &lt;a href=&quot;http://books.google.co.uk/books?id=SxPzSTcTalAC&amp;printsec=frontcover&amp;dq=okasaki+purely+functional&amp;hl=en&amp;ei=6GiHTdTcKY_RcfjR_ZkD&amp;sa=X&amp;oi=book_result&amp;ct=result&amp;resnum=1&amp;ved=0CC4Q6AEwAA#v=onepage&amp;q&amp;f=false&quot;&gt;Purely Functional Data Structures&lt;/a&gt; and by Conal Elliott's ideas about &lt;a href=&quot;http://conal.net/blog/posts/denotational-design-with-type-class-morphisms/&quot;&gt;denotational semantics and type class morphisms&lt;/a&gt;.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;-record(state, {
          fresh, % nodes which have not yet been contacted
          pinged, % nodes which have been contacted and have not replied
          waiting, % nodes in pinged which were contacted less than ?DIAL_TIMEOUT ago
          ponged, % nodes which have been contacted and have replied
          seen % all nodes which have been seen
         }). % invariant: pq:length(waiting) = ?A or pq:empty(fresh)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The dialer module exports the &lt;b&gt;dial&lt;/b&gt; function which creates the records and starts the event handler.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;dial(To, From, Timeout) -&amp;gt;
    log:info([?MODULE, dialing, To, From, Timeout]),
    Ref = erlang:make_ref(),
    Target = util:to_end(To),
    Conf = #conf{
      target = Target,
      timeout = Timeout,
      ref = Ref,
      caller = self()
     },
    Nodes = [{util:distance(Address, Target), Address}
             || Address &amp;lt;- From],
    State = #state{
      fresh=pq:from_list(Nodes),
      pinged=sets:new(),
      waiting=pq:empty(),
      ponged=pq:empty(),
      seen=sets:new()
     },
    ok = switch:add_handler(?MODULE, {Conf, State}),
    Ref.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The aim is to handle events and maintain the state invariants until we are finished. How do we define finished?
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;% is the dialing finished yet?
finished(#state{fresh=Fresh, waiting=Waiting, ponged=Ponged}) -&amp;gt;
    (pq:is_empty(Fresh) and pq:is_empty(Waiting)) % no way to continue
    or
    (case pq:length(Ponged) &amp;gt;= ?K of
         false -&amp;gt;
             false; % dont yet have K nodes
         true -&amp;gt;
             % finish if the K closest nodes we know are closer than all the nodes we haven't checked yet
             {Dist_fresh, _} = pq:peek(Fresh),
             {Dist_waiting, _} = pq:peek(Waiting),
             {Nodes, _} = pq:pop(Ponged, ?K),
             {Dist_ponged, _} = lists:last(Nodes),
             (Dist_ponged &amp;lt; Dist_fresh) and (Dist_ponged &amp;lt; Dist_waiting)
     end).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One of the invariants we aim to maintain is that either the &lt;b&gt;fresh&lt;/b&gt; queue is empty or the length of the &lt;b&gt;waiting&lt;/b&gt; queue is A. This ensures that we send out &lt;b&gt;+end&lt;/b&gt; signals whenever possible. This invariant is maintained by calling the &lt;b&gt;ping_nodes&lt;/b&gt; function after every event.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;% contact nodes from fresh until the waiting list is full
ping_nodes(#conf{target=Target}, #state{fresh=Fresh, waiting=Waiting, pinged=Pinged}=State) -&amp;gt;
    Num = ?A - pq:length(Waiting),
    {Nodes, Fresh2} = pq:pop(Fresh, Num),
    Telex = {struct, [{'+end', util:end_to_hex(Target)}]},
    lists:foreach(
      fun ({Dist, Address}=Node) -&amp;gt;
              log:info([?MODULE, ping, Dist, Address]),
              switch:send(Address, Telex),
              erlang:send_after(?DIAL_TIMEOUT, self(), {timeout, Node})
      end,
      Nodes),
    Waiting2 = pq:push(Nodes, Waiting),
    Pinged2 = sets:union(Pinged, sets:from_list(Nodes)),
    State#state{fresh=Fresh2, waiting=Waiting2, pinged=Pinged2}.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We handle replies by moving the replying node from the &lt;b&gt;waiting&lt;/b&gt; queue to the &lt;b&gt;ponged&lt;/b&gt; queue and inserting the &lt;b&gt;.see&lt;/b&gt; nodes into the &lt;b&gt;fresh&lt;/b&gt; list. We cannot allow duplicate nodes so the &lt;b&gt;seen&lt;/b&gt; set is kept up to date. The &lt;b&gt;pinged&lt;/b&gt; set will be used later to ensure that we only accept replies from nodes we have already contacted and only accept one reply per node.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;% handle a reply from a node
ponged(Node, See, #state{fresh=Fresh, waiting=Waiting, pinged=Pinged, ponged=Ponged, seen=Seen}=State) -&amp;gt;
    Waiting2 = pq:delete(Node, Waiting),
    Pinged2 = sets:del_element(Node, Pinged),
    Ponged2 = pq:push_one(Node, Ponged),
    New_nodes = lists:filter(fun (See_node) -&amp;gt; not(sets:is_element(See_node, Seen)) end, See),
    Fresh2 = pq:push(New_nodes, Fresh),
    Seen2 = sets:union(Seen, sets:from_list(See)),
    State#state{fresh=Fresh2, waiting=Waiting2, pinged=Pinged2, ponged=Ponged2, seen=Seen2}.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once we are finished we need to return the results to the caller.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;% return results to the caller
return(#conf{ref=Ref, caller=Caller}, #state{ponged=Ponged}) -&amp;gt;
    {Nodes, _} = pq:pop(Ponged, ?K),
    log:info([?MODULE, returning, Nodes]),
    Result = [Address || {_Dist, Address} &amp;lt;- Nodes],
    Caller ! {dialed, Ref, Result}.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, after each event we call &lt;b&gt;continue&lt;/b&gt; to decide whether to finish and return results or to carry on sending signals.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;% either continue to dial or return results
% meant for use at the end of a gen_event callback
continue(Conf, State) -&amp;gt;
    case finished(State) of
        true -&amp;gt;
            return(Conf, State),
            remove_handler;
        false -&amp;gt;
            State2 = ping_nodes(Conf, State),
            {ok, {Conf, State2}}
    end.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The functions above are glued together by a gen_event handler. The handler is attached to the switch gen_event manager and receives an event for each telex arriving at the switch.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;-behaviour(gen_event).
-export([init/1, handle_event/2, handle_call/2, handle_info/2, terminate/2, code_change/3]).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;b&gt;init&lt;/b&gt; function is called when the handler is started. It sends out the first &lt;b&gt;+end&lt;/b&gt; signals and sets a timer that tells the handler when to give up dialling.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;init({#conf{timeout=Timeout}=Conf, State}) -&amp;gt;
    erlang:send_after(Timeout, self(), giveup),
    State2 = ping_nodes(Conf, State),
    {ok, {Conf, State2}}.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The giveup timeout is simple to deal with.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;handle_info(giveup, {Conf, State}) -&amp;gt;
    log:info([?MODULE, giveup, Conf, State]),
    remove_handler;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As are the timeouts from individual signals.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;handle_info({timeout, Node}, {Conf, #state{waiting=Waiting}=State}) -&amp;gt;
    log:info([?MODULE, timeout, Node]),
    State2 = State#state{waiting=pq:delete(Node, Waiting)},
    continue(Conf, State2);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The last callback is the messiest. This essentially just calls &lt;b&gt;ponged&lt;/b&gt; and &lt;b&gt;continue&lt;/b&gt;, but first has to sanity check the incoming message.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;handle_event({recv, Address, Telex}, {#conf{target=Target}=Conf, #state{pinged=Pinged}=State}) -&amp;gt;
    case telex:get(Telex, '.see') of
        {error, not_found} -&amp;gt;
            {ok, {Conf, State}};
        {ok, Address_binaries} -&amp;gt;
            Dist = util:distance(Address, Target),
            Node = {Dist, Address},
            case sets:is_element(Node, Pinged) of % !!! command ids would make a better check
                false -&amp;gt;
                    {ok, {Conf, State}};
                true -&amp;gt;
                    try [{util:distance(Target, Bin), util:binary_to_address(Bin)} || Bin &amp;lt;- Address_binaries] of
                        Nodes -&amp;gt;
                            log:info([?MODULE, pong, Node, Nodes]),
                            State2 = ponged(Node, Nodes, State),
                            continue(Conf, State2)
                    catch
                        _:Error -&amp;gt;
                            log:info([?MODULE, bad_see, Address, Telex, Error, erlang:get_stacktrace()]),
                            {ok, {Conf, State}}
                    end
            end
    end;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That's pretty much it - we now (probably) have a working dialer. I spent a fair few hours teasing this apart but hopefully the end result is fairly simple to understand. The full code is in the &lt;a href=&quot;http://github.com/jamii/erl-telehash&quot;&gt;repo&lt;/a&gt; as always.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;4&amp;gt; switch:start_link().
{ok,&amp;lt;0.79.0&amp;gt;,&amp;lt;0.80.0&amp;gt;}
5&amp;gt; Root = {address, &quot;208.68.163.247&quot;, 42424}.
{address,&quot;208.68.163.247&quot;,42424}
6&amp;gt; dialer:dial_sync(Root, [Root], 10000).

=INFO REPORT==== 21-Mar-2011::14:48:06 ===
    pid: &amp;lt;0.35.0&amp;gt;
    dialer
    dialing
    {address,&quot;208.68.163.247&quot;,42424}
    [{address,&quot;208.68.163.247&quot;,42424}]
    10000

=INFO REPORT==== 21-Mar-2011::14:48:06 ===
    pid: &amp;lt;0.79.0&amp;gt;
    dialer
    ping
    0
    {address,&quot;208.68.163.247&quot;,42424}

=INFO REPORT==== 21-Mar-2011::14:48:06 ===
    pid: &amp;lt;0.80.0&amp;gt;
    switch_event
    send
    {address,&quot;208.68.163.247&quot;,42424}
    struct: [{&amp;lt;&amp;lt;&quot;_to&quot;&amp;gt;&amp;gt;,&amp;lt;&amp;lt;&quot;208.68.163.247:42424&quot;&amp;gt;&amp;gt;},
             {'+end',&amp;lt;&amp;lt;&quot;38666817e1b38470644e004b9356c1622368fa57&quot;&amp;gt;&amp;gt;}]

=INFO REPORT==== 21-Mar-2011::14:48:07 ===
    pid: &amp;lt;0.80.0&amp;gt;
    switch_event
    recv
    {address,&quot;208.68.163.247&quot;,42424}
    struct: [{&amp;lt;&amp;lt;&quot;_ring&quot;&amp;gt;&amp;gt;,18115},
             {&amp;lt;&amp;lt;&quot;.see&quot;&amp;gt;&amp;gt;,
              [&amp;lt;&amp;lt;&quot;204.232.205.180:42424&quot;&amp;gt;&amp;gt;,&amp;lt;&amp;lt;&quot;208.68.163.247:42424&quot;&amp;gt;&amp;gt;]},
             {&amp;lt;&amp;lt;&quot;_br&quot;&amp;gt;&amp;gt;,240},
             {&amp;lt;&amp;lt;&quot;_to&quot;&amp;gt;&amp;gt;,&amp;lt;&amp;lt;&quot;203.218.138.245:42424&quot;&amp;gt;&amp;gt;}]

=INFO REPORT==== 21-Mar-2011::14:48:07 ===
    pid: &amp;lt;0.79.0&amp;gt;
    dialer
    pong
    0: {address,&quot;208.68.163.247&quot;,42424}
    [{535375931004298447338698443374311161987273280591,
      {address,&quot;204.232.205.180&quot;,42424}},
     {0,{address,&quot;208.68.163.247&quot;,42424}}]

=INFO REPORT==== 21-Mar-2011::14:48:07 ===
    pid: &amp;lt;0.79.0&amp;gt;
    dialer
    ping
    0
    {address,&quot;208.68.163.247&quot;,42424}

=INFO REPORT==== 21-Mar-2011::14:48:07 ===
    pid: &amp;lt;0.79.0&amp;gt;
    dialer
    ping
    535375931004298447338698443374311161987273280591
    {address,&quot;204.232.205.180&quot;,42424}

=INFO REPORT==== 21-Mar-2011::14:48:07 ===
    pid: &amp;lt;0.80.0&amp;gt;
    switch_event
    send
    {address,&quot;208.68.163.247&quot;,42424}
    struct: [{&amp;lt;&amp;lt;&quot;_to&quot;&amp;gt;&amp;gt;,&amp;lt;&amp;lt;&quot;208.68.163.247:42424&quot;&amp;gt;&amp;gt;},
             {'+end',&amp;lt;&amp;lt;&quot;38666817e1b38470644e004b9356c1622368fa57&quot;&amp;gt;&amp;gt;}]

=INFO REPORT==== 21-Mar-2011::14:48:07 ===
    pid: &amp;lt;0.80.0&amp;gt;
    switch_event
    send
    {address,&quot;204.232.205.180&quot;,42424}
    struct: [{&amp;lt;&amp;lt;&quot;_to&quot;&amp;gt;&amp;gt;,&amp;lt;&amp;lt;&quot;204.232.205.180:42424&quot;&amp;gt;&amp;gt;},
             {'+end',&amp;lt;&amp;lt;&quot;38666817e1b38470644e004b9356c1622368fa57&quot;&amp;gt;&amp;gt;}]

=INFO REPORT==== 21-Mar-2011::14:48:07 ===
    pid: &amp;lt;0.80.0&amp;gt;
    switch_event
    recv
    {address,&quot;204.232.205.180&quot;,42424}
    struct: [{&amp;lt;&amp;lt;&quot;_ring&quot;&amp;gt;&amp;gt;,16506},
             {&amp;lt;&amp;lt;&quot;.see&quot;&amp;gt;&amp;gt;,
              [&amp;lt;&amp;lt;&quot;204.232.205.180:42424&quot;&amp;gt;&amp;gt;,&amp;lt;&amp;lt;&quot;208.68.163.247:42424&quot;&amp;gt;&amp;gt;]},
             {&amp;lt;&amp;lt;&quot;_br&quot;&amp;gt;&amp;gt;,162},
             {&amp;lt;&amp;lt;&quot;_to&quot;&amp;gt;&amp;gt;,&amp;lt;&amp;lt;&quot;203.218.138.245:42424&quot;&amp;gt;&amp;gt;}]

=INFO REPORT==== 21-Mar-2011::14:48:07 ===
    pid: &amp;lt;0.79.0&amp;gt;
    dialer
    pong
    535375931004298447338698443374311161987273280591: {address,
                                                       &quot;204.232.205.180&quot;,
                                                       42424}
    [{535375931004298447338698443374311161987273280591,
      {address,&quot;204.232.205.180&quot;,42424}},
     {0,{address,&quot;208.68.163.247&quot;,42424}}]

=INFO REPORT==== 21-Mar-2011::14:48:07 ===
    pid: &amp;lt;0.80.0&amp;gt;
    switch_event
    recv
    {address,&quot;208.68.163.247&quot;,42424}
    struct: [{&amp;lt;&amp;lt;&quot;_ring&quot;&amp;gt;&amp;gt;,18115},
             {&amp;lt;&amp;lt;&quot;.see&quot;&amp;gt;&amp;gt;,
              [&amp;lt;&amp;lt;&quot;204.232.205.180:42424&quot;&amp;gt;&amp;gt;,&amp;lt;&amp;lt;&quot;208.68.163.247:42424&quot;&amp;gt;&amp;gt;]},
             {&amp;lt;&amp;lt;&quot;_br&quot;&amp;gt;&amp;gt;,320},
             {&amp;lt;&amp;lt;&quot;_to&quot;&amp;gt;&amp;gt;,&amp;lt;&amp;lt;&quot;203.218.138.245:42424&quot;&amp;gt;&amp;gt;}]

=INFO REPORT==== 21-Mar-2011::14:48:07 ===
    pid: &amp;lt;0.79.0&amp;gt;
    dialer
    pong
    0: {address,&quot;208.68.163.247&quot;,42424}
    [{535375931004298447338698443374311161987273280591,
      {address,&quot;204.232.205.180&quot;,42424}},
     {0,{address,&quot;208.68.163.247&quot;,42424}}]

=INFO REPORT==== 21-Mar-2011::14:48:07 ===
    pid: &amp;lt;0.79.0&amp;gt;
    dialer
    returning
    [{0,{address,&quot;208.68.163.247&quot;,42424}},
     {535375931004298447338698443374311161987273280591,
      {address,&quot;204.232.205.180&quot;,42424}}]
{ok,[{address,&quot;208.68.163.247&quot;,42424},
     {address,&quot;204.232.205.180&quot;,42424}]}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One last note: after I finished writing this I started thinking about what would happen if I run more than one dialer in parallel. Unlike Kademlia, TeleHash does not currently use command IDs so the dialer cannot tell if the response came in reply to its own command or in reply to the command of another dialer on the same node. It's the kind of bug that would be very rare in actual use but might be carefully exploited by a malicious node. Finding these kinds of bugs is going to be really hard.
&lt;/p&gt;</description>
	<pubDate>Mon, 21 Mar 2011 15:14:39 +0000</pubDate>
</item>
<item>
	<title>Learn You Some Erlang: Who Supervises The Supervisors?</title>
	<guid>http://learnyousomeerlang.com/supervisors</guid>
	<link>http://learnyousomeerlang.com/supervisors</link>
	<description>Right in time before the Bay Area Erlang Conference, the supervisors make their place in Learn You Some Erlang. We see how to set up an OTP supervisor, the restart strategies available, how to write children specifications and have a little demonstration where a band manager takes pleasure at firing band members.</description>
	<pubDate>Fri, 18 Mar 2011 12:30:00 +0000</pubDate>
</item>
<item>
	<title>Process-one Blogs: Sea Beyond 2011 Talk 5: Marek Foss on designing mobile collaboration software</title>
	<guid>http://www.process-one.net/en/blogs/article/sea_beyond_2011_talk_5_marek_foss_on_designing_mobile_collaboration_softwar/</guid>
	<link>http://www.process-one.net/en/blogs/article/sea_beyond_2011_talk_5_marek_foss_on_designing_mobile_collaboration_softwar/</link>
	<description>&lt;p&gt;Sea Beyond event was this year heavily focused on mobile real time applications.&lt;/p&gt; &lt;p&gt;Marek Foss, Chief Web Officer at ProcessOne, gave a talk at Sea Beyond 2011 event, sharing some useful design oriented patterns for collaborative real time mobile applications.&lt;/p&gt;
&lt;p&gt;Here is the video of his presentation:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;You can see the slides here:&lt;/p&gt;
&lt;p&gt;








&lt;/p&gt;
&lt;p&gt;Do not miss the &lt;a href=&quot;http://www.process-one.net/en/blogs/article/sea_beyond_2011_video_summary/&quot;&gt;event summary and the other videos from Sea Beyond event&lt;/a&gt;.&lt;/p&gt;</description>
	<pubDate>Thu, 17 Mar 2011 15:46:51 +0000</pubDate>
</item>
<item>
	<title>Scattered Thoughts: telehash: basics</title>
	<guid>http://scattered-thoughts.net/one/1300/366038/597949</guid>
	<link>http://scattered-thoughts.net/one/1300/366038/597949</link>
	<description>&lt;p&gt;&lt;a href=&quot;http://telehash.org&quot;&gt;TeleHash&lt;/a&gt; is a p2p network based on the &lt;a href=&quot;http://en.wikipedia.org/wiki/Kademlia&quot;&gt;Kademlia DHT&lt;/a&gt; that provides addressing and NAT traversal. These are problems that every p2p app has to deal with, including my &lt;a href=&quot;https://github.com/jamii/dissertation&quot;&gt;poppi&lt;/a&gt;. Unfortunately there is no erlang implementation yet so I have to roll my own. The code so far lives &lt;a href=&quot;http://github.com/jamii/erl-telehash&quot;&gt;here&lt;/a&gt; In this first post I'll just cover the absolute basics - sending, receiving, encoding and decoding messages.
&lt;/p&gt;
&lt;p&gt;TeleHash messages (telexes) are utf8-encoded json packets sent over udp. Luckily, mochijson2 uses utf8 by default so encoding/decoding is trivial.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;encode(Telex) -&amp;gt;
    mochijson2:encode(Telex).

decode(Json) -&amp;gt;
    mochijson2:decode(Json).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;b&gt;telex&lt;/b&gt; module also defines some convenience methods for working with json - &lt;b&gt;get/2&lt;/b&gt;, &lt;b&gt;set/3&lt;/b&gt;, &lt;b&gt;update/4&lt;/b&gt; - which are used like this:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;2&amp;gt; T = telex:decode(&quot;{\&quot;foo\&quot;:[\&quot;bar\&quot;, {\&quot;baz\&quot;:0}]}&quot;).
{struct,[{&amp;lt;&amp;lt;&quot;foo&quot;&amp;gt;&amp;gt;,[&amp;lt;&amp;lt;&quot;bar&quot;&amp;gt;&amp;gt;,{struct,[{&amp;lt;&amp;lt;&quot;baz&quot;&amp;gt;&amp;gt;,0}]}]}]}
3&amp;gt; telex:get(T, foo).
[&amp;lt;&amp;lt;&quot;bar&quot;&amp;gt;&amp;gt;,{struct,[{&amp;lt;&amp;lt;&quot;baz&quot;&amp;gt;&amp;gt;,0}]}]
4&amp;gt; telex:get(T, {foo,2}).
{struct,[{&amp;lt;&amp;lt;&quot;baz&quot;&amp;gt;&amp;gt;,0}]}
5&amp;gt; telex:get(T, {foo,2,baz}).
0
6&amp;gt; telex:set(T, {foo,2,baz}, 1).
{struct,[{&amp;lt;&amp;lt;&quot;foo&quot;&amp;gt;&amp;gt;,[&amp;lt;&amp;lt;&quot;bar&quot;&amp;gt;&amp;gt;,{struct,[{&amp;lt;&amp;lt;&quot;baz&quot;&amp;gt;&amp;gt;,1}]}]}]}
7&amp;gt; telex:set(T, bigger, true).
{struct,[{&amp;lt;&amp;lt;&quot;bigger&quot;&amp;gt;&amp;gt;,true},
         {&amp;lt;&amp;lt;&quot;foo&quot;&amp;gt;&amp;gt;,[&amp;lt;&amp;lt;&quot;bar&quot;&amp;gt;&amp;gt;,{struct,[{&amp;lt;&amp;lt;&quot;baz&quot;&amp;gt;&amp;gt;,0}]}]}]}
8&amp;gt; telex:update(T, {foo,2,baz}, fun (X) -&amp;gt; X + 10 end, -1).
{struct,[{&amp;lt;&amp;lt;&quot;foo&quot;&amp;gt;&amp;gt;,[&amp;lt;&amp;lt;&quot;bar&quot;&amp;gt;&amp;gt;,{struct,[{&amp;lt;&amp;lt;&quot;baz&quot;&amp;gt;&amp;gt;,10}]}]}]}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The next step is to be able to send and receive messages. The &lt;b&gt;switch&lt;/b&gt; module runs a gen_server which manages the udp socket and a gen_event which allows other processes to subscribe to incoming messages.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;-module(switch).

-include(&quot;conf.hrl&quot;).

-export([start_link/0, add_handler/2, add_sup_handler/2, send/2]).

-behaviour(gen_server).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).

-record(state, {socket}).
-define(EVENT, switch_event).
-define(SERVER, switch_server).

% --- api ---

start_link() -&amp;gt;
    {ok, Gen_event} = gen_event:start_link({local, ?EVENT}),
    {ok, Gen_server} = gen_server:start_link({local, ?SERVER}, ?MODULE, [], []),
    {ok, Gen_event, Gen_server}.

add_handler(Module, Args) -&amp;gt;
    gen_event:add_handler(?EVENT, Module, Args).

add_sup_handler(Module, Args) -&amp;gt;
    gen_event:add_sup_handler(?EVENT, Module, Args).

send({address, _Host, _Port}=Address, Telex) -&amp;gt;
    gen_server:cast(?SERVER, {telex, Address, Telex}).

% --- gen_server callbacks ---

init([]) -&amp;gt;
    {ok, Socket} = gen_udp:open(?PORT),
    {ok, #state{socket=Socket}}.

handle_call(_Request, _From, State) -&amp;gt;
    {reply, ok, State}.

handle_cast({telex, {address, Host, Port}, Telex}, #state{socket=Socket}=State) -&amp;gt;
    gen_udp:send(Socket, Host, Port, telex:encode(Telex)),
    {noreply, State};
handle_cast(_Msg, State) -&amp;gt;
    {noreply, State}.

handle_info({udp, Socket, Host, Port, Msg}, #state{socket=Socket}=State) -&amp;gt;
    Event = {telex, {address, Host, Port}, telex:decode(Msg)},
    gen_event:notify(?EVENT, Event),
    {noreply, State};
handle_info(_Info, State) -&amp;gt;
    {noreply, State}.

terminate(_Reason, #state{socket=Socket}) -&amp;gt;
    gen_udp:close(Socket),
    ok.

code_change(_OldVsn, State, _Extra) -&amp;gt;
  {ok, State}.

% --- end ---
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To demonstrate this, let's write the simplest possible event handler:
&lt;/p&gt;
&lt;pre&gt;-module(log).

-export([start/0]).
-export([info/1, warn/1, error/1]).

-behaviour(gen_event).
-export([init/1, handle_event/2, handle_call/2, handle_info/2, terminate/2, code_change/3]).

% --- api ---

start() -&amp;gt;
    switch:add_sup_handler(?MODULE, none).

info(Info) -&amp;gt;
    error_logger:info_report([{pid, self()} | Info]).

warn(Warn) -&amp;gt;
    error_logger:warning_report([{pid, self()} | Warn]).

error(Error) -&amp;gt;
    error_logger:error_report([{pid, self()} | Error]).

% --- gen_event callbacks ---

init(none) -&amp;gt;
    {ok, none}.

handle_event(Event, State) -&amp;gt;
    log:info([Event]),
    {ok, State}.

handle_call(_Request, State) -&amp;gt;
    {ok, ok, State}.

handle_info(_Info, State) -&amp;gt;
    {ok, State}.

terminate(_Reason, _State) -&amp;gt;
    ok.

code_change(_OldVsn, State, _Extra) -&amp;gt;
    {ok, State}.

% --- end ---
&lt;/pre&gt;
&lt;p&gt;Here we have some wrappers around the standard error logger and an event handler which (after masses of gen_event boilerplate) simply logs every event.
&lt;/p&gt;
&lt;p&gt;This is enough functionality now to start talking to a TeleHash node:
&lt;/p&gt;
&lt;pre&gt;1&amp;gt; c(util), c(telex), c(switch), c(log).
{ok,log}
2&amp;gt; switch:start_link().
{ok,&amp;lt;0.55.0&amp;gt;,&amp;lt;0.56.0&amp;gt;}
3&amp;gt; log:start().
ok
4&amp;gt; T = {struct, [{'+end', 'a9993e364706816aba3e25717850c26c9cd0d89d'}]}.
{struct,[{'+end',a9993e364706816aba3e25717850c26c9cd0d89d}]}
5&amp;gt; switch:send({address, &quot;127.0.0.1&quot;, 55555}, T).
ok
6&amp;gt;
=INFO REPORT==== 17-Mar-2011::12:21:13 ===
    pid: &amp;lt;0.55.0&amp;gt;
    {telex,{address,{127,0,0,1},55555},
           {struct,[{&amp;lt;&amp;lt;&quot;_ring&quot;&amp;gt;&amp;gt;,5932},
                    {&amp;lt;&amp;lt;&quot;.see&quot;&amp;gt;&amp;gt;,[]},
                    {&amp;lt;&amp;lt;&quot;_br&quot;&amp;gt;&amp;gt;,51},
                    {&amp;lt;&amp;lt;&quot;_to&quot;&amp;gt;&amp;gt;,&amp;lt;&amp;lt;&quot;127.0.0.1:42424&quot;&amp;gt;&amp;gt;}]}}

&lt;/pre&gt;
&lt;p&gt;Here we ask localhost:55555 for the nearest nodes it knows to the end 'a99...89d'. The reply is contained in the &lt;b&gt;.see&lt;/b&gt; field (which is empty because localhost:55555 hasn't seeded itself yet and so doesn't know any nodes at all).
&lt;/p&gt;
&lt;p&gt;The next post will deal with dialing, at which point we will have a working announcer.
&lt;/p&gt;</description>
	<pubDate>Thu, 17 Mar 2011 12:47:18 +0000</pubDate>
</item>
<item>
	<title>erlang.org RSS Feed: R14B02 released</title>
	<guid>http://www.erlang.org/news/13</guid>
	<link>http://www.erlang.org/news/13</link>
	<description>&lt;p&gt;&lt;p&gt;
	&lt;b&gt;Erlang/OTP R14B02&lt;/b&gt; has been released as planned on March 16:th 2011. It is the second R14 service release.&lt;/p&gt;
&lt;p&gt;
	See the release notes in the &lt;a href=&quot;http://www.erlang.org/download/otp_src_R14B02.readme&quot;&gt;readme file&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
	Download the new release from the &lt;a href=&quot;http://www.erlang.org/download.html&quot;&gt;download page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
	&lt;strong&gt;Highlights:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;
		The &amp;quot;halfword&amp;quot; emulator is now official. A 64-bit emulator that uses less memory than the full 64-bit emulator.&lt;/li&gt;
	&lt;li&gt;
		EDoc handles Erlang specifications and types.&lt;/li&gt;
	&lt;li&gt;
		All test suites now run with CommonTest&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;</description>
	<pubDate>Thu, 17 Mar 2011 09:47:43 +0000</pubDate>
</item>
<item>
	<title>Functional Jobs: Junior Erlang Programmer at Klarna (Full-time)</title>
	<guid>urn:uuid:5f7a4a70-d4e1-fe46-52dd-c3fdb10739b5</guid>
	<link>http://functionaljobs.com/jobs/66/junior-erlang-programmer-at-klarna</link>
	<description>&lt;p&gt;&lt;em&gt;The year was 2005 and e-commerce had long been precarious. With an idea to offer secure and simple payment solutions, Klarna was founded that same year. Six years have passed and we have grown to an ambitious and creative company of 500 employees. We have been awarded Company of the Year in -07 (bragging), increased our turnover by 13 570 % (statistics) and managed to become the Nordic market leader (facts). Klarna is partly owned by Investment AB &amp;Ouml;resund and Sequoia Capital - a company that saw the same potential in Google, YouTube and Apple Computer, as they do in us. We think that is a good start.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;Want to join us on a journey beyond the ordinary?&lt;/h3&gt;

&lt;h3&gt;Klarna is looking for Passionate Junior Programmers to the office in Stockholm.&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What do you want?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You do not just wish to learn the techniques and tools used by Facebook, Google, and Amazon to build high-performance, reliable network services, but you also want join in and further develop them. You want to learn Erlang, the language that makes it easy to program in multi-core and distributed environments. You want to be part of an exceptional development team, working with some of the most famous names in the Erlang world.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What do we want?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At Klarna we put development at the center and our development team currently consists of over 40 reputable developers and technicians. We have a great passion and we strive to be in the technological forefront of everything we do: reliable servers, user-friendly Web interface and financial services. Klarna is expanding further and we need more developers who can take our proprietary systems to new heights - a system that is the essence of a financial business that serves millions of consumers around the Nordic and north European region.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who are you?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We are looking for someone who:&lt;/em&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;is a very good programmer and who loves to write qualitative code&lt;/li&gt;
&lt;li&gt;wants to work with a functional programming language at a young and forward business&lt;/li&gt;
&lt;li&gt;has a strong individual drive to get things done&lt;/li&gt;
&lt;li&gt;is creative and dares to think outside the box&lt;/li&gt;
&lt;li&gt;have strong analytical skills and can work independently&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since we have many different nationalities, and therefore several non-Swedish speaking co-workers, at Klarna, it&amp;#039;s important that you have very good knowledge in English. &lt;/p&gt;

&lt;p&gt;Note that we are hiring several people for this position! The selection process is ongoing, so apply immediately. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You want...&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&amp;hellip;to work at one of the fastest growing companies in Sweden where you set the limits.&lt;/li&gt;
&lt;li&gt;&amp;hellip;to be given the possibility to influence and make a difference within a rapidly growing organization on an international market.&lt;/li&gt;
&lt;li&gt;&amp;hellip;to have a workplace filled with job satisfaction, a drive to succeed and an entrepreneurial spirit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;We want...&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&amp;hellip; you to be as dedicated to us as we&amp;rsquo;ll be to you. We don&amp;rsquo;t want you to work for Klarna, we want you to work with Klarna.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Are you up for the challenge?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Send us your CV, a personal letter and a copy of your grade transcripts, all merged into a single pdf. Selection and interviews will be conducted continuously. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Application deadline: May 2nd 2011&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Start date: As soon as possible&lt;/p&gt;

&lt;p&gt;Contact: Lisa St&amp;aring;l, &lt;span class=&quot;spam-protect&quot;&gt;&lt;span class=&quot;user&quot;&gt;lisa [dot] stal&lt;/span&gt; [at] &lt;span class=&quot;host&quot;&gt;klarna [dot] com&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</description>
	<pubDate>Thu, 17 Mar 2011 09:06:49 +0000</pubDate>
</item>
<item>
	<title>Scattered Thoughts: transactional mealy machines</title>
	<guid>http://scattered-thoughts.net/one/1300/292121/72985</guid>
	<link>http://scattered-thoughts.net/one/1300/292121/72985</link>
	<description>&lt;p&gt;This is a hugely overdue post about an interesting system I worked on almost a year ago whilst at &lt;a href=&quot;http://smarkets.com&quot;&gt;Smarkets&lt;/a&gt; and never got around to writing about. Unfortunately I don't have the code in front of me but the overall idea is simple enough to explain without examples.
&lt;/p&gt;
&lt;p&gt;Smarkets is a betting exchange (effectively a small stock exchange for buying and selling bets). The exchange system which handles all the money and manages the markets has quite stringent requirements. We want events to be serializable (because ordering is very important in a fast moving market), low latency and ideally distributed across more than one machine. However the exchange also has to handle a large number of bursty updates focused on a small number of records (popular markets, power users). I'm told that the early prototypes using postgres simply couldn't handle the high contention so a move to a more loosely coupled system was necessary.
&lt;/p&gt;
&lt;p&gt;The architecture in place when I arrived at Smarkets was based on &lt;a href=&quot;http://www.cidrdb.org/cidr2007/papers/cidr07p15.pdf&quot;&gt;this paper&lt;/a&gt; which I highly recommend reading. The main idea is that serializability across machines is difficult verging on impossible and that systems which try to paper over this (eg fully ACID distributed transactions) tend to be fragile at scale. The proposed solution is to identify specific sets of actions which must be serializable and handle each set with a single actor on a single machine. These actors then communicate with each other via asynchronous messages. In Smarkets' case the actors are individual markets, users, accounts and orders. These can be modeled nicely as &lt;a href=&quot;http://en.wikipedia.org/wiki/Mealy_machine&quot;&gt;mealy machines&lt;/a&gt; where the output value is a list of messages, hence the title.
&lt;/p&gt;
&lt;p&gt;This idea was very effective but the implementation at Smarkets was some of the scariest code in the repository (thanks mostly to being the oldest code). Each actor was implemented as a single erlang process which archived messages (using couchdb) after reading them. There was a lot of repetitive boilerplate code, it was hard to test (because the actors message each other directly) and worst of all there were ways to lose messages before they were archived (eg process inbox is lost if the process dies, messages between machines can be dropped silently).
&lt;/p&gt;
&lt;p&gt;I wrote a new system to handle the actor implementation whilst keeping the domain-specific logic of each actor mostly unchanged. Each actor is defined by a pair of callback functions (a behaviour, in erlang-speak). The &lt;b&gt;init&lt;/b&gt; function sets the initial state of the actor. The &lt;b&gt;transition&lt;/b&gt; function takes the current state and an incoming message and returns the new state and possibly some outgoing messages. Everything else is handled by a generic module which takes this behaviour and turns it into a running actor. Each actor consists of an inbox, outbox and a current state, all of which are persisted using mnesia. Each actor also has a unique id used for addressing messages. The transition process - pop a message off the inbox queue, run the transition function, store the new state, push outgoing messages to the outbox - is implemented as a single ACID transaction using mnesia. For actors on the same machine messages are moved directly from one actor’s outbox to another's inbox directly using mnesia transactions. For actors on different machines the outbox using erlang messages and sends repeatedly (with exponential backoff) until the receiver confirms receipt. The outbox attaches auto-incrementing message ids to each message which, together with the actor id of the sender, allows the receiver to ignore duplicate messages.
&lt;/p&gt;
&lt;p&gt;In this way the domain-specific logic is separated from message handling and storage. This led to much less repetition and a more maintainable system. It also made it easy to setup tests or replay past events without recreating the whole system. Last, but certainly not least, it can only lose messages if the database or disk fails and even then is easier to restore from backup than the previous system.
&lt;/p&gt;
&lt;p&gt;Note that this explanation is somewhat simplified. I have glossed over some fiddly implementation details like error handling (if an actor fails to handle a message the sender needs to be notified in many cases) and also left out extra features like subscribing to state changes (eg notify me when this order is filled). There is also a knack to designing actors which must cooperate without &lt;a href=&quot;http://en.wikipedia.org/wiki/Common_knowledge_(logic&quot;&gt;common knowledge&lt;/a&gt;). Hopefully the &lt;a href=&quot;https://smarkets.com/about/contact/&quot;&gt;Smarkets team&lt;/a&gt; will find some time to open-source the actual code.
&lt;/p&gt;</description>
	<pubDate>Wed, 16 Mar 2011 16:15:21 +0000</pubDate>
</item>
<item>
	<title>Erlang Training and Consulting &lt;br/&gt;- News: 16 March 2011: Erlang/OTP R14B02 has been released</title>
	<guid>http://www.erlang-solutions.com/news/1/entry/1227</guid>
	<link>http://www.erlang-solutions.com/news/1/entry/1227</link>
	<description>&lt;p&gt;&lt;strong&gt;Erlang/OTP R14B02&lt;/strong&gt; has been released as previously announced.&lt;/p&gt;
&lt;p&gt;See the release notes in the &lt;a href=&quot;http://erlang.org/download/otp_src_R14B02.readme&quot;&gt;readme file&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Download the new release from the &lt;a href=&quot;http://erlang.org/download.html&quot;&gt;download page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Highlights:&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;EDoc handles Erlang specifications and types&lt;/li&gt;
&lt;li&gt;All tests run with Common Test&lt;/li&gt;
&lt;li&gt;halfword emulator is offcial. Usage --enable-halfword-emulator  during configure. This is Faster and uses less memory than the standard 64-bit  emulator.&lt;/li&gt;
&lt;li&gt;Dependency generation for Makefiles has been added to the compiler and erlc.&lt;/li&gt;
&lt;/ul&gt;</description>
	<pubDate>Wed, 16 Mar 2011 15:17:09 +0000</pubDate>
</item>
<item>
	<title>Erlang Inside: Interview with Tino Breddin, Embedded Erlang developer, on the social science of tech communities.</title>
	<guid>http://erlanginside.com/?p=261</guid>
	<link>http://erlanginside.com/interview-with-tino-breddin-ruby-vs-python-vs-erlang-communities-261</link>
	<description>Why are communities such as Erlang&amp;#8217;s and Ruby&amp;#8217;s so different? What makes them approchable or not? Is America the problem? Should we forcibly relocate all Ruby developers to Sweden? Tino talks about that question and others in this fascinating interview. Follow Tino on twitter at @tolbrino and follow me at @chaddepue. Get an alert when [...]</description>
	<pubDate>Wed, 16 Mar 2011 14:18:17 +0000</pubDate>
</item>
<item>
	<title>ejabberd@jabber.ru: ejabberd 3.0.0-alpha-2 - more alpha testing</title>
	<guid>http://www.ejabberd.im/4586 at http://www.ejabberd.im</guid>
	<link>http://www.ejabberd.im/ejabberd-3.0.0-alpha-2</link>
	<description>&lt;p&gt;This second alpha includes many bugfixes over &lt;a href=&quot;http://www.ejabberd.im/ejabberd-3.0.0-alpha-1&quot;&gt;alpha-1&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The complete list of related tickets can be found on:&lt;br /&gt;
&lt;a href=&quot;http://redir.process-one.net/ejabberd-3.0.0-alpha2&quot; title=&quot;http://redir.process-one.net/ejabberd-3.0.0-alpha2&quot;&gt;http://redir.process-one.net/ejabberd-3.0.0-alpha2&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Please note that the database schema used in this preliminary release is not yet definitive, and it will probably change in the next alpha and beta releases.&lt;/p&gt;
&lt;p&gt;When compiling the source code, it is necessary to install &lt;a href=&quot;http://exmpp.org&quot;&gt;exmpp&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.ejabberd.im/ejabberd-3.0.0-alpha-2&quot; target=&quot;_blank&quot;&gt;read more&lt;/a&gt;&lt;/p&gt;</description>
	<pubDate>Wed, 16 Mar 2011 12:12:17 +0000</pubDate>
</item>
<item>
	<title>Programming in the 21st Century: Don't Distract New Programmers with OOP</title>
	<guid>http://prog21.dadgum.com/93.html</guid>
	<link>http://prog21.dadgum.com/93.html</link>
	<description>When I get asked &quot;What's a good first programming language to teach my [son / daughter / other-person-with-no-programming-experience]?&quot; my answer has been the same for the last 5+ years: Python.
&lt;br /&gt;&lt;br /&gt;That may be unexpected, coming from someone who often talks about non-mainstream languages, but I stand by it.
&lt;br /&gt;&lt;br /&gt;Python is good for a wide range of simple and interesting problems that would be too much effort in C. (Seriously, a basic &lt;a href=&quot;http://prog21.dadgum.com/29.html&quot;&gt;spellchecker&lt;/a&gt; can be implemented in a few lines of Python.) There are surprisingly few sticking points where the solution is easy to see, but there's a tricky mismatch between it and the core language features. Erlang has a couple of biggies. Try implementing any algorithm that's most naturally phrased in terms of in-place array updates, for example. In Python the sailing tends to be smooth. Arrays and dictionaries and sets cover a lot of ground.
&lt;br /&gt;&lt;br /&gt;There's one caveat to using Python as an introductory programming language: avoid the object-oriented features. You can't dodge them completely, as fundamental data types have useful methods associated with them, and that's okay. Just make use of what's already provided and resist talking about how to create classes, and especially avoid talking about any notions of object-oriented design where every little bit of data has to be wrapped up in a class.
&lt;br /&gt;&lt;br /&gt;The shift from procedural to OO brings with it a shift from thinking about problems and solutions to thinking about  &lt;i&gt;architecture&lt;/i&gt;. That's easy to see just by comparing a procedural Python program with an object-oriented one. The latter is almost always longer, full of extra interface and indentation and annotations. The temptation is to start moving trivial bits of code into classes and adding all these little methods and anticipating methods that aren't needed yet but might be someday.
&lt;br /&gt;&lt;br /&gt;When you're trying to help someone learn how to go from a problem statement to working code, the last thing you want is to get them sidetracked by faux-engineering busywork. Some people are going to run with those scraps of OO knowledge and build crazy class hierarchies and end up not as focused on on what they should be learning. Other people are going to lose interest because there's a layer of extra nonsense that makes programming even more cumbersome.
&lt;br /&gt;&lt;br /&gt;At some point, yes, you'll need to discuss how to create objects in Python, but resist for as long as you can.
&lt;br /&gt;&lt;br /&gt;(If you liked this, you might like &lt;a href=&quot;http://prog21.dadgum.com/53.html&quot;&gt;How I Learned to Stop Worrying and Love Erlang's Process Dictionary&lt;/a&gt;.)</description>
	<pubDate>Wed, 16 Mar 2011 06:00:00 +0000</pubDate>
</item>
<item>
	<title>Erlang Factory News: Only 5 Places left at the Erlang Factory SF Bay Area!</title>
	<guid>http://erlang-factory.com/news/rss/e11067ef6a7ce4536d1da29f9dfb8544</guid>
	<link></link>
	<description>&lt;p&gt;We only have 5 places left at the Erlang Factory SF Bay Area so if you haven't booked yet, don't miss out and &lt;a href=&quot;https://www.erlang-factory.com/conference/SFBay2011/register&quot;&gt;book now!&lt;/a&gt; The OTP Express course has now sold out but there are a few places left on the other courses at the &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/university&quot;&gt;University&lt;/a&gt;.&lt;/p&gt;</description>
	<pubDate>Mon, 14 Mar 2011 16:01:17 +0000</pubDate>
</item>
<item>
	<title>Process-one Blogs: Sea Beyond 2011 Talk 4: Eric Cestari on XMPP over Websocket and GitLive web push</title>
	<guid>http://www.process-one.net/en/blogs/article/sea_beyond_2011_talk_4_eric_cestari_on_xmpp_over_websocket_and_gitlive_web_/</guid>
	<link>http://www.process-one.net/en/blogs/article/sea_beyond_2011_talk_4_eric_cestari_on_xmpp_over_websocket_and_gitlive_web_/</link>
	<description>&lt;p&gt;Eric Cestari, From ProcessOne, explains his work on Websocket integration in ejabberd and introduce &lt;a href=&quot;http://gitlive.com&quot;&gt;GitLive&lt;/a&gt; as a demonstration of our web push platform.&lt;/p&gt; &lt;p&gt;This is an interesting view of the present and future of XMPP in the browser. The talk also shows that you can already today build web push service that already takes advantage of websockets for web platforms that supports it.&lt;/p&gt;
&lt;p&gt;All details are in Eric Cestari's talk at Sea Beyond:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;You can see the slides here:&lt;/p&gt;
&lt;p&gt;







&lt;/p&gt;
&lt;p&gt;Do not miss the &lt;a href=&quot;http://www.process-one.net/en/blogs/article/sea_beyond_2011_video_summary/&quot;&gt;event summary and the other videos from Sea Beyond event&lt;/a&gt;.&lt;/p&gt;</description>
	<pubDate>Mon, 14 Mar 2011 11:19:06 +0000</pubDate>
</item>
<item>
	<title>Programming in the 21st Century: Exploring Audio Files with Erlang</title>
	<guid>http://prog21.dadgum.com/92.html</guid>
	<link>http://prog21.dadgum.com/92.html</link>
	<description>It takes surprisingly little Erlang code to dig into the contents of an uncompressed audio file. And it turns out that three of the most common uncompressed audio file formats--WAV, AIFF, and Apple's CAF--all follow the same general structure. Once you understand the basics of one, it's easy to deal with the others. AIFF is the trickiest of the three, so that's the one I'll use as an example.
&lt;br /&gt;&lt;br /&gt;First, load the entire file into a binary:
&lt;pre&gt;load(Filename) -&amp;gt;
   {ok, B} = file:read_file(Filename),
   B.
&lt;/pre&gt;There's a small header: four characters spelling out &quot;FORM&quot;, a length which doesn't matter, then four more characters spelling out &quot;AIFF&quot;. The interesting part is the rest of the file, so let's just validate the header and put the rest of the file into a binary called B:
&lt;pre&gt;&amp;lt;&amp;lt;&quot;FORM&quot;, _:32, &quot;AIFF&quot;, B/binary&amp;gt;&amp;gt; = load(Filename).
&lt;/pre&gt;The &quot;rest of file&quot; binary is broken into chunks that follow a simple format: a four character chunk name, the length of the data in the chunk (which doesn't include the header), and then the data itself. Here's a little function that breaks a binary into a list of &lt;tt&gt;{Chunk_Name, Contents}&lt;/tt&gt; pairs:
&lt;pre&gt;chunkify(Binary) -&amp;gt; chunkify(Binary, []).
chunkify(&amp;lt;&amp;lt;N1,N2,N3,N4, Len:32,
   Data:Len/binary, Rest/binary&amp;gt;&amp;gt;, Chunks) -&amp;gt;
   Name = list_to_atom([N1,N2,N3,N4]),
   chunkify(adjust(Len, Rest), [{Name, Data}|Chunks]);
chunkify(&amp;lt;&amp;lt;&amp;gt;&amp;gt;, Chunks) -&amp;gt;
   Chunks.
&lt;/pre&gt;Ignore the &lt;tt&gt;adjust&lt;/tt&gt; function for now; I'll get back to that. 
&lt;br /&gt;&lt;br /&gt;Given the results of &lt;tt&gt;chunkify&lt;/tt&gt;, it's easy to find a specific chunk using &lt;tt&gt;lists:keyfind/3&lt;/tt&gt;. Really, though, other than to test the chunkification code, there's rarely a reason to iterate through all the chunks in a file. It's nicer to return a function that makes lookups easy. Replace the last line of &lt;tt&gt;chunkify&lt;/tt&gt; with this:
&lt;pre&gt;fun(Name) -&amp;gt; element(2, lists:keyfind(Name, 1, Chunks)) end.
&lt;/pre&gt;The key info about sample rates and number of channels and all that is in a chunk called &lt;tt&gt;COMM&lt;/tt&gt; and now we've got an easy way to get at and decode that chunk:
&lt;pre&gt;Chunks = chunkify(B).
&amp;lt;&amp;lt;Channels:16, Frames:32, Sample_Size:16, Rate:10/binary&amp;gt;&amp;gt; =
   Chunks('COMM').
&lt;/pre&gt;The sound samples themselves are in a chunk called &lt;tt&gt;SSND&lt;/tt&gt;. The first eight bytes of that chunk don't matter, so to decode that chunk it's just:
&lt;pre&gt;&amp;lt;&amp;lt;_:8/binary, Samples/binary&amp;gt;&amp;gt; = Chunks('SSND').
&lt;/pre&gt;Okay, now the few weird bits of the AIFF format. First, if the size of a chunk is odd, then there's one extra pad byte following it. That's what the &lt;tt&gt;adjust&lt;/tt&gt; function is for. It checks if a pad byte exists and removes it before decoding the rest of the binary. The second quirk is that the sample rate is encoded as a ten-byte extended floating point value, and most languages don't have support for them--including Erlang. There's an algorithm in the AIFF spec for encoding and decoding extended floats, and I translated it into Erlang.
&lt;br /&gt;&lt;br /&gt;Here's the complete code for the AIFF decoder:
&lt;pre&gt;load_aiff(Filename) -&amp;gt;
   &amp;lt;&amp;lt;&quot;FORM&quot;, _:32, &quot;AIFF&quot;, B/binary&amp;gt;&amp;gt; = load(Filename),
   Chunks = chunkify(B),
   &amp;lt;&amp;lt;Channels:16, Frames:32, Sample_Size:16, Rate:10/binary&amp;gt;&amp;gt; =
      Chunks('COMM'),
   &amp;lt;&amp;lt;_:8/binary, Samples/binary&amp;gt;&amp;gt; = Chunks('SSND'),
   {Channels, Frames, Sample_Size, extended_to_int(Rate), Samples}.

chunkify(Binary) -&amp;gt; chunkify(Binary, []).
chunkify(&amp;lt;&amp;lt;N1,N2,N3,N4, Length:32,
   Data:Length/binary, Rest/binary&amp;gt;&amp;gt;, Chunks) -&amp;gt;
   Name = list_to_atom([N1,N2,N3,N4]),
   chunkify(adjust(Length, Rest), [{Name, Data}|Chunks]);
chunkify(&amp;lt;&amp;lt;&amp;gt;&amp;gt;, Chunks) -&amp;gt;
   fun(Name) -&amp;gt; element(2, lists:keyfind(Name, 1, Chunks)) end.

adjust(Length, B) -&amp;gt;
   case Length band 1 of
      1 -&amp;gt; &amp;lt;&amp;lt;_:8, Rest/binary&amp;gt;&amp;gt; = B, Rest;
      _ -&amp;gt; B
   end.

extended_to_int(&amp;lt;&amp;lt;_, Exp, Mantissa:32, _:4/binary&amp;gt;&amp;gt;) -&amp;gt;
   extended_to_int(30 - Exp, Mantissa, 0).
extended_to_int(0, Mantissa, Last) -&amp;gt;
   Mantissa + (Last band 1);
extended_to_int(Exp, Mantissa, _Last) -&amp;gt;
   extended_to_int(Exp - 1, Mantissa bsr 1, Mantissa).

load(Filename) -&amp;gt;
   {ok, B} = file:read_file(Filename),
   B.
&lt;/pre&gt;WAV and CAF both follow the same general structure of a header followed by chunks. WAV uses little-endian values, while the other two are big-endian. CAF doesn't have chunk alignment requirements, so that removes the need for &lt;tt&gt;adjust&lt;/tt&gt;. And fortunately it's only AIFF that requires that ugly conversion from extended floating point in order to get the sample rate.</description>
	<pubDate>Sat, 12 Mar 2011 06:00:00 +0000</pubDate>
</item>
<item>
	<title>Process-one Blogs: Sea Beyond 2011 Talk 3: David Banes on Cleartext</title>
	<guid>http://www.process-one.net/en/blogs/article/sea_beyond_2011_talk_3_david_banes_on_cleartext/</guid>
	<link>http://www.process-one.net/en/blogs/article/sea_beyond_2011_talk_3_david_banes_on_cleartext/</link>
	<description>&lt;p&gt;David Banes introduces &lt;a href=&quot;http://www.cleartextsystems.com/&quot;&gt;Cleartext&lt;/a&gt; new opensource product: an Enterprise Messaging 2.0, based on ejabberd for the server part and developed in Adobe Air for the client part.&lt;/p&gt; &lt;p&gt;The platform features of course EIM, Group Chat &amp;amp; Microblogging, has security and compliance designed in, and notably has Integrated Content Filtering, Malware Protection, URL &amp;amp; Image Filtering and Archiving with eDiscovery.&lt;/p&gt;
&lt;p&gt;Enjoy David Bane's presentation:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;You can see the slides here:&lt;/p&gt;
&lt;p&gt;







/p&amp;gt;&lt;/p&gt;
&lt;p&gt;Do not miss the &lt;a href=&quot;http://www.process-one.net/en/blogs/article/sea_beyond_2011_video_summary/&quot;&gt;event summary and the other videos from Sea Beyond event&lt;/a&gt;.&lt;/p&gt;</description>
	<pubDate>Thu, 10 Mar 2011 13:48:46 +0000</pubDate>
</item>
<item>
	<title>Programming in the 21st Century: Accidental Innovation, Part 3</title>
	<guid>http://prog21.dadgum.com/91.html</guid>
	<link>http://prog21.dadgum.com/91.html</link>
	<description>I didn't write the &lt;a href=&quot;http://prog21.dadgum.com/89.html&quot;&gt;previous&lt;/a&gt; &lt;a href=&quot;http://prog21.dadgum.com/90.html&quot;&gt;two&lt;/a&gt; installments so I could build up my ego. I wanted to give concrete examples of innovation and the circumstances surrounding it, to show that it's not magic or glamorous, to show that innovation is more than sitting down and saying &quot;Okay, time to innovate!&quot;
&lt;br /&gt;&lt;br /&gt;It's curious how often the &quot;innovative&quot; stamp is applied to things that don't fit any kind of reasonable definition of the word. How many times have you seen text like this on random company X's &quot;About&quot; page:
&lt;blockquote&gt;We develop innovative solutions which enable enterprise-class cloud computing infrastructure that...something something synergy...something something &quot;outside the box.&quot;
&lt;/blockquote&gt;I've seen that enough that I've formulated a simple rule: If you have to say that you're innovating, then you're not. Or in a less snarky way: Innovation in itself is an empty goal, so if you're using it in the mission statement for the work you're doing, then odds are the rest of the mission statement is equally vacant.
&lt;br /&gt;&lt;br /&gt;Really, the only way to innovate is to do so accidentally.
&lt;br /&gt;&lt;br /&gt;In both the examples I gave, I wasn't thinking about how to do things differently. I was thinking about how to solve a problem and only that problem. The results ended up being interesting because I didn't spend all my time fixated on what other people had done, to the point where that's all I could see. If I started designing a puzzle game in 2011, I'd know all about Tetris and all the knock-offs of Tetris and all the incremental changes and improvements that stemmed from Tetris. It would be difficult work within the restrictions of the label &quot;puzzle game&quot; and come up with something that transcends the boundaries of those restrictions.
&lt;br /&gt;&lt;br /&gt;Suppose it's the late 1990s, and your goal is to design a next generation graphical interface for desktop PCs--something better than Windows. Already you're sunk, because you're looking at Windows, you're thinking about Windows, and all of your decisions will be colored by a long exposure to Windows-like interfaces. There are icons, a desktop, resizable windows, some kind of task bar, etc. What you end up with will almost certainly not be completely identical to Windows, but it won't be innovative.
&lt;br /&gt;&lt;br /&gt;Now there are some interesting problems behind that vague goal of building a next generation GUI. The core question is how to let the user run multiple applications at the same time and switch between them. And that question has some interesting and wide-ranging answers. You can see the results of some of those lines of thinking in current systems, such as doing away with the &quot;app in a movable window&quot; idea and having each application take over the entire screen. Then the question becomes a different one: How to switch between multiple full-screen apps? This is all very different than starting with the desktop metaphor and trying to morph it into something innovative.
&lt;br /&gt;&lt;br /&gt;(If you liked this, you might like &lt;a href=&quot;http://prog21.dadgum.com/69.html&quot;&gt;How to Think Like a Pioneer&lt;/a&gt;.)</description>
	<pubDate>Wed, 09 Mar 2011 06:00:00 +0000</pubDate>
</item>
<item>
	<title>Erlang Training and Consulting &lt;br/&gt;- News: 15 February 2011: Ulf Wiger and Michal Ptaszek will be presenting at the ACCU 2011</title>
	<guid>http://www.erlang-solutions.com/news/1/entry/1226</guid>
	<link>http://www.erlang-solutions.com/news/1/entry/1226</link>
	<description>&lt;p&gt;Two of &lt;a href=&quot;http://www.erlang-solutions.com&quot;&gt;Erlang Solutions&lt;/a&gt; finest programmers will be talking at this years ACCU on April 13-16, 2011 at the Barcelo Oxford Hotel, Oxford, UK.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ulf Wiger &lt;/strong&gt;will give a 90 minute talk titled &quot;How hard can it be? How never to learn from failure.&quot;&lt;/p&gt;
&lt;p&gt;Abstract: Do we ever learn from failure? Already in the Mythical Man-month, Fred Brooks talked about how programmers constantly underestimate difficulty, and, if they didn't, they wouldn't even dare to get started writing code. Programmers get to grips with hard problems by trying to solve them. Boldly exclaiming &quot;how hard can it be?&quot;, we dive in, and often find out exactly how hard it can be. We then try to teach others, but find that they are dead-set on learning the hard way too. In this talk, we will explore with practical examples how this dynamic leads to repeated disasters when scaled to large projects.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Michal Ptaszek &lt;/strong&gt;will give a 90 minute talk on &quot;ComputErl - Erlang-based Framework for Many Task Computing&quot;&lt;/p&gt;
&lt;p&gt;Abstract: This talk shows how the Erlang programming language can be used for creating a framework for distributing and coordinating the execution of many task computing problems. The goals of the proposed solution are (1) to disperse the computation into many tasks, (2) to support multiple well-known computation models (such as master-worker, map-reduce, and pipeline), (3) to exploit the advantages of Erlang for developing an efficient and scalable framework and (4) to build a system that can scale from small to large number of tasks with minimum effort. We present the ComputErl framework, and the promising results in preliminary experiments with benchmarks as well as real scientific applications deployed over hundreds of nodes.&lt;/p&gt;
&lt;p&gt;Other speakers include John Hughes, Tom Preston-Werner and Michael Feathers. you can find more information &lt;a href=&quot;http://www.erlang-solutions.com/events/2/entry/1188&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;</description>
	<pubDate>Mon, 07 Mar 2011 18:02:36 +0000</pubDate>
</item>
<item>
	<title>Process-one Blogs: Sea Beyond 2011 Talk 2: Christophe Romain, Karim Gemayel on Pubsub and distributed social networks</title>
	<guid>http://www.process-one.net/en/blogs/article/sea_beyond_2011_talk_2_christophe_romain_karim_gemayel_on_pubsub_and_distri/</guid>
	<link>http://www.process-one.net/en/blogs/article/sea_beyond_2011_talk_2_christophe_romain_karim_gemayel_on_pubsub_and_distri/</link>
	<description>&lt;p&gt;Christophe Romain and Karim Gemayel presents XMPP pubsub in the context of distributed social networking.&lt;/p&gt; &lt;p&gt;Christophe Romain and Karim Gemayel have been working on XMPP pubsub for several years now. They have build ejabberd implementation as well as custom improvements in various customers context, for features and scalability.&lt;/p&gt;
&lt;p&gt;In this presentation, they explains XMPP pubsub and how it can be used to build distributed social networks.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Do not miss the &lt;a href=&quot;http://www.process-one.net/en/blogs/article/sea_beyond_2011_video_summary/&quot;&gt;event summary and the other videos from Sea Beyond event&lt;/a&gt;.&lt;/p&gt;</description>
	<pubDate>Mon, 07 Mar 2011 14:24:55 +0000</pubDate>
</item>
<item>
	<title>Damien Katz: Is Node.js an application server?</title>
	<guid>tag:damienkatz.net,2011://1.593</guid>
	<link>http://damienkatz.net/2011/03/is_nodejs_an_application_serve.html</link>
	<description>&lt;p&gt;&lt;a href=&quot;http://www.reddit.com/r/programming/comments/fyjod/is_nodejs_wrong/c1jmhjq&quot;&gt;An  insightful comment on Reddit about Node.js&lt;/a&gt;:&lt;br /&gt;
&lt;blockquote&gt;&lt;div&gt;And the idea that you fully understand your own code is a bit suspect, too. My code's all nice and fast until somebody passes me in a POST request with a million keys, or decides to upload a 10GB file where I was expecting a 5KB file and I run a hash algorithm over it, or I accidentally use way more memory than I expected and push the system into swap, or any number of other things like that. My life would be a lot easier if my code never did anything I didn't expect.&lt;/div&gt;&lt;/blockquote&gt;&lt;/p&gt;

&lt;p&gt;I keep wondering where Node fits in a production environment and who writes the code that powers it.&lt;/p&gt;</description>
	<pubDate>Mon, 07 Mar 2011 03:00:04 +0000</pubDate>
</item>
<item>
	<title>Erlang, Testing and TDD: Erlang TDD hand on project – WorkerNet part 8</title>
	<guid>http://erlcode.wordpress.com/?p=685</guid>
	<link>http://erlcode.wordpress.com/2011/03/05/erlang-tdd-hand-on-project-workernet-part-8/</link>
	<description>&lt;p&gt;Last story to play  on the workernet job layer,&lt;/p&gt;
&lt;p&gt;“&lt;em&gt;I want to be able to delete a job once it’s done, through any node&lt;/em&gt;.”&lt;/p&gt;
&lt;p&gt;To design this &amp;#8211; the test is written first (as usual)&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;done_job_deleted&lt;/span&gt;() -&amp;gt;
    &lt;span&gt;wn_resource_layer&lt;/span&gt;:&lt;span&gt;register&lt;/span&gt;(#&lt;span&gt;wn_resource&lt;/span&gt;{&lt;span&gt;name&lt;/span&gt; = &lt;span&gt;&quot;Laptop&quot;&lt;/span&gt;,
                                     &lt;span&gt;type&lt;/span&gt; = [{&lt;span&gt;perl&lt;/span&gt;,1}],
                                     &lt;span&gt;resides&lt;/span&gt; = &lt;span&gt;node&lt;/span&gt;()
                                    }),
    &lt;span&gt;Path&lt;/span&gt; = &lt;span&gt;create_file_at&lt;/span&gt;(?&lt;span&gt;NODE_ROOT&lt;/span&gt;),
    &lt;span&gt;File1&lt;/span&gt; = #&lt;span&gt;wn_file&lt;/span&gt;{&lt;span&gt;id&lt;/span&gt; = &lt;span&gt;&quot;File1&quot;&lt;/span&gt;,&lt;span&gt;file&lt;/span&gt; = &lt;span&gt;Path&lt;/span&gt;,&lt;span&gt;resides&lt;/span&gt; = &lt;span&gt;node&lt;/span&gt;()},
    &lt;span&gt;Job1&lt;/span&gt; = #&lt;span&gt;wn_job&lt;/span&gt;{&lt;span&gt;id&lt;/span&gt; = &lt;span&gt;&quot;JobId&quot;&lt;/span&gt;,
                   &lt;span&gt;files&lt;/span&gt; = [&lt;span&gt;File1&lt;/span&gt;],
                   &lt;span&gt;resources&lt;/span&gt; = [&lt;span&gt;perl&lt;/span&gt;],
                   &lt;span&gt;commands&lt;/span&gt; = [&lt;span&gt;&quot;perl -e 'print(\&quot;HelloWorld\n\&quot;)'&quot;&lt;/span&gt;],
                   &lt;span&gt;timeout&lt;/span&gt; = 1000
                  },
    &lt;span&gt;ok&lt;/span&gt; = &lt;span&gt;wn_job_layer&lt;/span&gt;:&lt;span&gt;register&lt;/span&gt;(&lt;span&gt;Job1&lt;/span&gt;),
    &lt;span&gt;ok&lt;/span&gt; = &lt;span&gt;wn_job_layer&lt;/span&gt;:&lt;span&gt;stream&lt;/span&gt;(&lt;span&gt;user&lt;/span&gt;,&lt;span&gt;&quot;JobId&quot;&lt;/span&gt;),
    &lt;span&gt;timer&lt;/span&gt;:&lt;span&gt;sleep&lt;/span&gt;(500),
    &lt;span&gt;ok&lt;/span&gt; = &lt;span&gt;wn_job_layer&lt;/span&gt;:&lt;span&gt;delete&lt;/span&gt;(&lt;span&gt;&quot;JobId&quot;&lt;/span&gt;),
    ?&lt;span&gt;assertMatch&lt;/span&gt;([#&lt;span&gt;wn_file&lt;/span&gt;{&lt;span&gt;id&lt;/span&gt;=&lt;span&gt;&quot;File1&quot;&lt;/span&gt;}],&lt;span&gt;wn_file_layer&lt;/span&gt;:&lt;span&gt;list_files&lt;/span&gt;()),
    ?&lt;span&gt;assertEqual&lt;/span&gt;([],&lt;span&gt;wn_job_layer&lt;/span&gt;:&lt;span&gt;list_all_jobs&lt;/span&gt;()),
    &lt;span&gt;ok&lt;/span&gt;.&lt;/pre&gt;
&lt;p&gt;&lt;!-- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;Es usual, this will not even compile first as stuff is missing and dialyzer should get a headache about it. Now, everything is there except the &lt;em&gt;wn_job_layer:delete/1&lt;/em&gt; function.&lt;/p&gt;
&lt;p&gt;Therefore, the first implementation goes into &lt;em&gt;wn_job_layer.erl&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;-spec&lt;/span&gt;(&lt;span&gt;delete&lt;/span&gt;(&lt;span&gt;string&lt;/span&gt;()) -&amp;gt; &lt;span&gt;ok&lt;/span&gt; | {&lt;span&gt;error&lt;/span&gt;,&lt;span&gt;term&lt;/span&gt;()}).
&lt;span&gt;delete&lt;/span&gt;(&lt;span&gt;Id&lt;/span&gt;) -&amp;gt;
    &lt;span&gt;gen_server&lt;/span&gt;:&lt;span&gt;call&lt;/span&gt;(?&lt;span&gt;MODULE&lt;/span&gt;,{&lt;span&gt;delete&lt;/span&gt;,&lt;span&gt;Id&lt;/span&gt;}).&lt;/pre&gt;
&lt;p&gt;8!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;next the internal handle_call/3 clause for handling the delete request&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;handle_call&lt;/span&gt;({&lt;span&gt;delete&lt;/span&gt;,&lt;span&gt;Id&lt;/span&gt;},&lt;span&gt;_&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;) -&amp;gt;
    &lt;span&gt;Result&lt;/span&gt; = &lt;span&gt;try_delete&lt;/span&gt;(&lt;span&gt;Id&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;),
    {&lt;span&gt;reply&lt;/span&gt;,&lt;span&gt;Result&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;};&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;this raises the need to implement the internal try_delete/2 function&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;try_delete&lt;/span&gt;(&lt;span&gt;Id&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;) -&amp;gt;
    &lt;span&gt;case&lt;/span&gt; &lt;span&gt;ets&lt;/span&gt;:&lt;span&gt;lookup&lt;/span&gt;(&lt;span&gt;State&lt;/span&gt;#&lt;span&gt;state&lt;/span&gt;.&lt;span&gt;jobs&lt;/span&gt;,&lt;span&gt;Id&lt;/span&gt;) &lt;span&gt;of&lt;/span&gt;
        [{&lt;span&gt;Id&lt;/span&gt;,&lt;span&gt;JobKeeperPid&lt;/span&gt;,&lt;span&gt;_&lt;/span&gt;}] -&amp;gt;
            &lt;span&gt;case&lt;/span&gt; &lt;span&gt;wn_job_keeper&lt;/span&gt;:&lt;span&gt;get_stored_result&lt;/span&gt;(&lt;span&gt;JobKeeperPid&lt;/span&gt;) &lt;span&gt;of&lt;/span&gt;
                {&lt;span&gt;ok&lt;/span&gt;,&lt;span&gt;Result&lt;/span&gt;} -&amp;gt;
                    &lt;span&gt;ok&lt;/span&gt; = &lt;span&gt;wn_job_keeper&lt;/span&gt;:&lt;span&gt;delete&lt;/span&gt;(&lt;span&gt;JobKeeperPid&lt;/span&gt;),
                    &lt;span&gt;ets&lt;/span&gt;:&lt;span&gt;delete&lt;/span&gt;(&lt;span&gt;State&lt;/span&gt;#&lt;span&gt;state&lt;/span&gt;.&lt;span&gt;jobs&lt;/span&gt;,&lt;span&gt;Id&lt;/span&gt;),
                    &lt;span&gt;wn_file_layer&lt;/span&gt;:&lt;span&gt;delete_file&lt;/span&gt;(&lt;span&gt;node&lt;/span&gt;(),&lt;span&gt;Result&lt;/span&gt;);
                &lt;span&gt;X&lt;/span&gt; -&amp;gt; &lt;span&gt;X&lt;/span&gt;
            &lt;span&gt;end&lt;/span&gt;;
        [] -&amp;gt;
            {&lt;span&gt;error&lt;/span&gt;,&lt;span&gt;no_such_job&lt;/span&gt;}
    &lt;span&gt;end&lt;/span&gt;.&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;That was all the code needed inside &lt;em&gt; wn_job_layer.erl &lt;/em&gt;.  However, the last internal function brought up the need for a new function; &lt;em&gt;wn_job_keeper:delete/1&lt;/em&gt; so the function is to be implemented next!&lt;/p&gt;
&lt;p&gt;In &lt;em&gt; wn_job_keeper.erl&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;-spec&lt;/span&gt;(&lt;span&gt;delete&lt;/span&gt;(&lt;span&gt;pid&lt;/span&gt;()) -&amp;gt; &lt;span&gt;ok&lt;/span&gt; | {&lt;span&gt;error&lt;/span&gt;,&lt;span&gt;term&lt;/span&gt;()}).
&lt;span&gt;delete&lt;/span&gt;(&lt;span&gt;Pid&lt;/span&gt;) -&amp;gt;
    &lt;span&gt;gen_fsm&lt;/span&gt;:&lt;span&gt;sync_send_all_state_event&lt;/span&gt;(&lt;span&gt;Pid&lt;/span&gt;,&lt;span&gt;delete&lt;/span&gt;).&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;try_delete&lt;/span&gt;(&lt;span&gt;Id&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;) -&amp;gt;
    &lt;span&gt;case&lt;/span&gt; &lt;span&gt;ets&lt;/span&gt;:&lt;span&gt;lookup&lt;/span&gt;(&lt;span&gt;State&lt;/span&gt;#&lt;span&gt;state&lt;/span&gt;.&lt;span&gt;jobs&lt;/span&gt;,&lt;span&gt;Id&lt;/span&gt;) &lt;span&gt;of&lt;/span&gt;
        [{&lt;span&gt;Id&lt;/span&gt;,&lt;span&gt;JobKeeperPid&lt;/span&gt;,&lt;span&gt;_&lt;/span&gt;}] -&amp;gt;
            &lt;span&gt;case&lt;/span&gt; &lt;span&gt;wn_job_keeper&lt;/span&gt;:&lt;span&gt;get_stored_result&lt;/span&gt;(&lt;span&gt;JobKeeperPid&lt;/span&gt;) &lt;span&gt;of&lt;/span&gt;
                {&lt;span&gt;ok&lt;/span&gt;,&lt;span&gt;Result&lt;/span&gt;} -&amp;gt;
                    &lt;span&gt;ok&lt;/span&gt; = &lt;span&gt;wn_job_keeper&lt;/span&gt;:&lt;span&gt;delete&lt;/span&gt;(&lt;span&gt;JobKeeperPid&lt;/span&gt;),
                    &lt;span&gt;ets&lt;/span&gt;:&lt;span&gt;delete&lt;/span&gt;(&lt;span&gt;State&lt;/span&gt;#&lt;span&gt;state&lt;/span&gt;.&lt;span&gt;jobs&lt;/span&gt;,&lt;span&gt;Id&lt;/span&gt;),
                    &lt;span&gt;wn_file_layer&lt;/span&gt;:&lt;span&gt;delete_file&lt;/span&gt;(&lt;span&gt;node&lt;/span&gt;(),&lt;span&gt;Result&lt;/span&gt;);
                &lt;span&gt;X&lt;/span&gt; -&amp;gt; &lt;span&gt;X&lt;/span&gt;
            &lt;span&gt;end&lt;/span&gt;;
        [] -&amp;gt;
            {&lt;span&gt;error&lt;/span&gt;,&lt;span&gt;no_such_job&lt;/span&gt;}
    &lt;span&gt;end&lt;/span&gt;.&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;With a handle_call clause inside it for the delete request&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;handle_sync_event&lt;/span&gt;(&lt;span&gt;delete&lt;/span&gt;,&lt;span&gt;_&lt;/span&gt;,&lt;span&gt;done&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;) -&amp;gt;
    {&lt;span&gt;stop&lt;/span&gt;,&lt;span&gt;normal&lt;/span&gt;,&lt;span&gt;ok&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;};
&lt;span&gt;handle_sync_event&lt;/span&gt;(&lt;span&gt;delete&lt;/span&gt;,&lt;span&gt;_&lt;/span&gt;,&lt;span&gt;X&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;) -&amp;gt;
    {&lt;span&gt;reply&lt;/span&gt;,{&lt;span&gt;error&lt;/span&gt;,&lt;span&gt;not_done&lt;/span&gt;},&lt;span&gt;X&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;};&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;That would be all! Since so much had already been written in prior tests, this one turned out to be quite a breeze. Of course this passes both compilation, dialyzation and testing. The judge &amp;#8216;make full&amp;#8217; turns it&amp;#8217;s mighty eye on this&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;zen&lt;/span&gt;:&lt;span&gt;worker_net&lt;/span&gt;-0.1 &lt;span&gt;zenon&lt;/span&gt;&lt;span&gt;$ &lt;/span&gt;&lt;span&gt;make&lt;/span&gt; &lt;span&gt;full&lt;/span&gt;
&lt;span&gt;erlc&lt;/span&gt; -&lt;span&gt;pa&lt;/span&gt; . -&lt;span&gt;o&lt;/span&gt; &lt;span&gt;ebin&lt;/span&gt;/  &lt;span&gt;src&lt;/span&gt;/*.&lt;span&gt;erl&lt;/span&gt; &lt;span&gt;test&lt;/span&gt;/*.&lt;span&gt;erl&lt;/span&gt;
&lt;span&gt;erl&lt;/span&gt; -&lt;span&gt;pa&lt;/span&gt; &lt;span&gt;ebin&lt;/span&gt;/ -&lt;span&gt;eval&lt;/span&gt; 'eunit:&lt;span&gt;test&lt;/span&gt;(&lt;span&gt;wn_resource_layer&lt;/span&gt;,[&lt;span&gt;verbose&lt;/span&gt;]), &lt;span&gt;init&lt;/span&gt;:&lt;span&gt;stop&lt;/span&gt;().'
&lt;span&gt;Erlang&lt;/span&gt; &lt;span&gt;R14B&lt;/span&gt; (&lt;span&gt;erts&lt;/span&gt;-5.8.1) [&lt;span&gt;source&lt;/span&gt;] [&lt;span&gt;smp&lt;/span&gt;:4:4] [&lt;span&gt;rq&lt;/span&gt;:4] [&lt;span&gt;async&lt;/span&gt;-&lt;span&gt;threads&lt;/span&gt;:0] [&lt;span&gt;hipe&lt;/span&gt;] [&lt;span&gt;kernel&lt;/span&gt;-&lt;span&gt;poll&lt;/span&gt;:&lt;span&gt;false&lt;/span&gt;]

&lt;span&gt;Eshell&lt;/span&gt; &lt;span&gt;V5&lt;/span&gt;.8.1  (&lt;span&gt;abort&lt;/span&gt; &lt;span&gt;with&lt;/span&gt; ^&lt;span&gt;G&lt;/span&gt;)
1&amp;gt; ======================== &lt;span&gt;EUnit&lt;/span&gt; ========================
&lt;span&gt;module&lt;/span&gt; &lt;span&gt;'wn_resource_layer'&lt;/span&gt;
  &lt;span&gt;module&lt;/span&gt; &lt;span&gt;'wn_resource_layer_tests'&lt;/span&gt;
    &lt;span&gt;wn_resource_layer_tests&lt;/span&gt;: &lt;span&gt;local_resource_test_&lt;/span&gt; (&lt;span&gt;Can&lt;/span&gt; &lt;span&gt;register&lt;/span&gt; &lt;span&gt;resources&lt;/span&gt; &lt;span&gt;locally&lt;/span&gt;)...[0.001 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_resource_layer_tests&lt;/span&gt;: &lt;span&gt;register_distributed&lt;/span&gt; (&lt;span&gt;Can&lt;/span&gt; &lt;span&gt;Register&lt;/span&gt; &lt;span&gt;Distributed&lt;/span&gt;)...[0.006 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_resource_layer_tests&lt;/span&gt;: &lt;span&gt;register_restart_register&lt;/span&gt; (&lt;span&gt;Can&lt;/span&gt; &lt;span&gt;Register&lt;/span&gt;, &lt;span&gt;Restart&lt;/span&gt; &lt;span&gt;and&lt;/span&gt; &lt;span&gt;Register&lt;/span&gt;)...[0.015 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_resource_layer_tests&lt;/span&gt;: &lt;span&gt;register_deregister&lt;/span&gt; (&lt;span&gt;Can&lt;/span&gt; &lt;span&gt;Register&lt;/span&gt;, &lt;span&gt;Deregister&lt;/span&gt; &lt;span&gt;and&lt;/span&gt; &lt;span&gt;Register&lt;/span&gt;)...[0.013 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    [&lt;span&gt;done&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; 6.324 &lt;span&gt;s&lt;/span&gt;]
  [&lt;span&gt;done&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; 6.325 &lt;span&gt;s&lt;/span&gt;]
=======================================================
  &lt;span&gt;All&lt;/span&gt; 4 &lt;span&gt;tests&lt;/span&gt; &lt;span&gt;passed&lt;/span&gt;.
&lt;span&gt;erl&lt;/span&gt; -&lt;span&gt;pa&lt;/span&gt; &lt;span&gt;ebin&lt;/span&gt;/ -&lt;span&gt;eval&lt;/span&gt; 'eunit:&lt;span&gt;test&lt;/span&gt;(&lt;span&gt;wn_file_layer&lt;/span&gt;,[&lt;span&gt;verbose&lt;/span&gt;]), &lt;span&gt;init&lt;/span&gt;:&lt;span&gt;stop&lt;/span&gt;().'
&lt;span&gt;Erlang&lt;/span&gt; &lt;span&gt;R14B&lt;/span&gt; (&lt;span&gt;erts&lt;/span&gt;-5.8.1) [&lt;span&gt;source&lt;/span&gt;] [&lt;span&gt;smp&lt;/span&gt;:4:4] [&lt;span&gt;rq&lt;/span&gt;:4] [&lt;span&gt;async&lt;/span&gt;-&lt;span&gt;threads&lt;/span&gt;:0] [&lt;span&gt;hipe&lt;/span&gt;] [&lt;span&gt;kernel&lt;/span&gt;-&lt;span&gt;poll&lt;/span&gt;:&lt;span&gt;false&lt;/span&gt;]

&lt;span&gt;Eshell&lt;/span&gt; &lt;span&gt;V5&lt;/span&gt;.8.1  (&lt;span&gt;abort&lt;/span&gt; &lt;span&gt;with&lt;/span&gt; ^&lt;span&gt;G&lt;/span&gt;)
1&amp;gt; ======================== &lt;span&gt;EUnit&lt;/span&gt; ========================
&lt;span&gt;module&lt;/span&gt; &lt;span&gt;'wn_file_layer'&lt;/span&gt;
  &lt;span&gt;module&lt;/span&gt; &lt;span&gt;'wn_file_layer_tests'&lt;/span&gt;
    &lt;span&gt;wn_file_layer_tests&lt;/span&gt;: &lt;span&gt;file_layer_local_test_&lt;/span&gt; (&lt;span&gt;Can&lt;/span&gt; &lt;span&gt;store&lt;/span&gt; &lt;span&gt;file&lt;/span&gt; &lt;span&gt;locally&lt;/span&gt;)...[0.326 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_file_layer_tests&lt;/span&gt;: &lt;span&gt;file_layer_local_test_&lt;/span&gt; (&lt;span&gt;Can&lt;/span&gt; &lt;span&gt;retrieve&lt;/span&gt; &lt;span&gt;files&lt;/span&gt; &lt;span&gt;locally&lt;/span&gt;)...[0.003 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_file_layer_tests&lt;/span&gt;: &lt;span&gt;file_layer_local_test_&lt;/span&gt; (&lt;span&gt;Can&lt;/span&gt; &lt;span&gt;delete&lt;/span&gt; &lt;span&gt;files&lt;/span&gt; &lt;span&gt;locally&lt;/span&gt;)...[0.002 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_file_layer_tests&lt;/span&gt;: &lt;span&gt;can_store_distributed&lt;/span&gt; (&lt;span&gt;Can&lt;/span&gt; &lt;span&gt;store&lt;/span&gt; &lt;span&gt;file&lt;/span&gt; &lt;span&gt;distributed&lt;/span&gt;)...[0.024 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_file_layer_tests&lt;/span&gt;: &lt;span&gt;can_retrieve_distributed&lt;/span&gt; (&lt;span&gt;Can&lt;/span&gt; &lt;span&gt;retrieve&lt;/span&gt; &lt;span&gt;file&lt;/span&gt; &lt;span&gt;distributed&lt;/span&gt;)...[0.018 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_file_layer_tests&lt;/span&gt;: &lt;span&gt;can_delete_distributed&lt;/span&gt; (&lt;span&gt;Can&lt;/span&gt; &lt;span&gt;delete&lt;/span&gt; &lt;span&gt;file&lt;/span&gt; &lt;span&gt;distributed&lt;/span&gt;)...[0.020 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_file_layer_tests&lt;/span&gt;: &lt;span&gt;must_retain&lt;/span&gt; (&lt;span&gt;Must&lt;/span&gt; &lt;span&gt;retain&lt;/span&gt; &lt;span&gt;information&lt;/span&gt; &lt;span&gt;between&lt;/span&gt; &lt;span&gt;node&lt;/span&gt; &lt;span&gt;kill&lt;/span&gt; &lt;span&gt;and&lt;/span&gt; &lt;span&gt;node&lt;/span&gt; &lt;span&gt;restart&lt;/span&gt;)...[0.391 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    [&lt;span&gt;done&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; 2.348 &lt;span&gt;s&lt;/span&gt;]
  [&lt;span&gt;done&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; 2.348 &lt;span&gt;s&lt;/span&gt;]
=======================================================
  &lt;span&gt;All&lt;/span&gt; 7 &lt;span&gt;tests&lt;/span&gt; &lt;span&gt;passed&lt;/span&gt;.
&lt;span&gt;erl&lt;/span&gt; -&lt;span&gt;pa&lt;/span&gt; &lt;span&gt;ebin&lt;/span&gt;/ -&lt;span&gt;eval&lt;/span&gt; 'eunit:&lt;span&gt;test&lt;/span&gt;(&lt;span&gt;wn_job_layer&lt;/span&gt;,[&lt;span&gt;verbose&lt;/span&gt;]), &lt;span&gt;init&lt;/span&gt;:&lt;span&gt;stop&lt;/span&gt;().'
&lt;span&gt;Erlang&lt;/span&gt; &lt;span&gt;R14B&lt;/span&gt; (&lt;span&gt;erts&lt;/span&gt;-5.8.1) [&lt;span&gt;source&lt;/span&gt;] [&lt;span&gt;smp&lt;/span&gt;:4:4] [&lt;span&gt;rq&lt;/span&gt;:4] [&lt;span&gt;async&lt;/span&gt;-&lt;span&gt;threads&lt;/span&gt;:0] [&lt;span&gt;hipe&lt;/span&gt;] [&lt;span&gt;kernel&lt;/span&gt;-&lt;span&gt;poll&lt;/span&gt;:&lt;span&gt;false&lt;/span&gt;]

&lt;span&gt;Eshell&lt;/span&gt; &lt;span&gt;V5&lt;/span&gt;.8.1  (&lt;span&gt;abort&lt;/span&gt; &lt;span&gt;with&lt;/span&gt; ^&lt;span&gt;G&lt;/span&gt;)
1&amp;gt; ======================== &lt;span&gt;EUnit&lt;/span&gt; ========================
&lt;span&gt;module&lt;/span&gt; &lt;span&gt;'wn_job_layer'&lt;/span&gt;
  &lt;span&gt;module&lt;/span&gt; &lt;span&gt;'wn_job_layer_tests'&lt;/span&gt;
    &lt;span&gt;wn_job_layer_tests&lt;/span&gt;: &lt;span&gt;local_test_&lt;/span&gt; (&lt;span&gt;Can&lt;/span&gt; &lt;span&gt;register&lt;/span&gt; &lt;span&gt;locally&lt;/span&gt;)...[0.005 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_job_layer_tests&lt;/span&gt;: &lt;span&gt;local_test_&lt;/span&gt; (&lt;span&gt;Executed&lt;/span&gt; &lt;span&gt;locally&lt;/span&gt;)...{1299,338969,204767} : &lt;span&gt;file_fetching_done&lt;/span&gt;
{1299,338969,204771} : &lt;span&gt;executing_commands&lt;/span&gt;
{1299,338969,218209} : {&lt;span&gt;executing&lt;/span&gt;,&lt;span&gt;&quot;more EUnitFile&quot;&lt;/span&gt;}
{1299,338969,225651} : &lt;span&gt;&quot;1,2,3&quot;&lt;/span&gt;
{1299,338969,226358} : &lt;span&gt;no_more_commands&lt;/span&gt;
{1299,338969,226362} : &lt;span&gt;building_result_tgz&lt;/span&gt;
{1299,338969,226462} : &lt;span&gt;done&lt;/span&gt;
[1.018 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_job_layer_tests&lt;/span&gt;: &lt;span&gt;local_test_&lt;/span&gt; (&lt;span&gt;Executed&lt;/span&gt; &lt;span&gt;queue&lt;/span&gt;)...{1299,338970,229138} : &lt;span&gt;file_fetching_done&lt;/span&gt;
{1299,338970,229141} : &lt;span&gt;executing_commands&lt;/span&gt;
{1299,338970,229539} : {&lt;span&gt;executing&lt;/span&gt;,&lt;span&gt;&quot;file EunitFile&quot;&lt;/span&gt;}
{1299,338970,239052} : &lt;span&gt;&quot;EunitFile: ASCII text&quot;&lt;/span&gt;
{1299,338970,239301} : &lt;span&gt;no_more_commands&lt;/span&gt;
{1299,338970,239304} : &lt;span&gt;building_result_tgz&lt;/span&gt;
{1299,338970,239476} : &lt;span&gt;done&lt;/span&gt;
{1299,338970,243238} : &lt;span&gt;file_fetching_done&lt;/span&gt;
{1299,338970,243250} : &lt;span&gt;executing_commands&lt;/span&gt;
{1299,338970,243360} : {&lt;span&gt;executing&lt;/span&gt;,&lt;span&gt;&quot;cat EUnitFile&quot;&lt;/span&gt;}
{1299,338970,250730} : &lt;span&gt;&quot;1,2,3&quot;&lt;/span&gt;
{1299,338970,250782} : &lt;span&gt;no_more_commands&lt;/span&gt;
{1299,338970,250785} : &lt;span&gt;building_result_tgz&lt;/span&gt;
{1299,338970,250856} : &lt;span&gt;done&lt;/span&gt;
[1.105 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_job_layer_tests&lt;/span&gt;: &lt;span&gt;local_test_&lt;/span&gt; (&lt;span&gt;Queueus&lt;/span&gt; &lt;span&gt;on&lt;/span&gt; &lt;span&gt;resource&lt;/span&gt; &lt;span&gt;type&lt;/span&gt; &lt;span&gt;amount&lt;/span&gt;)...[0.001 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_job_layer_tests&lt;/span&gt;: &lt;span&gt;local_test_&lt;/span&gt; (&lt;span&gt;Canceled&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; &lt;span&gt;queue&lt;/span&gt;)...[0.001 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_job_layer_tests&lt;/span&gt;: &lt;span&gt;local_test_&lt;/span&gt; (&lt;span&gt;Done&lt;/span&gt; &lt;span&gt;Job&lt;/span&gt; &lt;span&gt;Stored&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; &lt;span&gt;file&lt;/span&gt; &lt;span&gt;layer&lt;/span&gt;)...[0.606 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_job_layer_tests&lt;/span&gt;: &lt;span&gt;local_test_&lt;/span&gt; (&lt;span&gt;Done&lt;/span&gt; &lt;span&gt;Job&lt;/span&gt; &lt;span&gt;canceled&lt;/span&gt;)...{1299,338971,966369} : &lt;span&gt;file_fetching_done&lt;/span&gt;
{1299,338971,966377} : &lt;span&gt;executing_commands&lt;/span&gt;
{1299,338971,966651} : {&lt;span&gt;executing&lt;/span&gt;,&lt;span&gt;&quot;perl -e 'print(\&quot;HelloWorld\n\&quot;)'&quot;&lt;/span&gt;}
{1299,338972,3168} : &lt;span&gt;&quot;HelloWorld&quot;&lt;/span&gt;
{1299,338972,3405} : &lt;span&gt;no_more_commands&lt;/span&gt;
{1299,338972,3408} : &lt;span&gt;building_result_tgz&lt;/span&gt;
{1299,338972,3508} : &lt;span&gt;done&lt;/span&gt;
[0.504 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    [&lt;span&gt;done&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; 3.305 &lt;span&gt;s&lt;/span&gt;]
  [&lt;span&gt;done&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; 3.305 &lt;span&gt;s&lt;/span&gt;]
=======================================================
  &lt;span&gt;All&lt;/span&gt; 7 &lt;span&gt;tests&lt;/span&gt; &lt;span&gt;passed&lt;/span&gt;.
&lt;span&gt;dialyzer&lt;/span&gt; &lt;span&gt;src&lt;/span&gt;/*.&lt;span&gt;erl&lt;/span&gt; &lt;span&gt;test&lt;/span&gt;/*.&lt;span&gt;erl&lt;/span&gt;
  &lt;span&gt;Checking&lt;/span&gt; &lt;span&gt;whether&lt;/span&gt; &lt;span&gt;the&lt;/span&gt; &lt;span&gt;PLT&lt;/span&gt; /&lt;span&gt;Users&lt;/span&gt;/&lt;span&gt;zenon&lt;/span&gt;/.&lt;span&gt;dialyzer_plt&lt;/span&gt; &lt;span&gt;is&lt;/span&gt; &lt;span&gt;up&lt;/span&gt;-&lt;span&gt;to&lt;/span&gt;-&lt;span&gt;date&lt;/span&gt;... &lt;span&gt;yes&lt;/span&gt;
  &lt;span&gt;Proceeding&lt;/span&gt; &lt;span&gt;with&lt;/span&gt; &lt;span&gt;analysis&lt;/span&gt;...
&lt;span&gt;Unknown&lt;/span&gt; &lt;span&gt;functions&lt;/span&gt;:
  &lt;span&gt;eunit&lt;/span&gt;:&lt;span&gt;test/1&lt;/span&gt;
 &lt;span&gt;done&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; 0m6.92s
&lt;span&gt;done&lt;/span&gt; (&lt;span&gt;passed&lt;/span&gt; &lt;span&gt;successfully&lt;/span&gt;)
&lt;span&gt;zen&lt;/span&gt;:&lt;span&gt;worker_net&lt;/span&gt;-0.1 &lt;span&gt;zenon&lt;/span&gt;&lt;span&gt;$ &lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;h3&gt;The end&lt;/h3&gt;
&lt;h3&gt;This concludes the TDD hands on project for the WorkerNet &amp;#8211; the source can now be found through my github repository for this.&lt;/h3&gt;
&lt;p&gt;git://github.com/Gianfrancoalongi/WorkerNet.git&lt;/p&gt;
&lt;br /&gt;  &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gocomments/erlcode.wordpress.com/685/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/comments/erlcode.wordpress.com/685/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/godelicious/erlcode.wordpress.com/685/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/delicious/erlcode.wordpress.com/685/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gofacebook/erlcode.wordpress.com/685/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/facebook/erlcode.wordpress.com/685/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gotwitter/erlcode.wordpress.com/685/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/twitter/erlcode.wordpress.com/685/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gostumble/erlcode.wordpress.com/685/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/stumble/erlcode.wordpress.com/685/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/godigg/erlcode.wordpress.com/685/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/digg/erlcode.wordpress.com/685/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/goreddit/erlcode.wordpress.com/685/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/reddit/erlcode.wordpress.com/685/&quot; /&gt;&lt;/a&gt; &lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=erlcode.wordpress.com&amp;blog=15510807&amp;post=685&amp;subd=erlcode&amp;ref=&amp;feed=1&quot; width=&quot;1&quot; height=&quot;1&quot; /&gt;</description>
	<pubDate>Sat, 05 Mar 2011 15:46:09 +0000</pubDate>
</item>
<item>
	<title>RedHotErlang: Using SimpleBridge</title>
	<guid>http://www.redhoterlang.com/web/b4e6c0afca712a3b4f15869018000b2e</guid>
	<link>http://www.redhoterlang.com/web/plink?id=b4e6c0afca712a3b4f15869018000b2e</link>
	<description>I like [SimpleBridge][1]; written by [Rusty][2] and part of [Nitrogen][3]. 
I often use it as a separate component, i.e without using Nitrogen. 
SimpleBridge provides an abstraction above the underlying 
HTTP engine. Apart from being a nice programmi...</description>
	<pubDate>Sat, 05 Mar 2011 08:38:23 +0000</pubDate>
</item>
<item>
	<title>Erlang Inside: Interview with Kostis Sagonas – On Erlang tools, type systems, and how HiPE compares to JIT</title>
	<guid>http://erlanginside.com/?p=244</guid>
	<link>http://erlanginside.com/interview-with-kostis-sagonas-leader-of-the-hipe-team-and-erlang-tool-developer-244</link>
	<description>Chad DePue long form interview with Kostis Sagonas, leader of the HiPE and Dialyzer teams and a speaker at the upcoming Erlang Factory SF Bay.</description>
	<pubDate>Fri, 04 Mar 2011 15:22:45 +0000</pubDate>
</item>
<item>
	<title>Process-one Blogs: Sea Beyond 2011 Talk 1: Mickaël Rémond on ProcessOne and TextOne protocol</title>
	<guid>http://www.process-one.net/en/blogs/article/sea_beyond_2011_talk_1_mickael_remond_on_processone_and_textone_protocol/</guid>
	<link>http://www.process-one.net/en/blogs/article/sea_beyond_2011_talk_1_mickael_remond_on_processone_and_textone_protocol/</link>
	<description>&lt;p&gt;Micka&amp;euml;l R&amp;eacute;mond speaks about a few of&amp;nbsp;ProcessOne focus for 2011 and presents TextOne Protocol.&lt;/p&gt; &lt;p&gt;Micka&amp;euml;l R&amp;eacute;mond, ProcessOne's CEO, explains at Sea Beyond what you can expect soon from ProcessOne on a few XMPP related topics.&lt;/p&gt;
&lt;p&gt;He then introduces TextOne Protocol, XMPP related optimisation for mobile usage.&lt;/p&gt;
&lt;p&gt;Enjoy the presentation here:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;You can see the slides here:&lt;/p&gt;
&lt;p&gt;








&lt;/p&gt;
&lt;p&gt;You can watch &lt;a href=&quot;http://www.process-one.net/en/blogs/article/sea_beyond_2011_video_summary/&quot;&gt;Sea Beyond video&lt;/a&gt; summary to get an overview of the full event.&lt;/p&gt;</description>
	<pubDate>Thu, 03 Mar 2011 20:14:01 +0000</pubDate>
</item>
<item>
	<title>Damien Katz: So You Wanna Learn About CouchDB?</title>
	<guid>tag:damienkatz.net,2011://1.592</guid>
	<link>http://damienkatz.net/2011/03/so_you_wanna_learn_about_couch.html</link>
	<description>&lt;p&gt;CouchDB World Tour Coming! Along with Alan McKean, I and other Couchbase staff will be doing 5 training sessions in 5 different cities starting in March. I'll be teaching the San Francisco one :)  We've developed some incredible material that I'm really excited to present. So go ahead and sign up, and bring a friend!&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://info.membase.com/CouchDB-Training.html&quot;&gt;Sign up now&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Claire was so inspired she wrote a song about it:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://vimeo.com/20499717&quot;&gt;http://vimeo.com/20499717&lt;/a&gt;&lt;/p&gt;</description>
	<pubDate>Thu, 03 Mar 2011 01:43:28 +0000</pubDate>
</item>
<item>
	<title>Erlang, Testing and TDD: gianfrancoalongi</title>
	<guid>http://erlcode.wordpress.com/?p=633</guid>
	<link>http://erlcode.wordpress.com/2011/03/01/erlang-tdd-hands-on-project-part-7/</link>
	<description>&lt;p&gt;This evenings entertainment is&lt;/p&gt;
&lt;p&gt;“&lt;em&gt;Once a job is done, the result should be stored in the file layer,  together with the logs.&lt;/em&gt;“&lt;/p&gt;
&lt;p&gt;A new test needs to be devised to prove the result is stored in the file layer once a job is done. Of course the test is put in  &lt;em&gt;wn_job_layer_tests.erl . &lt;/em&gt;The test  can be seen below &amp;#8211; and as always &amp;#8211; the test is written  &lt;em&gt;first. &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;stored_in_file_layer&lt;/span&gt;() -&amp;gt;
    &lt;span&gt;%% &lt;/span&gt;&lt;span&gt;(1)
&lt;/span&gt;    &lt;span&gt;wn_resource_layer&lt;/span&gt;:&lt;span&gt;register&lt;/span&gt;(#&lt;span&gt;wn_resource&lt;/span&gt;{&lt;span&gt;name&lt;/span&gt; = &lt;span&gt;&quot;Laptop&quot;&lt;/span&gt;,
                                     &lt;span&gt;type&lt;/span&gt; = [{&lt;span&gt;laptop&lt;/span&gt;,1}],
                                     &lt;span&gt;resides&lt;/span&gt; = &lt;span&gt;node&lt;/span&gt;()
                                    }),
    &lt;span&gt;%% &lt;/span&gt;&lt;span&gt;(2)
&lt;/span&gt;    &lt;span&gt;Path&lt;/span&gt; = &lt;span&gt;create_file_at&lt;/span&gt;(?&lt;span&gt;NODE_ROOT&lt;/span&gt;),
    &lt;span&gt;%% &lt;/span&gt;&lt;span&gt;(3)
&lt;/span&gt;    &lt;span&gt;File1&lt;/span&gt; = #&lt;span&gt;wn_file&lt;/span&gt;{&lt;span&gt;id&lt;/span&gt; = &lt;span&gt;&quot;File1&quot;&lt;/span&gt;,&lt;span&gt;file&lt;/span&gt; = &lt;span&gt;Path&lt;/span&gt;,&lt;span&gt;resides&lt;/span&gt; = &lt;span&gt;node&lt;/span&gt;()},
    &lt;span&gt;Job1&lt;/span&gt; = #&lt;span&gt;wn_job&lt;/span&gt;{&lt;span&gt;id&lt;/span&gt; = &lt;span&gt;&quot;JobId&quot;&lt;/span&gt;,
                   &lt;span&gt;files&lt;/span&gt; = [&lt;span&gt;File1&lt;/span&gt;],
                   &lt;span&gt;resources&lt;/span&gt; = [&lt;span&gt;laptop&lt;/span&gt;],
                   &lt;span&gt;commands&lt;/span&gt; = [&lt;span&gt;&quot;cat EunitFile&quot;&lt;/span&gt;,&lt;span&gt;&quot;touch MadeFile&quot;&lt;/span&gt;],
                   &lt;span&gt;timeout&lt;/span&gt; = 100
                  },
    &lt;span&gt;%% &lt;/span&gt;&lt;span&gt;(4)
&lt;/span&gt;    &lt;span&gt;ok&lt;/span&gt; = &lt;span&gt;wn_job_layer&lt;/span&gt;:&lt;span&gt;register&lt;/span&gt;(&lt;span&gt;Job1&lt;/span&gt;),
    &lt;span&gt;%% &lt;/span&gt;&lt;span&gt;(5)
&lt;/span&gt;    &lt;span&gt;timer&lt;/span&gt;:&lt;span&gt;sleep&lt;/span&gt;(500),

    &lt;span&gt;%% &lt;/span&gt;&lt;span&gt;(6)
&lt;/span&gt;    {&lt;span&gt;ok&lt;/span&gt;,&lt;span&gt;T&lt;/span&gt;} = &lt;span&gt;wn_job_layer&lt;/span&gt;:&lt;span&gt;finished_at&lt;/span&gt;(&lt;span&gt;&quot;JobId&quot;&lt;/span&gt;),

    &lt;span&gt;%% &lt;/span&gt;&lt;span&gt;(7)
&lt;/span&gt;    &lt;span&gt;TimeSuffix&lt;/span&gt; = &lt;span&gt;wn_util&lt;/span&gt;:&lt;span&gt;time_marker_to_string&lt;/span&gt;(&lt;span&gt;T&lt;/span&gt;),
    &lt;span&gt;ExpectedFileName&lt;/span&gt; = &lt;span&gt;&quot;JobId_result_&quot;&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;TimeSuffix&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;&quot;.tgz&quot;&lt;/span&gt;,
    &lt;span&gt;ExpectedFileId&lt;/span&gt; = &lt;span&gt;&quot;JobId_result&quot;&lt;/span&gt;,
    &lt;span&gt;ExpectedFiles&lt;/span&gt; = [&lt;span&gt;F1&lt;/span&gt;,&lt;span&gt;F2&lt;/span&gt;,&lt;span&gt;F3&lt;/span&gt;] = [&lt;span&gt;&quot;EUnitFile&quot;&lt;/span&gt;,&lt;span&gt;&quot;MadeFile&quot;&lt;/span&gt;,&lt;span&gt;&quot;Log.txt&quot;&lt;/span&gt;],

    &lt;span&gt;%% &lt;/span&gt;&lt;span&gt;(8)
&lt;/span&gt;    {&lt;span&gt;ok&lt;/span&gt;,&lt;span&gt;ResultId&lt;/span&gt;} = &lt;span&gt;wn_job_layer&lt;/span&gt;:&lt;span&gt;stored_result&lt;/span&gt;(&lt;span&gt;&quot;JobId&quot;&lt;/span&gt;),
    ?&lt;span&gt;assertEqual&lt;/span&gt;(&lt;span&gt;ExpectedFileId&lt;/span&gt;,&lt;span&gt;ResultId&lt;/span&gt;),

    &lt;span&gt;%% &lt;/span&gt;&lt;span&gt;(9)
&lt;/span&gt;    [&lt;span&gt;_&lt;/span&gt;,&lt;span&gt;Res&lt;/span&gt;] = &lt;span&gt;wn_file_layer&lt;/span&gt;:&lt;span&gt;list_files&lt;/span&gt;(),
    ?&lt;span&gt;assertEqual&lt;/span&gt;(&lt;span&gt;ExpectedFileName&lt;/span&gt;,&lt;span&gt;filename&lt;/span&gt;:&lt;span&gt;basename&lt;/span&gt;(&lt;span&gt;Res&lt;/span&gt;#&lt;span&gt;wn_file&lt;/span&gt;.&lt;span&gt;file&lt;/span&gt;)),
    ?&lt;span&gt;assertEqual&lt;/span&gt;(&lt;span&gt;ExpectedFileId&lt;/span&gt;,&lt;span&gt;Res&lt;/span&gt;#&lt;span&gt;wn_file&lt;/span&gt;.&lt;span&gt;id&lt;/span&gt;),

    &lt;span&gt;%% &lt;/span&gt;&lt;span&gt;(10)
&lt;/span&gt;    {&lt;span&gt;ok&lt;/span&gt;,&lt;span&gt;Tar&lt;/span&gt;} = &lt;span&gt;wn_file_layer&lt;/span&gt;:&lt;span&gt;retrieve_file&lt;/span&gt;(&lt;span&gt;node&lt;/span&gt;(),&lt;span&gt;ResultId&lt;/span&gt;),
    ?&lt;span&gt;assertMatch&lt;/span&gt;({&lt;span&gt;ok&lt;/span&gt;,&lt;span&gt;ExpectedFiles&lt;/span&gt;},&lt;span&gt;erl_tar&lt;/span&gt;:&lt;span&gt;table&lt;/span&gt;(&lt;span&gt;Tar&lt;/span&gt;,[&lt;span&gt;compressed&lt;/span&gt;])),

    &lt;span&gt;%% &lt;/span&gt;&lt;span&gt;(11)
&lt;/span&gt;    &lt;span&gt;erl_tar&lt;/span&gt;:&lt;span&gt;extract&lt;/span&gt;(&lt;span&gt;Tar&lt;/span&gt;,[{&lt;span&gt;files&lt;/span&gt;,[&lt;span&gt;F3&lt;/span&gt;]},&lt;span&gt;compressed&lt;/span&gt;]),
    {&lt;span&gt;ok&lt;/span&gt;,&lt;span&gt;IoDev&lt;/span&gt;} = &lt;span&gt;file&lt;/span&gt;:&lt;span&gt;open&lt;/span&gt;(&lt;span&gt;&quot;local_stream.txt&quot;&lt;/span&gt;,[&lt;span&gt;write&lt;/span&gt;]),
    &lt;span&gt;ok&lt;/span&gt;  = &lt;span&gt;wn_job_layer&lt;/span&gt;:&lt;span&gt;stream&lt;/span&gt;(&lt;span&gt;IoDev&lt;/span&gt;,&lt;span&gt;&quot;JobId&quot;&lt;/span&gt;),
    &lt;span&gt;timer&lt;/span&gt;:&lt;span&gt;sleep&lt;/span&gt;(100),
    &lt;span&gt;file&lt;/span&gt;:&lt;span&gt;close&lt;/span&gt;(&lt;span&gt;IoDev&lt;/span&gt;),
    {&lt;span&gt;ok&lt;/span&gt;,&lt;span&gt;LocalStreamBin&lt;/span&gt;} = &lt;span&gt;file&lt;/span&gt;:&lt;span&gt;read_file&lt;/span&gt;(&lt;span&gt;&quot;local_stream.txt&quot;&lt;/span&gt;),
    {&lt;span&gt;ok&lt;/span&gt;,&lt;span&gt;JobLogBin&lt;/span&gt;} = &lt;span&gt;file&lt;/span&gt;:&lt;span&gt;read_file&lt;/span&gt;(&lt;span&gt;F3&lt;/span&gt;),
    ?&lt;span&gt;assertEqual&lt;/span&gt;(&lt;span&gt;LocalStreamBin&lt;/span&gt;,&lt;span&gt;JobLogBin&lt;/span&gt;),    

    &lt;span&gt;%% &lt;/span&gt;&lt;span&gt;(12)
&lt;/span&gt;    &lt;span&gt;erl_tar&lt;/span&gt;:&lt;span&gt;extract&lt;/span&gt;(&lt;span&gt;Tar&lt;/span&gt;,[{&lt;span&gt;files&lt;/span&gt;,[&lt;span&gt;F1&lt;/span&gt;]},&lt;span&gt;compressed&lt;/span&gt;]),
    {&lt;span&gt;ok&lt;/span&gt;,&lt;span&gt;LocalEunitBin&lt;/span&gt;} = &lt;span&gt;file&lt;/span&gt;:&lt;span&gt;read_file&lt;/span&gt;(&lt;span&gt;Path&lt;/span&gt;),
    {&lt;span&gt;ok&lt;/span&gt;,&lt;span&gt;JobEunitBin&lt;/span&gt;} = &lt;span&gt;file&lt;/span&gt;:&lt;span&gt;read_file&lt;/span&gt;(&lt;span&gt;F1&lt;/span&gt;),
    ?&lt;span&gt;assertEqual&lt;/span&gt;(&lt;span&gt;LocalEunitBin&lt;/span&gt;,&lt;span&gt;JobEunitBin&lt;/span&gt;),

    &lt;span&gt;%% &lt;/span&gt;&lt;span&gt;(13)
&lt;/span&gt;    &lt;span&gt;erl_tar&lt;/span&gt;:&lt;span&gt;extract&lt;/span&gt;(&lt;span&gt;Tar&lt;/span&gt;,[{&lt;span&gt;files&lt;/span&gt;,[&lt;span&gt;F2&lt;/span&gt;]},&lt;span&gt;compressed&lt;/span&gt;]),
    ?&lt;span&gt;assertEqual&lt;/span&gt;({&lt;span&gt;ok&lt;/span&gt;,&amp;lt;&amp;lt;&amp;gt;&amp;gt;},&lt;span&gt;file&lt;/span&gt;:&lt;span&gt;read_file&lt;/span&gt;(&lt;span&gt;F2&lt;/span&gt;)),

    &lt;span&gt;%% &lt;/span&gt;&lt;span&gt;(14)
&lt;/span&gt;    &lt;span&gt;ok&lt;/span&gt; = &lt;span&gt;file&lt;/span&gt;:&lt;span&gt;delete&lt;/span&gt;(&lt;span&gt;&quot;local_stream.txt&quot;&lt;/span&gt;),
    &lt;span&gt;ok&lt;/span&gt; = &lt;span&gt;file&lt;/span&gt;:&lt;span&gt;delete&lt;/span&gt;(&lt;span&gt;F1&lt;/span&gt;),
    &lt;span&gt;ok&lt;/span&gt; = &lt;span&gt;file&lt;/span&gt;:&lt;span&gt;delete&lt;/span&gt;(&lt;span&gt;F2&lt;/span&gt;),
    &lt;span&gt;ok&lt;/span&gt; = &lt;span&gt;file&lt;/span&gt;:&lt;span&gt;delete&lt;/span&gt;(&lt;span&gt;F3&lt;/span&gt;),
    &lt;span&gt;ok&lt;/span&gt; = &lt;span&gt;file&lt;/span&gt;:&lt;span&gt;delete&lt;/span&gt;(&lt;span&gt;Tar&lt;/span&gt;).&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;This test is one of the bigger ones, and deserves some guidance. From the top to bottom: (1) resource registration, (2) creation of the file I wish to send as part of the job, (3) file and job declaration, (4) job registration, (5) waiting for the job to finish (one of the structural weaknesses of this test) and (6) job finish checking by getting the timestamp at the moment of finish. (7) Setting up the expected result values for comparison, (8) getting the result-id and comparing it with the expected result. (9) Listing all files in the file layer and comparing with expected result (note that there SHOULD be two files in the layer &amp;#8211; [1] First EunitFile, [2] the result package). (10) Retrieving the expected tgz file and checking that it should contain only two specific files (the log and the sent file). (11) Extraction of the payload logfile and checking with a streamed version that it&amp;#8217;s the same. (12) Extraction of the job file to see that it&amp;#8217;s there, and comparison to see it&amp;#8217;s the same content. (13) Testing that the created file is the one which we sent back, (14) Cleanup of the extracted files and the tgz result.&lt;/p&gt;
&lt;p&gt;So, of to write the code &amp;#8211; first the wn_util:time_marker_to_string/1 function.  One important aspect is that this utility function &lt;em&gt;should not be allowed to exists&lt;/em&gt; for the &lt;em&gt;sole purpose of the testing&lt;/em&gt; &amp;#8211; however as we shall see, this function does have other applications and thus survives.&lt;/p&gt;
&lt;p&gt;In &lt;em&gt;wn_util.erl&lt;/em&gt;, (skipping to show the export, &lt;em&gt;that &lt;/em&gt;part should be bread and butter by now)&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;-spec&lt;/span&gt;(&lt;span&gt;time_marker_to_string&lt;/span&gt;(&lt;span&gt;time_marker&lt;/span&gt;()) -&amp;gt; &lt;span&gt;string&lt;/span&gt;()).
&lt;span&gt;time_marker_to_string&lt;/span&gt;({&lt;span&gt;Date&lt;/span&gt;,&lt;span&gt;Time&lt;/span&gt;,&lt;span&gt;Now&lt;/span&gt;}) -&amp;gt;
    &lt;span&gt;F&lt;/span&gt; = &lt;span&gt;fun&lt;/span&gt;(&lt;span&gt;X&lt;/span&gt;) -&amp;gt; &lt;span&gt;string&lt;/span&gt;:&lt;span&gt;join&lt;/span&gt;([&lt;span&gt;integer_to_list&lt;/span&gt;(&lt;span&gt;Y&lt;/span&gt;)&lt;span&gt;||&lt;/span&gt;&lt;span&gt;Y&lt;/span&gt;&lt;span&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt;tuple_to_list&lt;/span&gt;(&lt;span&gt;X&lt;/span&gt;)],&lt;span&gt;&quot;_&quot;&lt;/span&gt;)
        &lt;span&gt;end&lt;/span&gt;,
    &lt;span&gt;F&lt;/span&gt;(&lt;span&gt;Date&lt;/span&gt;)&lt;span&gt;++&lt;/span&gt;&lt;span&gt;&quot;_&quot;&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;F&lt;/span&gt;(&lt;span&gt;Time&lt;/span&gt;)&lt;span&gt;++&lt;/span&gt;&lt;span&gt;&quot;_&quot;&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;F&lt;/span&gt;(&lt;span&gt;Now&lt;/span&gt;).&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;following the test-code, the expected filename is already given in (7), and it&amp;#8217;s time to write up the &lt;em&gt;wn_job_layer:stored_result/1&lt;/em&gt; function, taking the JobId as parameter and giving the file-name.&lt;/p&gt;
&lt;p&gt;Next the missing part in (8), in &lt;em&gt;wn_job_layer.erl&lt;/em&gt; , the API function&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;-spec&lt;/span&gt;(&lt;span&gt;stored_result&lt;/span&gt;(&lt;span&gt;string&lt;/span&gt;()) -&amp;gt; {&lt;span&gt;ok&lt;/span&gt;,&lt;span&gt;string&lt;/span&gt;()} | {&lt;span&gt;error&lt;/span&gt;,&lt;span&gt;term&lt;/span&gt;()}).
&lt;span&gt;stored_result&lt;/span&gt;(&lt;span&gt;Id&lt;/span&gt;) -&amp;gt;
    &lt;span&gt;gen_server&lt;/span&gt;:&lt;span&gt;call&lt;/span&gt;(?&lt;span&gt;MODULE&lt;/span&gt;,{&lt;span&gt;stored_result&lt;/span&gt;,&lt;span&gt;Id&lt;/span&gt;}).&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;and internal logic for handling it&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;handle_call&lt;/span&gt;({&lt;span&gt;stored_result&lt;/span&gt;,&lt;span&gt;Id&lt;/span&gt;},&lt;span&gt;_&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;) -&amp;gt;
    &lt;span&gt;Result&lt;/span&gt; = &lt;span&gt;try_get_stored&lt;/span&gt;(&lt;span&gt;Id&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;),
    {&lt;span&gt;reply&lt;/span&gt;,&lt;span&gt;Result&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;};&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;and the seen helper function for stored result retrieval.&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;try_get_stored&lt;/span&gt;(&lt;span&gt;Id&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;) -&amp;gt;
    &lt;span&gt;case&lt;/span&gt; &lt;span&gt;ets&lt;/span&gt;:&lt;span&gt;lookup&lt;/span&gt;(&lt;span&gt;State&lt;/span&gt;#&lt;span&gt;state&lt;/span&gt;.&lt;span&gt;jobs&lt;/span&gt;,&lt;span&gt;Id&lt;/span&gt;) &lt;span&gt;of&lt;/span&gt;
        [{&lt;span&gt;Id&lt;/span&gt;,&lt;span&gt;JobKeeperPid&lt;/span&gt;,&lt;span&gt;_&lt;/span&gt;}] -&amp;gt;
            &lt;span&gt;wn_job_keeper&lt;/span&gt;:&lt;span&gt;get_stored_result&lt;/span&gt;(&lt;span&gt;JobKeeperPid&lt;/span&gt;);
        [] -&amp;gt; {&lt;span&gt;error&lt;/span&gt;,&lt;span&gt;no_such_job&lt;/span&gt;}
    &lt;span&gt;end&lt;/span&gt;.&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;This directly leads to the need in fleshing out the wn_job_keeper code. Thus, time to write the &lt;em&gt;wn_job_keeper:get_stored_result/1&lt;/em&gt; function. However, as you are not inside my head (thanks for that!) I might need to give a quick explanation. The idea is that the job keeper holds the &lt;em&gt;name&lt;/em&gt; of the stored result, not the result itself. So it&amp;#8217;s not the actual tgz we get here. Remember that &lt;em&gt;all&lt;/em&gt; files should be handled through the wn_file_layer.&lt;/p&gt;
&lt;p&gt;In &lt;em&gt; wn_job_keeper.erl: &lt;/em&gt;In order to maintain the stored result in the state, a new field has to be added (and while doing so I took the liberty of making the state type-declarations nicer)&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;-record&lt;/span&gt;(&lt;span&gt;state&lt;/span&gt;, {&lt;span&gt;job&lt;/span&gt; :: #&lt;span&gt;wn_job&lt;/span&gt;{},
             &lt;span&gt;info&lt;/span&gt; :: [{&lt;span&gt;time&lt;/span&gt;(),&lt;span&gt;term&lt;/span&gt;()}],
             &lt;span&gt;result&lt;/span&gt; :: [{&lt;span&gt;time&lt;/span&gt;(),&lt;span&gt;term&lt;/span&gt;()}],
             &lt;span&gt;stored_result&lt;/span&gt; :: &lt;span&gt;string&lt;/span&gt;(),
             &lt;span&gt;stream&lt;/span&gt; :: [&lt;span&gt;pid&lt;/span&gt;()],
             &lt;span&gt;done_at&lt;/span&gt; :: &lt;span&gt;undefined&lt;/span&gt; | &lt;span&gt;time_marker&lt;/span&gt;()
               }).&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;onward and downwards (in the source file), the API function&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;-spec&lt;/span&gt;(&lt;span&gt;get_stored_result&lt;/span&gt;(&lt;span&gt;pid&lt;/span&gt;()) -&amp;gt; {&lt;span&gt;ok&lt;/span&gt;,&lt;span&gt;string&lt;/span&gt;()} | {&lt;span&gt;error&lt;/span&gt;,&lt;span&gt;term&lt;/span&gt;()}).
&lt;span&gt;get_stored_result&lt;/span&gt;(&lt;span&gt;Pid&lt;/span&gt;) -&amp;gt;
    &lt;span&gt;gen_fsm&lt;/span&gt;:&lt;span&gt;sync_send_all_state_event&lt;/span&gt;(&lt;span&gt;Pid&lt;/span&gt;,&lt;span&gt;get_stored_result&lt;/span&gt;).&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;alongside the internal function for handling the call&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;handle_sync_event&lt;/span&gt;(&lt;span&gt;get_stored_result&lt;/span&gt;,&lt;span&gt;_&lt;/span&gt;,&lt;span&gt;X&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;) -&amp;gt;
    {&lt;span&gt;reply&lt;/span&gt;,
     &lt;span&gt;case&lt;/span&gt; &lt;span&gt;State&lt;/span&gt;#&lt;span&gt;state&lt;/span&gt;.&lt;span&gt;stored_result&lt;/span&gt; &lt;span&gt;of&lt;/span&gt;
         &lt;span&gt;undefined&lt;/span&gt; -&amp;gt; {&lt;span&gt;error&lt;/span&gt;,&lt;span&gt;no_result&lt;/span&gt;};
         &lt;span&gt;R&lt;/span&gt; -&amp;gt; {&lt;span&gt;ok&lt;/span&gt;,&lt;span&gt;R&lt;/span&gt;}
     &lt;span&gt;end&lt;/span&gt;,&lt;span&gt;X&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;};&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;while working my way through this I noticed a bug in the get_done clause of handle_sync_event with done as StateName, and fixed it (should now be what is seen below)&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;handle_sync_event&lt;/span&gt;(&lt;span&gt;get_done&lt;/span&gt;,&lt;span&gt;_From&lt;/span&gt;,&lt;span&gt;done&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;) -&amp;gt;
    {&lt;span&gt;reply&lt;/span&gt;,{&lt;span&gt;ok&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;#&lt;span&gt;state&lt;/span&gt;.&lt;span&gt;done_at&lt;/span&gt;},&lt;span&gt;done&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;};&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;The natural question is now &amp;#8211; &lt;em&gt;who&lt;/em&gt; called &lt;em&gt;some&lt;/em&gt; API function to put the value we are retrieving? The wn_job_worker would seem to be a good place to do this from since the job_worker knows when it&amp;#8217;s finished and hence can generate the resulting file, put it into the file layer and signal the wn_job_keeper.&lt;/p&gt;
&lt;p&gt;So, going to &lt;em&gt;wn_job_worker.erl, &lt;/em&gt;to the part when all commands have been executed, (the handle_info clause of the gen_server) &amp;#8211; this is what I put there (&lt;em&gt;not working&lt;/em&gt; &amp;#8211; needs to be implemented)&lt;/p&gt;
&lt;p&gt;&lt;!-- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;handle_info&lt;/span&gt;({&lt;span&gt;Port&lt;/span&gt;,&lt;span&gt;eof&lt;/span&gt;},#&lt;span&gt;state&lt;/span&gt;{&lt;span&gt;port&lt;/span&gt; = &lt;span&gt;Port&lt;/span&gt;} = &lt;span&gt;State&lt;/span&gt;) -&amp;gt;
    &lt;span&gt;case&lt;/span&gt; &lt;span&gt;State&lt;/span&gt;#&lt;span&gt;state&lt;/span&gt;.&lt;span&gt;commands&lt;/span&gt; &lt;span&gt;of&lt;/span&gt;
        [] -&amp;gt;
            &lt;span&gt;wn_job_keeper&lt;/span&gt;:&lt;span&gt;info&lt;/span&gt;(&lt;span&gt;State&lt;/span&gt;#&lt;span&gt;state&lt;/span&gt;.&lt;span&gt;pid&lt;/span&gt;,&lt;span&gt;no_more_commands&lt;/span&gt;),
            &lt;span&gt;wn_job_keeper&lt;/span&gt;:&lt;span&gt;info&lt;/span&gt;(&lt;span&gt;State&lt;/span&gt;#&lt;span&gt;state&lt;/span&gt;.&lt;span&gt;pid&lt;/span&gt;,&lt;span&gt;building_result_tgz&lt;/span&gt;),
            &lt;span&gt;ok&lt;/span&gt; = &lt;span&gt;file&lt;/span&gt;:&lt;span&gt;set_cwd&lt;/span&gt;(&lt;span&gt;State&lt;/span&gt;#&lt;span&gt;state&lt;/span&gt;.&lt;span&gt;olddir&lt;/span&gt;),
            &lt;span&gt;Keeper&lt;/span&gt; = &lt;span&gt;State&lt;/span&gt;#&lt;span&gt;state&lt;/span&gt;.&lt;span&gt;pid&lt;/span&gt;,
            &lt;span&gt;TimeMarker&lt;/span&gt; = &lt;span&gt;wn_util&lt;/span&gt;:&lt;span&gt;time_marker&lt;/span&gt;(),
            &lt;span&gt;wn_job_keeper&lt;/span&gt;:&lt;span&gt;done&lt;/span&gt;(&lt;span&gt;Keeper&lt;/span&gt;,&lt;span&gt;TimeMarker&lt;/span&gt;),
            &lt;span&gt;Job&lt;/span&gt; = &lt;span&gt;wn_job_keeper&lt;/span&gt;:&lt;span&gt;get_job&lt;/span&gt;(&lt;span&gt;Keeper&lt;/span&gt;),
            &lt;span&gt;Logs&lt;/span&gt; = &lt;span&gt;wn_job_keeper&lt;/span&gt;:&lt;span&gt;logs&lt;/span&gt;(&lt;span&gt;Keeper&lt;/span&gt;),
            {&lt;span&gt;Id&lt;/span&gt;,&lt;span&gt;Name&lt;/span&gt;} = &lt;span&gt;make_tgz_result&lt;/span&gt;(&lt;span&gt;TimeMarker&lt;/span&gt;,
                                        &lt;span&gt;State&lt;/span&gt;#&lt;span&gt;state&lt;/span&gt;.&lt;span&gt;workdir&lt;/span&gt;,
                                        &lt;span&gt;Job&lt;/span&gt;,&lt;span&gt;Logs&lt;/span&gt;),
            &lt;span&gt;ok&lt;/span&gt; = &lt;span&gt;wn_file_layer&lt;/span&gt;:&lt;span&gt;add_file&lt;/span&gt;(#&lt;span&gt;wn_file&lt;/span&gt;{&lt;span&gt;id&lt;/span&gt; = &lt;span&gt;Id&lt;/span&gt;,
                                                 &lt;span&gt;file&lt;/span&gt; = &lt;span&gt;Name&lt;/span&gt;,
                                                 &lt;span&gt;resides&lt;/span&gt; = &lt;span&gt;node&lt;/span&gt;()}),
            &lt;span&gt;file&lt;/span&gt;:&lt;span&gt;delete&lt;/span&gt;(&lt;span&gt;Name&lt;/span&gt;),
            &lt;span&gt;wn_job_keeper&lt;/span&gt;:&lt;span&gt;set_stored_result&lt;/span&gt;(&lt;span&gt;Keeper&lt;/span&gt;,&lt;span&gt;Id&lt;/span&gt;),
            {&lt;span&gt;stop&lt;/span&gt;,&lt;span&gt;normal&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;};
        [&lt;span&gt;C&lt;/span&gt;|&lt;span&gt;Commands&lt;/span&gt;] -&amp;gt;
            &lt;span&gt;wn_job_keeper&lt;/span&gt;:&lt;span&gt;info&lt;/span&gt;(&lt;span&gt;State&lt;/span&gt;#&lt;span&gt;state&lt;/span&gt;.&lt;span&gt;pid&lt;/span&gt;,{&lt;span&gt;executing&lt;/span&gt;,&lt;span&gt;C&lt;/span&gt;}),
            &lt;span&gt;NewPort&lt;/span&gt; = &lt;span&gt;erlang&lt;/span&gt;:&lt;span&gt;open_port&lt;/span&gt;({&lt;span&gt;spawn&lt;/span&gt;,&lt;span&gt;C&lt;/span&gt;},[&lt;span&gt;eof&lt;/span&gt;,{&lt;span&gt;line&lt;/span&gt;,2048}]),
            {&lt;span&gt;noreply&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;#&lt;span&gt;state&lt;/span&gt;{&lt;span&gt;commands&lt;/span&gt; = &lt;span&gt;Commands&lt;/span&gt;,&lt;span&gt;port&lt;/span&gt; = &lt;span&gt;NewPort&lt;/span&gt;}}
    &lt;span&gt;end&lt;/span&gt;;&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;This block of code jumps out of the current worker-dir, creates a resulting &lt;em&gt;tgz&lt;/em&gt;, adds all files in the worker-dir to it, signals done to the wn_job_keeper and puts the &lt;em&gt;tgz&lt;/em&gt; file into the file layer. Of course this is designing as we go and hence there are some functions missing. Finishing off the stuff here first,  the local make_tgz_result/4 function&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;make_tgz_result&lt;/span&gt;(&lt;span&gt;TimeMarker&lt;/span&gt;,&lt;span&gt;Dir&lt;/span&gt;,&lt;span&gt;WnJob&lt;/span&gt;,&lt;span&gt;Logs&lt;/span&gt;) -&amp;gt;
    &lt;span&gt;Id&lt;/span&gt; = &lt;span&gt;WnJob&lt;/span&gt;#&lt;span&gt;wn_job&lt;/span&gt;.&lt;span&gt;id&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;&quot;_result&quot;&lt;/span&gt;,
    &lt;span&gt;Name&lt;/span&gt; = &lt;span&gt;Id&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;&quot;_&quot;&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;wn_util&lt;/span&gt;:&lt;span&gt;time_marker_to_string&lt;/span&gt;(&lt;span&gt;TimeMarker&lt;/span&gt;)&lt;span&gt;++&lt;/span&gt;&lt;span&gt;&quot;.tgz&quot;&lt;/span&gt;,
    {&lt;span&gt;ok&lt;/span&gt;,&lt;span&gt;TarFile&lt;/span&gt;} = &lt;span&gt;erl_tar&lt;/span&gt;:&lt;span&gt;open&lt;/span&gt;(&lt;span&gt;Name&lt;/span&gt;,[&lt;span&gt;write&lt;/span&gt;,&lt;span&gt;compressed&lt;/span&gt;]),
    &lt;span&gt;Files&lt;/span&gt; = &lt;span&gt;filelib&lt;/span&gt;:&lt;span&gt;wildcard&lt;/span&gt;(&lt;span&gt;Dir&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;&quot;*&quot;&lt;/span&gt;),
    &lt;span&gt;lists&lt;/span&gt;:&lt;span&gt;foreach&lt;/span&gt;(
      &lt;span&gt;fun&lt;/span&gt;(&lt;span&gt;File&lt;/span&gt;) -&amp;gt;
              &lt;span&gt;ok&lt;/span&gt; = &lt;span&gt;erl_tar&lt;/span&gt;:&lt;span&gt;add&lt;/span&gt;(&lt;span&gt;TarFile&lt;/span&gt;,&lt;span&gt;File&lt;/span&gt;,&lt;span&gt;filename&lt;/span&gt;:&lt;span&gt;basename&lt;/span&gt;(&lt;span&gt;File&lt;/span&gt;),[])
      &lt;span&gt;end&lt;/span&gt;,&lt;span&gt;Files&lt;/span&gt;),
    &lt;span&gt;LogStr&lt;/span&gt; = &lt;span&gt;lists&lt;/span&gt;:&lt;span&gt;foldl&lt;/span&gt;(
               &lt;span&gt;fun&lt;/span&gt;({&lt;span&gt;TimeMark&lt;/span&gt;,&lt;span&gt;Entry&lt;/span&gt;},&lt;span&gt;Str&lt;/span&gt;) -&amp;gt;
                       &lt;span&gt;Str&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;io_lib&lt;/span&gt;:&lt;span&gt;format&lt;/span&gt;(&lt;span&gt;&quot;~p : ~p~n&quot;&lt;/span&gt;,[&lt;span&gt;TimeMark&lt;/span&gt;,&lt;span&gt;Entry&lt;/span&gt;])
               &lt;span&gt;end&lt;/span&gt;,&lt;span&gt;&quot;&quot;&lt;/span&gt;,&lt;span&gt;lists&lt;/span&gt;:&lt;span&gt;sort&lt;/span&gt;(&lt;span&gt;lists&lt;/span&gt;:&lt;span&gt;append&lt;/span&gt;([&lt;span&gt;Lines&lt;/span&gt; &lt;span&gt;||&lt;/span&gt; {&lt;span&gt;_&lt;/span&gt;,&lt;span&gt;Lines&lt;/span&gt;} &lt;span&gt;&amp;lt;-&lt;/span&gt; &lt;span&gt;Logs&lt;/span&gt;]))),
    &lt;span&gt;ok&lt;/span&gt; = &lt;span&gt;erl_tar&lt;/span&gt;:&lt;span&gt;add&lt;/span&gt;(&lt;span&gt;TarFile&lt;/span&gt;,&lt;span&gt;erlang&lt;/span&gt;:&lt;span&gt;list_to_binary&lt;/span&gt;(&lt;span&gt;LogStr&lt;/span&gt;),&lt;span&gt;&quot;Log.txt&quot;&lt;/span&gt;,[]),
    &lt;span&gt;erl_tar&lt;/span&gt;:&lt;span&gt;close&lt;/span&gt;(&lt;span&gt;TarFile&lt;/span&gt;),
    {&lt;span&gt;Id&lt;/span&gt;,&lt;span&gt;Name&lt;/span&gt;}.&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of List --&gt;&lt;/p&gt;
&lt;p&gt;luckily this one does not rely on any more internal / external functions. So that closes this branch of the dev. Backtracking to the handle_info clause, there are some new external functions which has to be developed, one of them is the &lt;em&gt;wn_util:time_marker/0&lt;/em&gt;&lt;br /&gt;
function.&lt;/p&gt;
&lt;p&gt;In &lt;em&gt; wn_util.erl &lt;/em&gt;i add the following&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;-spec&lt;/span&gt;(&lt;span&gt;time_marker&lt;/span&gt;() -&amp;gt; &lt;span&gt;time_marker&lt;/span&gt;()).
&lt;span&gt;time_marker&lt;/span&gt;() -&amp;gt;
    {&lt;span&gt;date&lt;/span&gt;(),&lt;span&gt;time&lt;/span&gt;(),&lt;span&gt;now&lt;/span&gt;()}.&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;the way of signalling that a job is done has now changed, and the second argument is the time_marker of when this happened &amp;#8211; this as the wn_job_worker must create the resulting tgz file with the correct time-stamp in the filename.&lt;/p&gt;
&lt;p&gt;So, to change the done-signaling, the new lines in &lt;em&gt;wn_job_keeper.erl &lt;/em&gt; are&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;-spec&lt;/span&gt;(&lt;span&gt;done&lt;/span&gt;(&lt;span&gt;pid&lt;/span&gt;(),&lt;span&gt;time_marker&lt;/span&gt;()) -&amp;gt; &lt;span&gt;ok&lt;/span&gt;).
&lt;span&gt;done&lt;/span&gt;(&lt;span&gt;Pid&lt;/span&gt;,&lt;span&gt;TimeMarker&lt;/span&gt;) -&amp;gt;
    &lt;span&gt;gen_fsm&lt;/span&gt;:&lt;span&gt;send_all_state_event&lt;/span&gt;(&lt;span&gt;Pid&lt;/span&gt;,{&lt;span&gt;done&lt;/span&gt;,&lt;span&gt;TimeMarker&lt;/span&gt;}).&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;the internal clause for the handle_event to process this change is&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;handle_event&lt;/span&gt;({&lt;span&gt;done&lt;/span&gt;,&lt;span&gt;TimeMarker&lt;/span&gt;}, &lt;span&gt;working&lt;/span&gt;, #&lt;span&gt;state&lt;/span&gt;{&lt;span&gt;info&lt;/span&gt; = &lt;span&gt;Info&lt;/span&gt;} = &lt;span&gt;State&lt;/span&gt;) -&amp;gt;
    &lt;span&gt;Now&lt;/span&gt; = &lt;span&gt;now&lt;/span&gt;(),
    &lt;span&gt;stream_msg&lt;/span&gt;(&lt;span&gt;State&lt;/span&gt;#&lt;span&gt;state&lt;/span&gt;.&lt;span&gt;stream&lt;/span&gt;,{&lt;span&gt;Now&lt;/span&gt;,&lt;span&gt;done&lt;/span&gt;}),
    {&lt;span&gt;next_state&lt;/span&gt;, &lt;span&gt;done&lt;/span&gt;, &lt;span&gt;State&lt;/span&gt;#&lt;span&gt;state&lt;/span&gt;{&lt;span&gt;info&lt;/span&gt; = [{&lt;span&gt;Now&lt;/span&gt;,&lt;span&gt;done&lt;/span&gt;}|&lt;span&gt;Info&lt;/span&gt;],
                                   &lt;span&gt;done_at&lt;/span&gt; = &lt;span&gt;TimeMarker&lt;/span&gt;
                                  }};&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;Next &amp;#8211; still handle_info of &lt;em&gt;wn_job_worker.erl&lt;/em&gt; there is a new function to be implemented, &lt;em&gt;wn_job_keeper:logs/1&lt;/em&gt; which will retrieve the stdout result of the processing to be put into the Log.txt file that was seen in &lt;em&gt;make_tgz_result/4. &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt; &lt;/em&gt;Going into &lt;em&gt;wn_job_keeper.erl &lt;/em&gt;, i add the following type-spec and function&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;-spec&lt;/span&gt;(&lt;span&gt;logs&lt;/span&gt;(&lt;span&gt;pid&lt;/span&gt;()) -&amp;gt; [{&lt;span&gt;info&lt;/span&gt;|&lt;span&gt;result&lt;/span&gt;,[{&lt;span&gt;time&lt;/span&gt;(),&lt;span&gt;term&lt;/span&gt;()}]}]).
&lt;span&gt;logs&lt;/span&gt;(&lt;span&gt;Pid&lt;/span&gt;) -&amp;gt;
    &lt;span&gt;gen_fsm&lt;/span&gt;:&lt;span&gt;sync_send_all_state_event&lt;/span&gt;(&lt;span&gt;Pid&lt;/span&gt;,&lt;span&gt;get_logs&lt;/span&gt;).&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;and the function clause to handle the log retrieval request&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;handle_sync_event&lt;/span&gt;(&lt;span&gt;get_logs&lt;/span&gt;,&lt;span&gt;_From&lt;/span&gt;,&lt;span&gt;X&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;) -&amp;gt;
    {&lt;span&gt;reply&lt;/span&gt;,[{&lt;span&gt;info&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;#&lt;span&gt;state&lt;/span&gt;.&lt;span&gt;info&lt;/span&gt;},
            {&lt;span&gt;result&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;#&lt;span&gt;state&lt;/span&gt;.&lt;span&gt;result&lt;/span&gt;}],&lt;span&gt;X&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;};&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;Going &lt;em&gt;back&lt;/em&gt; to the &lt;em&gt;handle_info&lt;/em&gt; clause in &lt;em&gt;wn_job_worker.erl&lt;/em&gt;, the next new thing to implement is the function for setting the result inside the wn_job_keeper. The implementation is thus naturally put in &lt;em&gt;wn_job_keeper.erl.&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;-spec&lt;/span&gt;(&lt;span&gt;set_stored_result&lt;/span&gt;(&lt;span&gt;pid&lt;/span&gt;(),&lt;span&gt;string&lt;/span&gt;()) -&amp;gt; &lt;span&gt;ok&lt;/span&gt;).
&lt;span&gt;set_stored_result&lt;/span&gt;(&lt;span&gt;Pid&lt;/span&gt;,&lt;span&gt;Id&lt;/span&gt;) -&amp;gt;
    &lt;span&gt;gen_fsm&lt;/span&gt;:&lt;span&gt;sync_send_all_state_event&lt;/span&gt;(&lt;span&gt;Pid&lt;/span&gt;,{&lt;span&gt;stored_result&lt;/span&gt;,&lt;span&gt;Id&lt;/span&gt;}).&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;Of course we also need the clause to handle this synchronous request&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;handle_sync_event&lt;/span&gt;({&lt;span&gt;stored_result&lt;/span&gt;,&lt;span&gt;Id&lt;/span&gt;},&lt;span&gt;_&lt;/span&gt;,&lt;span&gt;X&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;) -&amp;gt;
    {&lt;span&gt;reply&lt;/span&gt;,&lt;span&gt;ok&lt;/span&gt;,&lt;span&gt;X&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;#&lt;span&gt;state&lt;/span&gt;{&lt;span&gt;stored_result&lt;/span&gt; = &lt;span&gt;Id&lt;/span&gt;}};&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;very straight forward and nothing fishy on that sandwich. Ending the wn_job_worker&amp;#8217;s &lt;em&gt;handle_info&lt;/em&gt; clause, some changes where made in the &lt;em&gt;wn_resource_process.erl&lt;/em&gt;. The wn_resource_process should now no longer signal done to the wn_job_keeper as the wn_job_worker does it herself.&lt;/p&gt;
&lt;p&gt;As the right of done-signalling has been revoked from the wn_resource_process, some code modification had to be done to the &lt;em&gt;handle_info&lt;/em&gt; clause in &lt;em&gt;wn_resource_process.erl &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;handle_info&lt;/span&gt;({&lt;span&gt;'EXIT'&lt;/span&gt;,&lt;span&gt;WorkerPid&lt;/span&gt;,&lt;span&gt;_&lt;/span&gt;}, &lt;span&gt;State&lt;/span&gt;) -&amp;gt;
    {&lt;span&gt;noreply&lt;/span&gt;,
     &lt;span&gt;begin&lt;/span&gt;
      [{&lt;span&gt;WorkerPid&lt;/span&gt;,&lt;span&gt;_&lt;/span&gt;,&lt;span&gt;QueueType&lt;/span&gt;}] = &lt;span&gt;ets&lt;/span&gt;:&lt;span&gt;lookup&lt;/span&gt;(&lt;span&gt;State&lt;/span&gt;#&lt;span&gt;state&lt;/span&gt;.&lt;span&gt;working&lt;/span&gt;,&lt;span&gt;WorkerPid&lt;/span&gt;),
      &lt;span&gt;true&lt;/span&gt; = &lt;span&gt;ets&lt;/span&gt;:&lt;span&gt;delete&lt;/span&gt;(&lt;span&gt;State&lt;/span&gt;#&lt;span&gt;state&lt;/span&gt;.&lt;span&gt;working&lt;/span&gt;,&lt;span&gt;WorkerPid&lt;/span&gt;),

      &lt;span&gt;case&lt;/span&gt; &lt;span&gt;lists&lt;/span&gt;:&lt;span&gt;keytake&lt;/span&gt;(&lt;span&gt;QueueType&lt;/span&gt;,1,&lt;span&gt;State&lt;/span&gt;#&lt;span&gt;state&lt;/span&gt;.&lt;span&gt;queues&lt;/span&gt;) &lt;span&gt;of&lt;/span&gt;
        {&lt;span&gt;value&lt;/span&gt;,{&lt;span&gt;_&lt;/span&gt;,[]},&lt;span&gt;_&lt;/span&gt;} -&amp;gt;
          &lt;span&gt;case&lt;/span&gt; &lt;span&gt;ets&lt;/span&gt;:&lt;span&gt;lookup&lt;/span&gt;(&lt;span&gt;State&lt;/span&gt;#&lt;span&gt;state&lt;/span&gt;.&lt;span&gt;slots&lt;/span&gt;,&lt;span&gt;QueueType&lt;/span&gt;) &lt;span&gt;of&lt;/span&gt;
             [{&lt;span&gt;QueueType&lt;/span&gt;,&lt;span&gt;infinity&lt;/span&gt;}] -&amp;gt; &lt;span&gt;ignore&lt;/span&gt;;
             [{&lt;span&gt;QueueType&lt;/span&gt;,&lt;span&gt;X&lt;/span&gt;}] -&amp;gt; &lt;span&gt;ets&lt;/span&gt;:&lt;span&gt;insert&lt;/span&gt;(&lt;span&gt;State&lt;/span&gt;#&lt;span&gt;state&lt;/span&gt;.&lt;span&gt;slots&lt;/span&gt;,{&lt;span&gt;QueueType&lt;/span&gt;,&lt;span&gt;X&lt;/span&gt;+1})
          &lt;span&gt;end&lt;/span&gt;,
          &lt;span&gt;State&lt;/span&gt;;
        {&lt;span&gt;value&lt;/span&gt;,{&lt;span&gt;Type&lt;/span&gt;,[&lt;span&gt;QueuedPid&lt;/span&gt;|&lt;span&gt;R&lt;/span&gt;]},&lt;span&gt;Queues&lt;/span&gt;} -&amp;gt;
          &lt;span&gt;case&lt;/span&gt; &lt;span&gt;try_dispatch_job&lt;/span&gt;(&lt;span&gt;QueuedPid&lt;/span&gt;,&lt;span&gt;State&lt;/span&gt;,&lt;span&gt;QueueType&lt;/span&gt;) &lt;span&gt;of&lt;/span&gt;
             &lt;span&gt;ok&lt;/span&gt; -&amp;gt;
               &lt;span&gt;State&lt;/span&gt;#&lt;span&gt;state&lt;/span&gt;{&lt;span&gt;queues&lt;/span&gt; = [{&lt;span&gt;Type&lt;/span&gt;,&lt;span&gt;R&lt;/span&gt;}|&lt;span&gt;Queues&lt;/span&gt;]};
            {&lt;span&gt;error&lt;/span&gt;,&lt;span&gt;taken&lt;/span&gt;} -&amp;gt;
               &lt;span&gt;State&lt;/span&gt;
          &lt;span&gt;end&lt;/span&gt;
         &lt;span&gt;end&lt;/span&gt;
     &lt;span&gt;end&lt;/span&gt;}.&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;As the &lt;em&gt;wn_job_worker:make_tgz_result/4&lt;/em&gt; dictated, the input in the Log.txt file changed what the streamer should get &amp;#8211; in unison with (11) in the test. Thus this format change has to be accommodated in the &lt;em&gt; wn_job_layer:&lt;/em&gt;stream/2 function&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;-spec&lt;/span&gt;(&lt;span&gt;stream&lt;/span&gt;(&lt;span&gt;term&lt;/span&gt;(),&lt;span&gt;string&lt;/span&gt;()) -&amp;gt; &lt;span&gt;ok&lt;/span&gt; | {&lt;span&gt;error&lt;/span&gt;,&lt;span&gt;term&lt;/span&gt;()}).
&lt;span&gt;stream&lt;/span&gt;(&lt;span&gt;IoDev&lt;/span&gt;,&lt;span&gt;Id&lt;/span&gt;) -&amp;gt;
    &lt;span&gt;Stream&lt;/span&gt; = &lt;span&gt;fun&lt;/span&gt;(&lt;span&gt;F&lt;/span&gt;) -&amp;gt; &lt;span&gt;receive&lt;/span&gt; {&lt;span&gt;T&lt;/span&gt;,&lt;span&gt;E&lt;/span&gt;} -&amp;gt; &lt;span&gt;io&lt;/span&gt;:&lt;span&gt;format&lt;/span&gt;(&lt;span&gt;IoDev&lt;/span&gt;,&lt;span&gt;&quot;~p : ~p~n&quot;&lt;/span&gt;,[&lt;span&gt;T&lt;/span&gt;,&lt;span&gt;E&lt;/span&gt;]) &lt;span&gt;end&lt;/span&gt;, &lt;span&gt;F&lt;/span&gt;(&lt;span&gt;F&lt;/span&gt;) &lt;span&gt;end&lt;/span&gt;,
    &lt;span&gt;StreamPid&lt;/span&gt; = &lt;span&gt;spawn_link&lt;/span&gt;(&lt;span&gt;fun&lt;/span&gt;() -&amp;gt; &lt;span&gt;Stream&lt;/span&gt;(&lt;span&gt;Stream&lt;/span&gt;) &lt;span&gt;end&lt;/span&gt;),
    &lt;span&gt;case&lt;/span&gt; &lt;span&gt;gen_server&lt;/span&gt;:&lt;span&gt;call&lt;/span&gt;(?&lt;span&gt;MODULE&lt;/span&gt;,{&lt;span&gt;stream&lt;/span&gt;,&lt;span&gt;StreamPid&lt;/span&gt;,&lt;span&gt;Id&lt;/span&gt;}) &lt;span&gt;of&lt;/span&gt;
        &lt;span&gt;ok&lt;/span&gt; -&amp;gt; &lt;span&gt;ok&lt;/span&gt;;
        &lt;span&gt;Err&lt;/span&gt; -&amp;gt;
            &lt;span&gt;exit&lt;/span&gt;(&lt;span&gt;StreamPid&lt;/span&gt;,&lt;span&gt;Err&lt;/span&gt;),
            &lt;span&gt;Err&lt;/span&gt;
    &lt;span&gt;end&lt;/span&gt;.&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;Also, the &lt;em&gt;wn_job_layer:replay/2&lt;/em&gt; function had to be changed&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;replay&lt;/span&gt;(&lt;span&gt;Pid&lt;/span&gt;,#&lt;span&gt;state&lt;/span&gt;{&lt;span&gt;info&lt;/span&gt; = &lt;span&gt;Info&lt;/span&gt;,&lt;span&gt;result&lt;/span&gt;=&lt;span&gt;Result&lt;/span&gt;}) -&amp;gt;
    &lt;span&gt;lists&lt;/span&gt;:&lt;span&gt;foreach&lt;/span&gt;(&lt;span&gt;fun&lt;/span&gt;(&lt;span&gt;Entry&lt;/span&gt;) -&amp;gt; &lt;span&gt;Pid&lt;/span&gt; ! &lt;span&gt;Entry&lt;/span&gt; &lt;span&gt;end&lt;/span&gt;,
                  &lt;span&gt;lists&lt;/span&gt;:&lt;span&gt;sort&lt;/span&gt;(&lt;span&gt;Info&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;Result&lt;/span&gt;)).&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;Finally! This satisfies the test! However, there is one point of concern. One of the previous tests can cause this one to fail! The culprit is&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt; {&lt;span&gt;&quot;Queueus on resource type amount&quot;&lt;/span&gt;, &lt;span&gt;fun&lt;/span&gt; &lt;span&gt;queues_on_resource_types_amount/0&lt;/span&gt;},&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;That culprit-test queued several jobs but never removed them properly &amp;#8211; causing some interesting effects on the current working directory of the processes. The effect of having this intermediate test &lt;em&gt;interfering&lt;/em&gt; is a good example of &lt;span&gt;&lt;em&gt;bad test behaviour&lt;/em&gt;&lt;/span&gt;. In the best case &amp;#8211; we would be expecting each test to be set up in it&amp;#8217;s own clean universe, and to die in that same universe as well, without overspilling into other parallel realities!&lt;/p&gt;
&lt;p&gt;As can be seen &amp;#8211; the make test shows the failure&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;1&amp;gt; ======================== &lt;span&gt;EUnit&lt;/span&gt; ========================
&lt;span&gt;module&lt;/span&gt; &lt;span&gt;'wn_job_layer'&lt;/span&gt;
  &lt;span&gt;module&lt;/span&gt; &lt;span&gt;'wn_job_layer_tests'&lt;/span&gt;
    &lt;span&gt;wn_job_layer_tests&lt;/span&gt;: &lt;span&gt;local_test_&lt;/span&gt; (&lt;span&gt;Can&lt;/span&gt; &lt;span&gt;register&lt;/span&gt; &lt;span&gt;locally&lt;/span&gt;)...[0.004 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_job_layer_tests&lt;/span&gt;: &lt;span&gt;local_test_&lt;/span&gt; (&lt;span&gt;Executed&lt;/span&gt; &lt;span&gt;locally&lt;/span&gt;)...{1298,929708,203063} : &lt;span&gt;file_fetching_done&lt;/span&gt;
{1298,929708,203067} : &lt;span&gt;executing_commands&lt;/span&gt;
{1298,929708,203217} : {&lt;span&gt;executing&lt;/span&gt;,&lt;span&gt;&quot;more EUnitFile&quot;&lt;/span&gt;}
{1298,929708,210033} : &lt;span&gt;&quot;1,2,3&quot;&lt;/span&gt;
{1298,929708,210134} : &lt;span&gt;no_more_commands&lt;/span&gt;
{1298,929708,210137} : &lt;span&gt;building_result_tgz&lt;/span&gt;
{1298,929708,210187} : &lt;span&gt;done&lt;/span&gt;
[1.004 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_job_layer_tests&lt;/span&gt;: &lt;span&gt;local_test_&lt;/span&gt; (&lt;span&gt;Executed&lt;/span&gt; &lt;span&gt;queue&lt;/span&gt;)...{1298,929709,215132} : &lt;span&gt;file_fetching_done&lt;/span&gt;
{1298,929709,215134} : &lt;span&gt;executing_commands&lt;/span&gt;
{1298,929709,215221} : {&lt;span&gt;executing&lt;/span&gt;,&lt;span&gt;&quot;file EunitFile&quot;&lt;/span&gt;}
{1298,929709,222661} : &lt;span&gt;&quot;EunitFile: ASCII text&quot;&lt;/span&gt;
{1298,929709,222721} : &lt;span&gt;no_more_commands&lt;/span&gt;
{1298,929709,222725} : &lt;span&gt;building_result_tgz&lt;/span&gt;
{1298,929709,222801} : &lt;span&gt;done&lt;/span&gt;
{1298,929709,225999} : &lt;span&gt;file_fetching_done&lt;/span&gt;
{1298,929709,226001} : &lt;span&gt;executing_commands&lt;/span&gt;
{1298,929709,226189} : {&lt;span&gt;executing&lt;/span&gt;,&lt;span&gt;&quot;cat EUnitFile&quot;&lt;/span&gt;}
{1298,929709,231033} : &lt;span&gt;&quot;1,2,3&quot;&lt;/span&gt;
{1298,929709,231087} : &lt;span&gt;no_more_commands&lt;/span&gt;
{1298,929709,231090} : &lt;span&gt;building_result_tgz&lt;/span&gt;
{1298,929709,231149} : &lt;span&gt;done&lt;/span&gt;
[1.104 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_job_layer_tests&lt;/span&gt;: &lt;span&gt;local_test_&lt;/span&gt; (&lt;span&gt;Queueus&lt;/span&gt; &lt;span&gt;on&lt;/span&gt; &lt;span&gt;resource&lt;/span&gt; &lt;span&gt;type&lt;/span&gt; &lt;span&gt;amount&lt;/span&gt;)...[0.001 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
&lt;span&gt;shell&lt;/span&gt;-&lt;span&gt;init&lt;/span&gt;: &lt;span&gt;error&lt;/span&gt; &lt;span&gt;retrieving&lt;/span&gt; &lt;span&gt;current&lt;/span&gt; &lt;span&gt;directory&lt;/span&gt;: &lt;span&gt;getcwd&lt;/span&gt;: &lt;span&gt;cannot&lt;/span&gt; &lt;span&gt;access&lt;/span&gt; &lt;span&gt;parent&lt;/span&gt; &lt;span&gt;directories&lt;/span&gt;: &lt;span&gt;No&lt;/span&gt; &lt;span&gt;such&lt;/span&gt; &lt;span&gt;file&lt;/span&gt; &lt;span&gt;or&lt;/span&gt; &lt;span&gt;directory&lt;/span&gt;
                                                                                                                       &lt;span&gt;wn_job_layer_tests&lt;/span&gt;: &lt;span&gt;local_test_&lt;/span&gt; (&lt;span&gt;Canceled&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; &lt;span&gt;queue&lt;/span&gt;)...&lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_job_layer_tests&lt;/span&gt;: &lt;span&gt;local_test_&lt;/span&gt; (&lt;span&gt;Done&lt;/span&gt; &lt;span&gt;Job&lt;/span&gt; &lt;span&gt;Stored&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; &lt;span&gt;file&lt;/span&gt; &lt;span&gt;layer&lt;/span&gt;)...
=&lt;span&gt;ERROR&lt;/span&gt; &lt;span&gt;REPORT&lt;/span&gt;==== 28-&lt;span&gt;Feb&lt;/span&gt;-2011::21:48:30 ===
** &lt;span&gt;Generic&lt;/span&gt; &lt;span&gt;server&lt;/span&gt; &amp;lt;0.174.0&amp;gt; &lt;span&gt;terminating&lt;/span&gt;
** &lt;span&gt;Last&lt;/span&gt; &lt;span&gt;message&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; &lt;span&gt;was&lt;/span&gt; {&lt;span&gt;'$gen_cast'&lt;/span&gt;,{&lt;span&gt;signal&lt;/span&gt;,&amp;lt;0.178.0&amp;gt;,&lt;span&gt;a&lt;/span&gt;}}
** &lt;span&gt;When&lt;/span&gt; &lt;span&gt;Server&lt;/span&gt; &lt;span&gt;state&lt;/span&gt; == {&lt;span&gt;state&lt;/span&gt;,&lt;span&gt;&quot;/Users/zenon/ErlangBlog/worker_net-0.1/node_root/&quot;&lt;/span&gt;,
                               [{&lt;span&gt;a&lt;/span&gt;,[]}],
                               127001,122904}
** &lt;span&gt;Reason&lt;/span&gt; &lt;span&gt;for&lt;/span&gt; &lt;span&gt;termination&lt;/span&gt; ==
** {{&lt;span&gt;badmatch&lt;/span&gt;,
        {&lt;span&gt;error&lt;/span&gt;,
            {&lt;span&gt;function_clause&lt;/span&gt;,
                [{&lt;span&gt;wn_job_worker&lt;/span&gt;,'-&lt;span&gt;init/1&lt;/span&gt;-&lt;span&gt;fun&lt;/span&gt;-0-',[{&lt;span&gt;error&lt;/span&gt;,&lt;span&gt;enoent&lt;/span&gt;}]},
                 {&lt;span&gt;wn_job_worker&lt;/span&gt;,&lt;span&gt;init&lt;/span&gt;,1},
                 {&lt;span&gt;gen_server&lt;/span&gt;,&lt;span&gt;init_it&lt;/span&gt;,6},
                 {&lt;span&gt;proc_lib&lt;/span&gt;,&lt;span&gt;init_p_do_apply&lt;/span&gt;,3}]}}},
    [{&lt;span&gt;wn_resource_process&lt;/span&gt;,&lt;span&gt;try_dispatch_job&lt;/span&gt;,3},
     {&lt;span&gt;wn_resource_process&lt;/span&gt;,&lt;span&gt;handle_cast&lt;/span&gt;,2},
     {&lt;span&gt;gen_server&lt;/span&gt;,&lt;span&gt;handle_msg&lt;/span&gt;,5},
     {&lt;span&gt;proc_lib&lt;/span&gt;,&lt;span&gt;init_p_do_apply&lt;/span&gt;,3}]}
*&lt;span&gt;failed&lt;/span&gt;*
::&lt;span&gt;error&lt;/span&gt;:{&lt;span&gt;badmatch&lt;/span&gt;,{&lt;span&gt;error&lt;/span&gt;,&lt;span&gt;not_done&lt;/span&gt;}}
  &lt;span&gt;in&lt;/span&gt; &lt;span&gt;function&lt;/span&gt; &lt;span&gt;wn_job_layer_tests&lt;/span&gt;:&lt;span&gt;stored_in_file_layer/0&lt;/span&gt;

    [&lt;span&gt;done&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; 2.687 &lt;span&gt;s&lt;/span&gt;]
  [&lt;span&gt;done&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; 2.687 &lt;span&gt;s&lt;/span&gt;]
=======================================================
  &lt;span&gt;Failed&lt;/span&gt;: 1.  &lt;span&gt;Skipped&lt;/span&gt;: 0.  &lt;span&gt;Passed&lt;/span&gt;: 5.
&lt;span&gt;zen&lt;/span&gt;:&lt;span&gt;worker_net&lt;/span&gt;-0.1 &lt;span&gt;zenon&lt;/span&gt;&lt;span&gt;$ &lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;While the version in where we comment out the test in question succeeds quite nice&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;1&amp;gt; ======================== &lt;span&gt;EUnit&lt;/span&gt; ========================
&lt;span&gt;module&lt;/span&gt; &lt;span&gt;'wn_job_layer'&lt;/span&gt;
  &lt;span&gt;module&lt;/span&gt; &lt;span&gt;'wn_job_layer_tests'&lt;/span&gt;
    &lt;span&gt;wn_job_layer_tests&lt;/span&gt;: &lt;span&gt;local_test_&lt;/span&gt; (&lt;span&gt;Can&lt;/span&gt; &lt;span&gt;register&lt;/span&gt; &lt;span&gt;locally&lt;/span&gt;)...[0.005 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_job_layer_tests&lt;/span&gt;: &lt;span&gt;local_test_&lt;/span&gt; (&lt;span&gt;Executed&lt;/span&gt; &lt;span&gt;locally&lt;/span&gt;)...{1298,929858,474814} : &lt;span&gt;file_fetching_done&lt;/span&gt;
{1298,929858,474817} : &lt;span&gt;executing_commands&lt;/span&gt;
{1298,929858,474949} : {&lt;span&gt;executing&lt;/span&gt;,&lt;span&gt;&quot;more EUnitFile&quot;&lt;/span&gt;}
{1298,929858,481366} : &lt;span&gt;&quot;1,2,3&quot;&lt;/span&gt;
{1298,929858,481451} : &lt;span&gt;no_more_commands&lt;/span&gt;
{1298,929858,481454} : &lt;span&gt;building_result_tgz&lt;/span&gt;
{1298,929858,481489} : &lt;span&gt;done&lt;/span&gt;
[1.005 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_job_layer_tests&lt;/span&gt;: &lt;span&gt;local_test_&lt;/span&gt; (&lt;span&gt;Executed&lt;/span&gt; &lt;span&gt;queue&lt;/span&gt;)...{1298,929859,486690} : &lt;span&gt;file_fetching_done&lt;/span&gt;
{1298,929859,486693} : &lt;span&gt;executing_commands&lt;/span&gt;
{1298,929859,486733} : {&lt;span&gt;executing&lt;/span&gt;,&lt;span&gt;&quot;file EunitFile&quot;&lt;/span&gt;}
{1298,929859,493820} : &lt;span&gt;&quot;EunitFile: ASCII text&quot;&lt;/span&gt;
{1298,929859,493937} : &lt;span&gt;no_more_commands&lt;/span&gt;
{1298,929859,493939} : &lt;span&gt;building_result_tgz&lt;/span&gt;
{1298,929859,494065} : &lt;span&gt;done&lt;/span&gt;
{1298,929859,497623} : &lt;span&gt;file_fetching_done&lt;/span&gt;
{1298,929859,497627} : &lt;span&gt;executing_commands&lt;/span&gt;
{1298,929859,497716} : {&lt;span&gt;executing&lt;/span&gt;,&lt;span&gt;&quot;cat EUnitFile&quot;&lt;/span&gt;}
{1298,929859,503066} : &lt;span&gt;&quot;1,2,3&quot;&lt;/span&gt;
{1298,929859,503118} : &lt;span&gt;no_more_commands&lt;/span&gt;
{1298,929859,503120} : &lt;span&gt;building_result_tgz&lt;/span&gt;
{1298,929859,503188} : &lt;span&gt;done&lt;/span&gt;
[1.105 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_job_layer_tests&lt;/span&gt;: &lt;span&gt;local_test_&lt;/span&gt; (&lt;span&gt;Canceled&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; &lt;span&gt;queue&lt;/span&gt;)...&lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_job_layer_tests&lt;/span&gt;: &lt;span&gt;local_test_&lt;/span&gt; (&lt;span&gt;Done&lt;/span&gt; &lt;span&gt;Job&lt;/span&gt; &lt;span&gt;Stored&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; &lt;span&gt;file&lt;/span&gt; &lt;span&gt;layer&lt;/span&gt;)...[0.607 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    [&lt;span&gt;done&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; 2.766 &lt;span&gt;s&lt;/span&gt;]
  [&lt;span&gt;done&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; 2.766 &lt;span&gt;s&lt;/span&gt;]
=======================================================
  &lt;span&gt;All&lt;/span&gt; 5 &lt;span&gt;tests&lt;/span&gt; &lt;span&gt;passed&lt;/span&gt;.&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;This was fixed by constraining the previous test (and making it more actual to what it should test)&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;queues_on_resource_types_amount&lt;/span&gt;() -&amp;gt;
    &lt;span&gt;wn_resource_layer&lt;/span&gt;:&lt;span&gt;register&lt;/span&gt;(#&lt;span&gt;wn_resource&lt;/span&gt;{&lt;span&gt;name&lt;/span&gt; = &lt;span&gt;&quot;Laptop&quot;&lt;/span&gt;,
                                            &lt;span&gt;type&lt;/span&gt; = [{&lt;span&gt;a&lt;/span&gt;,0},{&lt;span&gt;b&lt;/span&gt;,0}],
                                            &lt;span&gt;resides&lt;/span&gt; = &lt;span&gt;node&lt;/span&gt;()
                                           }),
    &lt;span&gt;Queued&lt;/span&gt; = &lt;span&gt;fun&lt;/span&gt;() -&amp;gt; &lt;span&gt;wn_resource_layer&lt;/span&gt;:&lt;span&gt;queued&lt;/span&gt;(&lt;span&gt;node&lt;/span&gt;(),&lt;span&gt;&quot;Laptop&quot;&lt;/span&gt;) &lt;span&gt;end&lt;/span&gt;,
    &lt;span&gt;Job1&lt;/span&gt; = #&lt;span&gt;wn_job&lt;/span&gt;{&lt;span&gt;id&lt;/span&gt; = &lt;span&gt;&quot;JobId&quot;&lt;/span&gt;,&lt;span&gt;files&lt;/span&gt; = [],&lt;span&gt;resources&lt;/span&gt; = [&lt;span&gt;a&lt;/span&gt;]},
    &lt;span&gt;Job2&lt;/span&gt; = &lt;span&gt;Job1&lt;/span&gt;#&lt;span&gt;wn_job&lt;/span&gt;{&lt;span&gt;id&lt;/span&gt; = &lt;span&gt;&quot;JobId2&quot;&lt;/span&gt;, &lt;span&gt;resources&lt;/span&gt; = [&lt;span&gt;a&lt;/span&gt;]},
    &lt;span&gt;Job3&lt;/span&gt; = &lt;span&gt;Job1&lt;/span&gt;#&lt;span&gt;wn_job&lt;/span&gt;{&lt;span&gt;id&lt;/span&gt; = &lt;span&gt;&quot;JobId3&quot;&lt;/span&gt;, &lt;span&gt;resources&lt;/span&gt; = [&lt;span&gt;a&lt;/span&gt;,&lt;span&gt;b&lt;/span&gt;]},

    &lt;span&gt;wn_job_layer&lt;/span&gt;:&lt;span&gt;register&lt;/span&gt;(&lt;span&gt;Job1&lt;/span&gt;),
    ?&lt;span&gt;assertMatch&lt;/span&gt;({&lt;span&gt;ok&lt;/span&gt;,[{&lt;span&gt;a&lt;/span&gt;,[&lt;span&gt;Job1&lt;/span&gt;]},{&lt;span&gt;b&lt;/span&gt;,[]}]},&lt;span&gt;Queued&lt;/span&gt;()),

    &lt;span&gt;wn_job_layer&lt;/span&gt;:&lt;span&gt;register&lt;/span&gt;(&lt;span&gt;Job2&lt;/span&gt;),
    ?&lt;span&gt;assertMatch&lt;/span&gt;({&lt;span&gt;ok&lt;/span&gt;,[{&lt;span&gt;a&lt;/span&gt;,[&lt;span&gt;Job1&lt;/span&gt;, &lt;span&gt;Job2&lt;/span&gt;]},{&lt;span&gt;b&lt;/span&gt;,[]}]},&lt;span&gt;Queued&lt;/span&gt;()),

    &lt;span&gt;wn_job_layer&lt;/span&gt;:&lt;span&gt;register&lt;/span&gt;(&lt;span&gt;Job3&lt;/span&gt;),
    ?&lt;span&gt;assertMatch&lt;/span&gt;({&lt;span&gt;ok&lt;/span&gt;,[{&lt;span&gt;b&lt;/span&gt;,[&lt;span&gt;Job3&lt;/span&gt;]},
                      {&lt;span&gt;a&lt;/span&gt;,[&lt;span&gt;Job1&lt;/span&gt;,&lt;span&gt;Job2&lt;/span&gt;,&lt;span&gt;Job3&lt;/span&gt;]}
                     ]},&lt;span&gt;Queued&lt;/span&gt;()).&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;This story has now ended &amp;#8211; with the following output of &lt;em&gt; &amp;#8216;make full&amp;#8217; &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;!--- Snippet --&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;zen&lt;/span&gt;:&lt;span&gt;worker_net&lt;/span&gt;-0.1 &lt;span&gt;zenon&lt;/span&gt;&lt;span&gt;$ &lt;/span&gt;&lt;span&gt;make&lt;/span&gt; &lt;span&gt;full&lt;/span&gt;
&lt;span&gt;erlc&lt;/span&gt; -&lt;span&gt;pa&lt;/span&gt; . -&lt;span&gt;o&lt;/span&gt; &lt;span&gt;ebin&lt;/span&gt;/  &lt;span&gt;src&lt;/span&gt;/*.&lt;span&gt;erl&lt;/span&gt; &lt;span&gt;test&lt;/span&gt;/*.&lt;span&gt;erl&lt;/span&gt;
&lt;span&gt;erl&lt;/span&gt; -&lt;span&gt;pa&lt;/span&gt; &lt;span&gt;ebin&lt;/span&gt;/ -&lt;span&gt;eval&lt;/span&gt; 'eunit:&lt;span&gt;test&lt;/span&gt;(&lt;span&gt;wn_resource_layer&lt;/span&gt;,[&lt;span&gt;verbose&lt;/span&gt;]), &lt;span&gt;init&lt;/span&gt;:&lt;span&gt;stop&lt;/span&gt;().'
&lt;span&gt;Erlang&lt;/span&gt; &lt;span&gt;R14B&lt;/span&gt; (&lt;span&gt;erts&lt;/span&gt;-5.8.1) [&lt;span&gt;source&lt;/span&gt;] [&lt;span&gt;smp&lt;/span&gt;:4:4] [&lt;span&gt;rq&lt;/span&gt;:4] [&lt;span&gt;async&lt;/span&gt;-&lt;span&gt;threads&lt;/span&gt;:0] [&lt;span&gt;hipe&lt;/span&gt;] [&lt;span&gt;kernel&lt;/span&gt;-&lt;span&gt;poll&lt;/span&gt;:&lt;span&gt;false&lt;/span&gt;]

&lt;span&gt;Eshell&lt;/span&gt; &lt;span&gt;V5&lt;/span&gt;.8.1  (&lt;span&gt;abort&lt;/span&gt; &lt;span&gt;with&lt;/span&gt; ^&lt;span&gt;G&lt;/span&gt;)
1&amp;gt; ======================== &lt;span&gt;EUnit&lt;/span&gt; ========================
&lt;span&gt;module&lt;/span&gt; &lt;span&gt;'wn_resource_layer'&lt;/span&gt;
  &lt;span&gt;module&lt;/span&gt; &lt;span&gt;'wn_resource_layer_tests'&lt;/span&gt;
    &lt;span&gt;wn_resource_layer_tests&lt;/span&gt;: &lt;span&gt;local_resource_test_&lt;/span&gt; (&lt;span&gt;Can&lt;/span&gt; &lt;span&gt;register&lt;/span&gt; &lt;span&gt;resources&lt;/span&gt; &lt;span&gt;locally&lt;/span&gt;)...[0.001 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_resource_layer_tests&lt;/span&gt;: &lt;span&gt;register_distributed&lt;/span&gt; (&lt;span&gt;Can&lt;/span&gt; &lt;span&gt;Register&lt;/span&gt; &lt;span&gt;Distributed&lt;/span&gt;)...[0.004 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_resource_layer_tests&lt;/span&gt;: &lt;span&gt;register_restart_register&lt;/span&gt; (&lt;span&gt;Can&lt;/span&gt; &lt;span&gt;Register&lt;/span&gt;, &lt;span&gt;Restart&lt;/span&gt; &lt;span&gt;and&lt;/span&gt; &lt;span&gt;Register&lt;/span&gt;)...[0.010 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_resource_layer_tests&lt;/span&gt;: &lt;span&gt;register_deregister&lt;/span&gt; (&lt;span&gt;Can&lt;/span&gt; &lt;span&gt;Register&lt;/span&gt;, &lt;span&gt;Deregister&lt;/span&gt; &lt;span&gt;and&lt;/span&gt; &lt;span&gt;Register&lt;/span&gt;)...[0.008 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    [&lt;span&gt;done&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; 0.894 &lt;span&gt;s&lt;/span&gt;]
  [&lt;span&gt;done&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; 0.894 &lt;span&gt;s&lt;/span&gt;]
=======================================================
  &lt;span&gt;All&lt;/span&gt; 4 &lt;span&gt;tests&lt;/span&gt; &lt;span&gt;passed&lt;/span&gt;.
&lt;span&gt;erl&lt;/span&gt; -&lt;span&gt;pa&lt;/span&gt; &lt;span&gt;ebin&lt;/span&gt;/ -&lt;span&gt;eval&lt;/span&gt; 'eunit:&lt;span&gt;test&lt;/span&gt;(&lt;span&gt;wn_file_layer&lt;/span&gt;,[&lt;span&gt;verbose&lt;/span&gt;]), &lt;span&gt;init&lt;/span&gt;:&lt;span&gt;stop&lt;/span&gt;().'
&lt;span&gt;Erlang&lt;/span&gt; &lt;span&gt;R14B&lt;/span&gt; (&lt;span&gt;erts&lt;/span&gt;-5.8.1) [&lt;span&gt;source&lt;/span&gt;] [&lt;span&gt;smp&lt;/span&gt;:4:4] [&lt;span&gt;rq&lt;/span&gt;:4] [&lt;span&gt;async&lt;/span&gt;-&lt;span&gt;threads&lt;/span&gt;:0] [&lt;span&gt;hipe&lt;/span&gt;] [&lt;span&gt;kernel&lt;/span&gt;-&lt;span&gt;poll&lt;/span&gt;:&lt;span&gt;false&lt;/span&gt;]

&lt;span&gt;Eshell&lt;/span&gt; &lt;span&gt;V5&lt;/span&gt;.8.1  (&lt;span&gt;abort&lt;/span&gt; &lt;span&gt;with&lt;/span&gt; ^&lt;span&gt;G&lt;/span&gt;)
1&amp;gt; ======================== &lt;span&gt;EUnit&lt;/span&gt; ========================
&lt;span&gt;module&lt;/span&gt; &lt;span&gt;'wn_file_layer'&lt;/span&gt;
  &lt;span&gt;module&lt;/span&gt; &lt;span&gt;'wn_file_layer_tests'&lt;/span&gt;
   $&lt;span&gt;wn_file_layer_tests&lt;/span&gt;: &lt;span&gt;file_layer_local_test_&lt;/span&gt; (&lt;span&gt;Can&lt;/span&gt; &lt;span&gt;store&lt;/span&gt; &lt;span&gt;file&lt;/span&gt; &lt;span&gt;locally&lt;/span&gt;)...[0.001 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_file_layer_tests&lt;/span&gt;: &lt;span&gt;file_layer_local_test_&lt;/span&gt; (&lt;span&gt;Can&lt;/span&gt; &lt;span&gt;retrieve&lt;/span&gt; &lt;span&gt;files&lt;/span&gt; &lt;span&gt;locally&lt;/span&gt;)...[0.002 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_file_layer_tests&lt;/span&gt;: &lt;span&gt;file_layer_local_test_&lt;/span&gt; (&lt;span&gt;Can&lt;/span&gt; &lt;span&gt;delete&lt;/span&gt; &lt;span&gt;files&lt;/span&gt; &lt;span&gt;locally&lt;/span&gt;)...[0.001 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_file_layer_tests&lt;/span&gt;: &lt;span&gt;can_store_distributed&lt;/span&gt; (&lt;span&gt;Can&lt;/span&gt; &lt;span&gt;store&lt;/span&gt; &lt;span&gt;file&lt;/span&gt; &lt;span&gt;distributed&lt;/span&gt;)...[0.016 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_file_layer_tests&lt;/span&gt;: &lt;span&gt;can_retrieve_distributed&lt;/span&gt; (&lt;span&gt;Can&lt;/span&gt; &lt;span&gt;retrieve&lt;/span&gt; &lt;span&gt;file&lt;/span&gt; &lt;span&gt;distributed&lt;/span&gt;)...[0.017 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_file_layer_tests&lt;/span&gt;: &lt;span&gt;can_delete_distributed&lt;/span&gt; (&lt;span&gt;Can&lt;/span&gt; &lt;span&gt;delete&lt;/span&gt; &lt;span&gt;file&lt;/span&gt; &lt;span&gt;distributed&lt;/span&gt;)...[0.018 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_file_layer_tests&lt;/span&gt;: &lt;span&gt;must_retain&lt;/span&gt; (&lt;span&gt;Must&lt;/span&gt; &lt;span&gt;retain&lt;/span&gt; &lt;span&gt;information&lt;/span&gt; &lt;span&gt;between&lt;/span&gt; &lt;span&gt;node&lt;/span&gt; &lt;span&gt;kill&lt;/span&gt; &lt;span&gt;and&lt;/span&gt; &lt;span&gt;node&lt;/span&gt; &lt;span&gt;restart&lt;/span&gt;)...[0.321 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    [&lt;span&gt;done&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; 1.667 &lt;span&gt;s&lt;/span&gt;]
  [&lt;span&gt;done&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; 1.667 &lt;span&gt;s&lt;/span&gt;]
=======================================================
  &lt;span&gt;All&lt;/span&gt; 7 &lt;span&gt;tests&lt;/span&gt; &lt;span&gt;passed&lt;/span&gt;.
&lt;span&gt;erl&lt;/span&gt; -&lt;span&gt;pa&lt;/span&gt; &lt;span&gt;ebin&lt;/span&gt;/ -&lt;span&gt;eval&lt;/span&gt; 'eunit:&lt;span&gt;test&lt;/span&gt;(&lt;span&gt;wn_job_layer&lt;/span&gt;,[&lt;span&gt;verbose&lt;/span&gt;]), &lt;span&gt;init&lt;/span&gt;:&lt;span&gt;stop&lt;/span&gt;().'
&lt;span&gt;Erlang&lt;/span&gt; &lt;span&gt;R14B&lt;/span&gt; (&lt;span&gt;erts&lt;/span&gt;-5.8.1) [&lt;span&gt;source&lt;/span&gt;] [&lt;span&gt;smp&lt;/span&gt;:4:4] [&lt;span&gt;rq&lt;/span&gt;:4] [&lt;span&gt;async&lt;/span&gt;-&lt;span&gt;threads&lt;/span&gt;:0] [&lt;span&gt;hipe&lt;/span&gt;] [&lt;span&gt;kernel&lt;/span&gt;-&lt;span&gt;poll&lt;/span&gt;:&lt;span&gt;false&lt;/span&gt;]

&lt;span&gt;Eshell&lt;/span&gt; &lt;span&gt;V5&lt;/span&gt;.8.1  (&lt;span&gt;abort&lt;/span&gt; &lt;span&gt;with&lt;/span&gt; ^&lt;span&gt;G&lt;/span&gt;)
1&amp;gt; ======================== &lt;span&gt;EUnit&lt;/span&gt; ========================
&lt;span&gt;module&lt;/span&gt; &lt;span&gt;'wn_job_layer'&lt;/span&gt;
  &lt;span&gt;module&lt;/span&gt; &lt;span&gt;'wn_job_layer_tests'&lt;/span&gt;
    &lt;span&gt;wn_job_layer_tests&lt;/span&gt;: &lt;span&gt;local_test_&lt;/span&gt; (&lt;span&gt;Can&lt;/span&gt; &lt;span&gt;register&lt;/span&gt; &lt;span&gt;locally&lt;/span&gt;)...[0.004 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_job_layer_tests&lt;/span&gt;: &lt;span&gt;local_test_&lt;/span&gt; (&lt;span&gt;Executed&lt;/span&gt; &lt;span&gt;locally&lt;/span&gt;)...{1299,10791,575180} : &lt;span&gt;file_fetching_done&lt;/span&gt;
{1299,10791,575182} : &lt;span&gt;executing_commands&lt;/span&gt;
{1299,10791,575370} : {&lt;span&gt;executing&lt;/span&gt;,&lt;span&gt;&quot;more EUnitFile&quot;&lt;/span&gt;}
{1299,10791,582067} : &lt;span&gt;&quot;1,2,3&quot;&lt;/span&gt;
{1299,10791,582181} : &lt;span&gt;no_more_commands&lt;/span&gt;
{1299,10791,582183} : &lt;span&gt;building_result_tgz&lt;/span&gt;
{1299,10791,582278} : &lt;span&gt;done&lt;/span&gt;
[1.005 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_job_layer_tests&lt;/span&gt;: &lt;span&gt;local_test_&lt;/span&gt; (&lt;span&gt;Executed&lt;/span&gt; &lt;span&gt;queue&lt;/span&gt;)...{1299,10792,587205} : &lt;span&gt;file_fetching_done&lt;/span&gt;
{1299,10792,587208} : &lt;span&gt;executing_commands&lt;/span&gt;
{1299,10792,587299} : {&lt;span&gt;executing&lt;/span&gt;,&lt;span&gt;&quot;file EunitFile&quot;&lt;/span&gt;}
{1299,10792,594990} : &lt;span&gt;&quot;EunitFile: ASCII text&quot;&lt;/span&gt;
{1299,10792,595034} : &lt;span&gt;no_more_commands&lt;/span&gt;
{1299,10792,595037} : &lt;span&gt;building_result_tgz&lt;/span&gt;
{1299,10792,595117} : &lt;span&gt;done&lt;/span&gt;
{1299,10792,598436} : &lt;span&gt;file_fetching_done&lt;/span&gt;
{1299,10792,598446} : &lt;span&gt;executing_commands&lt;/span&gt;
{1299,10792,598525} : {&lt;span&gt;executing&lt;/span&gt;,&lt;span&gt;&quot;cat EUnitFile&quot;&lt;/span&gt;}
{1299,10792,603488} : &lt;span&gt;&quot;1,2,3&quot;&lt;/span&gt;
{1299,10792,603533} : &lt;span&gt;no_more_commands&lt;/span&gt;
{1299,10792,603536} : &lt;span&gt;building_result_tgz&lt;/span&gt;
{1299,10792,603593} : &lt;span&gt;done&lt;/span&gt;
[1.104 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_job_layer_tests&lt;/span&gt;: &lt;span&gt;local_test_&lt;/span&gt; (&lt;span&gt;Queueus&lt;/span&gt; &lt;span&gt;on&lt;/span&gt; &lt;span&gt;resource&lt;/span&gt; &lt;span&gt;type&lt;/span&gt; &lt;span&gt;amount&lt;/span&gt;)...&lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_job_layer_tests&lt;/span&gt;: &lt;span&gt;local_test_&lt;/span&gt; (&lt;span&gt;Canceled&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; &lt;span&gt;queue&lt;/span&gt;)...&lt;span&gt;ok&lt;/span&gt;
    &lt;span&gt;wn_job_layer_tests&lt;/span&gt;: &lt;span&gt;local_test_&lt;/span&gt; (&lt;span&gt;Done&lt;/span&gt; &lt;span&gt;Job&lt;/span&gt; &lt;span&gt;Stored&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; &lt;span&gt;file&lt;/span&gt; &lt;span&gt;layer&lt;/span&gt;)...[0.609 &lt;span&gt;s&lt;/span&gt;] &lt;span&gt;ok&lt;/span&gt;
    [&lt;span&gt;done&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; 2.773 &lt;span&gt;s&lt;/span&gt;]
  [&lt;span&gt;done&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; 2.773 &lt;span&gt;s&lt;/span&gt;]
=======================================================
  &lt;span&gt;All&lt;/span&gt; 6 &lt;span&gt;tests&lt;/span&gt; &lt;span&gt;passed&lt;/span&gt;.
&lt;span&gt;dialyzer&lt;/span&gt; &lt;span&gt;src&lt;/span&gt;/*.&lt;span&gt;erl&lt;/span&gt; &lt;span&gt;test&lt;/span&gt;/*.&lt;span&gt;erl&lt;/span&gt;
  &lt;span&gt;Checking&lt;/span&gt; &lt;span&gt;whether&lt;/span&gt; &lt;span&gt;the&lt;/span&gt; &lt;span&gt;PLT&lt;/span&gt; /&lt;span&gt;Users&lt;/span&gt;/&lt;span&gt;zenon&lt;/span&gt;/.&lt;span&gt;dialyzer_plt&lt;/span&gt; &lt;span&gt;is&lt;/span&gt; &lt;span&gt;up&lt;/span&gt;-&lt;span&gt;to&lt;/span&gt;-&lt;span&gt;date&lt;/span&gt;... &lt;span&gt;yes&lt;/span&gt;
  &lt;span&gt;Proceeding&lt;/span&gt; &lt;span&gt;with&lt;/span&gt; &lt;span&gt;analysis&lt;/span&gt;...
&lt;span&gt;Unknown&lt;/span&gt; &lt;span&gt;functions&lt;/span&gt;:
  &lt;span&gt;eunit&lt;/span&gt;:&lt;span&gt;test/1&lt;/span&gt;
 &lt;span&gt;done&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; 0m5.21s
&lt;span&gt;done&lt;/span&gt; (&lt;span&gt;passed&lt;/span&gt; &lt;span&gt;successfully&lt;/span&gt;)&lt;/pre&gt;
&lt;p&gt;&lt;!--- End Of Snippet --&gt;&lt;/p&gt;
&lt;p&gt;The status of the stories is now&lt;/p&gt;
&lt;h2&gt;Done stories&lt;/h2&gt;
&lt;p&gt;“&lt;em&gt;I want to be able to describe a job as&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;A set of Files [#wn_file{}]&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;The possible resource types needed (disjunction)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;A list of commands for running the job&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;A timeout the job is given while running (in seconds)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;A job id – primary key for the job&lt;/em&gt;&lt;em&gt;“&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;“&lt;em&gt;I want to be able to register a job in the job layer,  through  any node.&lt;/em&gt;“&lt;/p&gt;
&lt;p&gt;“&lt;em&gt;Several jobs should be queued on the same resource type(s),  being processed one and one in order as they where queued&lt;/em&gt;“&lt;/p&gt;
&lt;p&gt;“&lt;em&gt;I want to be able to list all jobs in the system, through any node&lt;/em&gt;.”&lt;/p&gt;
&lt;p&gt;“&lt;em&gt;The output generated by a job should be possible to see in realtime,  through any node and stored to logfiles&lt;/em&gt;.”&lt;/p&gt;
&lt;p&gt;“&lt;em&gt;A job must be possible to cancel before it starts running, through any node.&lt;/em&gt;“&lt;/p&gt;
&lt;p&gt;“&lt;em&gt;Once a job is done, the result should be stored in the file layer,  together with the logs.&lt;/em&gt;“&lt;/p&gt;
&lt;h2&gt;Not done stories&lt;/h2&gt;
&lt;p&gt;“&lt;em&gt;I want to be able to delete a job once it’s done, through any node&lt;/em&gt;.”&lt;/p&gt;
&lt;p&gt;In the next post, I shall write the test and implementation of the current final story on the job layer &amp;#8211; to delete a job from any node &amp;#8211; once it&amp;#8217;s done.&lt;/p&gt;
&lt;p&gt;Cheers&lt;/p&gt;
&lt;p&gt;/G&lt;/p&gt;
&lt;br /&gt;  &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gocomments/erlcode.wordpress.com/633/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/comments/erlcode.wordpress.com/633/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/godelicious/erlcode.wordpress.com/633/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/delicious/erlcode.wordpress.com/633/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gofacebook/erlcode.wordpress.com/633/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/facebook/erlcode.wordpress.com/633/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gotwitter/erlcode.wordpress.com/633/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/twitter/erlcode.wordpress.com/633/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gostumble/erlcode.wordpress.com/633/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/stumble/erlcode.wordpress.com/633/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/godigg/erlcode.wordpress.com/633/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/digg/erlcode.wordpress.com/633/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/goreddit/erlcode.wordpress.com/633/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/reddit/erlcode.wordpress.com/633/&quot; /&gt;&lt;/a&gt; &lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=erlcode.wordpress.com&amp;blog=15510807&amp;post=633&amp;subd=erlcode&amp;ref=&amp;feed=1&quot; width=&quot;1&quot; height=&quot;1&quot; /&gt;</description>
	<pubDate>Tue, 01 Mar 2011 21:07:42 +0000</pubDate>
</item>
<item>
	<title>Programming in the 21st Century: Accidental Innovation, Part 2</title>
	<guid>http://prog21.dadgum.com/90.html</guid>
	<link>http://prog21.dadgum.com/90.html</link>
	<description>In 1995 I was writing a book, a collection of interviews with people who wrote video and computer games in the 1980s. I had the inside track on the whereabouts of many of those game designers--this was before they were easy to find via Google--and decided to make use of that knowledge. But at the time technology books that weren't &quot;how to&quot; were a tough sell, so after a number of rejections from publishers I set the project aside.
&lt;br /&gt;&lt;br /&gt;A year later, my wife and I were running a small game development company, and those interviews resurfaced as a potential product. We were already set-up to handle orders and mail games to customers, so the book could be entirely digital. But what format to use? PDF readers were clunky and slow. Not everyone had Microsoft Word. Then it hit me: What about using HTML as a portable document format? I know, I know, it's &lt;i&gt;designed&lt;/i&gt; to be a portable document format, but I was thinking of it as an off-line format, not just for viewing websites. I hadn't seen anyone do this yet. It was before HTML became a common format for documentation and help files.
&lt;br /&gt;&lt;br /&gt;And so for the next couple of years people paid $20 for &lt;a href=&quot;http://en.wikipedia.org/wiki/Halcyon_Days_%28book%29&quot;&gt;Halcyon Days: Interviews with Classic Computer and Video Game Programmers&lt;/a&gt;. Shipped via U.S. mail. On a 3 1/2 inch floppy disc. Five years later I put it &lt;a href=&quot;http://www.dadgum.com/halcyon/&quot;&gt;on the web for free&lt;/a&gt;.
&lt;br /&gt;&lt;br /&gt;Even though I made the leap of using HTML for off-line e-books, and web browsers as the readers, I still didn't realize how ubiquitous HTML and browsers would become. I don't remember the details of how it happened, but I asked &lt;a href=&quot;http://en.wikipedia.org/wiki/John_Romero&quot;&gt;John Romero&lt;/a&gt; to write the introduction, which he enthusiastically did. I mentioned that I was looking for a distribution format for those people who didn't use browsers, and his comment was (paraphrased): &quot;Are you crazy! Don't look backward! This is the future!&quot;
&lt;br /&gt;&lt;br /&gt;Obviously, he was right.</description>
	<pubDate>Tue, 01 Mar 2011 06:00:00 +0000</pubDate>
</item>
<item>
	<title>Process-one Blogs: Sea Beyond 2011: Video summary</title>
	<guid>http://www.process-one.net/en/blogs/article/sea_beyond_2011_video_summary/</guid>
	<link>http://www.process-one.net/en/blogs/article/sea_beyond_2011_video_summary/</link>
	<description>&lt;p&gt;&lt;a href=&quot;http://www.process-one.net/seabeyond/&quot;&gt;Sea Beyond&lt;/a&gt; is an event on Realtime communication and collaboration organized by ProcessOne. Second edition took place in Paris on February 3rd, 2011. Focus this year was on mobile realtime collaboration and federated social networks.&lt;/p&gt; &lt;p&gt;Here is the summary video of the event:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;We will release video of each demo and presentation in the &quot;Developer Sandbox&quot; part of the event and all the talks from the &quot;lighthouse&quot; conference part.&lt;/p&gt;
&lt;p&gt;Here is the schedule for the release:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;March 3rd: Micka&amp;euml;l R&amp;eacute;mond, &lt;a href=&quot;http://www.process-one.net&quot;&gt;ProcessOne&lt;/a&gt;: &lt;a href=&quot;http://www.process-one.net/en/blogs/article/sea_beyond_2011_talk_1_mickael_remond_on_processone_and_textone_protocol/&quot;&gt;TextOne protocol presentation: Improving XMPP for mobile messaging&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;March 7th: Christophe Romain and Karim Gemayel, &lt;a href=&quot;http://www.process-one.net&quot;&gt;ProcessOne&lt;/a&gt;: Pubsub introduction and use case in the context of federated social networks.&lt;/li&gt;
&lt;li&gt;March 10th: David Banes, &lt;a href=&quot;http://www.cleartextsystems.com/&quot;&gt;Cleartext&lt;/a&gt;: Cleartext microblogging extension for the XMPP protocol. He will demo and Cleartext IM and Microblogging Desktop App as well as server component. Don't miss David's surprise announcement ;)&lt;/li&gt;
&lt;li&gt;March 14th: Alexandre Eisenchteter and Thierry Bomandouki, &lt;a href=&quot;http://af83.com/&quot;&gt;AF83&lt;/a&gt;: UC Engine (Unified Collaboration Engine) and tools to help developers build real-time applications or integrate real-time features to existing applications.&lt;/li&gt;
&lt;li&gt;March 17th: Eric Cestari, &lt;a href=&quot;http://www.process-one.net&quot;&gt;ProcessOne&lt;/a&gt;: XMPP based web socket implementation and emphasizes the benefit compared to previous techniques like BOSH socket. Don't miss the launch of the showcase real time pubsub push over websocket, Gitlive.&lt;/li&gt;
&lt;li&gt;March 21st: Marek Foss, &lt;a href=&quot;http://www.process-one.net&quot;&gt;ProcessOne&lt;/a&gt;: Different approaches for designing mobile collaboration software.&lt;/li&gt;
&lt;li&gt;March 24th: Diana Cheng, &lt;a href=&quot;http://www.vodafone.com/&quot;&gt;Vodafone&lt;/a&gt;: OneSocialWeb: XMPP-based distributed social network for web and mobile usage.&lt;/li&gt;
&lt;li&gt;March 28th: Jukka Alakontiola, &lt;a href=&quot;http://www.nokia.com/&quot;&gt;Nokia&lt;/a&gt;: Nokia Push notification platform and API.&lt;/li&gt;
&lt;li&gt;March 31st: Julien Genestoux, &lt;a href=&quot;http://superfeedr.com/&quot;&gt;Superfeedr&lt;/a&gt;: XMPP and pubsubhubbub for real-time large scale events and notification distribution.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Stay tuned for this extraordinary event videos and prepare yourself to attend to the next edition, hopefully in the United States in mid 2011.&lt;/p&gt;</description>
	<pubDate>Mon, 28 Feb 2011 16:30:44 +0000</pubDate>
</item>
<item>
	<title>RedHotErlang: External access to Intranet Polish</title>
	<guid>http://www.redhoterlang.com/web/98951c7196e0d91999bb238de5defe47</guid>
	<link>http://www.redhoterlang.com/web/plink?id=98951c7196e0d91999bb238de5defe47</link>
	<description>We are making heavy use of [Polish][1] for all our translation efforts. So far we have been using our in-house personnel to do the actual translation work. However, increasing demands for both quality and quantity made us look for external translator...</description>
	<pubDate>Thu, 24 Feb 2011 19:25:02 +0000</pubDate>
</item>
<item>
	<title>Erlang Training and Consulting &lt;br/&gt;- News: 24 February 2011: Erlang Factory London 2011 - Talk Submission Open</title>
	<guid>http://www.erlang-solutions.com/news/1/entry/1224</guid>
	<link>http://www.erlang-solutions.com/news/1/entry/1224</link>
	<description>&lt;p&gt;&lt;a href=&quot;http://www.erlang-factory.com/conference/London2011&quot;&gt;&lt;br /&gt;The Erlang Factory London 2011&lt;/a&gt; is returning once again and will be held on 6th &amp;ndash; 10th June 2011 and we have opened the call for talk submissions.&lt;/p&gt;
&lt;p&gt;Do you have what it takes to lead a conference session or tutorial?    Have you made an interesting innovation, open source application or    product with Erlang/OTP? Have you used Erlang in a real-world project    and want to present a case study? Or have you developed a cool tool and    want to give a hands-on tutorial? Tell us about it.&lt;/p&gt;
&lt;p&gt;We welcome submissions from developers, system designers, testers,    community leaders, inventors, CTOs, evangelists, students, researchers    and entrepreneurs alike. Participants at the Erlang Factory want to  hear   about how Erlang/OTP is used real-world scenarios, talks about  tricks,   tools and applications which increase productivity or enable   developers  to write better code.&lt;br /&gt;&lt;br /&gt;The deadline for talk submissions is the 13th April 2011 and you can submit yours &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/submit_talk&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can follow &lt;a href=&quot;http://www.twitter.com/erlangfactory&quot;&gt;@erlangfactory&lt;/a&gt; on twitter for the latest news.&lt;/p&gt;</description>
	<pubDate>Thu, 24 Feb 2011 10:17:03 +0000</pubDate>
</item>
<item>
	<title>ProTest news: Erlang Factory London 2011 - Talk Submission Open</title>
	<guid>http://www.protest-project.eu/news.html#117</guid>
	<link>http://www.protest-project.eu/news.html#117</link>
	<description>&lt;p&gt;&lt;a href=&quot;http://www.erlang-factory.com/conference/London2011&quot;&gt;The Erlang Factory London 2011&lt;/a&gt; is returning once again and will be held on 6th – 10th June 2011 and we have opened the call for talk submissions.
&lt;/p&gt;&lt;p&gt;Do you have what it takes to lead a conference session or tutorial?  
  Have you made an interesting innovation, open source application or   
 product with Erlang/OTP? Have you used Erlang in a real-world project  
  and want to present a case study? Or have you developed a cool tool 
and    want to give a hands-on tutorial? Tell us about it.&lt;/p&gt;
&lt;p&gt;We welcome submissions from developers, system designers, testers,   
 community leaders, inventors, CTOs, evangelists, students, researchers 
   and entrepreneurs alike. Participants at the Erlang Factory want to  
hear   about how Erlang/OTP is used real-world scenarios, talks about  
tricks,   tools and applications which increase productivity or enable  
 developers  to write better code.&lt;br /&gt;&lt;br /&gt;The deadline for talk submissions is the 11th April 2011 and you can submit yours &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/submit_talk&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can follow &lt;a href=&quot;http://www.twitter.com/erlangfactory&quot;&gt;@erlangfactory&lt;/a&gt; on twitter for the latest news.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
	<pubDate>Thu, 24 Feb 2011 00:00:00 +0000</pubDate>
</item>
<item>
	<title>Erlang Factory News: Erlang Factory London 2011 - Talk Submission Open!</title>
	<guid>http://erlang-factory.com/news/rss/50ca1dca5cae6799144854fcf27a28a0</guid>
	<link></link>
	<description>&lt;p&gt;Do you have  something you want to share with the programming world? A  great  project, something new or innovative then we want to hear from  you. If  you want to give a presentation at the Erlang Factory, you can  find  more information how to do that, &lt;a href=&quot;http://www.erlang-factory.com/conference/London2011/submit_talk&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The submission deadline is the 11th April 2011.&lt;/p&gt;</description>
	<pubDate>Wed, 23 Feb 2011 11:31:13 +0000</pubDate>
</item>
<item>
	<title>Erlang Inside: Erlang Factory San Francisco Bay last day for early bird special of $200 off is FEB-28</title>
	<guid>http://erlanginside.com/?p=236</guid>
	<link>http://erlanginside.com/erlang-factory-san-francisco-bay-last-day-for-early-bird-special-of-200-off-is-today-236</link>
	<description>Erlang Factory San Francisco Bay last day for early bird special of $200 off is FEB-28</description>
	<pubDate>Mon, 21 Feb 2011 22:34:12 +0000</pubDate>
</item>
<item>
	<title>Erlang Factory News: Early Bird Rate - 1 Week left to save over $200!</title>
	<guid>http://erlang-factory.com/news/rss/6bd7a52d527e1841e9bea3e2e2351acd</guid>
	<link></link>
	<description>&lt;div&gt;There is only 1 week left to book your place at the Early Bird Rate of $690 so don't miss out!&lt;br /&gt;
&lt;p&gt;You will get the chance to, see some &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers&quot;&gt;fantastic names&lt;/a&gt; from the Erlang world including, Joe Armstrong, Kostis Sagonas, Damien   Katz, and Dan Ingalls, network with your fellow programmers and find  out  what&amp;rsquo;s new not only in the world of Erlang but in the world of   programming.&lt;/p&gt;
&lt;p&gt;Register now to receive the Early Bird Rate and save over $200!&lt;/p&gt;
&lt;/div&gt;</description>
	<pubDate>Mon, 21 Feb 2011 18:01:33 +0000</pubDate>
</item>
<item>
	<title>Programming in the 21st Century: Accidental Innovation, Part 1</title>
	<guid>http://prog21.dadgum.com/89.html</guid>
	<link>http://prog21.dadgum.com/89.html</link>
	<description>In the mid-1980s I was writing 8-bit computer games. Looking back, it was the epitome of indie. I came up with the idea, worked out the design, drew the art, wrote the code, made the sound effects, all without any kind of collaboration or outside opinions. Then I'd send the finished game off to a magazine like &lt;a href=&quot;http://en.wikipedia.org/wiki/A.N.A.L.O.G.&quot;&gt;ANALOG Computing&lt;/a&gt; or &lt;a href=&quot;http://en.wikipedia.org/wiki/Antic_%28magazine%29&quot;&gt;Antic&lt;/a&gt;, get a check for a few hundred dollars, and show up in print six months or a year later.
&lt;br /&gt;&lt;br /&gt;Where I got the ideas for those games is a good question. I was clearly influenced by frequent visits to arcades, but I also didn't just want to rip-off designs and write my own versions of the games I played there. 
&lt;br /&gt;&lt;br /&gt;I remember seeing screenshots of some public domain games that appeared to have puzzle elements, though I never actually played them so I didn't know for sure. The puzzley aspects may have been entirely in my head. I had a flash of an idea about arranging objects so that no two of the same type could touch. Initially those objects were oranges, lemons, and limes, which made no sense, and there was still no gameplay mechanic. Somewhere in there I hit upon the idea of dropping the fruits in a pile and switched the theme to be about cans of radioactive waste that would hit critical mass if the same types were near each other for 
more than a moment.
&lt;br /&gt;&lt;br /&gt;Here's what I ended up with, designed and implemented in five days, start to finish: Uncle Henry's Nuclear Waste Dump.
&lt;blockquote&gt;&lt;img src=&quot;http://prog21.dadgum.com/images/uncle_henrys.png&quot; alt=&quot;Uncle Henry's Nuclear Waste Dump&quot; height=&quot;240&quot; width=&quot;336&quot; /&gt;
&lt;/blockquote&gt;At first glance, this may look like any of the dozens of post-Tetris puzzle games. There's a pit that you drop stuff into, and you move back and forth over the top if it. Stuff piles up at the bottom, and the primary gameplay is in deciding where to drop the next randomly-determined item. It's all very familiar, and except that the goal is reversed--to fill the pit instead preventing it from filling--there's nothing remarkable here.
&lt;br /&gt;&lt;br /&gt;Except that Tetris wasn't released in the United States until 1987 and Uncle Henry's Nuclear Waste Dump was published in 1986. I didn't even know what Tetris was until a few years later.
&lt;br /&gt;&lt;br /&gt;Was Uncle Henry's as good as Tetris? No. Not a chance. I missed the obvious idea of guiding each piece as it fell and instead used the heavy-handed mechanic of releasing the piece before a timer expired (that's the number in the upper right corner). And keeping three waste types separated wasn't nearly as addictive as fitting irregular shapes together. Overall the game wasn't what it could have been, and yet it's interesting that it's instantly recognizable as having elements of a genre that didn't exist at the time.
&lt;br /&gt;&lt;br /&gt;So close.
&lt;br /&gt;&lt;br /&gt;(While looking for the above screenshot, I found that someone wrote a &lt;a href=&quot;http://members.chello.at/theodor.lauppert/games/nwdump.htm&quot;&gt;clone&lt;/a&gt; in 2006. The part about the game ending when the pile gets too high sounds like the gameplay isn't exactly the same, but the countdown timer for dropping a can is still there.)</description>
	<pubDate>Sat, 19 Feb 2011 06:00:00 +0000</pubDate>
</item>
<item>
	<title>BeerRiot Blog: Baseball + Riak Map/Reduce: the Movie</title>
	<guid>http://blog.beerriot.com/?p=296</guid>
	<link>http://blog.beerriot.com/2011/02/18/baseball-riak-mapreduce-the-movie/</link>
	<description>&lt;p&gt;If you &lt;a href=&quot;http://blog.beerriot.com/2011/01/16/mapreducing-luwak/&quot;&gt;have&lt;/a&gt; &lt;a href=&quot;http://blog.beerriot.com/2011/01/20/baseball-riak-mapreduce/&quot;&gt;been&lt;/a&gt; &lt;a href=&quot;http://blog.beerriot.com/2011/01/26/baseball-riak-mapreduce-round-2/&quot;&gt;following&lt;/a&gt; my posts about using Riak&amp;#8217;s map/reduce system to compute &lt;a href=&quot;http://github.com/beerriot/baseball/&quot;&gt;baseball statistics&lt;/a&gt; via the &lt;a href=&quot;http://github.com/beerriot/luwak_mr&quot;&gt;luwak_mr library&lt;/a&gt;, or if they&amp;#8217;re still sitting in your ‘read later’ pile, you may be interested in a presentation I gave yesterday on the same topic.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://vimeo.com/20074937&quot;&gt;Video of that presentation&lt;/a&gt; is available on Vimeo.  It covers most of the content in the blog posts, while also providing a little extra background about why luwak_mr was necessary for the work.&lt;/p&gt;
&lt;br /&gt;  &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gocomments/beerriot.wordpress.com/296/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/comments/beerriot.wordpress.com/296/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/godelicious/beerriot.wordpress.com/296/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/delicious/beerriot.wordpress.com/296/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gofacebook/beerriot.wordpress.com/296/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/facebook/beerriot.wordpress.com/296/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gotwitter/beerriot.wordpress.com/296/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/twitter/beerriot.wordpress.com/296/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gostumble/beerriot.wordpress.com/296/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/stumble/beerriot.wordpress.com/296/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/godigg/beerriot.wordpress.com/296/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/digg/beerriot.wordpress.com/296/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/goreddit/beerriot.wordpress.com/296/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/reddit/beerriot.wordpress.com/296/&quot; /&gt;&lt;/a&gt; &lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=blog.beerriot.com&amp;blog=1135025&amp;post=296&amp;subd=beerriot&amp;ref=&amp;feed=1&quot; width=&quot;1&quot; height=&quot;1&quot; /&gt;</description>
	<pubDate>Fri, 18 Feb 2011 13:09:19 +0000</pubDate>
</item>
<item>
	<title>Erlang Training and Consulting &lt;br/&gt;- News: 18 February 2011: Programme Announced for the Erlang Factory SF Bay Area 2011</title>
	<guid>http://www.erlang-solutions.com/news/1/entry/1218</guid>
	<link>http://www.erlang-solutions.com/news/1/entry/1218</link>
	<description>&lt;p&gt;The &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/programme&quot;&gt;programme&lt;/a&gt; has been announced for this year's Erlang Factory SF Bay Area. The 3rd Erlang Factory SF Bay Area will take place at the Hilton Hotel San Francisco Airport on the 21st -25th March.&lt;/p&gt;
&lt;p&gt;Keynote talks this year will come from &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers/KostisSagonas&quot;&gt;Kostis Sagonas&lt;/a&gt; who will discuss &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers/KostisSagonas&quot;&gt;Half a Dozen Tools for Modern Erlang Program Development&lt;/a&gt; and &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers/DanIngalls&quot;&gt;Dan Ingalls &lt;/a&gt;who will explore &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers/DanIngalls&quot;&gt;From Metacircular IDE to End User Programming, It's just not that hard&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With other speakers including &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers/DamienKatz&quot;&gt;Damien Katz,&lt;/a&gt; Creator of CouchDB and CouchOne Founder, &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers/RobertVirding&quot;&gt;Robert Virding&lt;/a&gt;, inventor of Erlang and Bluetail co-founder, &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers/CliffMoon&quot;&gt;Cliff Moon&lt;/a&gt;, Dynomite creator and committer and &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers/NoahGift&quot;&gt;Noah Gift&lt;/a&gt;, co-author of &quot;Python For Unix and Linux System Administration&quot; this years Factory boasts the best programme we have ever put together.&lt;/p&gt;
&lt;p&gt;The Early Bird Rate of $690 for the just the conference or $1490 for the University course with free entry to the conference is available until the 28th February. This is a saving of over $200 so don&amp;rsquo;t miss out and &lt;a href=&quot;https://www.erlang-factory.com/conference/SFBay2011/register&quot;&gt;book now&lt;/a&gt;.&lt;/p&gt;</description>
	<pubDate>Fri, 18 Feb 2011 12:17:21 +0000</pubDate>
</item>
<item>
	<title>Erlang Training and Consulting &lt;br/&gt;- News: 11 February 2011: Erlang Solutions are proudly sponsoring QCon London 2011</title>
	<guid>http://www.erlang-solutions.com/news/1/entry/1211</guid>
	<link>http://www.erlang-solutions.com/news/1/entry/1211</link>
	<description>&lt;p&gt;This year's Qcon London will be on the 9th - 11th March 2011 at the The  Queen Elizabeth II Conference Centre London and has a great line up of  names from the programming world.&lt;/p&gt;
&lt;p&gt;As well as sponsoring the event, we will also have the Erlang Trio, Robert Virding, Ulf Wiger and Francesco Cesarini speaking at the conference. We will have a stand there, so please drop by and say hi and feel free to talk to us about your Erlang needs.&lt;br /&gt;&lt;br /&gt;We look forward to seeing you there.&lt;/p&gt;</description>
	<pubDate>Fri, 18 Feb 2011 12:17:21 +0000</pubDate>
</item>
<item>
	<title>Erlang Training and Consulting &lt;br/&gt;- News: 02 February 2011: Erlang Solutions Appoints new MD of Nordic Countries</title>
	<guid>http://www.erlang-solutions.com/news/1/entry/1208</guid>
	<link>http://www.erlang-solutions.com/news/1/entry/1208</link>
	<description>&lt;p&gt;Anders Waldner joins the Erlang Solutions expert team as its new Managing Director of Nordic countries, with immediate effect. He will be based in our Stockholm office. Anders responsibilities will include overseeing the operational aspects of the business and managing the workforce to ensure Erlang Solutions&amp;rsquo; continued and rapid expansion in the Nordic market. &lt;br /&gt;&lt;br /&gt;We are delighted by the 23 years experience in the technology industry that Anders will bring to Erlang Solutions. Before joining Erlang Solutions he worked with Logica, a business and technology service company. Within Logica he held a number of roles including acting CEO, Director of Operations, Senior Business Developer and Group Head of e-Commerce. &lt;br /&gt;&lt;br /&gt;All of us here at &lt;a href=&quot;http://www.erlang-solutions.com&quot;&gt;Erlang Solutions&lt;/a&gt; look forward to working with Anders.&lt;br /&gt;&lt;br /&gt;For more information please see the &lt;a href=&quot;http://www.erlang-solutions.com/press-releases/3/entry/1209&quot;&gt;press release&lt;/a&gt;.&lt;/p&gt;</description>
	<pubDate>Fri, 18 Feb 2011 12:17:21 +0000</pubDate>
</item>
<item>
	<title>Erlang Training and Consulting &lt;br/&gt;- News: 31 January 2011: Call for Summer Interns 2011</title>
	<guid>http://www.erlang-solutions.com/news/1/entry/1207</guid>
	<link>http://www.erlang-solutions.com/news/1/entry/1207</link>
	<description>&lt;p&gt;Erlang Solutions regularly provides summer internships for IT undergraduate students with a basic understanding of Erlang or other functional programming languages. Many former interns have said that this was the best learning experience they have ever had. We will be interviewing for this year's summer internships over the next couple of months.&lt;br /&gt;&lt;br /&gt;With offices in 3 exciting European locations, Stockholm, London and Krakow, the internships offer you the chance to work with some of the best Erlang programmers around.&lt;br /&gt;&lt;br /&gt;The Internships can be tailored around the University holidays or be taken as Erasmus Scholarships.&lt;br /&gt;&lt;br /&gt;For more information and to apply, please visit our &lt;a href=&quot;http://www.erlang-solutions.com/jobs/listing&quot;&gt;Jobs section&lt;/a&gt;.&lt;/p&gt;</description>
	<pubDate>Fri, 18 Feb 2011 12:17:21 +0000</pubDate>
</item>
<item>
	<title>Erlang Training and Consulting &lt;br/&gt;- Jobs: Student Software Developer (abroad)  , Abroad</title>
	<guid>http://www.erlang-solutions.com/jobs/detail/38/</guid>
	<link>http://www.erlang-solutions.com/jobs/detail/38/</link>
	<description>&lt;p&gt;&lt;strong&gt;For students of Computer Sciences and Information Technology &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Your Chance:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;bdquo;...Opening the door to start your career after graduation.&amp;ldquo;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;We offer you the chance to deploy your expert knowledges in practice and prepare your entry into professional life as a computer scientist. As an intern at Travelping you are involved in current projects and take on responsible tasks in software development, network and system design and application engineering. You get the opportunity to enlarge your methodical and social skills in both the team and independently .&lt;/em&gt;We also provide support and technical environment for writing your thesis.. We are happy to assist you in choosing a suitable subject and guide you from planning to completion of the work.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Your advantages:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Deepening and expansion of IT knowledge in the professional world&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Internship compensation&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Potential employment prospects in Travelping&lt;strong&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Support and technical know-how&lt;strong&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Provision of modern working materials&lt;strong&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Our requirements:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You should have completed the undergraduate level and a basic knowledge of telecommunication networks. Required is the safe use of linux operating systems and some experience developing web applications. Both experience in &lt;em&gt;PHPMySQL&lt;/em&gt; or PostgreSQL based websites and in the technologies &lt;em&gt;JavaScript, jQuery&lt;/em&gt; and &lt;em&gt;Ajax&lt;/em&gt; is also required. Familiarity and/or experience with the webtechnologies HTML5, CouchDB, node.js, Django and Erlang/OTP is highly desired, but not required. Finally, you should be characterized by general criteria such as a high willingness to learn and stringency, by openness and a solution-oriented way of thinking.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;ldquo;... &amp;nbsp;get the chance to learn about your potential employer.&amp;ldquo;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;nbsp;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Please send your application like the following&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Motivation letter&lt;/li&gt;
&lt;li&gt;CV (with photo)&lt;/li&gt;
&lt;li&gt;Certifications &amp;amp; Reviews&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
	<pubDate>Fri, 18 Feb 2011 12:16:02 +0000</pubDate>
</item>
<item>
	<title>Learn You Some Erlang: Event Handlers</title>
	<guid>http://learnyousomeerlang.com/event-handlers</guid>
	<link>http://learnyousomeerlang.com/event-handlers</link>
	<description>Event handlers are one of the most underappreciated behaviours available in OTP (generally only used for alarms and loggers). In this chapter, we see them from a broader angle. We'll be seeing the principles behind event handlers, their generic OTP form with gen_event, and then how event managers and handlers can be used in the context of an Olympic curling game where we need to react to a bunch of events happening as we go.</description>
	<pubDate>Tue, 15 Feb 2011 12:30:00 +0000</pubDate>
</item>
<item>
	<title>Erlang Inside: Andrew Thompson on optimizing egitd (Erlang’s git daemon, written by github)</title>
	<guid>http://erlanginside.com/?p=241</guid>
	<link>http://erlanginside.com/andrew-thompson-on-optimizing-egitd-erlangs-git-daemon-written-by-github-241</link>
	<description>Here's a gripping series on optimizing egitd by using OTP best practices.</description>
	<pubDate>Sun, 13 Feb 2011 00:13:34 +0000</pubDate>
</item>
<item>
	<title>Damien Katz: CouchOne + Membase = Couchbase</title>
	<guid>tag:damienkatz.net,2011://1.591</guid>
	<link>http://damienkatz.net/2011/02/couchone_membase_couchbase.html</link>
	<description>&lt;p&gt;I've got some news I'm extremely excited to finally announce: a merger between &lt;a href=&quot;http://couchone.com/&quot;&gt;CouchOne&lt;/a&gt; and &lt;a href=&quot;http://membase.com/&quot;&gt;Membase&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;A little background, I met James Phillips, the co-founder of Membase, for the first time in December. I'd heard a little about Membase up to that point, but I was most impressed with some of their high profile users. For example, Membase is a key part of Zynga, where giving millions of users a fast, low latency experience is critical.&lt;/p&gt;

&lt;p&gt;Membase has been targeting large scale mission critical apps, being able to scale out quickly and support millions of users, and getting impressive traction. They'd been going after a very specific pain point, a completely different part of the market than what we were targeting. They've focused on performance and scalability and exploiting all the power and memory available on modern servers. Simple, Fast, Elastic.&lt;/p&gt;

&lt;p&gt;At CouchOne we've been focusing on very different problems: mobile, sync and offline use cases. We make it easy to build applications that travel with you, allowing you access to your important data no matter the network conditions. Slow and unreliable connectivity means many businesses can't rely on the cloud for mission critical apps, all their data is gone when their network is down. But with Couch powered apps on your phone, tablet, putting data directly on the machines at the edge of the network, you have your apps and data with you at all times and safely backed up to the cloud.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://couchbase.com/&quot;&gt;Couchbase&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;What James had is the vision to see the great fit between the two companies. While independently we were both doing very well, we both have a lot of growing to do yet. And amazingly, the direction Membase needed to grow, we were already doing very well. And in the direction we needed to grow, Membase was already doing very well. Not only were the part of the stack we were focusing different and complementary, but the way we built out our teams was different and complementary. I'm not sure we could have planned it any better, and we didn't plan it at all!&lt;/p&gt;

&lt;p&gt;And so I'm thrilled to announce &lt;a href=&quot;http://couchbase.com/&quot;&gt;Couchbase&lt;/a&gt;, a merging of both our companies and our technology!&lt;/p&gt;

&lt;p&gt;Technologically, we'll be joining the products together to create a high volume, low latency, elastic clustered Couchbase server system. A Couch that's Simple, Fast, Elastic with all the reliability and power of CouchDB. We'll also continue to support the Membase API, for both backwards compatibility and it's performance advantages over HTTP.  We will be the only solution out there that can scale to Zynga sized workloads and down to phones and tablets and everything in between, supporting millions of users and keeping everything in sync.&lt;/p&gt;

&lt;p&gt;For existing CouchDB users, we will fully support CouchDB's HTTP API with all its associated benefits: seamless integration with other HTTP based infrastructure, a universally supported, human-readable protocol and direct-browser access just to name a few.&lt;/p&gt;

&lt;p&gt;Together as Couchbase, we'll have the fastest, most scalable (both scale up and scale down) NoSQL solution. We will become the standard storage for mobile devices, and the standard server technology for syncing them all together. Our unified solution will dramatically simplify your technology stack and maintenance for building fast responsive apps that scale to millions of users, and also scaling down to phones so people can work and play even when not connected to the network.&lt;/p&gt;

&lt;p&gt;My role at Couchbase will be CTO, overseeing the technical direction of the company. Dustin Sallings will be the chief architect. Bob Weiderhold will be CEO and co-founder James Phillips will continue to be product-oriented maniac :) CouchOne co-founders Chris Anderson and Jan Lehnardt will take roles to lead our mobile efforts and to work with our developers and community.&lt;/p&gt;

&lt;p&gt;What's in it for you?&lt;/p&gt;

&lt;p&gt;It's all upside! In the short-term we'll be able to provide a much better developer and support experience for both for CouchOne and Membase technologies, and move the development speed ahead much faster. The long term benefits are that CouchDB users will acquire the high performance, high scale easy-fast-elastic capabilities of Membase, while Membase users will acquire CouchDB's indexing features (map/reduce views, lucene, R-Tree GeoCouch), replication, reliability, and an easy path to mobile.&lt;/p&gt;

&lt;p&gt;This is hot stuff! 2011 is the year of Couchbase!&lt;/p&gt;</description>
	<pubDate>Wed, 09 Feb 2011 18:09:22 +0000</pubDate>
</item>
<item>
	<title>1011 Ltd Blog: I'm building a WebGL modelling tool for 3D printing</title>
	<guid>tag:1011ltd.com,2011-02-09:/web/blog/im_building_a_webgl_tool</guid>
	<link>http://www.1011ltd.com/</link>
	<description>&lt;p&gt;
2 weeks ago Father Christmas delivered a &lt;a href=&quot;http://store.makerbot.com/makerbot-thing-o-matic.html&quot;&gt;MakerBot Thing-O-Matic 3D Printer&lt;/a&gt; to my office. I think I understand how it must have felt to own an &lt;a href=&quot;http://en.wikipedia.org/wiki/Altair_8800&quot;&gt;Altair 8800&lt;/a&gt; back in the day when the world was on the brink of the consumer computing revolution. Consumer 3D printing could be another such revolution. But to print something in 3D you have to create a 3D model, and my survey of the software tools available for 3D modelling has been very disappointing. They broadly fall into the following categories:
&lt;/p&gt;

&lt;div&gt;&lt;a href=&quot;http://www.1011ltd.com/web/blog/post/im_building_a_webgl_tool&quot;&gt;continue reading...&lt;/a&gt;&lt;/div&gt;</description>
	<pubDate>Wed, 09 Feb 2011 15:10:00 +0000</pubDate>
</item>
<item>
	<title>Erlang Inside: Erlang Factory SF Bay – March 21st-25th</title>
	<guid>http://erlanginside.com/?p=237</guid>
	<link>http://erlanginside.com/erlang-factory-sf-bay-237</link>
	<description>Erlang Factory is back in the US http://www.erlang-factory.com/conference/SFBay2011 &amp;#8211; new speakers and a 3 day course from Learn You Some Erlang&amp;#8217;s Fred Trottier-Hébert. UPDATE: More speakers than last year, with speakers from from Basho, AT&amp;#038;T, CouchBase, and Ericsson (among others). Early bird rate is over Feb 28th. That is also the deadline to book the [...]</description>
	<pubDate>Wed, 09 Feb 2011 12:09:50 +0000</pubDate>
</item>
<item>
	<title>Erlang Factory News: Erlang Factory SF Bay Area - Save over $200</title>
	<guid>http://erlang-factory.com/news/rss/c90317eb359b84e3f5ab8268de62ffe8</guid>
	<link></link>
	<description>&lt;div&gt;We are offering a fantastic saving of over $200 when you register for the conference before the 1st of March 2011.
&lt;p&gt;You will get the chance to, see some &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers&quot;&gt;fantastic names&lt;/a&gt; from the Erlang world including, Joe Armstrong, Kostis Sagonas, Damien  Katz, and Dan Ingalls, network with your fellow programmers and find out  what&amp;rsquo;s new not only in the world of Erlang but in the world of  programming.&lt;/p&gt;
&lt;p&gt;Register now to receive the Early Bird Rate and save over $200!&lt;/p&gt;
&lt;/div&gt;</description>
	<pubDate>Wed, 09 Feb 2011 10:46:21 +0000</pubDate>
</item>
<item>
	<title>Scattered Thoughts: tunneling in china</title>
	<guid>http://scattered-thoughts.net/one/1297/70723/36582</guid>
	<link>http://scattered-thoughts.net/one/1297/70723/36582</link>
	<description>&lt;p&gt;In Shanghai I found that ssh was blocked at the protocol level so even running sshd on port 80 doesn't work. I don't whether this is widespread or whether it was our hotel in particular that was blocking it. Regardless, I found a workaround using httptunnel.
&lt;/p&gt;
&lt;p&gt;On a server outside China:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt-get install httptunnel
sudo hts -F localhost:22 80
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On your client machine:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt-get install httptunnel
sudo htc -F 22 my.server.com:80
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now you can use ssh to your hearts content:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ssh user@localhost
scp /some/file user@localhost:/some/file
darcs push user@localhost:/some/repo
&lt;/code&gt;&lt;/pre&gt;</description>
	<pubDate>Mon, 07 Feb 2011 09:25:23 +0000</pubDate>
</item>
<item>
	<title>Process-one Blogs: gitlive: display GitHub pushes in realtime on your website</title>
	<guid>http://www.process-one.net/en/blogs/article/gitlive/</guid>
	<link>http://www.process-one.net/en/blogs/article/gitlive/</link>
	<description>&lt;p&gt;&lt;a href=&quot;http://gitlive.com/&quot;&gt;gitlive&lt;/a&gt;&lt;img alt=&quot;gitlive logo&quot; src=&quot;http://gitlive.com/images/gitlive_logo.png&quot; /&gt;&amp;nbsp;is a new service leveraging some of the new (and some of the proven) technologies in ejabberd.&lt;/p&gt;
&lt;p&gt;It's a widget displaying commits from &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt; ... live!&lt;/p&gt;
&lt;p&gt;Usage is very simple, just head over to the &lt;a href=&quot;http://gitlive.com/&quot;&gt;service&lt;/a&gt; for detailed instructions and sample usage.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;It is also deployed on the &lt;a href=&quot;http://www.process-one.net/en/tsung/downloads&quot;&gt;Tsung&lt;/a&gt; and &lt;a href=&quot;http://www.process-one.net/en/ejabberd/downloads&quot;&gt;ejabberd&lt;/a&gt; homepages (see the &amp;ldquo;Commits&amp;rdquo; section on the bottom right).&lt;/p&gt;
&lt;p&gt;There are two main components:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ejabberd with custom modules&lt;/li&gt;
&lt;li&gt;client code in javascript&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The client component will attempt to connect using the most efficient protocol to ejabberd but will fallback on BOSH is necessary. It will then connect anonymously and subscribe to the PubSub projects nodes.&lt;/p&gt;
&lt;p&gt;To be continued after the jump!&lt;/p&gt; &lt;h1&gt;Transport protocol&lt;/h1&gt;
&lt;h2&gt;Most efficient protocol?&lt;/h2&gt;
&lt;p&gt;The client will attempt to connect using the WebSocket transport to ejabberd. WebSockets are a bidirectional protocol that solve one of the problems HTTP can't solve &amp;mdash; by design. Many crutches have been built on HTTP to solve this problem. In the XMPP world it's BOSH. But it's not efficient on the server and on the client (think mobile applications).&lt;/p&gt;
&lt;p&gt;WebSockets will solve all this. &quot;Will solve&quot; because even though we have implementations in the latest versions of Safari, Chrome, Firefox and Opera, it is still an IETF draft. Little progress has been done on the subject in the last year, and the latest iterations of the protocol are not implemented. For a good overview of the issues, &lt;a href=&quot;http://blog.dave.cridland.net/?p=126&quot;&gt;Dave Cridland has you covered&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But still there is an installed base we can build on. So there, we have developped a native websocket server implementation for ejabberd. And for browsers not supporting websockets, we have Adobe Flash&amp;trade;.&lt;/p&gt;
&lt;h2&gt;Flash?&lt;/h2&gt;
&lt;p&gt;Yes, the irony isn't lost on us either. A nice project available on GitHub, &lt;a href=&quot;https://github.com/gimite/web-socket-js&quot;&gt;web-socket-js&lt;/a&gt;, implements the WebSocket API on the client and the protocol towards the server. So if you have Flash and no native WebSocket support, the gitlive widget will load the Flash file. It's only 18Kb.&lt;/p&gt;
&lt;h2&gt;Back to BOSH&lt;/h2&gt;
&lt;p&gt;If all the previous techniques fail, the widget will attempt a BOSH connection. It's many times slower than websockets and consumes more resources on client and server. But it's very failsafe as it works everywhere vanilla HTTP works.&lt;/p&gt;
&lt;p&gt;This combination of transport mechanisms make sure that gitlive notifications can be viewed with any browser, any time.&lt;/p&gt;
&lt;h1&gt;Front-end&lt;/h1&gt;
&lt;p&gt;The rest of the code is pretty much straightforward. The client code uses a combination of &lt;a href=&quot;https://github.com/metajack/strophejs&quot;&gt;StropheJS&lt;/a&gt; and &lt;a href=&quot;http://jquery.com/&quot;&gt;jQuery&lt;/a&gt;, and the commits are templated with &lt;a href=&quot;https://github.com/janl/mustache.js/&quot;&gt;mustache.js&lt;/a&gt;. Clients connect using anonymous authentication and subscribe to the project nodes.&lt;/p&gt;
&lt;p&gt;It also uses the p1:rebind feature, a mechanism enabling fast rebinds to a previous connection.&lt;/p&gt;
&lt;p&gt;You can actually customize the commits by overriding the CSS and mustache templates:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span&gt;var GithubPush = {nodes:[&quot;cstar/erlang-oauth&quot;],&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;location:&quot;#commits&quot;, &lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;css: &quot;http://web.site/your.css&quot;,&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;template: &quot;inline mustache template&quot;};&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This is default mustache template:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt; &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt; &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt; &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt; &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt; &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt; &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt; &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt; &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt; &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt; &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt; &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt; &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt; &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt; &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt; &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt; &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt; &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt; &lt;/code&gt;&lt;/p&gt;
&lt;div id=&quot;_mcePaste&quot;&gt;&lt;code&gt;&quot;&amp;lt;li class='gh_commit' id='{{id}}'&amp;gt;&quot;&lt;/code&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt; &lt;/code&gt;&lt;/p&gt;
&lt;div id=&quot;_mcePaste&quot;&gt;&lt;code&gt;&amp;nbsp;&lt;span&gt; &lt;/span&gt;+ &quot;&amp;lt;a class='gh_author' href='https://github.com/{{username}}'&amp;gt;&quot;&lt;/code&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt; &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;
&lt;div id=&quot;_mcePaste&quot;&gt;&amp;nbsp;&lt;span&gt; &lt;/span&gt;+ &quot;&amp;lt;img src=' &lt;a href=&quot;http://www.process-one.net/en?URL=http%3A%2F%2Fwww.gravatar.com%2Favatar%2F%7B%7Bavatarhash%7D%7D%3Fs%3D70%27%2F%26gt%3B%7B%7Bname%7D%7D%26lt%3B%2Fa%26gt%3B&quot;&gt;http://www.gravatar.com/avatar/{{avatarhash}}?s=70'/&amp;gt;{{name}}&amp;lt;/a&amp;gt;&quot;&lt;/a&gt;&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot;&gt;&amp;nbsp;&lt;span&gt; &lt;/span&gt;+ &quot;&amp;lt;div class='push'&amp;gt;&amp;lt;h5&amp;gt;&amp;lt;a href='{{repository_link}}'&amp;gt;{{repository_name}}&amp;lt;/a&amp;gt;&amp;lt;/h5&amp;gt;&quot;&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot;&gt;&amp;nbsp;&lt;span&gt; &lt;/span&gt;+ &quot;&amp;lt;h4&amp;gt;&amp;lt;a href='{{link}}'&amp;gt;{{title}}&amp;lt;/a&amp;gt;&amp;lt;/h4&amp;gt;&quot;&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot;&gt;&amp;nbsp;&amp;nbsp;+ &quot;&amp;lt;abbr class='timeago' title='{{time}}'&amp;gt;{{time}}&amp;lt;/abbr&amp;gt;&amp;lt;/div&amp;gt;&quot;&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot;&gt;&amp;nbsp;&amp;nbsp;+ &quot;&amp;lt;pre&amp;gt;{{message}}&amp;lt;/pre&amp;gt;&amp;lt;a class='watermark' href='http://gitlive.com'&amp;gt;GitLive&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&quot;&lt;/div&gt;
&lt;p&gt;&quot;&amp;lt;li class='gh_commit' id='{{id}}'&amp;gt;&quot;&lt;/p&gt;
&lt;p&gt;+ &quot;&amp;lt;a class='gh_author' href='https://github.com/{{username}}'&amp;gt;&quot;&lt;/p&gt;
&lt;p&gt;+ &quot;&amp;lt;img src=' &lt;a href=&quot;http://www.process-one.net/en?URL=http%3A%2F%2Fwww.gravatar.com%2Favatar%2F%7B%7Bavatarhash%7D%7D%3Fs%3D70%27%2F%26gt%3B%7B%7Bname%7D%7D%26lt%3B%2Fa%26gt%3B&quot;&gt;http://www.gravatar.com/avatar/{{avatarhash}}?s=70'/&amp;gt;{{name}}&amp;lt;/a&amp;gt;&quot;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;+ &quot;&amp;lt;div class='push'&amp;gt;&amp;lt;h5&amp;gt;&amp;lt;a href='{{repository_link}}'&amp;gt;{{repository_name}}&amp;lt;/a&amp;gt;&amp;lt;/h5&amp;gt;&quot;&lt;/p&gt;
&lt;p&gt;+ &quot;&amp;lt;h4&amp;gt;&amp;lt;a href='{{link}}'&amp;gt;{{title}}&amp;lt;/a&amp;gt;&amp;lt;/h4&amp;gt;&quot;&lt;/p&gt;
&lt;p&gt;+ &quot;&amp;lt;abbr class='timeago' title='{{time}}'&amp;gt;{{time}}&amp;lt;/abbr&amp;gt;&amp;lt;/div&amp;gt;&quot;&lt;/p&gt;
&lt;p&gt;+ &quot;&amp;lt;pre&amp;gt;{{message}}&amp;lt;/pre&amp;gt;&amp;lt;a class='watermark' href='http://gitlive.com'&amp;gt;GitLive&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&quot;&lt;/p&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Note: that would be nice if you'd leave a link back to &lt;a href=&quot;http://gitlive.com/&quot;&gt;http://gitlive.com/&lt;/a&gt; with your custom templates.&lt;/p&gt;
&lt;p&gt;The default CSS is available &lt;a href=&quot;http://gitlive.com/githublive.css&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;Back-end&lt;/h1&gt;
&lt;p&gt;It is a very streamlined ejabberd 2.2. The only module activated is mod_pubsub. On the HTTP side, we have our custom websocket module, the http-bind module and the GitHub webhook.&lt;/p&gt;
&lt;p&gt;After each push, GitHub will POST on the webhook a JSON payload with all the meta-information about the the commits just pushed. The GitHub webhook will create the pubsub node if necessary. (That's why you need to Test Hook on the GitHub admin inteface). The JSON payload is converted to an Atom PubSub payload, and published on the node. ejabberd takes care of the rest, distributing the payloads to subscribers.&lt;/p&gt;
&lt;h1&gt;Bugs&lt;/h1&gt;
&lt;p&gt;There are still a couple of bugs that I hid under the carpet. But this time, and this time only, I am going to remove the carpet:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;BOSH connections are not reattached. The last item is not sent in that case.&lt;/li&gt;
&lt;li&gt;WebSocket connections need to resubscribe to the channels every time even after rebind, putting an unnecessary load on the storage backend.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both bugs will be corrected soon, and workarounds are deployed to silence these bugs in the meantime.&lt;/p&gt;
&lt;h1&gt;Future plans&lt;/h1&gt;
&lt;p&gt;Though we plan to keep this product simple, but we will federate the gitlive server&amp;nbsp;with the XMPP community. You will be able to get GitHub push notifications in real time in your favorite XMPP client. Provided it can parse Atom payloads. A little birdie told me that &lt;a href=&quot;http://oneteam.im/&quot;&gt;OneTeam&lt;/a&gt; will in a not-so-distant future.&lt;/p&gt;
&lt;p&gt;This product is also the first of a series enabling websites to add realtime notifications, events, or ... Javascript.&lt;/p&gt;</description>
	<pubDate>Thu, 03 Feb 2011 14:26:01 +0000</pubDate>
</item>
<item>
	<title>Process-one Blogs: af83 presents UCengine</title>
	<guid>http://www.process-one.net/en/blogs/article/af83_presents_ucengine/</guid>
	<link>http://www.process-one.net/en/blogs/article/af83_presents_ucengine/</link>
	<description>&lt;p&gt;Alexandre Eisenchteter and Thierry Bomandouki, from af83, have presented UCengine at SeaBeyond.&lt;/p&gt; &lt;p&gt;UCengine, which stands for Unified Collaboration Engine, is an erlang server for generic publish and subscribe, with persistence. It is written for customized real time collaboration applications, under the AGPL license. It exposes a ReSTful HTTP API with JSON as its primary exchange format and can store the broadcasted events in a database.&lt;br /&gt;&lt;br /&gt;Here is short example of an event in a JSON format:&lt;/p&gt;
&lt;pre&gt;{ &quot;type&quot;&amp;nbsp;&amp;nbsp;&amp;nbsp; : &quot;chat.message.new&quot;,&lt;br /&gt;&amp;nbsp; &quot;datetime&quot;: 1292593766682,&lt;br /&gt;&amp;nbsp; &quot;id&quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : &quot;44099145822544409583064798111089&quot;,&lt;br /&gt;&amp;nbsp; &quot;meeting&quot; : &quot;introduction&quot;,&lt;br /&gt;&amp;nbsp; &quot;from&quot;&amp;nbsp;&amp;nbsp;&amp;nbsp; : &quot;ucengine@example.com&quot;,&lt;br /&gt;&amp;nbsp; &quot;metadata&quot;: {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;text&quot;: &quot;Hi there ! I'm an event !&quot;&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;An UX framework is also available, shipped with Javascript and Ruby on Rails libraries to access the API, under MIT or GPL licenses. Additionnally, several interactive jQuery widgets are available for UI building. It lets developpers build complete custom applications in a flexible fashion.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;Check out &lt;a href=&quot;http://www.ucengine.org/&quot;&gt;UCengine&lt;/a&gt; website, and also &lt;a href=&quot;https://github.com/AF83/ucengine&quot;&gt;check out the code&lt;/a&gt;!&lt;/p&gt;</description>
	<pubDate>Thu, 03 Feb 2011 13:57:05 +0000</pubDate>
</item>
<item>
	<title>Process-one Blogs: Cleartext Enterprise Messaging 2.0</title>
	<guid>http://www.process-one.net/en/blogs/article/cleartext/</guid>
	<link>http://www.process-one.net/en/blogs/article/cleartext/</link>
	<description>&lt;p&gt;David Banes, from Cleartext, has released a new opensource product: an Enterprise Messaging 2.0, based on ejabberd.&lt;/p&gt; &lt;p&gt;At the SeaBeyond event to day in Paris, David Banes, CEO of &lt;a href=&quot;http://www.cleartext.com/&quot;&gt;Cleartext&lt;/a&gt;, has introduced a new way of doing microblogging. It is a client-compatible, standards-based protocol extension, based on message stanzas. It is not relying on PubSub nor &lt;a href=&quot;http://xmpp.org/extensions/xep-0277.html&quot;&gt;XEP-0277: Microblogging over XMPP&lt;/a&gt;, that may not be ready yet, or not completely address all the requirements.&lt;/p&gt;
&lt;p&gt;It features of course EIM, Group Chat &amp;amp; Microblogging, has security and compliance designed in, and notably has Integrated Content Filtering, Malware Protection, URL &amp;amp; Image Filtering and Archiving with eDiscovery.&lt;/p&gt;
&lt;p&gt;Inspired by &quot;XMPP:The Definitive Guide&quot;, it is modelled on ProcessOne Twitter Gateway, and it is a Python XMPP component (&lt;a href=&quot;http://xmpp.org/extensions/xep-0114.html&quot;&gt;XEP-0114&lt;/a&gt;). It is NOT federated (yet)!&lt;/p&gt;
&lt;p&gt;The client has text-based commands:&lt;/p&gt;
&lt;pre&gt;&quot;me&quot; - shows who you are, your username and jid (Jabber ID)&lt;br /&gt;&quot;ers&quot; - shows your followers&lt;br /&gt;&quot;ing&quot; - shows who you follow &lt;br /&gt;&quot;f username&quot; - follow this user&lt;br /&gt;&quot;u username&quot; - unfollow this user &quot;&lt;br /&gt;&quot;d username message text&quot; - send direct message to the user &lt;br /&gt;&quot;@username message text&quot; - mention a user, a public message to a user &lt;br /&gt;&quot;s&quot; - show saved searches &lt;br /&gt;&quot;s word&quot; - save live search term &lt;br /&gt;&quot;us word&quot; - delete live search term &lt;br /&gt;&quot;help&quot; - show this help&lt;/pre&gt;
&lt;p&gt;Custom Stanzas&lt;/p&gt;
&lt;p&gt;To Tweet:&lt;/p&gt;
&lt;pre&gt;&amp;lt;message id=&quot;156&quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; from=&quot;dbanes@cleartext.com/9643007101295859746231576&quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; to=&quot;cleartext.cleartext.com&quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; type=&quot;chat&quot;&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;body&amp;gt;it's time for end of month expenses please&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;active xmlns=&quot;http://jabber.org/protocol/chatstates&quot;/&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;x from=&quot;dbanes@cleartext.com/9643007101295859746231576&quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; stamp=&quot;2011-01-24T10:49:05Z&quot; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; xmlns=&quot;urn:xmpp:delay&quot;/&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;x xmlns=&quot;http://cleartext.net/mblog&quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;buddy type=&quot;sender&quot;&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;displayName&amp;gt;dbanes@cleartext.com&amp;lt;/displayName&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;userName&amp;gt;dbanes&amp;lt;/userName&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;jid&amp;gt;dbanes@cleartext.com&amp;lt;/jid&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;avatar type=&quot;hash&quot;&amp;gt;56a03afdd9ab286d43c8f1715fac013d4c53f15a&amp;lt;/avatar&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;serviceJid&amp;gt;cleartext.cleartext.com&amp;lt;/serviceJid&amp;gt;&lt;br /&gt;&amp;lt;/buddy&amp;gt; &amp;lt;/x&amp;gt;&lt;br /&gt;&amp;lt;/message&amp;gt;&lt;/pre&gt;
&lt;p&gt;Incoming Tweet:&lt;/p&gt;
&lt;pre&gt;&amp;lt;message from='cleartext.cleartext.com'&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; to='dbanes@cleartext.com'&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; type='chat'&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;body&amp;gt;@admin: my expenses will be late&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;x xmlns='http://cleartext.net/mblog'&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;lt;buddy type='sender'&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;displayName&amp;gt;Ozzie&amp;lt;/displayName&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;userName&amp;gt;admin&amp;lt;/userName&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;jid&amp;gt;admin@cleartext.com&amp;lt;/jid&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;avatar type='hash'&amp;gt;ed90623da0e6963516abce705dd24bf0e84a03bd&amp;lt;/avatar&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;serviceJid&amp;gt;cleartext.cleartext.com&amp;lt;/serviceJid&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;text xmlns='http://cleartext.net/mblog'&amp;gt;my expenses will be late&amp;lt;/text&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;lt;/buddy&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;/x&amp;gt;&lt;br /&gt;&amp;lt;/message&amp;gt;&lt;/pre&gt;
&lt;p&gt;Follow command:&lt;/p&gt;
&lt;pre&gt;&amp;lt;message id=&quot;41&quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; from=&quot;dbanes@cleartext.com/4732502611296587389793170&quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; to=&quot;twitter.cleartext.com&quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; type=&quot;chat&quot;&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;body&amp;gt;f noornet&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;active xmlns=&quot;http://jabber.org/protocol/chatstates&quot;/&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;x from=&quot;dbanes@cleartext.com/4732502611296587389793170&quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; stamp=&quot;2011-02-01T19:23:38Z&quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; xmlns=&quot;urn:xmpp:delay&quot;/&amp;gt;&lt;br /&gt;&amp;lt;/message&amp;gt;&lt;/pre&gt;
&lt;p&gt;Server response:&lt;/p&gt;
&lt;pre&gt;&amp;lt;message from='twitter.cleartext.com'&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; to='dbanes@cleartext.com/4732502611296587389793170'&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; type='chat'&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;body&amp;gt;User noornet has been added to your following list&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/message&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;If you need more information, got to the &lt;a href=&quot;http://www.cleartext.com/&quot;&gt;Cleartext website&lt;/a&gt;, and &lt;a href=&quot;https://github.com/cleartext&quot;&gt;follow David Banes's GitHub account&lt;/a&gt;.&lt;/p&gt;</description>
	<pubDate>Thu, 03 Feb 2011 12:00:21 +0000</pubDate>
</item>
<item>
	<title>Process-one Blogs: OneSocialWeb for ejabberd</title>
	<guid>http://www.process-one.net/en/blogs/article/onesocialweb_for_ejabberd/</guid>
	<link>http://www.process-one.net/en/blogs/article/onesocialweb_for_ejabberd/</link>
	<description>&lt;p&gt;OneSocialWeb, the decentralized social network, now runs on ejabberd.&lt;/p&gt; &lt;p&gt;At SeaBeyond event, Micka&amp;euml;l R&amp;eacute;mond has demoed a functionnal service based on OneSocialWeb and ejabberd. It works with the default web interface, but it' not full featured yet.&lt;/p&gt;
&lt;p&gt;Diana Cheng from Vodafone will present and demo the full OneSocialWeb stack, the XMPP-based decentralized social network. Check in the afternoon for the full report.&lt;/p&gt;</description>
	<pubDate>Thu, 03 Feb 2011 10:30:42 +0000</pubDate>
</item>
<item>
	<title>Process-one Blogs: TextOne by example (part 3): Facebook friend search and federation</title>
	<guid>http://www.process-one.net/en/blogs/article/textone_by_example_part_3_facebook_friend_search_and_federation/</guid>
	<link>http://www.process-one.net/en/blogs/article/textone_by_example_part_3_facebook_friend_search_and_federation/</link>
	<description>&lt;p&gt;TextOne integrates well with Facebook, in a non-intrusive way.&lt;/p&gt; &lt;p&gt;We know that many of our users have already a good deal of friends in different places. We use the address book on the phone to simplify chat and discovery of contact using email (see &lt;a href=&quot;http://www.process-one.net/en/blogs/article/textone_by_example_part_2_email_federation&quot;&gt;TextOne by example Part 2: email fedearation&lt;/a&gt;). In two words, TextOne federates with email, thus you can chat with email users.&lt;/p&gt;
&lt;p&gt;However, many of you also have a large network of friends on Facebook. We deal with that situation in two ways: Facebook application and Facebook messaging federation (email).&lt;/p&gt;
&lt;h2&gt;Facebook application&lt;/h2&gt;
&lt;p&gt;If you log into Facebook and point your browser to &lt;a href=&quot;http://apps.facebook.com/textone/&quot;&gt;http://apps.facebook.com/textone/&lt;/a&gt; you can add it to your applications. This is a Facebook application that allows you to link your TextOne ID (username) to your Facebook account.&lt;/p&gt;
&lt;p&gt;On the following screen you can put your TextOne credentials:&lt;/p&gt;
&lt;p align=&quot;center&quot;&gt;&lt;img alt=&quot;Add the TextOne application on your Facebook profile&quot; height=&quot;418&quot; src=&quot;http://www.process-one.net/images/uploads/TO_Facebook_1.png&quot; width=&quot;500&quot; /&gt;&lt;/p&gt;
&lt;p&gt;If they are correct, your TextOne ID is broadcast on your wall to your friends (or every one if your prefer to select that option):&lt;/p&gt;
&lt;p align=&quot;center&quot;&gt;&lt;img alt=&quot;Post your TextOne ID to your Facebook wall&quot; height=&quot;84&quot; src=&quot;http://www.process-one.net/images/uploads/TO_Facebook_2.png&quot; width=&quot;506&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Once this is done, TextOne Facebook application presents you with your Facebook contacts that have already done the same process:&lt;/p&gt;
&lt;p align=&quot;center&quot;&gt;&lt;img alt=&quot;You Facebook friend who also use TextOne&quot; height=&quot;347&quot; src=&quot;http://www.process-one.net/images/uploads/TO_Facebook_3.png&quot; width=&quot;500&quot; /&gt;&lt;/p&gt;
&lt;p&gt;With the Facebook app it is easier to find your Facebook friends that are also using TextOne.&lt;/p&gt;
&lt;h2&gt;Facebook Messages federation&lt;/h2&gt;
&lt;p&gt;With the upcoming release of &lt;a href=&quot;http://www.facebook.com/about/messages/&quot;&gt;Facebook Messages&lt;/a&gt; (email + chat + internal Facebook messages, all in one), you get new opportunity to communicate. Throught the strong support of email in TextOne, you can have live chat conversations with Facebook contacts, without needing a Facebook account.&lt;/p&gt;
&lt;p&gt;We had the chance to play with Facebook Messages beta and here is a preview of what is coming for everyone.&lt;/p&gt;
&lt;p&gt;In this case, my contact initiated a conversation from Facebook Messages to my TextOne email address:&lt;/p&gt;
&lt;p align=&quot;center&quot;&gt;&lt;img alt=&quot;Arnaud emails Micka&amp;euml;l, from Facebook to TextOne&quot; height=&quot;678&quot; src=&quot;http://www.process-one.net/images/uploads/OT_facebook_6.jpg&quot; width=&quot;452&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Here is what the conversation looks like from TextOne:&lt;/p&gt;
&lt;p align=&quot;center&quot;&gt;&lt;img alt=&quot;Micka&amp;euml;l sends Arnaud a picture, from TextOne to Facebook Messages&quot; height=&quot;678&quot; src=&quot;http://www.process-one.net/images/uploads/OT_facebook_7.png&quot; width=&quot;452&quot; /&gt;&lt;/p&gt;
&lt;p&gt;So, it means you can transparently discuss with Facebook contacts using Facebook Messages from TextOne. It even supports photos sending and receiving.&lt;/p&gt;
&lt;p&gt;Do not forget however that you are not forced to use Facebook email addresses to communicate with your contact. They probably have a standard email address, supplied by more conventional providers.&lt;/p&gt;
&lt;h2&gt;Our philosophy? We respect our users&lt;/h2&gt;
&lt;p&gt;We want to give you the opportunity to link TextOne to your Facebook account and share your ID with friends in a controlled and non-intrusive way. We do not spam you with a message on your mobile each time a user is joining: you will receive a message only if your friends asks it specifically.&lt;/p&gt;
&lt;p&gt;We want also to separate the Facebook application from the iPhone and Android application to keep the application lightweight and not cluttered the experience with any Facebook settings inside the mobile app. If you are not a Facebook user yet, there is no reason to bother you with Facebook linking in our application. Moreover, this web approach works with all mobile clients, existing and future.&lt;/p&gt;
&lt;p&gt;This is the same reason why we will never bother you to beg for an iTunes rating your our application. We appreciate if you give us a good rating on iTunes, but will not clutter our application experience until you end up doing so.&lt;/p&gt;
&lt;p&gt;Finally, we provide you with a tool that is privacy friendly and work in a clean and simple way. We hope you will enjoy and share the way we respect our users.&lt;/p&gt;
&lt;p&gt;We know that with this radical stance, our application usage will be slower to take off, but we are convinced that doing the &quot;right thing&quot; for our users will pay off on the long term.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Read the whole &quot;TextOne by example&quot; series:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;http://www.process-one.net/en/blogs/article/textone_by_example_part_1_xmpp_federation/&quot;&gt;TextOne by example (part 1): XMPP federation&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt; &lt;a href=&quot;http://www.process-one.net/en/blogs/article/textone_by_example_part_2_email_federation/&quot;&gt;TextOne by example (part 2): email federation&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;http://www.process-one.net/en/blogs/article/textone_by_example_part_3_facebook_friend_search_and_federation/&quot;&gt;TextOne by example (part 3): Facebook friend search and federation&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
	<pubDate>Tue, 01 Feb 2011 13:59:40 +0000</pubDate>
</item>
<item>
	<title>Functional Jobs: Software Developer (Functional Programming) at Jane Street (Full-time)</title>
	<guid>urn:uuid:98e2297a-f87a-ba13-2844-7d31e72cc7ec</guid>
	<link>http://functionaljobs.com/jobs/63/software-developer-functional-programming-at-jane-street</link>
	<description>&lt;p&gt;Jane Street is looking to hire great software developers with an interest in functional programming. OCaml, a statically typed functional
programming with similarities to Haskell, Scheme, Erlang, F# and SML, is our language of choice. We&amp;#039;ve got the largest team of OCaml developers
in any industrial setting, and probably the world&amp;#039;s largest OCaml codebase. We use OCaml for running our entire business, supporting everything from research to systems administration to trading
systems. If you&amp;#039;re interested in seeing how functional programming plays out in the real world, there&amp;#039;s no better place.&lt;/p&gt;

&lt;p&gt;The atmosphere is informal and intellectual. There is a focus on education, and people learn about software and trading, both through
formal classes and on the job. The work is challenging, and you get to see the practical impact of your efforts in quick and dramatic terms. Jane Street is also small enough that people have the freedom to get involved in many different areas of the business. Compensation is highly competitive, and there&amp;#039;s a lot of room for growth.&lt;/p&gt;

&lt;p&gt;You can learn more about Jane Street and our technology from our main site, janestreet.com. You can also look at a a talk given at CMU about
why Jane Street uses functional programming
(ocaml.janestreet.com/?q=node/61) our programming blog (ocaml.janestreet.com), and some papers we&amp;#039;ve written about our experience using functional programming in the real world
(janestreet.com/technology/articles.php)&lt;/p&gt;

&lt;p&gt;We also have extensive benefits, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;90% book reimbursement for work-related books&lt;/li&gt;
&lt;li&gt;90% tuition reimbursement for continuing education&lt;/li&gt;
&lt;li&gt;Excellent, zero-premium medical and dental insurance&lt;/li&gt;
&lt;li&gt;Free lunch delivered daily from a selection of restaurants&lt;/li&gt;
&lt;li&gt;Catered breakfasts and fresh brewed Peet&amp;#039;s coffee&lt;/li&gt;
&lt;li&gt;An on-site, private gym in New York with towel service&lt;/li&gt;
&lt;li&gt;Kitchens fully stocked with a variety of snack choices&lt;/li&gt;
&lt;li&gt;Full company 401(k) match up to 6% of salary, vests immediately&lt;/li&gt;
&lt;li&gt;Three weeks of paid vacation for new hires in the US&lt;/li&gt;
&lt;li&gt;16 weeks fully paid maternity/paternity leave for primary caregivers, plus additional unpaid leave&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More information at http://janestreet.com/workplace/benefits.php&lt;/p&gt;</description>
	<pubDate>Thu, 27 Jan 2011 22:17:37 +0000</pubDate>
</item>
<item>
	<title>Process-one Blogs: XWave: A tribute to Google Wave team</title>
	<guid>http://www.process-one.net/en/blogs/article/xwave_a_tribute_to_google_wave_team/</guid>
	<link>http://www.process-one.net/en/blogs/article/xwave_a_tribute_to_google_wave_team/</link>
	<description>&lt;p&gt;Wave is not dead and it lives at ProcessOne.&lt;/p&gt; &lt;p&gt;Google Wave is a strange beast. Demo was acclaimed in &lt;a href=&quot;http://www.youtube.com/watch?v=v_UyVmITiYQ&quot;&gt;may 2009 at Google I/O&lt;/a&gt;, with people very excited by the annoucement of the Wave project. At this time, it was clear for anyone with project management that the ambition of the project was a five year target.&lt;/p&gt;
&lt;p&gt;The launch phase wanted to immediately target the end-user, while the platform should have been a platform for developers, to build an ecosystem. That's what the Wave team had in mind and on that level the Wave platform was quite a success. ProcessOne was in the &lt;a href=&quot;http://www.google.com/events/io/2010/sandbox.html&quot;&gt;Wave area sandbox&lt;/a&gt; at Google I/O 2010, and several companies were presenting interesting products. The ecosystem was being built. The developers were enthousiastic and the potential was there. One or two more years should have been sufficient to bring that to a true platform and ecosystem.&lt;/p&gt;
&lt;p&gt;This technical video of Wave in the enterprise is convincing for developers:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;When you have to work with many customers and partners with different bug trackers, I guess you can see the potential of a trully federated bug tracking system for example.&lt;/p&gt;
&lt;h2&gt;A fiasco?&lt;/h2&gt;
&lt;p&gt;Launched in fanfare, Google was however disappointed by the end result after just one year. Given the discrepency between the scope of the ambition and the expectation put by Google, this is where the fiasco lies. Google should have either not launched Wave at all or not kill it after just one year.&lt;/p&gt;
&lt;p&gt;The fiasco lies as well in the way Google handled the end of Google Wave. Having brought partners in that development, they just announcement in the middle of the summer that the initiative was stopped. They made no contact with partners nor gave them any opportunity at this time to gather to organise the future of Wave.&lt;/p&gt;
&lt;p&gt;Wave did a few things wrong. One of them is the fact that the initiative did not from the begining include federation with mail. This is something possible to design however. From the end-user point of view it has been a fatal flaw, giving one more inbox to check, when it could have been the killer feature.&lt;/p&gt;
&lt;p&gt;The Google Team did many things right however. The choice of the XMPP protocol for federation was just their best idea. XMPP is now the universal protocol for federation. The vibrant XMPP community had this part right and Instant Messaging on top of XMPP is a success showing that tens of different implementations running on thousands of domains can work together.&lt;/p&gt;
&lt;h2&gt;What is the situation with Wave now?&lt;/h2&gt;
&lt;p&gt;The Wave in a Box initiative has moved to Apache incubator and to be frank, things are getting wrong. What is plain wrong? The team now behind the protocol, I am not sure who they are, is killing the best vision of the protocol to build another HTTP based hack, like PubSubHubbub. PubSubHubbub is ugly, for example a notification does not include nor cannot include the payload, because the source cannot be trusted: the server receiving the notification has to connect back to the originating server to make sure he really sent the notification.&lt;/p&gt;
&lt;p&gt;Federation is the best and killer feature of XMPP. There is not a single protocol that can compete with this one to build federated distributed system.&lt;/p&gt;
&lt;p&gt;You have &lt;a href=&quot;http://xmpp.org/extensions/xep-0060.html&quot;&gt;XMPP pubsub&lt;/a&gt;. The protocol has its own flaw (we are working on improvements) but it is no comparaison to &lt;a href=&quot;http://code.google.com/p/pubsubhubbub/&quot;&gt;Pubsubhubbub&lt;/a&gt; hack. HTTP is good for a class of protocol, but when you need sessions, when you need user ID,&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;when you need internet-wide addressability, and when you need federation, it is simply not designed for this task (I plan to explain soon why HTTP misuse is responsible for today's online privacy concerns).&lt;/p&gt;
&lt;p&gt;Many projects fail because they do not take the existing solution on federation into account. &lt;a href=&quot;https://joindiaspora.com/&quot;&gt;Diaspora&lt;/a&gt; have build a nice web interface but ignored XMPP federation and even protocol design. &lt;a href=&quot;http://diaspora-x.com/&quot;&gt;Diaspora-X / Diaspora-X2&lt;/a&gt; is doing better at it, because they plugged it to XMPP. That's the reason our social initiative is focusing on &lt;a href=&quot;http://onesocialweb.org/&quot;&gt;OneSocialWeb&lt;/a&gt;, because they have the federation right.&lt;/p&gt;
&lt;p&gt;So, now the Wave protocol / Wave in a Box team is heading the way or &lt;a href=&quot;http://www.waveprotocol.org/protocol/design-proposals/http-based-federation-protocol&quot;&gt;trying to simulate session / connection and federation on top of HTTP&lt;/a&gt;. They are simply trying to fix the wrong part of Wave. Sure, they will be something quick because that's the force of HTTP, but it will be deeply broken, and will need to be patched and add dirty hacks  over time.&lt;span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;XWave = XMPP + Wave&lt;/h2&gt;
&lt;p&gt;We at ProcessOne are still commited to Wave, but Wave as originally designed by the Google Wave team. As we do not agree to were the Wave protocol is going now, we will stick to the original Wave ambition. We will call it XWave protocol as in XMPP Wave and as a tribute to Google Wave team vision. &lt;a href=&quot;http://www.process-one.net/en/blogs/article/waveone_a_wave_server_by_processone&quot;&gt;WaveOne server by ProcessOne&lt;/a&gt;, presented at Google I/O 2010, will thus be the reference implementation. As we are free from relaxing Wave compliance given the recent turn they are taking, we will keep on our work in building a dual headed protocol for Wave store using both original Wave protocol and XMPP pubsub.&lt;/p&gt;
&lt;p&gt;You can expect new products and services based on it to be release this year.&lt;/p&gt;
&lt;p&gt;Wave is not dead and its vision will live in XWave: Wave + XMPP vision. There is time when I know we must choose long term goal over rapid short term benefit.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Meet us at &lt;a href=&quot;http://www.process-one.net/seabeyond/&quot;&gt;Sea Beyond&lt;/a&gt; event on the future of collaboration in Paris on the 3rd of february 2011.&lt;/em&gt;&lt;/p&gt;</description>
	<pubDate>Thu, 27 Jan 2011 17:11:15 +0000</pubDate>
</item>
<item>
	<title>Erlang Training and Consulting &lt;br/&gt;- Jobs: Undergraduate Summer Interns, Krakow, London, Stockholm</title>
	<guid>http://www.erlang-solutions.com/jobs/detail/37/</guid>
	<link>http://www.erlang-solutions.com/jobs/detail/37/</link>
	<description>&lt;p&gt;Erlang Solutions has fifteen summer internship positions in its three  locations in London, Stockholm and Krakow. As in previous years, we are  looking for bright, dedicated, motivated, curious and self-driven  individuals in their second to fourth year of studies in the field of  Computer Science. Exposure to Erlang and Unix derivatives (preferably  Linux/Mac OSX) are a must. The right candidates will be working with  exciting new projects (SMS, Telecom, E-Commerce, Instant Messaging,  Banking) with some of the best Erlang developers around. And as a bonus,  you will be working in our new offices in these exciting European  locations.&lt;/p&gt;
&lt;p&gt;To apply please submit your CV with a covering letter, letting us  know about yourself, your hobby projects, and why you want to work with  us at Erlang Solutions. We need your applications by the 31st March.&lt;/p&gt;</description>
	<pubDate>Mon, 24 Jan 2011 13:45:54 +0000</pubDate>
</item>
<item>
	<title>Erlang Training and Consulting &lt;br/&gt;- News: 21 January 2011: New Offices for the Erlang Solutions Team in Krakow, Poland</title>
	<guid>http://www.erlang-solutions.com/news/1/entry/1205</guid>
	<link>http://www.erlang-solutions.com/news/1/entry/1205</link>
	<description>&lt;p&gt;The &lt;a href=&quot;http://www.erlang-solutions.com&quot;&gt;Erlang Solutions&lt;/a&gt; team in Krakow has once again outgrown their space. We have moved to a new central location in the old town, only a 5 minute walk from the main train station and the central square. The new offices have their own training facilities capable of hosting Erlang User Group meetings, the Evening School of Erlang and Hackathons, providing a hub for the growing local Erlang community. It will also allow the existing team to comfortably triple in size in the upcoming year.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img title=&quot;Krakow Office View&quot; src=&quot;http://www.erlang-solutions.com/upload/images/69/Krakowofficeview.gif&quot; alt=&quot;Krakow View&quot; width=&quot;184&quot; height=&quot;235&quot; /&gt;&lt;/p&gt;
&lt;p&gt;You can see the views from the other offices on the &lt;a href=&quot;http://www.facebook.com/album.php?aid=47752&amp;id=170711784976&amp;saved#!/album.php?aid=47752&amp;id=170711784976&quot;&gt;Erlang Solutions Facebook group&lt;/a&gt;.&lt;/p&gt;</description>
	<pubDate>Fri, 21 Jan 2011 14:32:18 +0000</pubDate>
</item>
<item>
	<title>Erlang Training and Consulting &lt;br/&gt;- News: 19 January 2011: Erlang Solutions appoints new CEO</title>
	<guid>http://www.erlang-solutions.com/news/1/entry/1198</guid>
	<link>http://www.erlang-solutions.com/news/1/entry/1198</link>
	<description>&lt;p&gt;Stuart Whitfield joins the Erlang Solutions expert team as its new Chief   Executive Officer, with immediate effect. He will be based primarily  in  our London office but will oversee all of the Erlang Solutions  offices  worldwide.&lt;/p&gt;
&lt;p&gt;Stuart&amp;rsquo;s role will be varied with his key responsibility being the day-to-day management of the&amp;nbsp;company, including operations, regional offices and finances, ensuring Erlang Solutions meets its objectives and continues its rapid expansion. Stuart has previously been involved with Erlang Solutions as a part-time, non-executive director, during which time the company doubled its turnover, whilst maintaining its profit margins.&lt;/p&gt;
&lt;p&gt;Stuart has been impressed with the range of talent within the company and looks forward to working with everyone to develop the company.&lt;/p&gt;
&lt;p&gt;All of us here at &lt;a href=&quot;http://www.erlang-solutions.com&quot;&gt;Erlang Solutions&lt;/a&gt; look forward to working with Stuart.&lt;/p&gt;
&lt;p&gt;For more information please see the &lt;a href=&quot;http://www.erlang-solutions.com/press-releases/3/entry/1203&quot;&gt;press release&lt;/a&gt;.&lt;/p&gt;</description>
	<pubDate>Wed, 19 Jan 2011 10:17:15 +0000</pubDate>
</item>
<item>
	<title>Erlang Training and Consulting &lt;br/&gt;- News: 18 January 2011: Erlang Solutions launches a course in Test Driven Development with Erlang</title>
	<guid>http://www.erlang-solutions.com/news/1/entry/1204</guid>
	<link>http://www.erlang-solutions.com/news/1/entry/1204</link>
	<description>&lt;p&gt;The course is aimed at Support and Test Engineers, and Software Developers who have knowledge of basic Erlang. Ultimately the course will allow you to write more reliable and maintainable software thus saving time and money.&lt;/p&gt;
&lt;p&gt;The first trip out for this course will be at the &lt;a href=&quot;http://www.erlang-solutions.com/http:www.erlang-factory.com&quot;&gt;Erlang Factory SF Bay Area 2011&lt;/a&gt; and it will also be delivered by Fred Hebert. &lt;a href=&quot;https://www.erlang-factory.com/conference/SFBay2011/register&quot;&gt;Registration&lt;/a&gt; is currently open and a Very Early Bird Discount is being offered which will save you $400 off the cost of the course and give you entry to the 2-day conference. This is a fantastic discount and one that is only valid for the first 50 people to register.&lt;/p&gt;
&lt;p&gt;The course will also be running in London in June. More information can be found on our &lt;a href=&quot;http://www.erlang-solutions.com/training/courses&quot;&gt;website&lt;/a&gt;.&lt;/p&gt;</description>
	<pubDate>Tue, 18 Jan 2011 17:03:02 +0000</pubDate>
</item>
<item>
	<title>ProTest news: Erlang Solutions launches a course in Test Driven Development with Erlang</title>
	<guid>http://www.protest-project.eu/news.html#118</guid>
	<link>http://www.protest-project.eu/news.html#118</link>
	<description>&lt;div class=&quot;blog_entry_extended_content&quot;&gt;
    &lt;p&gt;The course is aimed at Support and Test Engineers, and Software 
Developers who have knowledge of basic Erlang. Ultimately the course 
will allow you to write more reliable and maintainable software thus 
saving time and money.&lt;/p&gt;
&lt;p&gt;The first trip out for this course will be at the &lt;a href=&quot;http://www.erlang-solutions.com/http:www.erlang-factory.com&quot;&gt;Erlang Factory SF Bay Area 2011&lt;/a&gt; and it will also be delivered by Fred Hebert. &lt;a href=&quot;https://www.erlang-factory.com/conference/SFBay2011/register&quot;&gt;Registration&lt;/a&gt;
 is currently open and a Very Early Bird Discount is being offered which
 will save you $400 off the cost of the course and give you entry to the
 2-day conference. This is a fantastic discount and one that is only 
valid for the first 50 people to register.&lt;/p&gt;
&lt;p&gt;The course will also be running in London in June. More information can be found on our &lt;a href=&quot;http://www.erlang-solutions.com/training/courses&quot;&gt;website&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
  &lt;/div&gt;</description>
	<pubDate>Tue, 18 Jan 2011 00:00:00 +0000</pubDate>
</item>
<item>
	<title>Process-one Blogs: Pre-SeaBeyond training: “ejabberd and Erlang: understanding the big picture”</title>
	<guid>http://www.process-one.net/en/blogs/article/pre_seabeyond_training_ejabberd_and_erlang_understanding_the_big_picture/</guid>
	<link>http://www.process-one.net/en/blogs/article/pre_seabeyond_training_ejabberd_and_erlang_understanding_the_big_picture/</link>
	<description>&lt;p&gt;Before the SeaBeyond event, ProcessOne is organising a training around ejabberd and Erlang.&lt;/p&gt; &lt;p&gt;On the 2nd of February (just the day before &lt;a href=&quot;http://www.process-one.net/seabeyond/&quot;&gt;SeaBeyond&lt;/a&gt;), ProcessOne is inviting developers for a training around our core technologies: &lt;strong&gt;“ejabberd and Erlang: understanding the big picture”&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;Training: “ejabberd and Erlang: understanding the big picture”&lt;/h2&gt;

&lt;p&gt;This training covers the following subjects:
&lt;pre&gt;
    ejabberd, a scalable and reliable messaging platfrom
    Erlang/OTP, the technology behind ejabberd
    Basic understanding of ejabberd
        Config files option
        Basic system administration task (start/stop/simple diagnostic)
        Setting up ejabberd clustering
    Advanced ejabberd administration tasks
        Components (Internal and external components)
        Handling Web clients
    ejabberd databases
        Working with relational databases
        Understanding Mnesia role in ejabberd
        Backup and restore
    Practical mentoring session
&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;Training will be done by core ejabberd developer and long time erlang hackers.&lt;/p&gt;

&lt;p&gt;The participation cost is fixed to €500 per person, please &lt;a href=&quot;http://www.process-one.net/en/company/contact/&quot;&gt;contact us&lt;/a&gt; to book the training. We will be delighted to welcome you.&lt;/p&gt;

&lt;h2&gt;Meet our CEO&lt;/h2&gt;

&lt;p&gt;For Project Managers, our CEO is available for meetings around your projects. &lt;a href=&quot;http://www.process-one.net/en/company/contact/&quot;&gt;Book an appointment by contacting us&lt;/a&gt;.&lt;/p&gt;</description>
	<pubDate>Fri, 14 Jan 2011 16:00:00 +0000</pubDate>
</item>
<item>
	<title>Erlang Training and Consulting &lt;br/&gt;- News: 13 January 2011: Registration is now open for the Erlang Factory SF Bay Area 2011 - Save $400!</title>
	<guid>http://www.erlang-solutions.com/news/1/entry/1199</guid>
	<link>http://www.erlang-solutions.com/news/1/entry/1199</link>
	<description>&lt;p&gt;Registration for the third &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011&quot;&gt;Erlang Factory Bay Area Conference&lt;/a&gt; and the &lt;a href=&quot;http://erlang-factory.com/conference/SFBay2011/university&quot;&gt;Erlang University&lt;/a&gt; courses is now open. &lt;a href=&quot;https://www.erlang-factory.com/conference/SFBay2011/register&quot;&gt;Register&lt;/a&gt; now and the first 50 people will receive a Very Early Bird Discount of $400!&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011&quot;&gt;Erlang Factory&lt;/a&gt; Conference will take place at the &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/venue&quot;&gt;Hilton San Francisco Airport Hotel&lt;/a&gt; on 24th - 25th March 2011. As in previous years, the conference is aimed at Erlang enthusiasts from architects to newbies.&lt;/p&gt;
&lt;p&gt;You will get the chance to, see some fantastic names from the Erlang world including, &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers/joearmstrong&quot;&gt;Joe Armstrong&lt;/a&gt; and &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers/RobertVirding&quot;&gt;Robert Virding&lt;/a&gt;&amp;ndash; the inventors of Erlang, &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers/DamienKatz&quot;&gt;Damien Katz&lt;/a&gt; &amp;ndash; the creator of CouchDB, &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers/KostisSagonas&quot;&gt;Kostis Sagonas&lt;/a&gt; - Leader of the HiPE team at Uppsala University and inventor of Dialyzer&lt;/p&gt;
&lt;p&gt;Stay tuned and follow the &lt;a href=&quot;http://www.twitter.com/erlangfactory&quot;&gt;@erlangfactory&lt;/a&gt; on twitter for further announcements or check the &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011&quot;&gt;website&lt;/a&gt; where you can also register to receive the Very Early Bird Discount&lt;/p&gt;</description>
	<pubDate>Thu, 13 Jan 2011 14:17:32 +0000</pubDate>
</item>
<item>
	<title>Erlang Factory News: Erlang Factory SF Bay Area - Registration Open - Save $400!!</title>
	<guid>http://erlang-factory.com/news/rss/24db14e07dd38f52afa901b396184f06</guid>
	<link></link>
	<description>&lt;p&gt;We have opened &lt;a href=&quot;https://www.erlang-factory.com/conference/SFBay2011/register&quot;&gt;registration&lt;/a&gt; for the Erlang Factory SF Bay Area and are offering the first 50 people to register a discount of $400 off the cost of admission.&lt;/p&gt;
&lt;p&gt;You will get the chance to, see some &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers&quot;&gt;fantastic names&lt;/a&gt; from the Erlang world including, Joe Armstrong, Kostis Sagonas, Damien Katz, Justin Sheehy, network with your fellow programmers and find out what&amp;rsquo;s new not only in the world of Erlang but in the world of programming.&lt;/p&gt;
&lt;p&gt;Register now to be one of the first 50 to receive the Very Early Bird Rate!&lt;/p&gt;</description>
	<pubDate>Thu, 13 Jan 2011 14:01:34 +0000</pubDate>
</item>
<item>
	<title>ProTest news: Programme Announced for the Erlang Factory SF Bay Area 2011</title>
	<guid>http://www.protest-project.eu/news.html#116</guid>
	<link>http://www.protest-project.eu/news.html#116</link>
	<description>&lt;div class=&quot;blog_entry_extended_content&quot;&gt;
    &lt;p&gt;The &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/programme&quot;&gt;programme&lt;/a&gt;
 has been announced for this year's Erlang Factory SF Bay Area. The 3rd 
Erlang Factory SF Bay Area will take place at the Hilton Hotel San 
Francisco Airport on the 21st -25th March.&lt;/p&gt;
&lt;p&gt;Keynote talks this year will come from &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers/KostisSagonas&quot;&gt;Kostis Sagonas&lt;/a&gt; who will discuss &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers/KostisSagonas&quot;&gt;Half a Dozen Tools for Modern Erlang Program Development&lt;/a&gt; and &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers/DanIngalls&quot;&gt;Dan Ingalls &lt;/a&gt;who will explore &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers/DanIngalls&quot;&gt;From Metacircular IDE to End User Programming, It's just not that hard&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With other speakers including &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers/DamienKatz&quot;&gt;Damien Katz,&lt;/a&gt; Creator of CouchDB and CouchOne Founder, &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers/RobertVirding&quot;&gt;Robert Virding&lt;/a&gt;, inventor of Erlang and Bluetail co-founder, &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers/CliffMoon&quot;&gt;Cliff Moon&lt;/a&gt;, Dynomite creator and committer and &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers/NoahGift&quot;&gt;Noah Gift&lt;/a&gt;,
 co-author of &quot;Python For Unix and Linux System Administration&quot; this 
years Factory boasts the best programme we have ever put together.&lt;/p&gt;
&lt;p&gt;The Early Bird Rate of $690 for the just the conference or $1490 for 
the University course with free entry to the conference is available 
until the 28th February. This is a saving of over $200 so don’t miss out
 and &lt;a href=&quot;https://www.erlang-factory.com/conference/SFBay2011/register&quot;&gt;book now&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
  &lt;/div&gt;</description>
	<pubDate>Thu, 13 Jan 2011 00:00:00 +0000</pubDate>
</item>
<item>
	<title>Process-one Blogs: Major hosted.IM update</title>
	<guid>http://www.process-one.net/en/blogs/article/major_hosted.im_update/</guid>
	<link>http://www.process-one.net/en/blogs/article/major_hosted.im_update/</link>
	<description>&lt;p&gt;Our XMPP services hosted.IM has seen a major update.&lt;/p&gt; &lt;p&gt;We are proud to announce the latest update on hosted.IM including the following new features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Complete &lt;a href=&quot;http://hosted.im/&quot;&gt;redesign of the site&lt;/a&gt;, enhancing user experience and usability.&lt;/li&gt;
&lt;li&gt;Microsoft&amp;copy; OCS transparent gateway (beta). More information about OCS gateway usage &lt;a href=&quot;http://www.process-one.net/en/blogs/article/seamless_federation_between_xmpp_and_microsoft_ocs&quot;&gt;in our related blog post&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Multi User Chatroom control (MUC) panel to manage your chatrooms.&lt;/li&gt;
&lt;li&gt;CORS support (&lt;a href=&quot;http://www.w3.org/TR/cors/&quot;&gt;Cross-Origin Resource Sharing&lt;/a&gt;) to allow accessing &lt;a href=&quot;https://hosted.im/http-bind/&quot;&gt;our HTTP Connection Manager&lt;/a&gt; for BOSH from other web chat clients.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;This release also includes other fixes and improvements suggested by our users.&lt;br /&gt; &lt;br /&gt; We continue improving our service and welcome your feedback. Much more to come soon. Thank you!&lt;/p&gt;
&lt;p&gt;Links:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://hosted.im/&quot;&gt;http://hosted.im&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.process-one.net/en/forum/viewforum/26/&quot;&gt;hosted.IM support forum&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;Twitter: &lt;a href=&quot;https://twitter.com/hosted_im&quot;&gt;@hosted_im&lt;/a&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
	<pubDate>Wed, 12 Jan 2011 17:32:39 +0000</pubDate>
</item>
<item>
	<title>Erlang Factory News: More speakers have been announced for the Erlang Factory SF Bay Area</title>
	<guid>http://erlang-factory.com/news/rss/e74bb66be3c7297fe21fefac2286766d</guid>
	<link></link>
	<description>&lt;p&gt;With the latest round of names announced, the &lt;a href=&quot;http://www.erlang-factory.com/http:www.erlang-factory.com/conference/SFBay2011&quot;&gt;Erlang Factory&lt;/a&gt; looks set to be full of talent, fantastic speakers and inspiring projects.&lt;/p&gt;
&lt;p&gt;We are pleased to announce that speakers include, &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers/GeoffCant&quot;&gt;Geoff Cant&lt;/a&gt;, game messaging expert, &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers/CliffMoon&quot;&gt;Cliff Moon&lt;/a&gt;, Dynomite author, &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers/NoahGift&quot;&gt;Noah Gift&lt;/a&gt; of AT&amp;amp;T Interactive and merle creator, &lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers/JoeWilliams&quot;&gt;Joe Williams&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Registration will be opening soon. You can keep up to date with all the latest announcements by checking the &lt;a href=&quot;http://www.erlang-factory.com/&quot;&gt;website&lt;/a&gt; or following us on twitter &lt;a href=&quot;http://www.twitter.com/erlangfactory&quot;&gt;@erlangfactory.&lt;/a&gt;&lt;/p&gt;</description>
	<pubDate>Wed, 12 Jan 2011 12:01:23 +0000</pubDate>
</item>
<item>
	<title>Functional Jobs: Python and Erlang Engineers at Smarkets (Full-time)</title>
	<guid>urn:uuid:3cc90dfc-a103-0a9a-f047-a3ee6f75ad15</guid>
	<link>http://functionaljobs.com/jobs/60/python-and-erlang-engineers-at-smarkets</link>
	<description>&lt;p&gt;&lt;strong&gt;A bit about Smarkets&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Smarkets is a real-time online trading platform with an Erlang backend and Python frontend. Smarkets is one of the Wall Street Journal&amp;rsquo;s &lt;a href=&quot;http://on.wsj.com/dHumVW&quot;&gt;Top 10 Tech Startups to watch in Europe&lt;/a&gt;, was shortlisted for the &lt;a href=&quot;http://smarkets.com/press-releases/smarkets-finalist-startups-awards-2010-shortlist/&quot;&gt;Startups Awards&lt;/a&gt;, and is heavily driven by user-focused design and a focus on technology and engineering as a first class discipline. We use agile product development techniques and release changes frequently.&lt;/p&gt;

&lt;p&gt;We are also heavily invested in world-class technical talent from such pedigree as Wolverine Trading, UBS, Last.fm, and Yahoo!; and are looking to foster that reputation within the community and investors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A bit about the job and working environment&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The part of our stack which runs behind the website is one of the few websites that uses Erlang as a primary language, and is supported by other well-known Erlang projects such as RabbitMQ and CouchDB.&lt;/p&gt;

&lt;p&gt;The non-Erlang pieces of our stack are entirely written in Python, and relies heavily on asynchronous programming techniques and REST.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Responsibilities&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build new products and services that augment our exchange offering;&lt;/li&gt;
&lt;li&gt;Improve existing market exchange infrastructure and services;&lt;/li&gt;
&lt;li&gt;Program primarily using Python and Erlang; and&lt;/li&gt;
&lt;li&gt;Work in a start up environment where getting things done is crucial.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Requirements&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Computer Science (or related technical field) degree or equivalent professional experience;&lt;/li&gt;
&lt;li&gt;The ability to learn quickly with enthusiasm;&lt;/li&gt;
&lt;li&gt;The ability to work independently and lead design/architecture of new features;&lt;/li&gt;
&lt;li&gt;Knowledge of transaction processing and relational database design; and&lt;/li&gt;
&lt;li&gt;Prior experience delivering solid web-related products in a GNU/Linux environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Bonus points&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Functional programming experience;&lt;/li&gt;
&lt;li&gt;Experience with web technologies and methodologies like web servers, REST, and protocol buffers;&lt;/li&gt;
&lt;li&gt;Using Git in a multi-developer environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Other information about the job&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is a full time, on site job;&lt;/li&gt;
&lt;li&gt;Pay is &amp;pound;30k &amp;ndash; &amp;pound;60k, depending on experience plus options;&lt;/li&gt;
&lt;li&gt;The job is based in &lt;a href=&quot;https://smarkets.com/about/contact/&quot;&gt;Clerkenwell, London, United Kingdom&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;We&amp;rsquo;re open to helping you relocate to London for the right candidate.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Links&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://smarkets.com/about/team&quot;&gt;http://smarkets.com/about/team&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://smarkets.com/api/documentation/&quot;&gt;http://smarkets.com/api/documentation/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.smarkets.com&quot;&gt;http://blog.smarkets.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://smarkets.com/about/press/&quot;&gt;http://smarkets.com/about/press/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you&amp;rsquo;re looking for a flexible, agile team to work with; want to work somewhere free of big corporate politics; would like a cool project to work on; and fit the above criteria we&amp;rsquo;d love to hear from you! Please provide a CV and some examples of your recent or relevant work.&lt;/p&gt;</description>
	<pubDate>Tue, 11 Jan 2011 17:36:31 +0000</pubDate>
</item>
<item>
	<title>Functional Jobs: Junior Erlang Programmer at Klarna (Full-time)</title>
	<guid>urn:uuid:d0ffb0e4-3a12-96ee-a043-24b128d72ef6</guid>
	<link>http://functionaljobs.com/jobs/40/junior-erlang-programmer-at-klarna</link>
	<description>&lt;p&gt;The year was 2005 and e-commerce had long been precarious. With an idea to offer secure and simple payment solutions, Klarna was founded that same year. Six years have passed and we have grown to an ambitious and creative company of over 400 employees. We have been awarded Company of the Year in -07 (bragging), increased our turnover by 13 570 % (statistics) and managed to become the Nordic market leader (facts). Klarna is partly owned by Investment AB &amp;Ouml;resund and Sequoia Capital - a company that saw the same potential in Google, YouTube and Apple Computer, as they do in us. We think that is a good start.&lt;/p&gt;

&lt;p&gt;Take the opportunity to develop in the new wave of web interface!&lt;/p&gt;

&lt;p&gt;What do you want?&lt;/p&gt;

&lt;p&gt;You do not just wish to learn the techniques and tools used by Facebook, Google, and Amazon to build high-performance, reliable network services, but you also want join in and further develop them. You want to learn Erlang, the language that makes it easy to program in multi-core and distributed environments. You want to be part of an exceptional development team, working with some of the most famous names in the Erlang world.&lt;/p&gt;

&lt;p&gt;What do we want?&lt;/p&gt;

&lt;p&gt;At Klarna we put development at the center and our development team currently consists of over 40 reputable developers and technicians whom together have over 100 years experience in Erlang and over 300 years of programming experience. We have a great passion and we strive to be in the technological forefront of everything we do: reliable servers, user-friendly Web interface and financial services.&lt;/p&gt;

&lt;p&gt;Klarna is expanding and we need more developers who can take our proprietary systems to new heights - a system that is the essence of a financial business that serves millions of consumers around the Nordic region.&lt;/p&gt;

&lt;p&gt;We are looking for someone who:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;is a very good programmer and who loves to write qualitative code&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;wants to work with a functional programming language&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;has a strong individual drive to get things done
is creative and dares to think outside the box&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;have strong analytical skills&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;can work independently&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;wants to work at a young and forward business&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that we are hiring several people for this position! The selection process is ongoing, so apply immediately. The process also includes various tests. &lt;/p&gt;

&lt;p&gt;Location: Stockholm&lt;/p&gt;

&lt;p&gt;Start: As soon as possible&lt;/p&gt;

&lt;p&gt;Are you up for the challenge?&lt;/p&gt;</description>
	<pubDate>Mon, 10 Jan 2011 05:00:00 +0000</pubDate>
</item>
<item>
	<title>Functional Jobs: Senior Programmers at Klarna (Full-time)</title>
	<guid>urn:uuid:52e0eaa7-4904-55cd-a2a3-04a5abf79213</guid>
	<link>http://functionaljobs.com/jobs/41/senior-programmers-at-klarna</link>
	<description>&lt;p&gt;The year was 2005 and e-commerce had long been precarious. With an idea to offer secure and simple payment solutions, Klarna was founded that same year. Five years have passed and we have grown to an ambitious and creative company of 400 employees. We have been awarded Company of the Year in -07 (bragging), increased our turnover by 13 570 % (statistics) and managed to become the Nordic market leader (facts). Klarna is partly owned by Investment AB &amp;Ouml;resund and Sequoia Capital - a company that saw the same potential in Google, YouTube and Apple Computer, as they do in us. We think that is a good start.&lt;/p&gt;

&lt;p&gt;Our company&lt;/p&gt;

&lt;p&gt;Klarna has since it&amp;#039;s formation in 2005 focused on building a world class development department. Six years later we are well on the way to achieving this goal. With almost 45 reputable developers with over 100 years of combined experience in Erlang and over 300 years of programming experience. We are passionate about what we are achieving and working hard to keep at the forefront of delivering high quality financial services with extremely high levels of reliability and usability.&lt;/p&gt;

&lt;p&gt;Facebook, Google and Amazon have with great success been using new technologies and tools to build high performance and reliable services on the Internet. Now Klarna is looking for senior programmers who want to take these technologies even further. These positions are especially interesting to those of you wishing to join an exceptional development team with some of the worlds most renown Erlang programmers.&lt;/p&gt;

&lt;p&gt;The position&lt;/p&gt;

&lt;p&gt;Due to our continuous expansion we are looking for new colleagues who can help us develop the Klarna system. A system which is the core of our financial services that serve millions of consumers around Scandinavia. With us you will be working with Erlang - all to make it easy to program in mulitcore and distributed environments.&lt;/p&gt;

&lt;p&gt;As a developer you work will help Klarna reach 1,5 million consumers, directly affect your 400 fellow Klarna employees and support the 6000 e-stores that daily work in the Klarna system. Your code will analyse and process transactions for several billion kronor per year in a complex and distributed environment.&lt;/p&gt;

&lt;p&gt;In your work you will cooperate closely with the rest of the development department in an atmosphere of performance and entrepreneurship. We have chosen to create a development department that stimulates every developer and gives them great personal freedom. We develop using the Kanban agile methodology and each team has great freedom to organise it&amp;#039;s own work.&lt;/p&gt;

&lt;p&gt;We are looking for those of you who:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;are very talented programmers, at least 8 years of programming or 4 years of Erlang programming&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;have a strong desire to get things done&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;want to work with the latest technologies within web (e.g. Erlang and Ajax)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;are creative and innovative&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;are analytical&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;can work independently&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;love to program in functional languages (e.g. Erlang, Haskell, Scheme) or modern high level languages such as Scala, Ruby and Python&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We look positively on candidates with experience of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GUI-development, internet banks, distributed databases, Scrum, electronic payment methods, statistical analysis, Erlang, XML, HTML, Yaws, OTP, Mnesia.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that we are hiring several people for this position! The selection process is ongoing, so apply immediately. The process also includes various tests. &lt;/p&gt;

&lt;p&gt;Location: Stockholm&lt;/p&gt;

&lt;p&gt;Start: As soon as possible&lt;/p&gt;</description>
	<pubDate>Mon, 10 Jan 2011 05:00:00 +0000</pubDate>
</item>
<item>
	<title>Functional Jobs: Technical Web Developer at Streamtech (Full-time)</title>
	<guid>urn:uuid:4be65f6b-46ef-5615-98ea-c3a1040d69ec</guid>
	<link>http://functionaljobs.com/jobs/43/technical-web-developer-at-streamtech</link>
	<description>&lt;p&gt;We are on the lookout for programmers who like to write pragmatic but elegant code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;who we&amp;#039;re looking for&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Elegant code makes you happy.&lt;/p&gt;

&lt;p&gt;To you, programming is not just a job but a hobby. You&amp;#039;ve been programming for fun for years.&lt;/p&gt;

&lt;p&gt;You&amp;#039;re not blind to practical demands, but you relish doing things the right way. When something seems to work but you&amp;#039;re not sure how or why, you bang your head against it until you understand.&lt;/p&gt;

&lt;p&gt;You like the net.&lt;/p&gt;

&lt;p&gt;You love exploring interesting new languages, concepts and approaches.&lt;/p&gt;

&lt;p&gt;Having played with Lisp, Haskell, Erlang, Prolog, Smalltalk, or other &amp;quot;alternative&amp;quot; languages gets you bonus points. The same goes for language/compiler implementation, kernel hacking and cryptography.&lt;/p&gt;

&lt;p&gt;Because of the unfortunately strict immigration laws, already having permission to work in the Netherlands is also a plus.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;the job&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You&amp;#039;ll be working on the development of our diverse web based projects &amp;ndash; in streaming video, lawful interception and online ad management, to name a few topics &amp;ndash; together with the rest of the programming team, from our office in The Hague.&lt;/p&gt;

&lt;p&gt;Together with the rest of the team, you&amp;#039;ll make applications that are technically elegant and pleasant to work with, using whatever language and technologies suit the project best.&lt;/p&gt;

&lt;p&gt;You will be involved in projects from A to Z &amp;ndash; including finding out what exactly the customer needs, choosing the best approach for the job, and then developing it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;what we use&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We work with a variety of languages (Python, Lisp, PHP, Java and C, among others): whatever we think is best suited for the job. We don&amp;#039;t expect you to have experience with all the languages we use, but we do expect you to be able to learn new things and enjoy doing it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;what we offer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A challenging, fun job in a small but professional team that does not think Java, OOP and XML are the answer to every question.&lt;/p&gt;</description>
	<pubDate>Mon, 10 Jan 2011 05:00:00 +0000</pubDate>
</item>
<item>
	<title>Functional Jobs: Senior Erlang Engineer at ExactTarget (Full-time)</title>
	<guid>urn:uuid:ca592f79-4ce3-1489-3d8d-1f36ddc44ac5</guid>
	<link>http://functionaljobs.com/jobs/45/senior-erlang-engineer-at-exacttarget</link>
	<description>&lt;p&gt;ExactTarget is seeking a Senior Erlang Engineer to play a pivotal role in the development of new features for our industry leading one-to-one marketing platform. The successful candidate is a versatile developer with excellent proficiency in using Erlang in production environments and keen attention to detail that permits them to own the final quality assurance of their solutions. The successful candidate must be highly adaptable, capable of learning new technologies and APIs and demonstrate passion and enthusiasm for designing and implementing products.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Primary Responsibilities&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Design/implement software solutions based upon needs and requirements.&lt;/li&gt;
&lt;li&gt;Research issues identified by QA and develop succinct solutions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Required Skills/Experience&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bachelor&amp;rsquo;s degree or equivalent experience in software engineering, computer science, or computer &amp;amp; information systems.&lt;/li&gt;
&lt;li&gt;Excellent knowledge of Erlang and memcached.&lt;/li&gt;
&lt;li&gt;Proven experience with building and scaling high-traffic web services.&lt;/li&gt;
&lt;li&gt;Excellent written and verbal communication skills.&lt;/li&gt;
&lt;li&gt;Proven experience developing solutions to complex and unusual technology challenges.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Preferred Skills/Experience&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Intermediate/expert-level proficiency with Erlang, Amazon Web Services, message queuing architectures or developing SaaS API&amp;rsquo;s.&lt;/li&gt;
&lt;li&gt;Intermediate/expert-level proficiency with agile methods, git, or continuous integration.&lt;/li&gt;
&lt;/ul&gt;</description>
	<pubDate>Mon, 10 Jan 2011 05:00:00 +0000</pubDate>
</item>
<item>
	<title>Functional Jobs: Software Engineer at Quora (Full-time)</title>
	<guid>urn:uuid:2585cae4-4daa-47c9-1afc-83959f0f28ac</guid>
	<link>http://functionaljobs.com/jobs/47/software-engineer-at-quora</link>
	<description>&lt;p&gt;Quora is a continually improving collection of questions and answers. We believe it has the potential to become one of the largest sources of high-quality information available.&lt;/p&gt;

&lt;p&gt;We&amp;#039;re looking for engineers and product designers to help. Some of the challenges are highly algorithmic, such as coming up with ways to organize and categorize the information effectively so that users can efficiently find what they need; others are very technical, such as working to make a web application that is complex while still being very fast; and many of the challenges are in product design, such as figuring out a way to set up and grow a healthy community and constructing intuitive interfaces for users. Quora is based in downtown Palo Alto, CA and is funded by Benchmark Capital.&lt;/p&gt;

&lt;p&gt;We are committed to building a cutting-edge technology company that develops software the right way and is a place where engineers love to work. Some of the tools we are using include Python, Pylons, nginx, memcached, Thrift, and git. We&amp;#039;re using continuous deployment and EC2, so all code you write will go live to production within minutes no matter what time it is. Both founders are developers. We want to build a fantastically strong engineering team and the first engineers that join us should set the tone for that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Requirements:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;B.S., M.S., or Ph.D. in Computer Science or equivalent&lt;/li&gt;
&lt;li&gt;Extraordinary software engineering talent&lt;/li&gt;
&lt;li&gt;Substantial experience developing web applications&lt;/li&gt;
&lt;li&gt;Knowledge of TCP/IP and network programming&lt;/li&gt;
&lt;li&gt;Experience with compilers, distributed systems, and machine learning a plus&lt;/li&gt;
&lt;li&gt;Proficiency programming in Python a plus&lt;/li&gt;
&lt;li&gt;Familiarity with functional or declarative programming languages (OCaml, Erlang) a plus&lt;/li&gt;
&lt;li&gt;The number of years of professional experience you have isn&amp;#039;t important to us&lt;/li&gt;
&lt;li&gt;You should be ready to make this startup the primary focus of your life&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the short run, the most important thing is to scale and improve our first product, and so it is critical that you can immediately make big contributions to our complex web-based application. In addition to working with us in writing the software, the ideal candidate should be proficient outside the technical realm--making good product decisions, designing user interfaces that are both pretty and functional, being an effective marketer and recruiter, and being capable of handling anything else that comes up. You should also be fearless and broad inside the technical realm, happy to tackle CSS and JavaScript as readily as you are to take on optimizing the performance of a backend service in C or Java. You should be ready to jump down into C and write an interpreter for a simple language if necessary, or hook up a cluster of machines to run a distributed machine learning job you wrote. In general, you should be very good at getting things done outside your comfort zone.&lt;/p&gt;

&lt;p&gt;You will be required to make good decisions about important things without much oversight. You should be comfortable with autonomy and ownership of large areas of product and infrastructure. It&amp;#039;s a plus if you have worked on projects in your spare time, such as programming games in middle school or high school. An ideal candidate will have the potential to grow into a strong leadership role over time--in either a technical or management capacity (i.e. eventually the equivalent of a Google Fellow or a V.P.)&lt;/p&gt;</description>
	<pubDate>Mon, 10 Jan 2011 05:00:00 +0000</pubDate>
</item>
<item>
	<title>Functional Jobs: Erlang/OTP Developer at Cloudant (Full-time)</title>
	<guid>urn:uuid:1a01c474-0f1e-0c81-ea13-4e47df26ce52</guid>
	<link>http://functionaljobs.com/jobs/48/erlang-otp-developer-at-cloudant</link>
	<description>&lt;p&gt;At Cloudant we&amp;#039;re building a hosted data platform based on the Apache CouchDB project.  We&amp;#039;re serious about data management, analytics, search and distributed systems.  Our founding team consists of 3 physics PhDs from MIT and our company includes experts in database tech, devops, analytics, UI/UX, and search.&lt;/p&gt;

&lt;p&gt;We&amp;#039;re looking for talented and passionate software engineers to join us at our Boston and Seattle offices.  You should be a technical generalist ready and eager to jump into any problem and able to learn the skills necessary to do so.  You will be working closely with our CTO on the core parts of our data platform and have the opportunity to influence product development at the highest levels.  Our only requirement is that you have experience writing Erlang/OTP applications.  While not necessary, experience with the other tools we use for our platform (C/C++, CouchDB) is a huge plus.  We&amp;#039;re more impressed by talent, passion, and ability to execute well in a small team (since we are a small team).  Here is a list of requirements and other things that can&amp;#039;t hurt your chances:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;REQUIREMENTS&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mastery of Erlang/OTP Applications for distributed systems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;LIST OF THINGS THAT CAN&amp;#039;T HURT&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Experience developing in C/C++&lt;/li&gt;
&lt;li&gt;Familiarity with CouchDB and other NoSQL databases&lt;/li&gt;
&lt;li&gt;Notable experience working on open-source projects&lt;/li&gt;
&lt;li&gt;An advanced degree in Computer Science or equivalent technical field&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cloudant is a VC-funded software startup with offices in Boston and Seattle. Compensation includes full time salary, generous equity compensation plan, and benefits. More info at: http://cloudant.com&lt;/p&gt;</description>
	<pubDate>Mon, 10 Jan 2011 05:00:00 +0000</pubDate>
</item>
<item>
	<title>Functional Jobs: Clojure Developer at Runa (Full-time)</title>
	<guid>urn:uuid:4d292798-093d-3311-2895-840fee09cde3</guid>
	<link>http://functionaljobs.com/jobs/49/clojure-developer-at-runa</link>
	<description>&lt;p&gt;&lt;strong&gt;The language:&lt;/strong&gt; The majority of our codebase is in Clojure. We&amp;#039;re looking for accomplished Clojure programmers - be it in a professional setting, or open-source projects. If you&amp;#039;re just getting started with Clojure, that is OK too, as long as you also have experience with other languages such as Haskell, Erlang, an ML, or a Scheme/Lisp, or Prolog. Significant Ruby or Python experience (the languages, not just Rails or equivalent) might be OK also. &lt;/p&gt;

&lt;p&gt;The bottom line is that we&amp;#039;re looking for smart engineers who have taken the trouble to learn/use these other languages because they&amp;#039;re unsatisfied with the popular ones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bottom-up:&lt;/strong&gt; You should be able to think in a meta manner. You should understand what it means to create a system from the bottom-up... Runa is driven by several domain-specific languages - all the way from analytics through to what an end consumer sees on a merchant website. You need to be able to think in layers and abstractions, and understand that building up complexity by composing simpler pieces is the natural way to grow software.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Distributed systems:&lt;/strong&gt; Runa is a complex system - with a lot of moving parts. Such a distributed system comes with globs of incidental complexity. We need to minimize this complexity, but also deal with it effectively. You should have experience with such systems, and have battle-scars that will help avoid mistakes and improve the ability to debug the system, increase testability, maintainability, and so on. You should be familiar with architecture patterns of distributed systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Big data:&lt;/strong&gt; We collect a lot of data. A lot. And we need to quickly analyze all that data to extract insights and to create reports on the behavior of visitors vis a vis dozens of parameters. If you have experience wrangling large volumes of data, we want you!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance:&lt;/strong&gt; As you can imagine, the Runa SaaS is extremely time-sensitive, since it needs to respond to end-users in real-time, as they browse merchant sites. You should know how to profile and optimize large systems. Experience with various tools is a plus. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scaling:&lt;/strong&gt; Again, Runa is a SaaS that services online merchants. Each time we add a client, we have to handle all their traffic. Each page on a merchant website may call our servers multiple times.  We need to be able to scale the system up, and provide predictable and reliable throughput under loaded conditions. We should be able to determine how much capacity is needed at various points in the system. We need to be fault-tolerant and reliable (and never negatively impact a client website). Experience with scaling large systems is a plus, as is experience with various tools.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;General engineering:&lt;/strong&gt; We&amp;#039;re a small engineering team and we want to keep it as small as we can. Everyone needs to play multiple roles. You should be ready to roll up your sleeves and jump in to handle whatever comes up. It isn&amp;#039;t all about Clojure - it&amp;#039;s about getting things done.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agile/Lean:&lt;/strong&gt; We use Mingle to drive our development process. You should be familiar with various agile/lean methodologies. We are fanatics about automated testing so you should have extensive experience with various testing tools/frameworks/philosophies and understand designing for testability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Experience/education:&lt;/strong&gt; You should have at least 6 years of software development experience, most of them spent dealing with issues in the fields above. A degree in electrical engineering or computer science (or equivalent) is required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FPS:&lt;/strong&gt; Experience with Quake, Counter Strike, or any such game is a real bonus.&lt;/p&gt;

&lt;p&gt;Want to prove that traditional models of software development are lacking? That more can be done with less? Join the elite engineering team at Runa!&lt;/p&gt;</description>
	<pubDate>Mon, 10 Jan 2011 05:00:00 +0000</pubDate>
</item>
<item>
	<title>Functional Jobs: Sr. Software Engineer &amp;ndash; Skype Connect at Skype (Full-time)</title>
	<guid>urn:uuid:46d9ce93-1213-0031-eee1-554faae7f5f5</guid>
	<link>http://functionaljobs.com/jobs/53/sr-software-engineer--skype-connect-at-skype</link>
	<description>&lt;p&gt;&lt;strong&gt;The Wider Brief&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As a member of the Skype for Business Team, you will help build a new suite of services serving millions of business users. Our growing San Francisco-area team will leverage open standards to deliver communication services--including voice, video, chat and presence--to the web and enable radically new Skype applications and transform the way businesses collaborate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Business Specific brief&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Skype for Business builds on the community of Skype users to deliver collaboration experiences targeted at small teams in businesses of all sizes. By focusing on the way real teams work together we are making collaboration services more relevant to more people. The Skype community and the availability of the Skype experience (PCs, MACs, phones, TVs and on the web) allows us to bring the Skype collaboration experience to users on whatever device they use.  This coupled with the quality of the experience and the excitement and familiarity users already have for Skype experiences provides us with a unique opportunity to deliver wonderful, ubiquitous and genuinely useful collaboration experience that make Skype for Business users truly awesome&lt;/p&gt;

&lt;p&gt;Skype is seeking a motivated Software Engineer with a passion for delivering quality software solutions. You will be an integral part of a cross-functional team including Product Managers, Testers/Quality Engineers and Architects. This is not a manual testing job. You will be designing and developing a suite of web based collaboration and communication services for millions of business users.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Responsibilities&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;World-class Software Solutions&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Work within an agile development environment with the Product Managers on a daily basis to scope, develop and deliver world-class software solutions to support business requirements&lt;/li&gt;
&lt;li&gt;Play an active role in the design, development and unit testing of production software&lt;/li&gt;
&lt;li&gt;Collaborate with and assist the Product Managers to develop and execute release planning&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Development Process&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write code!&lt;/li&gt;
&lt;li&gt;Plan and estimate work effort and help to continuously improve the agile development process.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Service Building&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build efficient and reusable services that can scale to support large numbers of users building on top of scalable infrastructure&lt;/li&gt;
&lt;li&gt;Participate and contribute to architecture meetings for defining how backend systems will work for massively deployed web applications&lt;/li&gt;
&lt;li&gt;Coordinate with internal development teams in multiple geographies to deliver high quality integrated solutions on time and on budget&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Leadership&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The candidate should have demonstrated skills and experience in working within / contributing to high performing teams, while mentoring junior team members.&lt;/li&gt;
&lt;li&gt;Lead one or more teams of developers delivering collaboration SaaS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Expertise/Experience&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Proven track record of building and deploying large-scale distributed systems&lt;/li&gt;
&lt;li&gt;Extensive programming experience in an Object Oriented programming language. e.g. C++, Java, etc.&lt;/li&gt;
&lt;li&gt;Moderate experience with multiple scripting languages such as Python, Perl, Bash.&lt;/li&gt;
&lt;li&gt;Working knowledge of Erlang or some modern functional language desirable.&lt;/li&gt;
&lt;li&gt;Good working and applied knowledge of networking protocols including TCP and UDP&lt;/li&gt;
&lt;li&gt;Good working and applied knowledge of communication and web protocols including HTTP, SIP/SIMPLE and XMPP&lt;/li&gt;
&lt;li&gt;Extensive experience programming multi-threaded systems.&lt;/li&gt;
&lt;li&gt;Experience working with Cloud storage technologies such as Cassandra, Riak, Voldemort is desired.&lt;/li&gt;
&lt;li&gt;Applied working knowledge of Service-oriented architecture (SOA).&lt;/li&gt;
&lt;li&gt;Worked with messaging technologies such as Protocol Buffers, Thrift and/or Message Queues.&lt;/li&gt;
&lt;li&gt;Experience developing software in LAMP environments.&lt;/li&gt;
&lt;li&gt;Extensive experience using and/or designing RESTful APIs&lt;/li&gt;
&lt;li&gt;A working knowledge of Agile Development or an enthusiasm and passion to learn.&lt;/li&gt;
&lt;li&gt;Experience developing complex network and telecommunications or Web applications services such as Azure, S4 or another large-scale internet service are desirable.&lt;/li&gt;
&lt;li&gt;A minimum of 4 - 6 years experience leading software development team in a world class development environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Problem Solving Skills/Analytics&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Strong quantitative and qualitative analytical skills, with extensive technical troubleshooting and the ability to use all aspects of testing, including functional, regression, load and system testing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Interpersonal Skills&lt;/em&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Confident and articulate in expressing their ideas to a mixed audience with varying views and challenges&lt;/li&gt;
&lt;li&gt;Cultural sensitivity and a proven ability to work with teams and partners across multiple geographies&lt;/li&gt;
&lt;li&gt;A sense of personal ownership is required, together with the ability to deliver to tight deadlines while managing internal stakeholder expectations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Motivation and Passion&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The candidate should be creative and passionate about generating new ideas with a drive to explore areas where others haven&amp;#039;t gone.&lt;/li&gt;
&lt;li&gt;Have the stamina and tenacity to deliver great software solutions, with a passion for working with other developers of all personality types&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Qualifications&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;BS or MS degree in Computer Science or Engineering OR equivalent years of work experience.&lt;/li&gt;
&lt;li&gt;Min of 4 - 6 years experience of applicable work experience&lt;/li&gt;
&lt;/ul&gt;</description>
	<pubDate>Mon, 10 Jan 2011 05:00:00 +0000</pubDate>
</item>
<item>
	<title>Functional Jobs: Member of Research Staff at Nokia (Full-time)</title>
	<guid>urn:uuid:0de9bd81-e580-f663-e73a-734a50ccbe38</guid>
	<link>http://functionaljobs.com/jobs/57/member-of-research-staff-at-nokia</link>
	<description>&lt;p&gt;Nokia produces in a year more than 500 million mobile devices with rich communication, media and sensing capabilities. In addition to the device manufacturing being significant logistics operations producing terabytes of data, Nokia&amp;#039;s emerging services, software and content platforms result in various streams of diverse data.&lt;/p&gt;

&lt;p&gt;Data Insight team in Nokia Research Center Palo Alto foacuses on the challenges and opportunities of such data. The team aims at performing world-class research on processes and techniques to derive insights to data. The team&amp;#039;s approach combines the theoretical foundations of data analysis and computer science to hands-on skills on rapid development of scalable systems with practical relevance. The work includes gathering, analyzing, developing methods and building statistical and computational models from real-world datasets. The research topics include scalable mining of services and manufacturing, adaptivity in mobile terminals, and massively distributed information processing and collective mining in the planetary-scale networks of people and devices.&lt;/p&gt;

&lt;p&gt;This position gives you an opportunity to contribute to one of the most exciting open-source Map/Reduce implementations in the world, Disco (http://discoproject.org), using Erlang, Python and Javascript. You will engineer scalable infrastructure for Big Data from the ground up, together with specialists in large-scale computing, visualization, data mining and machine learning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Qualifications&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We are looking for candidates with strong experience using Erlang, Python, and Javascript and who are familiar with problems of scalability and distributed computing. Experience with other languages, such as C, Haskell or Standard ML, is a plus. Candidates should be comfortable thinking in the Map/Reduce paradigm and anxious to develop platforms for Big Data, as well as tools for data analysis and machine learning that go well beyond the state-of-the-art.&lt;/p&gt;</description>
	<pubDate>Mon, 10 Jan 2011 05:00:00 +0000</pubDate>
</item>
<item>
	<title>Process-one Blogs: TextOne by example (part 2): email federation</title>
	<guid>http://www.process-one.net/en/blogs/article/textone_by_example_part_2_email_federation/</guid>
	<link>http://www.process-one.net/en/blogs/article/textone_by_example_part_2_email_federation/</link>
	<description>&lt;p&gt;You might like it or not but the largest messaging community in the world is email. It is almost instant. Everyone has an email address. If you look at your address book, you will see lots of email addresses already.&lt;/p&gt; &lt;p&gt;Email has drawbacks but email is both a widespread communication endpoint (everyone has an email address on the internet) and a widespread identity.&lt;/p&gt;
&lt;p&gt;TextOne make use of both.&lt;/p&gt;
&lt;h2&gt;TextOne, XMPP and email federation&lt;/h2&gt;
&lt;p&gt;First, TextOne federates with email as a default. It takes your address book as defaut contact list so that you do not start TextOne with no one to talk to.&lt;/p&gt;
&lt;p&gt;That's a really good start.&lt;/p&gt;
&lt;p&gt;Create a conversation, by selecting contacts, whether they are email addresses or TextOne id:&lt;br /&gt; &lt;img alt=&quot;New message in TextOne&quot; src=&quot;http://www.process-one.net/images/uploads/TextOne_email03_thumb.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Now, you can use all instant messaging features of TextOne over email:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Send email&lt;/strong&gt;: Select a contact from address book and send a message to him. The contact will receive a short message in his mailbox.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Receive email&lt;/strong&gt;: Your contact can reply to the email he receives from your TextOne. He can even initiate a conversation. Every TextOne account has a matching email address on @text-one.com domain.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Chat-like experience by cleaning up the email messages&lt;/strong&gt;: The text received by email is cleaned up by the TextOne server. For example, it removes signatures, subject if redundant, previous email quotes remaining in case of reply...&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Support all TextOne features with email contact&lt;/strong&gt; 
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Groupchat&lt;/strong&gt;: Yes, you can do groupchat with several people using their email. You can even create groupchats and mix contacts with TextOne users and email addresses in the same conversation. It will be transparent and every one can participate, keeping the same initial list of participants.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Image transfer&lt;/strong&gt;: You can send photos to email contact and receive photos (attachment) using your TextOne email address. This is again transparent and we take care of optimising the incoming images for mobile size.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As a summary, TextOne offers both a JID (XMPP address) and an email address, in the form of username@text-one.com. TextOne does not do like Gmail/Gtalk, it goes way beyond, &lt;strong&gt;by fusioning both communication forms&lt;/strong&gt;, in one simple, beautiful and efficient smartphone application.&lt;/p&gt;
&lt;h2&gt;Email address as migration path&lt;/h2&gt;
&lt;p&gt;The email is also used in TextOne to provide a migration path for your contacts to TextOne messaging.&lt;/p&gt;
&lt;p&gt;The first thing to check is to make sure that you have filed your email address in the setting screen. Once, you have filed it, you will receive an email for verification. When validating your email becomes trusted:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It means you can use it for retrieving lost password (TextOne key), which is not possible if you did not fill it.&lt;/li&gt;
&lt;li&gt;It means it can be used by the server for TextOne message rerouting. If one of your contacts has TextOne and has declared his email, he will receive a TextOne message even if you only know his email. The client will even learn that TextOne id and use it directly in the future.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example screenshots:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Settings screen:&lt;br /&gt; &lt;img alt=&quot;Enter your email address in your TextOne settings&quot; height=&quot;480&quot; src=&quot;http://www.process-one.net/images/uploads/TextOne_email01_thumb.png&quot; width=&quot;320&quot; /&gt;&lt;/li&gt;
&lt;li&gt;Input email address:&lt;br /&gt; &lt;a href=&quot;http://www.process-one.net/en2_p1adm/Enter your email address in your TextOne settings&quot;&gt;&lt;img alt=&quot;Enter your email address in your TextOne settings&quot; height=&quot;480&quot; src=&quot;http://www.process-one.net/images/uploads/TextOne_email02_thumb.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;What does it imply from your user perspective?&lt;/p&gt;
&lt;p&gt;As your contacts slowly adopt TextOne, you will transparently switch to chatting using their TextOne id instead of their email address. It will be more real time use push, etc. This is transparent and you have nothing special to do about it. That's the beauty of it. The community is already large and will grow seamlessly.&lt;/p&gt;
&lt;h2&gt;Future&lt;/h2&gt;
&lt;p&gt;What needs to be done:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt; We will still further improve our incoming email clean up filter. If you find cases that could be optimised, please send then to us and we will implement corresponding filters. &lt;/li&gt;
&lt;li&gt; Send us you suggestions. We are listening! &lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;TextOne is not only federated with XMPP world, it is also federated with email. It means that using TextOne you have access to the world largest messaging community ever.&lt;/p&gt;
&lt;p&gt;Isn't it cool ?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Read the whole &quot;TextOne by example&quot; series:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;http://www.process-one.net/en/blogs/article/textone_by_example_part_1_xmpp_federation/&quot;&gt;TextOne by example (part 1): XMPP federation&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt; &lt;a href=&quot;http://www.process-one.net/en/blogs/article/textone_by_example_part_2_email_federation/&quot;&gt;TextOne by example (part 2): email federation&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;http://www.process-one.net/en/blogs/article/textone_by_example_part_3_facebook_friend_search_and_federation/&quot;&gt;TextOne by example (part 3): Facebook friend search and federation&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
	<pubDate>Fri, 07 Jan 2011 16:32:38 +0000</pubDate>
</item>
<item>
	<title>RedHotErlang: Rewriting history in Subversion with the help of Erlang</title>
	<guid>http://www.redhoterlang.com/web/7f18d73d4aed734cf3fe2544c2e10a8e</guid>
	<link>http://www.redhoterlang.com/web/plink?id=7f18d73d4aed734cf3fe2544c2e10a8e</link>
	<description>Our development department at [Klarna](http://www.klarna.com)
has grown quite a lot the last year, and because we are trying to be as
agile as we can, using scrum and kanban, this has meant more teams, more
branches, and more coordination and merging...</description>
	<pubDate>Mon, 03 Jan 2011 21:31:25 +0000</pubDate>
</item>
<item>
	<title>REALITY.SYS: The Social Network Soundtrack</title>
	<guid>http://www.brakmic.de/?p=444</guid>
	<link>http://www.brakmic.de/index.php/2010/12/29/the-social-network-soundtrack/</link>
	<description>&lt;p&gt;Für alle die nicht nur das geniale Album von Trent Reznor &amp;amp; Atticus Ross zu &lt;a href=&quot;http://www.thesocialnetwork-movie.com/&quot; target=&quot;_blank&quot;&gt;The Social Network&lt;/a&gt; mögen, sondern auch die ganzen Musikstücke aus den Filmszenen hören möchten.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://ecx.images-amazon.com/images/I/516m2UIkiLL._SS400_.jpg&quot; alt=&quot;&quot; width=&quot;332&quot; height=&quot;332&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Opening scene at the bar with his girlfriend&lt;/em&gt; - &lt;a href=&quot;http://www.amazon.com/gp/product/B001B9FI8S?ie=UTF8&amp;tag=reelsoundtrac-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B001B9FI8S&quot; target=&quot;_blank&quot;&gt;Ball And Biscuit&lt;/a&gt; – White Stripes&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Blogging on Live Journal after breakup&lt;/em&gt; - &lt;a href=&quot;http://www.amazon.com/gp/product/B000QWGWUY?ie=UTF8&amp;tag=reelsoundtrac-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B000QWGWUY&quot; target=&quot;_blank&quot;&gt;Man Fi Cool&lt;/a&gt; – Roots Manuva&lt;/li&gt;
&lt;li&gt;&lt;em&gt;(unknown scene)&lt;/em&gt; - &lt;a href=&quot;http://www.amazon.com/gp/product/B000W04NOC?ie=UTF8&amp;tag=reelsoundtrac-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B000W04NOC&quot; target=&quot;_blank&quot;&gt;Dreadlock Holiday&lt;/a&gt; – Eric Stewart and Graham Gouldman (performed by 10cc)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Caribbean party&lt;/em&gt; – So I Wait – &lt;a href=&quot;http://www.amazon.com/gp/product/B001BKCAVK?ie=UTF8&amp;tag=reelsoundtrac-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B001BKCAVK&quot; target=&quot;_blank&quot;&gt;Three Hour Tour&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;A capella singing group / thefacebook launches&lt;/em&gt; – &lt;a href=&quot;http://www.amazon.com/gp/product/B001OGLOOK?ie=UTF8&amp;tag=reelsoundtrac-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B001OGLOOK&quot; target=&quot;_blank&quot;&gt;I Swear&lt;/a&gt; – UCLA’s Bruin Harmony [ link to original by All-4-One]&lt;/li&gt;
&lt;li&gt;&lt;em&gt;(unknown scene)&lt;/em&gt; - &lt;a href=&quot;http://www.amazon.com/gp/product/B001PZ6HEM?ie=UTF8&amp;tag=reelsoundtrac-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B001PZ6HEM&quot; target=&quot;_blank&quot;&gt;Like A Bad Girl Should&lt;/a&gt; – The Cramps [link to version by the Torpedo Monkeys]&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Talk about moving to Palo Alto&lt;/em&gt; (?)- &lt;a href=&quot;http://www.amazon.com/gp/product/B000QLW74K?ie=UTF8&amp;tag=reelsoundtrac-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B000QLW74K&quot; target=&quot;_blank&quot;&gt;Ital Visions&lt;/a&gt; – Roots Manuva&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Intern coding &amp;amp; drinking contest &lt;/em&gt;- &lt;a href=&quot;http://www.amazon.com/gp/product/B000QNLJRO?ie=UTF8&amp;tag=reelsoundtrac-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B000QNLJRO&quot; target=&quot;_blank&quot;&gt;California Uber Alles&lt;/a&gt; – Dead Kennedys&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Swimming pool zipline&lt;/em&gt; - &lt;a href=&quot;http://www.amazon.com/gp/product/B000VEWCI8?ie=UTF8&amp;tag=reelsoundtrac-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B000VEWCI8&quot; target=&quot;_blank&quot;&gt;West Coast Poplock&lt;/a&gt; – Ronnie Hudson&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Club with Sean Parker&lt;/em&gt; - &lt;a href=&quot;http://www.amazon.com/gp/product/B002U22EDM?ie=UTF8&amp;tag=reelsoundtrac-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B002U22EDM&quot; target=&quot;_blank&quot;&gt;The Sound Of Violence&lt;/a&gt; – Dennis De Laat&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Rowing competition in England &lt;/em&gt;- &lt;a href=&quot;http://www.amazon.com/gp/product/B003R922KC?ie=UTF8&amp;tag=reelsoundtrac-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B003R922KC&quot; target=&quot;_blank&quot;&gt;In the Hall of the Mountain King Op. 23&lt;/a&gt; – Trent Reznor and Atticus Ross [link to version by San Francisco Symphony Orchestra]&lt;/li&gt;
&lt;li&gt;&lt;em&gt;After the rowing competition&lt;/em&gt; - &lt;a href=&quot;http://www.amazon.com/gp/product/B00126ZJYI?ie=UTF8&amp;tag=reelsoundtrac-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B00126ZJYI&quot; target=&quot;_blank&quot;&gt;Arrival Of The Queen Of Sheba&lt;/a&gt; – Lumiere String Quartet&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Girls playing videogames&lt;/em&gt; - &lt;a href=&quot;http://www.amazon.com/gp/product/B000V6PBMU?ie=UTF8&amp;tag=reelsoundtrac-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B000V6PBMU&quot; target=&quot;_blank&quot;&gt;Crazy Baldhead&lt;/a&gt; – Bob Marley &amp;amp; The Wailers&lt;/li&gt;
&lt;li&gt;&lt;em&gt;(unknown scene)&lt;/em&gt; – Hesitation (Instrumental Version) – &lt;a href=&quot;http://www.amazon.com/gp/product/B0044AE5NK?ie=UTF8&amp;tag=reelsoundtrac-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B0044AE5NK&quot; target=&quot;_blank&quot;&gt;Exray’s&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Zuckerberg in the car with Sean Parker on the way to play trick on Case investments&lt;/em&gt; - &lt;a href=&quot;http://www.amazon.com/gp/product/B000QN2LKI?ie=UTF8&amp;tag=reelsoundtrac-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B000QN2LKI&quot; target=&quot;_blank&quot;&gt;Underground Rapstar&lt;/a&gt; (Post-Mortem Remix) – Cage&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Eduardo contract (?)&lt;/em&gt; - &lt;a href=&quot;http://www.amazon.com/gp/product/B000SFXESC?ie=UTF8&amp;tag=reelsoundtrac-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B000SFXESC&quot; target=&quot;_blank&quot;&gt;Bleed Forever&lt;/a&gt; – Super Furry Animals&lt;/li&gt;
&lt;li&gt;&lt;em&gt;House party&lt;/em&gt; - &lt;a href=&quot;http://www.amazon.com/gp/product/B001B8NJ2G?ie=UTF8&amp;tag=reelsoundtrac-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B001B8NJ2G&quot; target=&quot;_blank&quot;&gt;Black Book Lodge&lt;/a&gt; – Gluecifer&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Tries to add Erica as a friend / end credits -&lt;/em&gt; &lt;a href=&quot;http://www.amazon.com/gp/product/B00330I83A?ie=UTF8&amp;tag=reelsoundtrac-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B00330I83A&quot; target=&quot;_blank&quot;&gt;Baby, You’re A Rich Man&lt;/a&gt; – The Beatles [cover version of the song]&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/B0044430H8?ie=UTF8&amp;tag=reelsoundtrac-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B0044430H8&quot; target=&quot;_blank&quot;&gt;Original music for The Social Network&lt;/a&gt; – Trent Reznor and Atticus Ross&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Diese Liste ist &lt;a href=&quot;http://reelsoundtrack.wordpress.com/2010/10/01/the-social-network-soundtrack/&quot; target=&quot;_blank&quot;&gt;auch hier zu finden&lt;/a&gt; (inkl. einiger Musikvideos).&lt;/p&gt;</description>
	<pubDate>Wed, 29 Dec 2010 19:40:43 +0000</pubDate>
</item>
<item>
	<title>Programming in the 21st Century: A Three-Year Retrospective</title>
	<guid>http://prog21.dadgum.com/88.html</guid>
	<link>http://prog21.dadgum.com/88.html</link>
	<description>This is not a comprehensive index, but a categorization of some of the more interesting or well-received entries from November 2007 through December 2010. Feel free to dig through the &lt;a href=&quot;http://prog21.dadgum.com/archives.html&quot;&gt;archives&lt;/a&gt; if you want everything. Items within each section are in chronological order.
&lt;br /&gt;&lt;br /&gt;Popular:
&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://prog21.dadgum.com/3.html&quot;&gt;Admitting that Functional Programming Can Be Awkward&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/6.html&quot;&gt;Sending Modern Languages Back to 1980s Game Programmers&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/15.html&quot;&gt;Why Garbage Collection Paranoia is Still (sometimes) Justified&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/16.html&quot;&gt;Garbage Collection in Erlang&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/19.html&quot;&gt;Five Memorable Books About Programming&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/23.html&quot;&gt;Purely Functional Retrogames&lt;/a&gt; (5 parts)&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/29.html&quot;&gt;A Spellchecker Used to Be a Major Feat of Software Engineering&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/30.html&quot;&gt;Want to Write a Compiler? Just Read These Two Papers.&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/38.html&quot;&gt;Puzzle Languages&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/48.html&quot;&gt;The World's Most Mind-Bending Language Has the Best Development Environment&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/61.html&quot;&gt;Optimizing for Fan Noise&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/68.html&quot;&gt;How Much Processing Power Does it Take to be Fast?&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/74.html&quot;&gt;Free Your Technical Aesthetic from the 1970s&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/76.html&quot;&gt;Stop the Vertical Tab Madness&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/80.html&quot;&gt;Advice to Aimless, Excited Programmers&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/87.html&quot;&gt;Write Code Like You Just Learned How to Program&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;Functional programming:
&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://prog21.dadgum.com/3.html&quot;&gt;Admitting that Functional Programming Can Be Awkward&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/14.html&quot;&gt;Functional Programming Archaeology&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/18.html&quot;&gt;Back to the Basics of Functional Programming&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/23.html&quot;&gt;Purely Functional Retrogames&lt;/a&gt; (5 parts)&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/31.html&quot;&gt;Functional Programming Went Mainstream Years Ago&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/36.html&quot;&gt;Accidentally Introducing Side Effects into Purely Functional Code&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/41.html&quot;&gt;Let's Take a Trivial Problem and Make it Hard&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/54.html&quot;&gt;Functional Programming Doesn't Work (and what to do about it)&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/73.html&quot;&gt;Explaining Functional Programming to Eight-Year-Olds&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;Erlang:
&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://prog21.dadgum.com/1.html&quot;&gt;A Deeper Look at Tail Recursion in Erlang&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/2.html&quot;&gt;On the Perils of Benchmarking Erlang&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/16.html&quot;&gt;Garbage Collection in Erlang&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/43.html&quot;&gt;How to Crash Erlang&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/53.html&quot;&gt;How I Learned to Stop Worrying and Love Erlang's Process Dictionary&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/60.html&quot;&gt;What to do About Erlang's Records?&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/70.html&quot;&gt;A Ramble Through Erlang IO Lists&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/79.html&quot;&gt;Erlang vs. Unintentionally Purely Functional Python&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/81.html&quot;&gt;A Concurrent Language for Non-Concurrent Software&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;Personal:
&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://prog21.dadgum.com/22.html&quot;&gt;My Road to Erlang&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/45.html&quot;&gt;A Personal History of Compilation Speed&lt;/a&gt; (2 parts)&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/46.html&quot;&gt;The Pure Tech Side is the Dark Side&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/50.html&quot;&gt;Tales of a Former Disassembly Addict&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/56.html&quot;&gt;The Recovering Programmer&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/57.html&quot;&gt;No Comment&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/64.html&quot;&gt;Eleven Years of Erlang&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/65.html&quot;&gt;A Short Story About Verbosity&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/83.html&quot;&gt;Easy to Please&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;Progress:
&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://prog21.dadgum.com/29.html&quot;&gt;A Spellchecker Used to Be a Major Feat of Software Engineering&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/39.html&quot;&gt;How My Brain Kept Me from Co-Founding YouTube&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/51.html&quot;&gt;How Did Things Ever Get This Good?&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/52.html&quot;&gt;Slow Languages Battle Across Time&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/59.html&quot;&gt;Nothing Like a Little Bit of Magic&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/68.html&quot;&gt;How Much Processing Power Does it Take to be Fast?&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/86.html&quot;&gt;Instant-On&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;J:
&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://prog21.dadgum.com/14.html&quot;&gt;Functional Programming Archaeology&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/48.html&quot;&gt;The World's Most Mind-Bending Language Has the Best Development Environment&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;Forth:
&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://prog21.dadgum.com/8.html&quot;&gt;Deriving Forth&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/33.html&quot;&gt;Understanding What It's Like to Program in Forth&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;Other entries that I think were successful:
&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://prog21.dadgum.com/21.html&quot;&gt;Slumming with BASIC Programmers&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/28.html&quot;&gt;Coding as Performance&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/34.html&quot;&gt;Macho Programming&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/35.html&quot;&gt;Timidity Does Not Convince&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/40.html&quot;&gt;On Being Sufficiently Smart&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/58.html&quot;&gt;Flickr as a Business Simulator&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/67.html&quot;&gt;Rethinking Programming Language Tutorials&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/71.html&quot;&gt;Tricky When You Least Expect It&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/72.html&quot;&gt;What Do People Like?&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/77.html&quot;&gt;Personal Programming&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/66.html&quot;&gt;Living Inside Your Own Black Box&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://prog21.dadgum.com/69.html&quot;&gt;How to Think Like a Pioneer&lt;/a&gt;</description>
	<pubDate>Wed, 29 Dec 2010 06:00:00 +0000</pubDate>
</item>
<item>
	<title>Programming in the 21st Century: Write Code Like You Just Learned How to Program</title>
	<guid>http://prog21.dadgum.com/87.html</guid>
	<link>http://prog21.dadgum.com/87.html</link>
	<description>I'm reading &lt;a href=&quot;http://www.amazon.com/Do-More-Faster-TechStars-Accelerate/dp/0470929839&quot;&gt;Do More Faster&lt;/a&gt;, which is more than a bit of an advertisement for the TechStars start-up incubator, but it's a good read nonetheless. What struck me is that several of the people who went through the program, successfully enough to at least get initial funding, didn't know how to program. They learned it so they could implement their start-up ideas.
&lt;br /&gt;&lt;br /&gt;Think about that. It's like having a song idea and learning to play an instrument so you can make it real. I suspect that the learning process in this case would horrify most professional musicians, but that horror doesn't necessarily mean that it's a bad idea, or that the end result won't be successful. After all, look at how many bands find success without the benefit of a degree in music theory.
&lt;br /&gt;&lt;br /&gt;I already knew how to program when I took an &quot;Intro to BASIC&quot; class in high school. One project was to make a visual demo using the sixteen-color, low-res mode of the Apple II. I quickly put together something algorithmic, looping across the screen coordinates and drawing lines and changing colors. It took me about half an hour to write and tweak, and I was done. 
&lt;br /&gt;&lt;br /&gt;I seriously underestimated what people would create.
&lt;br /&gt;&lt;br /&gt;One guy presented this amazing demo full of animation and shaded images. I'm talking crazy stuff, like a skull that dripped blood from its eye into a rising pool at the bottom of the screen. And that was just one segment of his project. I was stunned. Clearly I wasn't the hotshot programmer I thought was.
&lt;br /&gt;&lt;br /&gt;I eventually saw the BASIC listing for his program. It was hundreds and hundreds of lines of statements to change colors and draw points and lines. There were no loops or variables. To animate the blood he drew a red pixel, waited, then drew another red pixel below it. All the coordinates were hard-coded. How did he keep track of where to draw stuff? He had a piece of graph paper that he updated as he went.
&lt;br /&gt;&lt;br /&gt;My prior experience hurt me in this case. I was thinking about the &lt;i&gt;program&lt;/i&gt;, and how I could write something that was concise and clean. The guy who wrote the skull demo wasn't worried about any of that. He didn't care about what the program looked like or how maintainable it was. He just wanted a way to present his vision.
&lt;br /&gt;&lt;br /&gt;There's a lesson there that's easy to forget--or ignore. It's extremely difficult to be simultaneously concerned with the end-user experience of whatever it is that you're building and the architecture of the program that delivers that experience. Maybe impossible. I think the only way to pull it off is to simply not care about the latter. Write comically straightforward code, as if you just learned to program, and go out of your way avoid wearing any kind of software engineering hat--unless what you really want to be is a software engineer, and not the designer of an experience.
&lt;br /&gt;&lt;br /&gt;(If you liked this, you might like &lt;a href=&quot;http://prog21.dadgum.com/28.html&quot;&gt;Coding as Performance&lt;/a&gt;.)</description>
	<pubDate>Fri, 24 Dec 2010 06:00:00 +0000</pubDate>
</item>
<item>
	<title>Process-one Blogs: TextOne by example (part 1): XMPP federation</title>
	<guid>http://www.process-one.net/en/blogs/article/textone_by_example_part_1_xmpp_federation/</guid>
	<link>http://www.process-one.net/en/blogs/article/textone_by_example_part_1_xmpp_federation/</link>
	<description>&lt;p&gt;TextOne application is intended to be a simplified superset of the standard XMPP protocol, specially designed for mobile usage.&lt;/p&gt; &lt;p&gt;TextOne application is available on iPhone and Android.&lt;/p&gt;
&lt;p&gt;Being based on a standard protocol means that you can tap into the power federation. What's this strange thing? It means that you can send messages to users and receive replies even if they are using a different XMPP messaging service than the one you are using.&lt;/p&gt;
&lt;p&gt;Quick demonstration with TextOne iPhone app in version 2.0:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Log in to TextOne with your account &lt;/li&gt;
&lt;li&gt;Think about a friend using Gtalk chat service &lt;/li&gt;
&lt;li&gt;Send him a message to its address user@gmail.com &lt;/li&gt;
&lt;li&gt;Wait that he accepts you as a contact, since Gmail requires that to receive messages: you will be notified when that happens &lt;/li&gt;
&lt;li&gt;Start chatting together&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;See TextOne in action:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;New message:&lt;br /&gt; &lt;img alt=&quot;Write a new message in TextOne&quot; height=&quot;480&quot; src=&quot;http://www.process-one.net/images/uploads/TextOne_Gtalk01_thumb.png&quot; width=&quot;320&quot; /&gt;&lt;br /&gt;&lt;br /&gt; &lt;/li&gt;
&lt;li&gt;Gtalk address entered:&lt;br /&gt; &lt;img alt=&quot;Select a Gtalk address in TextOne&quot; height=&quot;480&quot; src=&quot;http://www.process-one.net/images/uploads/TextOne_Gtalk02_thumb.png&quot; width=&quot;320&quot; /&gt;&lt;br /&gt;&lt;br /&gt; &lt;/li&gt;
&lt;li&gt;First message sent:&lt;br /&gt; &lt;img alt=&quot;Informative message received on TextOne&quot; height=&quot;480&quot; src=&quot;http://www.process-one.net/images/uploads/TextOne_Gtalk03_thumb.png&quot; width=&quot;320&quot; /&gt;&lt;br /&gt;&lt;br /&gt; &lt;/li&gt;
&lt;li&gt;Your contact has accepted you:&lt;br /&gt; &lt;img alt=&quot;Gtalk friend has accepted you as a contact on TextOne&quot; height=&quot;480&quot; src=&quot;http://www.process-one.net/images/uploads/TextOne_Gtalk04_thumb.png&quot; width=&quot;320&quot; /&gt;&lt;br /&gt;&lt;br /&gt; &lt;/li&gt;
&lt;li&gt;Go on messaging:&lt;br /&gt; &lt;img alt=&quot;Chat between TextOne and Gtalk&quot; height=&quot;480&quot; src=&quot;http://www.process-one.net/images/uploads/TextOne_Gtalk05_thumb.png&quot; width=&quot;320&quot; /&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;That's it!&lt;/p&gt;
&lt;p&gt;Simple, isn't it ?&lt;/p&gt;
&lt;p&gt;What does it means for TextOne? It means that this beautiful texting application is not closed like all of its counterparts. It is open to the world. In the long run, it will make a huge difference.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Read the whole &quot;TextOne by example&quot; series:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;http://www.process-one.net/en/blogs/article/textone_by_example_part_1_xmpp_federation/&quot;&gt;TextOne by example (part 1): XMPP federation&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt; &lt;a href=&quot;http://www.process-one.net/en/blogs/article/textone_by_example_part_2_email_federation/&quot;&gt;TextOne by example (part 2): email federation&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href=&quot;http://www.process-one.net/en/blogs/article/textone_by_example_part_3_facebook_friend_search_and_federation/&quot;&gt;TextOne by example (part 3): Facebook friend search and federation&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
	<pubDate>Thu, 23 Dec 2010 11:00:37 +0000</pubDate>
</item>
<item>
	<title>1011 Ltd Blog: Evolving aircraft control values using a Genetic Algorithm</title>
	<guid>tag:1011ltd.com,2010-12-22:/web/blog/evolving_pid</guid>
	<link>http://www.1011ltd.com/</link>
	<description>&lt;p&gt;
If you've ever had to tune PID control values, you might realise what a pain they can be. I have started developing
an Erlang &lt;a href=&quot;http://en.wikipedia.org/wiki/Unmanned_aerial_vehicle&quot;&gt;UAV&lt;/a&gt; autopilot, with the principle of leveraging &lt;a href=&quot;http://en.wikipedia.org/wiki/In_silico&quot;&gt;in-silico&lt;/a&gt; simulation as much as possible. You can
see some videos of those experiments &lt;a href=&quot;http://vimeo.com/user2186349/videos&quot;&gt;here&lt;/a&gt; (especially the one labelled &quot;First bumpy, but successful landing in X-plane with Erlang autopilot&quot;).
&lt;/p&gt;

&lt;div&gt;&lt;a href=&quot;http://www.1011ltd.com/web/blog/post/evolving_pid&quot;&gt;continue reading...&lt;/a&gt;&lt;/div&gt;</description>
	<pubDate>Wed, 22 Dec 2010 17:16:00 +0000</pubDate>
</item>
<item>
	<title>Erlang Training and Consulting &lt;br/&gt;- News: 22 December 2010: Merry Christmas and a Happy New Year from Erlang Solutions</title>
	<guid>http://www.erlang-solutions.com/news/1/entry/1196</guid>
	<link>http://www.erlang-solutions.com/news/1/entry/1196</link>
	<description>&lt;p&gt;Erlang Solutions would like to wish everyone a Merry Christmas and a Happy New Year. This year we have decided that instead of sending Christmas cards, we would donate the money to a worthwhile cause. After much discussion we agreed that this year&amp;rsquo;s worthwhile cause would be Kiva.&lt;/p&gt;
&lt;p&gt;Kiva's mission is to connect people, through lending, for the sake of alleviating poverty. Kiva empowers individuals to lend to an entrepreneur across the globe. By combining microfinance with the internet, Kiva is creating a global community of people connected through lending. Lenders can choose which project they would like to donate to and can then track the progress of this project.&lt;/p&gt;
&lt;p&gt;Over the next year we will track our projects and keep you all up to date with how they are going. You can find out more about Kiva and how you to can become a lender on their &lt;a href=&quot;http://www.kiva.org&quot;&gt;website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the mean time we wish you happy holidays, a great rest, and we sincerely hope your software doesn't crash on you while you're gone (Well, if it is Erlang, it shouldn't)!! May snowflakes fall upon you like thousands of tiny concurrent processes.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.erlang-solutions.com&quot;&gt;&lt;img title=&quot;Xmas&quot; src=&quot;http://www.erlang-solutions.com/upload/images/65/erlangxmas.gif&quot; alt=&quot;Xmas&quot; width=&quot;195&quot; height=&quot;101&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description>
	<pubDate>Wed, 22 Dec 2010 15:32:16 +0000</pubDate>
</item>
<item>
	<title>Learn You Some Erlang: Rage Against The Finite-State Machines</title>
	<guid>http://learnyousomeerlang.com/finite-state-machines</guid>
	<link>http://learnyousomeerlang.com/finite-state-machines</link>
	<description>Rage Against The Finite-State Machines introduces the reader to the concept of finite-state machines and how they're generalised in the OTP framework. We get to write an asynchronous concurrent protocol for a trading system for items between two players for a fictive game. We then implement the protocol by using the gen_fsm behaviour in the OTP way.</description>
	<pubDate>Tue, 21 Dec 2010 12:30:00 +0000</pubDate>
</item>
<item>
	<title>Erlang Factory News: New Speaker Added for the Erlang Factory SF Bay Area - Dave Smith</title>
	<guid>http://erlang-factory.com/news/rss/8e06939cdfc17c5958cf1f1b63107de2</guid>
	<link></link>
	<description>&lt;p&gt;We are pleased to announce yet another top name from the world of Erlang will be speaking at next years conference.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://www.erlang-factory.com/conference/SFBay2011/speakers/DizzySmith&quot;&gt;Dave Smith (Dizzy)&lt;/a&gt; &lt;/strong&gt;who  is the author of rebar and bitcask wil be discussing and exploring how to use Rebar in a typical development environment for everything  from simple Erlang code to port drivers and embedded Erlang servers. Dizzy is a speaker not to miss!&lt;/p&gt;
&lt;p&gt;Registration will be opening soon. You can keep up to date with all  the latest announcements by checking the website or following us on  twitter &lt;a href=&quot;http://www.twitter.com/erlangfactory&quot;&gt;@erlangfactory.&lt;/a&gt;&lt;/p&gt;</description>
	<pubDate>Mon, 20 Dec 2010 18:01:22 +0000</pubDate>
</item>
<item>
	<title>Process-one Blogs: Tweet.IM update: retweets, hashtags and timeline refresh</title>
	<guid>http://www.process-one.net/en/blogs/article/tweet.im_update/</guid>
	<link>http://www.process-one.net/en/blogs/article/tweet.im_update/</link>
	<description>&lt;p&gt;New interesting features have been deployed on Tweet.IM.&lt;/p&gt; &lt;p&gt;Our Twitter gateway, and thus its installation on Tweet.IM, has received new features, enabling further integration of IM and microblogging.&lt;/p&gt;

&lt;p&gt;These will be available to clients that display formatted text, well known as &lt;a href=&quot;http://xmpp.org/extensions/xep-0071.html&quot;&gt;XHTML-IM&lt;/a&gt; by the specialists. For this, you will need to have XHTML enabled on Tweet.IM by sending &lt;code&gt;xhtml on&lt;/code&gt;. Reminder: type &lt;code&gt;help&lt;/code&gt; to have a list of all available commands&lt;/p&gt;

&lt;p&gt;Here are these features:
&lt;ul&gt;&lt;li&gt;Support for the display of retweet (official retweet format)
&lt;/li&gt;&lt;li&gt;Allow to force timeline fetch manually, by typing &lt;code&gt;update&lt;/code&gt;
&lt;/li&gt;&lt;li&gt;Render hash tag as a search link, which is then clickable&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;

&lt;p&gt;Here is a mouse hover of a hash tag: clicking on this one will open a new browser tab to the Twitter hashtag&lt;br /&gt;
&lt;img src=&quot;http://www.process-one.net/images/uploads/Tweet.IM-hashtag_.png&quot; alt=&quot;image&quot; width=&quot;410&quot; height=&quot;68&quot; /&gt;&lt;/p&gt;

&lt;p&gt;With these new features, we provide more fine-grained enhancements, enabling seamless integration between real-time push technologies based on XMPP and microblogging based on the web.&lt;/p&gt;</description>
	<pubDate>Mon, 20 Dec 2010 14:49:02 +0000</pubDate>
</item>
<item>
	<title>Scattered Thoughts: optimising texsearch: memory usage</title>
	<guid>http://scattered-thoughts.net/one/1292/752863/348678</guid>
	<link>http://scattered-thoughts.net/one/1292/752863/348678</link>
	<description>&lt;p&gt;In my last post I discussed the new search algorithm behind texsearch. There is a significant speed improvement over previous versions but it now consumes a ridiculous amount of memory. The instance running &lt;a href=&quot;http://latexsearch.com&quot;&gt;latexsearch.com&lt;/a&gt; wavers around 4.7 gb during normal operation and reaches 7-8 gb when updating the index. This pushes other services out of main memory and everything is horribly slow until they swap back in.
&lt;/p&gt;
&lt;p&gt;The main data structure looks like this:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type 'a t =
  { latexs : Latex.t DynArray.t
  ; opaques : 'a DynArray.t
  ; deleted : bool DynArray.t
  ; mutable next_id : id
  ; mutable array : (id * pos) array
  ; mutable unsorted : ('a * Latex.t) list }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The array field is responsible for the vast majority of the memory usage. Each cell in the array contains a pointer to a tuple containing two integers for a total of 4 words per suffix. The types id and pos are both small integers so if we pack them into a single unboxed integer we can reduce this to 1 word per suffix. We have a new module suffix.ml with some simple bit-munging:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type id = int
type pos = int

type t = int
      
let pack_size = (Sys.word_size / 2) - 1
let max_
