<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title>Adaltas</title>
  <link href="http://www.adaltas.com/atom.xml" rel="self"/>
  <link href="http://www.adaltas.com/"/>
  <updated>2012-04-14T01:49:37+02:00</updated>
  <id>http://www.adaltas.com/</id>
  <author>
    <name>David Worms</name>
    
      <email>open@adaltas.com</email>
    
  </author>

  
  <entry>
    <title>Nouveau regard sur les tests en Node.js avec Mocha, Should et Travis</title>
    <link href="http://www.adaltas.com/blog/2012/03/28/nodejs-test-mocha-should-travis/"/>
    <updated>2012-03-28T00:40:00+02:00</updated>
    <id>http://www.adaltas.com/blog/2012/03/28/nodejs-test-mocha-should-travis</id>
    <content type="html">&lt;p&gt;&lt;img class=&quot;right&quot; src=&quot;http://www.adaltas.com/images/blog/2012-02-18-nodejs-test-mocha-should-travis/logos.jpg&quot; title=&quot;Mocha, Should and Travis logos&quot; &gt;&lt;/p&gt;

&lt;p&gt;Suite à une demande, l&amp;#8217;article ci-dessous est la traduction d&amp;#8217;un précédent publié le 19 février 2012.&lt;/p&gt;

&lt;p&gt;Aujourd&amp;#8217;hui, j&amp;#8217;ai finalement décidé de passer une peu de temps autour de &lt;a href=&quot;http://about.travis-ci.org/&quot;&gt;Travis&lt;/a&gt;. Cette petite image verte en haut des pages d&amp;#8217;accueil de projets GitHub m&amp;#8217;intrigue de plus en plus ces derniers jours. En fait, pour être tout à fait honnête, ce n&amp;#8217;est pas exactement ainsi que j&amp;#8217;ai débuté ma soirée. Tout d&amp;#8217;abord, après deux ans de bon et loyaux services, j&amp;#8217;ai décidé d&amp;#8217;abandonner Expresso pour donner une chance à &lt;a href=&quot;http://visionmedia.github.com/mocha/&quot;&gt;Mocha&lt;/a&gt;. Et puisque je m&amp;#8217;étais habitué aux quelques petites fonction dont Expresso enrichit le module &lt;code&gt;assert&lt;/code&gt;, il m&amp;#8217;a fallut y remédier, ce qui m&amp;#8217;a conduit au module &lt;a href=&quot;https://github.com/visionmedia/should.js&quot;&gt;Should&lt;/a&gt;. Il me fut assez plaisant de voir comment ces deux derniers modules se complètent parfaitement l&amp;#8217;un et l&amp;#8217;autre, dans la plus pure tradition Unix: petit, puissant et bon citoyen.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;p&gt;Écrit par le même autheur qu&amp;#8217;Expresso, &lt;a href=&quot;http://visionmedia.github.com/mocha/&quot;&gt;Mocha&lt;/a&gt; est une alternative qui a pour objectif de le remplacer. Cette situation prévaut depuis plusieurs mois déjà mais je n&amp;#8217;avais jamais trouvé un grand intérêt à passer dans le monde des tests de type BDD. BDD signifie Behavior Driven Development, soit le développement des tests en mettant en valeur les comportements. Ils s&amp;#8217;opposent le plus souvent aux tests unitaires qui sont moins expressifs, et donc par la même moins verbeux. Par exemple le nom des tests sont exprimés comme des phrases entières. Le but est d&amp;#8217;encourager la collaboration entres les développeurs et les personnes non techniques comme les intervenants business dans la conception de logiciels. Il existe sans doutes des projets et des cultures d&amp;#8217;entreprises dans lesquels cela peut s&amp;#8217;appliquer mais de mon expérience personnelle, il m&amp;#8217;est impossible de faire participer mes clients dans l&amp;#8217;expression des tests unitaires. &lt;a href=&quot;http://cukes.info/&quot;&gt;Cucumber&lt;/a&gt; est probablement l&amp;#8217;outils de BDD le plus populaire, ce fut l&amp;#8217;un des premiers. Cet outil a ses inconditionnels mais j&amp;#8217;ai toujours été bien trop fainéant par le passé pour sauter dans cet enfer. À en juger par les exemples, cela implique grossièrement l&amp;#8217;apprentissage d&amp;#8217;un nouveau langage juste pour écrire des tests. Cette impression est certainement mauvaise et il se peut toutefois que ce soit plus simple qu&amp;#8217;il n&amp;#8217;y paraisse.&lt;/p&gt;

&lt;p&gt;Maintenant, regardons un peu comment s&amp;#8217;utilise Mocha]&lt;a href=&quot;http://visionmedia.github.com/mocha/&quot;&gt;mocha&lt;/a&gt;. L&amp;#8217;API est relativement simple, principalement deux fonctions qui sont &lt;code&gt;describe&lt;/code&gt; et &lt;code&gt;it&lt;/code&gt;. Chacune prend un texte comme premier argument qui combinés ensemble forment une phrase visible à l&amp;#8217;exécution des tests. Un exemple :&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;coffeescript&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nx&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Mon test&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;doit être synchronisé&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;() -&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;c1&quot;&gt;# do sth&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;doit être asynchronisé&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;(next) -&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;c1&quot;&gt;# do sth&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;nx&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Il est intéressant de noter comment &lt;a href=&quot;http://visionmedia.github.com/mocha/&quot;&gt;Mocha&lt;/a&gt; découvre et vous laisse décider pour chaque test si celui doit tourner en mode synchrone ou non, vous permettant de mixer les deux modes et rendant vulgaire l&amp;#8217;option &lt;code&gt;serial -s&lt;/code&gt; d&amp;#8217;Expresso. Il fait en effet appel à la propriété pas si populaire qu&amp;#8217;est &lt;code&gt;length&lt;/code&gt; attachée à toute fonction. Il y a aussi d&amp;#8217;autres méthodes qui sont utiles lors de l&amp;#8217;écriture de tests pour modifier la configuration, aider à la mise en place et nettoyer les tests. À titre d&amp;#8217;illustration, voici un exemple inspiré des tests de &lt;a href=&quot;http://www.adaltas.com/projects/node-mecano&quot;&gt;mecano&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;13&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;14&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;15&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;16&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;coffeescript&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nv&quot;&gt;should = &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;should&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nv&quot;&gt;mecano = &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;mecano&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nx&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;download&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;nx&quot;&gt;@beforeEach&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;(next) -&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;nx&quot;&gt;mecano&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;scratch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;next&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;nx&quot;&gt;@afterEach&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;(next) -&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;nx&quot;&gt;mecano&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;scratch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;next&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;should deal with ftp scheme&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;(next) -&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;nx&quot;&gt;@timeout&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10000&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;nx&quot;&gt;mecano&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;download&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;            &lt;span class=&quot;nv&quot;&gt;source: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;ftp://ftp.gnu.org/gnu/glibc/README.glibc&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;            &lt;span class=&quot;nv&quot;&gt;destination: &lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;#{scratch}/download_test&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;(err, downloaded) -&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;            &lt;span class=&quot;nx&quot;&gt;should&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;not&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;exist&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;            &lt;span class=&quot;nx&quot;&gt;downloaded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;should&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;eql&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;            &lt;span class=&quot;nx&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Les fonctions &lt;code&gt;beforeEach&lt;/code&gt; et &lt;code&gt;afterEach&lt;/code&gt; permettent l&amp;#8217;exécution d&amp;#8217;un code avant et après chacun des tests. La fonction &lt;code&gt;timeout&lt;/code&gt; modifie la temps d&amp;#8217;exécution maximale d&amp;#8217;un test (par défaut 2 secondes).&lt;/p&gt;

&lt;p&gt;Maintenant, introduisons l&amp;#8217;utilisation de &lt;a href=&quot;https://github.com/visionmedia/should.js&quot;&gt;Should&lt;/a&gt;. Son principe comme toute librairie d&amp;#8217;assertion est de détecter des valeurs incorrectes. Au début, le style d&amp;#8217;API de type BDD peut sembler compliqué mais je l&amp;#8217;ai tout de suite trouvé naturel et je n&amp;#8217;ai pas dû lutter contre lui. En fait, c&amp;#8217;est bien là l&amp;#8217;essentiel de ce dont j&amp;#8217;attend de ce type de librairie, ne pas avoir à ouvrir mon navigateur toutes les 5 minutes pour chercher comme utiliser ce satané API. Après 10 minutes d&amp;#8217;utilisation, &lt;a href=&quot;https://github.com/visionmedia/should.js&quot;&gt;Should&lt;/a&gt; s&amp;#8217;est avéré être simple, à la hauteur de ces ambitions et simplifie la lecture des tests, dû moins selon mon opinion.&lt;/p&gt;

&lt;p&gt;Finalement, j&amp;#8217;ai décidé de m&amp;#8217;occuper de &lt;a href=&quot;http://about.travis-ci.org/&quot;&gt;Travis&lt;/a&gt; et de ces images de statut. Obtenir une image en haut de la &lt;a href=&quot;https://www.github.com/wdavidw/node-mecano&quot;&gt;page d&amp;#8217;accueil de mecano sur GitHub&lt;/a&gt; fut facile. La mise en place grâce à son intégration avec GitHub est aisée et pour un nouveau venu prend une 15 de minutes. Faire en sorte que cette petite image soit verte me pris plus de temps. &lt;a href=&quot;http://www.adaltas.com/projects/node-mecano&quot;&gt;Mecano&lt;/a&gt; prend un peu de libertés quand il déroule ses tests. Il a besoin d&amp;#8217;être en ligne, GIT doit être installé et il a besoin de se connecter en SSH sur lui-même. Dès la première passe sur &lt;a href=&quot;http://about.travis-ci.org/&quot;&gt;Travis&lt;/a&gt;, je fus agréablement surpris en constatant que seulement 5 tests ne passaient pas. La plupart de ces erreurs étaient ma faute et furent aussitôt fixés. Une autre erreur était dû à ce que différentes version de Node.js étaient testées mais &lt;a href=&quot;https://github.com/visionmedia/should.js&quot;&gt;Should&lt;/a&gt; n&amp;#8217;est pas compatible avec la version &amp;#8220;0.4&amp;#8221;. Cela me laissait avec un dernier problème, préparé &lt;a href=&quot;http://about.travis-ci.org/&quot;&gt;Travis&lt;/a&gt; de tel manière que le compte utilisateur pour faire un SSH sur lui-même sans mot de passe. A la fin, mon fichier &amp;#8220;.travis.yml&amp;#8221; de configuration fut le suivant:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;yaml&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;l-Scalar-Plain&quot;&gt;language&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;node_js&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;l-Scalar-Plain&quot;&gt;node_js&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;p-Indicator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;0.6&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;p-Indicator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;0.7&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;l-Scalar-Plain&quot;&gt;before_script&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;p-Indicator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;ssh-keygen&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-t&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;rsa&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-f&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;~/.ssh/id_rsa&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-N&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&amp;#39;&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;p-Indicator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;cat&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;~/.ssh/id_rsa.pub&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;~/.ssh/authorized_keys&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Au cours de cet article, je n&amp;#8217;ai pas fournis d&amp;#8217;instruction sur l&amp;#8217;installation et la configuration de ses librairies mais chacun des projets est extrêmement bien documenté. Merci aux auteurs pour leur travail.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>HDFS and Hive storage - comparing file formats and compression methods</title>
    <link href="http://www.adaltas.com/blog/2012/03/13/hdfs-hive-storage-format-compression/"/>
    <updated>2012-03-13T21:50:00+01:00</updated>
    <id>http://www.adaltas.com/blog/2012/03/13/hdfs-hive-storage-format-compression</id>
    <content type="html">&lt;p&gt;A few days ago, we have conducted a test in order to compare various &lt;a href=&quot;http://hive.apache.org/&quot;&gt;Hive&lt;/a&gt; file formats and compression methods. Among those file formats, some are native to HDFS and apply to all Hadoop users. The test suite is composed of similar &lt;a href=&quot;http://hive.apache.org/&quot;&gt;Hive&lt;/a&gt; queries which create a table, eventually set a compression type and load the same dataset into the new table. Among all the queries, we tested the &amp;#8220;sequence file&amp;#8221;, &amp;#8220;text file&amp;#8221; and &amp;#8220;RCFILE&amp;#8221; formats and the &amp;#8220;default&amp;#8221;, &amp;#8220;bz&amp;#8221;, &amp;#8220;gz&amp;#8221;, &amp;#8220;LZO&amp;#8221; and &amp;#8220;Snappy&amp;#8221; compression codecs.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;p&gt;April 4th 2012: Answer to Huchev comment relative to LZ4.&lt;/p&gt;

&lt;h2&gt;Setup&lt;/h2&gt;

&lt;p&gt;The environment is a 20 nodes and 120 terabytes Hadoop cluster running &lt;a href=&quot;http://www.cloudera.com/&quot;&gt;Cloudera CDH3U3&lt;/a&gt;. The original dataset is a 1.33 Go folder with 80 compressed and unsplitable &amp;#8220;bz2&amp;#8221; files inside. The data inside is formatted as CSV for a total of about 125,000,000 lines.&lt;/p&gt;

&lt;p&gt;Below is an example of a &lt;a href=&quot;http://hive.apache.org/&quot;&gt;Hive&lt;/a&gt; Query importing data using a &amp;#8220;RCFILE&amp;#8221; format with &amp;#8220;LZO&amp;#8221; compression:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;13&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;14&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;15&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;16&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;sql&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;&#8211; Prepare&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rc_lzo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;BIGINT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctime&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;INT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mtime&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;INT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;STRING&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value_1&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;INT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value_2&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;INT&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;STORED&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RCFILE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;&#8211; Compression&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;exec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mapred&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compression&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;codec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hadoop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compression&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lzo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LzoCodec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;&#8211; Import&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;INSERT&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OVERWRITE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rc_lzo&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ctime&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mtime&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value_2&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;staging&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h2&gt;Results&lt;/h2&gt;

&lt;p&gt;The table below are the results we obtained. The query columns describe the type of test. The query name starts with the file format followed by the compression codec. Both &amp;#8220;block&amp;#8221; and &amp;#8220;record&amp;#8221; compression types have been reported for the &amp;#8220;sequence file&amp;#8221; format and the &amp;#8220;default&amp;#8221; compression codec.&lt;/p&gt;

&lt;p&gt;The &amp;#8220;serdesf&amp;#8221; family of queries makes use of a custom &lt;a href=&quot;https://cwiki.apache.org/confluence/display/Hive/SerDe&quot;&gt;SerDe&lt;/a&gt; which encode each column in an shorter size when appropriate. In our use case, the &lt;code&gt;code&lt;/code&gt; can be stored as 1 character (1 byte), the &lt;code&gt;value_2&lt;/code&gt; can be represented as the diff between itself and the &lt;code&gt;value_1&lt;/code&gt; (2 bytes). Overall, a line is stored as 16 bytes compared to 65 bytes originally.&lt;/p&gt;

&lt;p&gt;The &amp;#8220;bss&amp;#8221; query uses the &lt;code&gt;BinarySortableSerDe&lt;/code&gt; serialization which is a custom &lt;a href=&quot;https://cwiki.apache.org/confluence/display/Hive/SerDe&quot;&gt;Hive Serde&lt;/a&gt; that we associated to the &amp;#8220;sequence file&amp;#8221; format.&lt;/p&gt;

&lt;p&gt;The &amp;#8220;b64&amp;#8221; family of queries use the &lt;code&gt;base64&lt;/code&gt; package present in the &lt;a href=&quot;http://hive.apache.org/&quot;&gt;Hive&lt;/a&gt; contrib project.&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;right&quot;&gt;query                  &lt;/th&gt;
&lt;th align=&quot;right&quot;&gt; time           &lt;/th&gt;
&lt;th align=&quot;right&quot;&gt; size&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;sf                     &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 2mn 3s         &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 7.91 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;sf_string              &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 2mn 22s        &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 8.72 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;sf_df_block            &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 2mn 17s        &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 8.72 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;sf_df_record           &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 2mn 12s        &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 7.32 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;sf_bz                  &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 2h 43mn 24s    &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 9.9 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;sf_gz                  &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 2mn 29s        &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 8.72 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;sf_lzo                 &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 2mn 36s        &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 8.80 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;sf_snappy              &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 3mn 55s        &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 8.23 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;tf                     &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 1mn 45s        &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 6.44 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;tf_bz                  &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 2mn 14s        &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 1.12 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;tf_df                  &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 2mn 16s        &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 1.12 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;tf_gz                  &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 48s            &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 1.34 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;tf_lzo                 &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 1mn 28s        &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 2.41 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;tf_snappy              &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 1mn 2s         &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 2.55 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;rc                     &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 1mn 30s        &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 5.78 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;rc_df                  &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 5mn 15s        &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 917.68 Mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;rc_gz                  &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 4mn 36s        &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 917.80 Mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;rc_snappy              &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 52s            &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 1.85 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;rc_lzo                 &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 38s            &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 1.67 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;serdesf                &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 59s            &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 3.63 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;serdesf_df             &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 1mn 27s        &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 4.61 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;serdesf_bz             &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 3h 6mn 9s      &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 9.63 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;serdesf_gz             &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 1mn 51s        &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 6.02 Go &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;serdesf_snappy         &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 1mn 35s        &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 4.80 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;bss                    &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 1mn 25s        &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 5.73 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;b64                    &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 2mn 5s         &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 9.17 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;b64_bz                 &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 21mn 15s       &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 1.14 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;b64_df                 &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 21mn 25s       &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 1.14 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;b64_gz                 &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 53s            &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 1.62 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;b64_snappy             &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 59s            &lt;/td&gt;
&lt;td align=&quot;right&quot;&gt; 2.89 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;h2&gt;Some notes&lt;/h2&gt;

&lt;p&gt;We wish we had run the tests on a larger input data set with a more common file format but cluster time is a scarce resource at the moment. As a result, the file sizes are probably representative but the speed results should be interpreted with care.&lt;/p&gt;

&lt;p&gt;The speed reflects importing time only (with not so standard files as input) and not how fast those formats are against map/reduce jobs.&lt;/p&gt;

&lt;p&gt;As part of the test, we also tested &lt;code&gt;block&lt;/code&gt; type of compression on other type of codecs but they had no effect so we came to the conclusion that &lt;code&gt;block&lt;/code&gt; type only apply to the default codec in sequence files.&lt;/p&gt;

&lt;p&gt;We tried to run the &lt;code&gt;serdesf&lt;/code&gt; test in a similar mode but using the &lt;code&gt;RCFILE&lt;/code&gt; format instead of &lt;code&gt;sequence file&lt;/code&gt; but the results are identical to the &lt;code&gt;rc&lt;/code&gt; family of queries.&lt;/p&gt;

&lt;h2&gt;Interpretation&lt;/h2&gt;

&lt;p&gt;The &amp;#8220;tf&amp;#8221; query act as a reference since it stores our data in an uncompressed CSV format. It is kind of awkward to see that all the &amp;#8220;sequence file&amp;#8221; queries generate larger file size. This isn&amp;#8217;t something we expected but maybe is it due to our high usage of the integer type.&lt;/p&gt;

&lt;p&gt;In term of file size, the &amp;#8220;RCFILE&amp;#8221; format with the &amp;#8220;default&amp;#8221; and &amp;#8220;gz&amp;#8221; compression achieve the best results. The &amp;#8220;base64&amp;#8221; &lt;a href=&quot;https://cwiki.apache.org/confluence/display/Hive/SerDe&quot;&gt;SerDe&lt;/a&gt; using &amp;#8220;sequence file&amp;#8221; with &amp;#8220;bz&amp;#8221; and &amp;#8220;default&amp;#8221; compression aren&amp;#8217;t so far away. However, those &amp;#8220;base64&amp;#8221; results are slow enough to be bypassed.&lt;/p&gt;

&lt;p&gt;In term of speed, the &amp;#8220;RCFILE&amp;#8221; formats with the &amp;#8220;lzo&amp;#8221; and &amp;#8220;snappy&amp;#8221; are very fast while preserving a high compression rate.&lt;/p&gt;

&lt;h2&gt;About LZ4&lt;/h2&gt;

&lt;p&gt;We didn&amp;#8217;t test LZ4. From our understanding of &lt;a href=&quot;https://issues.apache.org/jira/browse/HADOOP-7657&quot;&gt;HADOOP-7657&lt;/a&gt;, the support for LZ4 target Hadoop version 0.23.1, 0.24.0 and is not backported to our running Cloudera CDH3U3. If you are curious about LZ4, here&amp;#8217;s an interesing article &lt;a href=&quot;http://fastcompression.blogspot.fr/2011/06/lz4-improved-performance.html&quot;&gt;comparing LZ4 to Snappy&lt;/a&gt;. Also worth of interest is the &lt;a href=&quot;http://encode.ru/threads/1266-In-memory-benchmark-with-fastest-LZSS-%28QuickLZ-Snappy%29-compressors&quot;&gt;in-memory benchmark of the fastest compressors&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Two Hive UDAF to convert an aggregation to a map</title>
    <link href="http://www.adaltas.com/blog/2012/03/06/hive-udaf-map-conversion/"/>
    <updated>2012-03-06T01:30:00+01:00</updated>
    <id>http://www.adaltas.com/blog/2012/03/06/hive-udaf-map-conversion</id>
    <content type="html">&lt;p&gt;I am publishing two new Hive UDAF to help with maps in &lt;a href=&quot;http://hive.apache.org/&quot;&gt;Apache Hive&lt;/a&gt;. The source code is available on &lt;a href=&quot;https://github.com/wdavidw/hive-udf&quot;&gt;GitHub&lt;/a&gt; in two Java classes: &amp;#8220;UDAFToMap&amp;#8221; and &amp;#8220;UDAFToOrderedMap&amp;#8221; or you can &lt;a href=&quot;https://github.com/wdavidw/hive-udf/downloads&quot;&gt;download the jar file&lt;/a&gt;. The first function converts an aggregation into a map and is internally using a Java &lt;code&gt;HashMap&lt;/code&gt;. The second function extends the first one. It converts an aggregation into an ordered map and is internally using a Java &lt;code&gt;TreeMap&lt;/code&gt;.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;h2&gt;API&lt;/h2&gt;

&lt;p&gt;As a reminder, an &lt;a href=&quot;https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF&quot;&gt;UDF&lt;/a&gt; stands for a User Defined Function and an &lt;a href=&quot;https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF&quot;&gt;UDAF&lt;/a&gt; stands for User Defined Aggregate Function. When an UDF is a custom scalar function on one or more column of a single row (for example the &lt;code&gt;CONCAT&lt;/code&gt; function in SQL), an UDAF work on a aggregation of one or multiple columns (for example the &lt;code&gt;MAX&lt;/code&gt; function in SQL).&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;MAP to_map(primitive, primitive_or_complex)
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;MAP to_ordered_map(primitive, primitive_or_complex)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Both function share the same API. They accept two arguments, first is the key and second is the value. Keys may be any primitive type. Values may be a primitive or a complex type. In &lt;a href=&quot;http://hive.apache.org/&quot;&gt;Hive&lt;/a&gt;, primitive types are integer, boolean, floating point number, string, date and binary while complex types are structure, map and array.&lt;/p&gt;

&lt;h2&gt;Motivation&lt;/h2&gt;

&lt;p&gt;While working on time series in &lt;a href=&quot;http://hive.apache.org/&quot;&gt;Hive&lt;/a&gt;, I created those functions out of the following needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Since UDF are much trivial to implement than UDAF, it is convenient to write and use a UDF which takes the result of a generic UDAF as its input, for example: &lt;br/&gt;
&lt;code&gt;select MY_UDF( MY_UDAF(column_1, column_2) ) from my_table group by column_3&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;a href=&quot;http://hbase.apache.org/&quot;&gt;HBase&lt;/a&gt; structure we are modeling use keys to store customer identifiers and columns to store dates. &lt;a href=&quot;https://cwiki.apache.org/confluence/display/Hive/HBaseIntegration&quot;&gt;Importing data from Hive to HBase&lt;/a&gt; could be done in two ways: with a select statement or with an complicated low-level bulk loading strategy. Using a select statement, since it is making usage of a map and since we couldn&amp;#8217;t find any way to convert the result of an aggregation into a map, we had to insert on row per metering data which we suspect to be less efficient than inserting one row of multiple metering data for a single customer. Using a bulk loading strategy, we also faced the need to group our dataset into an ordered map to reflect to final layout of the &lt;a href=&quot;http://hbase.apache.org/&quot;&gt;HBase&lt;/a&gt; storage file format.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We are experimenting a custom HDFS file format integrated to &lt;a href=&quot;http://hive.apache.org/&quot;&gt;Hive&lt;/a&gt; which internally need to group the metering data of a customer to optimize their storage. We first wrote an implementation which takes an ordered result set as its input. This work but is a much more complicated implementation. Also, because of the nature of HDFS and MapReduce, we had no guaranty that all the data of a single customer would be store in a same file which prevent us from a complete optimization. Once again, structuring the data as a map was a requirement.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Usage&lt;/h2&gt;

&lt;p&gt;Considering a source data set as follow made of 4 columns (customer id, timestamp, meter value, meter state):&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;13&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;14&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;15&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;16&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;195100,1199145600,607527807,B
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;185100,1199145600,775031942,A
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;195100,1199156400,607532682,B
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;185100,1199156400,775032584,A
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;195100,1199167200,607535485,B
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;185100,1199167200,775033200,A
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;195100,1199178000,582924326,C
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;185100,1199178000,775034241,A
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;195100,1199188800,582927007,C
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;185100,1199188800,775035698,A
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;195100,1199199600,582929212,C
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;185100,1199199600,775036891,A
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;195100,1199210400,582932070,C
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;185100,1199210400,775038268,A
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;195100,1199221200,582935353,B
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;185100,1199221200,775039703,A&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;The CSV source is imported into &lt;a href=&quot;http://hive.apache.org/&quot;&gt;Hive&lt;/a&gt; with the next statements:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;sql&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;DROP&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;customer&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;INT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;emission&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;INT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;INT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;k&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;STRING&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;ROW&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FORMAT&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DELIMITED&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;FIELDS&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TERMINATED&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;,&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;LINES&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TERMINATED&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;\n&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;STORED&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TEXTFILE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;LOAD&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DATA&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;LOCAL&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;INPATH&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;./sample/data.csv&amp;#39;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OVERWRITE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;INTO&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Now we can declare our two UDAF:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;sql&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;ADD&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;JAR&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;adaltas&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hive&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;udf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SNAPSHOT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TEMPORARY&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FUNCTION&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_map&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;com.adaltas.UDAFToMap&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TEMPORARY&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FUNCTION&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_ordered_map&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;com.adaltas.UDAFToOrderedMap&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;And we can finally used them with the following queries:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;sql&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;customer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from_unixtime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;emission&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;GROUP&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;customer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;customer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_ordered_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from_unixtime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;emission&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;GROUP&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;customer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;The output of the last select statement looks like:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;13&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;14&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;15&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;16&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;17&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;18&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;coffeescript&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;mi&quot;&gt;185100&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;s2&quot;&gt;&amp;quot;2008-01-01 01:00:00&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;775031942&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;s2&quot;&gt;&amp;quot;2008-01-01 04:00:00&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;775032584&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;s2&quot;&gt;&amp;quot;2008-01-01 07:00:00&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;775033200&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;s2&quot;&gt;&amp;quot;2008-01-01 10:00:00&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;775034241&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;s2&quot;&gt;&amp;quot;2008-01-01 13:00:00&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;775035698&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;s2&quot;&gt;&amp;quot;2008-01-01 16:00:00&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;775036891&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;s2&quot;&gt;&amp;quot;2008-01-01 19:00:00&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;775038268&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;s2&quot;&gt;&amp;quot;2008-01-01 22:00:00&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;775039703&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A&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&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;mi&quot;&gt;195100&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;s2&quot;&gt;&amp;quot;2008-01-01 01:00:00&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;607527807&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;B&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;s2&quot;&gt;&amp;quot;2008-01-01 04:00:00&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;607532682&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;B&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;s2&quot;&gt;&amp;quot;2008-01-01 07:00:00&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;607535485&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;B&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;s2&quot;&gt;&amp;quot;2008-01-01 10:00:00&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;582924326&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;s2&quot;&gt;&amp;quot;2008-01-01 13:00:00&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;582927007&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;s2&quot;&gt;&amp;quot;2008-01-01 16:00:00&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;582929212&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;s2&quot;&gt;&amp;quot;2008-01-01 19:00:00&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;582932070&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;s2&quot;&gt;&amp;quot;2008-01-01 22:00:00&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;582935353&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;B&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;If you have clone our &lt;a href=&quot;https://github.com/wdavidw/hive-udf&quot;&gt;GitHub&lt;/a&gt; repository, you can run the above sample with the command &lt;code&gt;mvn install &amp;amp;&amp;amp; hive -f sample/to_map.hive&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;While writing this article, I also published a JIRA enhancement issue (&lt;a href=&quot;https://issues.apache.org/jira/browse/HIVE-2843&quot;&gt;HIVE-2843&lt;/a&gt;) proposing the integration of the source code into &lt;a href=&quot;http://hive.apache.org/&quot;&gt;Hive&lt;/a&gt;. I&amp;#8217;ll prepare the patch for its inclusion into Hive if the community express its interest.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Java versus JS fun, a quote from the Node.js mailing list</title>
    <link href="http://www.adaltas.com/blog/2012/02/23/nodejs-mailinglist-funny-quote/"/>
    <updated>2012-02-23T18:52:00+01:00</updated>
    <id>http://www.adaltas.com/blog/2012/02/23/nodejs-mailinglist-funny-quote</id>
    <content type="html">&lt;p&gt;I just read that one on the mailing list. I found it relevant enough to share it with those who did not subscribe to it:&lt;/p&gt;

&lt;p&gt;First Lothar Pfeiler:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;I still wonder, if it&amp;#8217;s cool to have such a big discussion on how to
convert a string into an integer, or if all the java developers laugh
at us.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Then dolphin278:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;They are busy with their spaceship-size configuration files, so we safe&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;A geek joke&amp;#8230; but I fully backup that statement as a good caricature of the Java versus JS situation.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>A fresh look at testing Node.js projects: Mocha, Should and Travis</title>
    <link href="http://www.adaltas.com/blog/2012/02/19/nodejs-test-mocha-should-travis/"/>
    <updated>2012-02-19T15:59:00+01:00</updated>
    <id>http://www.adaltas.com/blog/2012/02/19/nodejs-test-mocha-should-travis</id>
    <content type="html">&lt;p&gt;&lt;img class=&quot;right&quot; src=&quot;http://www.adaltas.com/images/blog/2012-02-18-nodejs-test-mocha-should-travis/logos.jpg&quot; title=&quot;Mocha, Should and Travis logos&quot; &gt;&lt;/p&gt;

&lt;p&gt;Today, I finally decided to spend some time around &lt;a href=&quot;http://about.travis-ci.org/&quot;&gt;Travis&lt;/a&gt;. It&amp;#8217;s been a weeks since that little green image on top of GitHub homepages has been buzzing me. Well, to be totally honest, this isn&amp;#8217;t how I started my evening. First, after 2 years of good and faithfull service, I decided to drop Expresso and give a chance to &lt;a href=&quot;http://visionmedia.github.com/mocha/&quot;&gt;Mocha&lt;/a&gt;. Because Expresso enriches the &lt;code&gt;assert&lt;/code&gt; module with one or two functions which I became addicted to, I also had to find the same functionalities into another assertion library which lead me to testing &lt;a href=&quot;https://github.com/visionmedia/should.js&quot;&gt;Should&lt;/a&gt;. It is very pleasant to see those two working together, as in the Unix tradition: small, powerful and naturally integrated.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;p&gt;Written by the same author than Expresso, &lt;a href=&quot;http://visionmedia.github.com/mocha/&quot;&gt;Mocha&lt;/a&gt; is meant to replace it. It&amp;#8217;s been the case since quite a while but I&amp;#8217;ve always been reluctant to jumping into BDD testing. BDD stands for Behavior Driven Development and is an alternative way to express your tests. For example, test names are expressed as a full sentence. Its goal is to encourage collaboration between developers, QA and non-technical or business participants in a software project. This is probably applicable in some workspaces but from a personal experience, it can&amp;#8217;t expect our clients to participate in test coverage. &lt;a href=&quot;http://cukes.info/&quot;&gt;Cucumber&lt;/a&gt; is probably the most popular BDD tool, it has its fans but I&amp;#8217;ve been too lazy in the past to jump into BDD. Facing any sample, It feels like learning a new language to write tests. Probably it was a wrong impression and it might be much easier than I think.&lt;/p&gt;

&lt;p&gt;Now let&amp;#8217;s have a look at &lt;a href=&quot;http://visionmedia.github.com/mocha/&quot;&gt;Mocha&lt;/a&gt;. the API is quite simple, mainly two functions which are &lt;code&gt;describe&lt;/code&gt; and &lt;code&gt;it&lt;/code&gt;. They both take a text as a first argument which combining together produce a sweet sentence during the run. An example:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;coffeescript&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nx&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;My test&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;should run synchronously&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;() -&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;c1&quot;&gt;# do sth&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;should run asynchronously&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;(next) -&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;c1&quot;&gt;# do sth&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;nx&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Notice how &lt;a href=&quot;http://visionmedia.github.com/mocha/&quot;&gt;Mocha&lt;/a&gt; discover and let yet decide whether you wish to run your tests synchronously or not, even mixing the two modes. Behind the hood, it&amp;#8217;s making use of the not so popular &lt;code&gt;length&lt;/code&gt; property attached to a function. There are few additionnal methods that come handy to modify settings and to setup and cleanup your tests. For illustration purpose, here is an example inspired from the &lt;a href=&quot;http://www.adaltas.com/projects/node-mecano&quot;&gt;mecano&lt;/a&gt; test suite:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;13&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;14&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;15&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;16&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;coffeescript&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nv&quot;&gt;should = &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;should&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nv&quot;&gt;mecano = &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;mecano&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nx&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;download&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;nx&quot;&gt;@beforeEach&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;(next) -&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;nx&quot;&gt;mecano&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;scratch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;next&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;nx&quot;&gt;@afterEach&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;(next) -&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;nx&quot;&gt;mecano&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;scratch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;next&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;should deal with ftp scheme&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;(next) -&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;nx&quot;&gt;@timeout&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10000&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;nx&quot;&gt;mecano&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;download&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;            &lt;span class=&quot;nv&quot;&gt;source: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;ftp://ftp.gnu.org/gnu/glibc/README.glibc&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;            &lt;span class=&quot;nv&quot;&gt;destination: &lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;#{scratch}/download_test&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;(err, downloaded) -&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;            &lt;span class=&quot;nx&quot;&gt;should&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;not&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;exist&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;            &lt;span class=&quot;nx&quot;&gt;downloaded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;should&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;eql&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;            &lt;span class=&quot;nx&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;The functions &lt;code&gt;beforeEach&lt;/code&gt; and &lt;code&gt;afterEach&lt;/code&gt; allow code execution before and after each test. The function &lt;code&gt;timeout&lt;/code&gt; modify the maximum execution time of a tests (by default 2 seconds).&lt;/p&gt;

&lt;p&gt;Here, let&amp;#8217;s introduce the usage of &lt;a href=&quot;https://github.com/visionmedia/should.js&quot;&gt;Should&lt;/a&gt;. Its purpose like any assertion library is to detect incorrect returned variable. At first, the BDD style API may look complicated but I found it natural and I didn&amp;#8217;t have to fight against it. Well, I said it all. This is essentially what I&amp;#8217;m expecting from such a library, not opening my browser to figure out how to use the API. After 10mn of usage, &lt;a href=&quot;https://github.com/visionmedia/should.js&quot;&gt;Should&lt;/a&gt; has proved to be easy, delivered its promises and enhance code readability (to my opinion).&lt;/p&gt;

&lt;p&gt;Finally, I decided to deal with this &lt;a href=&quot;http://about.travis-ci.org/&quot;&gt;Travis&lt;/a&gt; status. Getting the image popping up into the &lt;a href=&quot;https://www.github.com/wdavidw/node-mecano&quot;&gt;mecano GitHub page&lt;/a&gt; was easy. &lt;a href=&quot;http://about.travis-ci.org/&quot;&gt;Travis&lt;/a&gt; setup and GitHub integration for a newbie took less that 15 minutes. To make it green took a little longer. &lt;a href=&quot;http://www.adaltas.com/projects/node-mecano&quot;&gt;Mecano&lt;/a&gt; is making a few assumptions when running its test. It must be online, have GIT installed and be able to SSH itself. It turns out I was positively surprise on the first run, only 5 tests when not passing. Most of them were my fault and I fixed them. Another one was &lt;a href=&quot;https://github.com/visionmedia/should.js&quot;&gt;Should&lt;/a&gt; usage of JavaScript which was incompatible with the one used by &lt;a href=&quot;http://www.nodejs.org&quot;&gt;Node.js&lt;/a&gt; in version &amp;#8220;0.4&amp;#8221;. That left me with only one issue, setting up the Travis user account in such a way it can SSH itself without a password asked. In the end, my &amp;#8220;.travis.yml&amp;#8221; configuration file looks like:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;yaml&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;l-Scalar-Plain&quot;&gt;language&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;node_js&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;l-Scalar-Plain&quot;&gt;node_js&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;p-Indicator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;0.6&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;p-Indicator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;0.7&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;l-Scalar-Plain&quot;&gt;before_script&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;p-Indicator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;ssh-keygen&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-t&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;rsa&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-f&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;~/.ssh/id_rsa&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-N&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&amp;#39;&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;p-Indicator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;cat&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;~/.ssh/id_rsa.pub&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;~/.ssh/authorized_keys&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;During this presentation, I did not provide any instruction related to installation and configuration because each project is very well documented. Thanks to the author of those tools for their appreciable work.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Coffee script, how do I debug that damn js line?</title>
    <link href="http://www.adaltas.com/blog/2012/02/15/coffeescript-print-debug-line/"/>
    <updated>2012-02-15T01:20:00+01:00</updated>
    <id>http://www.adaltas.com/blog/2012/02/15/coffeescript-print-debug-line</id>
    <content type="html">&lt;p&gt;Update April 12th, 2012: &lt;a href=&quot;https://github.com/jashkenas/coffee-script/pull/2050&quot;&gt;Pull request adding error reporting to CoffeeScript with line mapping&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Chances are that, if you code in &lt;a href=&quot;http://coffeescript.org/&quot;&gt;CoffeeScript&lt;/a&gt;, you often find yourself facing a JavaScript exception telling you a problem occured on a specific line. Problem is that the line number in question in the one of the generated JavaScript, not your in &lt;a href=&quot;http://coffeescript.org/&quot;&gt;CoffeeScript&lt;/a&gt; line number. Even worse, if you generate your JavaScript transparently, you wont have any JavaScript file to look into and the all process of finding where this error occored is even more frustrating.&lt;/p&gt;

&lt;p&gt;Well, it seems like the future version of JavaScript could come to the rescue, but not before a few months. In the mean time, here&amp;#8217;s a little of fun about writing a small Bash script that may save you some time.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;p&gt;We&amp;#8217;ll call our script &lt;code&gt;coffeep&lt;/code&gt;, an enhance version of &lt;code&gt;coffee -p&lt;/code&gt; and it&amp;#8217;s purpose is to print to the console the JavaScript code translated from your coffee file with line numbered. To make it even more useful, the script may take one or two additional arguments after the coffee file path to limit the printed lines to only the section which you wish to debug.&lt;/p&gt;

&lt;p&gt;For example, &lt;code&gt;coffeep myfile.coffee&lt;/code&gt; will output the generated JavaScript like &lt;code&gt;coffee -p myfile.coffee&lt;/code&gt; would do, but with each line prefixed by its line number. Calling &lt;code&gt;coffeep myfile.coffee 20&lt;/code&gt; will print the line 20 as well as the 5 preceding lines and the 5 following lines. Calling &lt;code&gt;coffeep myfile.coffee 20 30&lt;/code&gt; will print the line 20 to 30.&lt;/p&gt;

&lt;p&gt;This is certainly not rocket science but shall become part of your coffee swiss army knife. Leveraging &lt;code&gt;cat -n&lt;/code&gt; which given some content passed through stdin prefix each line with its line number starting at 1, our first version of coffeep looks like:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;bash&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;coffee -p &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt; | cat -n
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;If you are not familiar with bash scripting, &lt;code&gt;$1&lt;/code&gt; stands for the first argument passed to &lt;code&gt;coffeep&lt;/code&gt;, which in our case is our coffee file.&lt;/p&gt;

&lt;p&gt;Now we&amp;#8217;ll add two possible usages. If one argument is provided after the path, it is expected to be the JavaScript line number you wish to debug and we&amp;#8217;ll output the preceding and following 5 lines. If two arguments are provided after the path, there are expected to be the first line and the last line to output.&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;13&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;bash&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$# &lt;/span&gt;-eq 1 &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;    &lt;/span&gt;coffee -p &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt; | cat -n
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$# &lt;/span&gt;-eq 2 &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;head_count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;nv&quot;&gt;tail_count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;11
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    coffee -p &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt; | cat -n | head -&lt;span class=&quot;nv&quot;&gt;$head_count&lt;/span&gt; | tail -&lt;span class=&quot;nv&quot;&gt;$tail_count&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$# &lt;/span&gt;-eq 3 &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;head_count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$3&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;nv&quot;&gt;tail_count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$3&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    coffee -p &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt; | cat -n | head -&lt;span class=&quot;nv&quot;&gt;$head_count&lt;/span&gt; | tail -&lt;span class=&quot;nv&quot;&gt;$tail_count&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;With some little arithmetic, we make use of &lt;code&gt;head&lt;/code&gt; and &lt;code&gt;tail&lt;/code&gt; to first limit the output to &lt;code&gt;head_count&lt;/code&gt; first lines with &lt;code&gt;head&lt;/code&gt;, and finally limit the output to &lt;code&gt;tail_count&lt;/code&gt; last lines with &lt;code&gt;tail&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Finally, for convenience, just copy/paste the following code into your terminal and it shall create an executable file named &amp;#8220;coffeep&amp;#8221; in &amp;#8220;/usr/local/bin&amp;#8221; (accessible from your &lt;code&gt;$PATH&lt;/code&gt;, make sure to have the permission to modify this directory):&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;13&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;14&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;15&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;16&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;bash&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;cat &amp;gt; /usr/local/bin/coffeep &lt;span class=&quot;s&quot;&gt;&amp;lt;&amp;lt;DELIM&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;s&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;s&quot;&gt;if [ $# -eq 1 ]&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;s&quot;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;s&quot;&gt;    coffee -p $1 | cat -n&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;s&quot;&gt;elif [ $# -eq 2 ]; then&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;s&quot;&gt;    head_count=$(($2+5))&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;s&quot;&gt;    tail_count=11&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;s&quot;&gt;    coffee -p $1 | cat -n | head -$head_count | tail -$tail_count&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;s&quot;&gt;elif [ $# -eq 3 ]; then&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;s&quot;&gt;    head_count=$(($2+$3))&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;s&quot;&gt;    tail_count=$3&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;s&quot;&gt;    coffee -p $1 | cat -n | head -$head_count | tail -$tail_count&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;s&quot;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;s&quot;&gt;DELIM&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;chmod +x /usr/local/bin/coffeep
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;



</content>
  </entry>
  
  <entry>
    <title>Announcing Mecano, a set of functions for system deployment</title>
    <link href="http://www.adaltas.com/blog/2012/02/12/node-mecano-utils-system-deployment/"/>
    <updated>2012-02-12T22:40:00+01:00</updated>
    <id>http://www.adaltas.com/blog/2012/02/12/node-mecano-utils-system-deployment</id>
    <content type="html">&lt;p&gt;We are releasing &lt;a href=&quot;http://www.adaltas.com/projects/node-mecano/&quot;&gt;Node Mecano&lt;/a&gt; on &lt;a href=&quot;http://www.github.com/wdavidw/node-mecano&quot;&gt;GitHub&lt;/a&gt; which gather common functions used while deploying systems. The idea was to group those functions into a comprehensive library.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;p&gt;The code started when we wrote &lt;a href=&quot;http://www.github.com/wdavidw/heco&quot;&gt;Heco&lt;/a&gt; as well as when we deployed a Hadoop cluster for one of our customer. It found inspiration in the &lt;a href=&quot;http://wiki.opscode.com/display/chef/Resources&quot;&gt;Chef Resource API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The functionalities are sill limited and there are obviously many potential improvements but we wanted to release the code early. We found it already very usefully and the API should be stable enough to integrate it into your own project.&lt;/p&gt;

&lt;p&gt;The functions covered by Mecano are &lt;code&gt;copy&lt;/code&gt;, &lt;code&gt;download&lt;/code&gt;, &lt;code&gt;execute&lt;/code&gt;, &lt;code&gt;extract&lt;/code&gt;, &lt;code&gt;git&lt;/code&gt;, &lt;code&gt;ln&lt;/code&gt;, &lt;code&gt;mkdir&lt;/code&gt;, &lt;code&gt;remove&lt;/code&gt; and &lt;code&gt;render&lt;/code&gt;. Their API is always the same. The first argument defines one or more command to run (an object or an array of objects) and the second one is a callback called on completion which tell you how many common where really run. For example, to copy 2 files, the code will look like:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;javascript&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nx&quot;&gt;mecano&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;mecano&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nx&quot;&gt;mecano&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;file_1&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;destination&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;dest_1&amp;#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;file_2&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;destination&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;dest_2&amp;#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&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;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;copied&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Number of file copied: &amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;copied&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Calling the same command a second time and the value of &lt;code&gt;copied&lt;/code&gt; will be &amp;#8220;0&amp;#8221; because no new file was copied.&lt;/p&gt;

&lt;p&gt;The command share a set of common properties to conditionally  run the command and validate its result. For example, the following command will only run if a specified file exists and will emit an error if the exit code isn&amp;#8217;t the one provided.&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;javascript&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nx&quot;&gt;mecano&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;mecano&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nx&quot;&gt;mecano&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;nx&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;whoami&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;nx&quot;&gt;if_exists&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;/home/itsme&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;nx&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// default exit code&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&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;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;executed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Did the command run &amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;executed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;yes&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;no&amp;#39;&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&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Hope you&amp;#8217;ll find it useful as well and don&amp;#8217;t hesitate to provide us with feedback.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>OS module on steroids with the SIGAR Node binding</title>
    <link href="http://www.adaltas.com/blog/2012/01/11/node-sigar-announcement/"/>
    <updated>2012-01-11T22:40:00+01:00</updated>
    <id>http://www.adaltas.com/blog/2012/01/11/node-sigar-announcement</id>
    <content type="html">&lt;p&gt;Today we are announcing the first release of the Node binding to the &lt;a href=&quot;http://www.hyperic.com/products/sigar&quot;&gt;SIGAR&lt;/a&gt; library. Visit the &lt;a href=&quot;http://www.adaltas.com/projects/node-sigar&quot;&gt;project website&lt;/a&gt; or the &lt;a href=&quot;https://github.com/wdavidw/node-sigar&quot;&gt;source code&lt;/a&gt; repository on &lt;a href=&quot;http://www.github.com&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;SIGAR is a cross platform interface for gathering system information. From the project website, such information include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;System memory, swap, cpu, load average, uptime, logins&lt;/li&gt;
&lt;li&gt;Per-process memory, cpu, credential info, state, arguments, environment, open files&lt;/li&gt;
&lt;li&gt;File system detection and metrics&lt;/li&gt;
&lt;li&gt;Network interface detection, configuration info and metrics&lt;/li&gt;
&lt;li&gt;TCP and UDP connection tables&lt;/li&gt;
&lt;li&gt;Network route table&lt;/li&gt;
&lt;/ul&gt;


&lt;!&#8211;more&#8211;&gt;


&lt;p&gt;Please consult the &lt;a href=&quot;http://support.hyperic.com/display/SIGAR/Home&quot;&gt;SIGAR documentation&lt;/a&gt; for a complete list of supported operating systems, architectures and versions.&lt;/p&gt;

&lt;p&gt;The current version is a complete binding of the SIGAR API. There are still however a few minor issues left due to our lack of C++ skills and SIGAR understanding. Please give us some help if you are a knowledgeable Node C++ binder or an experienced SIGAR user.&lt;/p&gt;

&lt;p&gt;Here is an example returning CPU information:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;js&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sigar&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;sigar&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cpus&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sigar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cpuList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cpus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cpus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Visit the &lt;a href=&quot;http://www.adaltas.com/projects/node-sigar&quot;&gt;Node SIGAR&lt;/a&gt; website for a complete view of the API.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Timeseries storage in Hadoop and Hive</title>
    <link href="http://www.adaltas.com/blog/2012/01/10/timeseries-hadoop-hive/"/>
    <updated>2012-01-10T12:23:00+01:00</updated>
    <id>http://www.adaltas.com/blog/2012/01/10/timeseries-hadoop-hive</id>
    <content type="html">&lt;p&gt;In the next few weeks, we will be exploring the storage and analytic of a large generated dataset. This dataset is composed of CRM tables associated to one timeserie table of about 7,000 billiard rows.&lt;/p&gt;

&lt;p&gt;Before importing the dataset into Hive, we will be exploring different optimization options expected to impact speed and storage size.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;p&gt;Note, the following advantage and disadvantage of each optimization reflect our current understanding of Hadoop and Hive.&lt;/p&gt;

&lt;h2&gt;Hive partitioning&lt;/h2&gt;

&lt;p&gt;The distribution of the data files in HDFS under hierarchical directories.&lt;/p&gt;

&lt;p&gt;Advantage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;With partition pruning, some queries may only need to read a subset of the files&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Disadvantage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiply the number of files managed by the namenode&lt;/li&gt;
&lt;li&gt;A query may work against the partition thus requiring to traverse more files. For example a query which aggregates the data of a single customer over a year would be less efficient under a table partitioned by day.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Block size&lt;/h2&gt;

&lt;p&gt;Each file in HDFS is split under different chunks of fixed size to be distributed across the Hadoop cluster. This block size is by default set to 64M but could be increased to 126M or more.&lt;/p&gt;

&lt;p&gt;Advantage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Less work between M/R tasks&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Disadvantage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Decrease the potential load repartition with smaller files (think Hive partitioning)&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Hive index&lt;/h2&gt;

&lt;p&gt;Maintain an index against a Hive table&lt;/p&gt;

&lt;p&gt;Advantage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Work on any columns with impacting the HDFS layout&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Disadvantage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Still slower than a natural file storing layout (think sorted Clustering)&lt;/li&gt;
&lt;li&gt;Duplication of index for each Hive partition (might not be a problem)&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Clustering&lt;/h2&gt;

&lt;p&gt;Dispatch data into a defined number of buckets (HDFS files) using a hash key on one or more columns and order the data.&lt;/p&gt;

&lt;p&gt;Advantage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sampling&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Advantages not yet implemented:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bucket pruning when filtering on the bucket column&lt;/li&gt;
&lt;li&gt;Take advantage of the sorted schema&lt;/li&gt;
&lt;li&gt;Join optimization between two tables using the same column hash&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Disadvantage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiply the number of files managed by the namenode.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Native file formats&lt;/h2&gt;

&lt;p&gt;Text versus binary and row versus column layout. Hive offers &lt;code&gt;TEXTFILE&lt;/code&gt;, &lt;code&gt;SEQUENCEFILE&lt;/code&gt; and &lt;code&gt;RCFILE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Advantage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;RCFILE&lt;/code&gt; may benefit better file size and increase speed on joins&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SEQUENCEFILE&lt;/code&gt; shall better handle map phase referencing multiple columns&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Hive format&lt;/h2&gt;

&lt;p&gt;Best usage of Hive data type and experiment Hive data structure in the context of timeseries. For example, instead of storing one measure per row, we could store all the measure of a single customer in a Hive structure type of 144 elements for each day (one data every 10mn).&lt;/p&gt;

&lt;p&gt;Advantage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Drastically reduce the storage size (while increasing speed)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Disadvantage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Increase queries complexity&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Custom file formats&lt;/h2&gt;

&lt;p&gt;Leverage Hive SerDe to implement a custom layout. This is similar to the solution described above but pushed one step further.&lt;/p&gt;

&lt;h2&gt;Compression&lt;/h2&gt;

&lt;p&gt;Find the right equilibrium between IO and CPU usage by testing the various Codecs.&lt;/p&gt;

&lt;h2&gt;MR framework&lt;/h2&gt;

&lt;p&gt;Text various map and reduce tuning properties.&lt;/p&gt;

&lt;h2&gt;Preparation&lt;/h2&gt;

&lt;p&gt;Before we start we need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a consequent cluster (around 20 nodes)&lt;/li&gt;
&lt;li&gt;a simplified data schema&lt;/li&gt;
&lt;li&gt;a medium sized data sets (around 1To)&lt;/li&gt;
&lt;li&gt;a few representative queries&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Cluster&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Number of servers: 19 (waiting for 2 more)&lt;/li&gt;
&lt;li&gt;Number of cpus: 320 logical thread&lt;/li&gt;
&lt;li&gt;Number of disk: 124 * 1Go SATA 7200rpm&lt;/li&gt;
&lt;li&gt;Number of rack: 2&lt;/li&gt;
&lt;li&gt;Hadoop version: Cloudera 0.20.2-cdh3u2&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Data schema&lt;/h3&gt;

&lt;p&gt;The original Hive database schema is:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;13&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;14&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;15&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;16&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;17&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;18&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;19&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;20&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;21&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;22&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;23&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;24&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;25&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;26&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;27&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;28&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;29&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;30&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;31&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;32&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;sql&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DATABASE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timeseries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;USE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timeseries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;&#8211; Cities table&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cities&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;id_city&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;BIGINT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;fk_region&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;INT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;zipcode&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;INT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;STRING&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;STORED&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SEQUENCEFILE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;&#8211; Client table&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;id_client&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;BIGINT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;fk_city&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;INT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;lastname&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;STRING&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;STORED&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SEQUENCEFILE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;&#8211; Metering table&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;metering&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;fk_client&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;BIGINT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;date_emission&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;INT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;date_reception&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;INT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;STRING&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;k&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;INT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;diff&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;INT&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;PARTITIONED&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;date_emission_day&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;STRING&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;CLUSTERED&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fk_client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SORTED&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;date_emission&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;INTO&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BUCKETS&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;STORED&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SEQUENCEFILE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;



</content>
  </entry>
  
  <entry>
    <title>How Node CSV parser may save your weekend</title>
    <link href="http://www.adaltas.com/blog/2011/12/13/save-weekend-node-csv-parser/"/>
    <updated>2011-12-13T21:50:00+01:00</updated>
    <id>http://www.adaltas.com/blog/2011/12/13/save-weekend-node-csv-parser</id>
    <content type="html">&lt;p&gt;Last Friday, an hour before the doors of my customer close for the weekend, a co-worker came to me. He just finished to export 9 CSV files from &lt;a href=&quot;http://www.oracle.com&quot;&gt;Oracle&lt;/a&gt; which he wanted to import into &lt;a href=&quot;http://www.greenplum.com&quot;&gt;Greenplum&lt;/a&gt; such as our customer could start testing on Monday morning.&lt;/p&gt;

&lt;p&gt;The problem as exposed was quite simple. He needed a quick solution (less than an hour, coding included) to transform all the date in the source CSV file into a format suitable for &lt;a href=&quot;http://www.greenplum.com&quot;&gt;Greenplum&lt;/a&gt;. While &lt;a href=&quot;http://www.oracle.com&quot;&gt;Oracle&lt;/a&gt; exported dates in the form of &amp;#8216;DD/MM/YYYY&amp;#8217;, &lt;a href=&quot;http://www.greenplum.com&quot;&gt;Greenplum&lt;/a&gt; was picky enough to expect dates in the form of &amp;#8216;YYYY-MM-DD&amp;#8217;.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;p&gt;Here are the files we needed to import:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;bash&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;-rw-r&#8211;r&#8211; 1 ingres ingres  41G 2011-12-09 18:23 a.csv
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;-rw-r&#8211;r&#8211; 1 ingres ingres 418M 2011-12-09 17:22 b.csv
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;-rw-r&#8211;r&#8211; 1 ingres ingres  45G 2011-12-09 18:26 c.csv
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;-rw-r&#8211;r&#8211; 1 ingres ingres 1,8G 2011-12-09 17:37 d.csv
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;-rw-r&#8211;r&#8211; 1 ingres ingres 896M 2011-12-09 17:33 e.csv
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;-rw-r&#8211;r&#8211; 1 ingres ingres 382M 2011-12-09 17:13 f.csv
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;-rw-r&#8211;r&#8211; 1 ingres ingres 7,6G 2011-12-09 18:09 g.csv
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;-rw-r&#8211;r&#8211; 1 ingres ingres 621M 2011-12-09 17:33 h.csv
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;-rw-r&#8211;r&#8211; 1 ingres ingres 3,1G 2011-12-09 17:46 i.csv
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Among those files, two are larger than 45Gb.&lt;/p&gt;

&lt;p&gt;Since generating new files would probably have taken too long, the first question asked was whether  or not the &lt;a href=&quot;http://www.greenplum.com&quot;&gt;Greenplum&lt;/a&gt; import command would accept &lt;code&gt;stdin&lt;/code&gt; data through unix pipe, which question luckily answered to yes. So my first suggestion was to cat a file, pipe it to &lt;a href=&quot;http://www.gnu.org/s/gawk/manual/gawk.html&quot;&gt;Awk&lt;/a&gt; which would reformat the date line by line and finally pipe it to the import tool. The command would look like:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;bash&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;cat a.csv | awk &lt;span class=&quot;s1&quot;&gt;&amp;#39;&#8230;&amp;#39;&lt;/span&gt; | psql -p &lt;span class=&quot;nv&quot;&gt;$port&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$database&lt;/span&gt; -c &lt;span class=&quot;s2&quot;&gt;&amp;quot;COPY $table FROM STDIN WITH CSV;&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;The solution seems workable. Problem, we are no &lt;a href=&quot;http://www.gnu.org/s/gawk/manual/gawk.html&quot;&gt;Awk&lt;/a&gt; expert and I could not guaranty him an hour would be enough to write and test the command.&lt;/p&gt;

&lt;p&gt;Considering how familiar I am with &lt;a href=&quot;http://www.nodejs.org&quot;&gt;Node&lt;/a&gt; those days, I told him that writing a small JavaScript script which interact with &lt;code&gt;stdin&lt;/code&gt; and &lt;code&gt;stdout&lt;/code&gt; would be much more secure. This is when we though of using the &lt;a href=&quot;https://github.com/wdavidw/node-csv-parser&quot;&gt;CSV parser&lt;/a&gt;, the first library I wrote for &lt;a href=&quot;http://www.nodejs.org&quot;&gt;Node&lt;/a&gt; a little more than a year ago.&lt;/p&gt;

&lt;p&gt;We first had to configure the proxy and install &lt;a href=&quot;http://www.nodejs.org&quot;&gt;Node&lt;/a&gt; on this server which took about 10mn. For this we used &lt;a href=&quot;https://github.com/creationix/nvm&quot;&gt;NVM&lt;/a&gt;. Then, we wrote the following JavaScript:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;13&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;14&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;15&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;16&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;javascript&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/usr/bin/env node&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;csv&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;./csv&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nx&quot;&gt;csv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fromStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;stdin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/(\d{2})\/(\d{2})\/(\d{2})/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])){&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;            &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/(\d{2})\/(\d{2})\/(\d{2})/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;20$3-$2-$1&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;stdin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resume&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Note how the usage of the regular expression could have been optimized. But our goal wasn&amp;#8217;t to speed the import process, only to make it run as soon as possible.&lt;/p&gt;

&lt;p&gt;We alread had at our disposal a small bash script which could loop trough the CSV files and launch the &lt;a href=&quot;http://www.greenplum.com&quot;&gt;Greenplum&lt;/a&gt; import command. We tweak it a bit such as the final version looked like:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;bash&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;csv in &lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;ls ~/export/*.csv&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$csv&lt;/span&gt;|cut -d&lt;span class=&quot;s1&quot;&gt;&amp;#39;/&amp;#39;&lt;/span&gt; -f 5&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;nv&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$table&lt;/span&gt;|cut -d&lt;span class=&quot;s1&quot;&gt;&amp;#39;.&amp;#39;&lt;/span&gt; -f 1&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;nv&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$table&lt;/span&gt;| sed &lt;span class=&quot;s1&quot;&gt;&amp;#39;s/\(.*\)../\1/&amp;#39;&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        cat &lt;span class=&quot;nv&quot;&gt;$csv&lt;/span&gt; | transform.js | psql -p 5433 my_database -c &lt;span class=&quot;s2&quot;&gt;&amp;quot;COPY $table FROM STDIN WITH CSV;&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Well, on Monday morning, the &lt;a href=&quot;https://github.com/wdavidw/node-csv-parser&quot;&gt;CSV parser&lt;/a&gt; handled the volume and all the CSV files were ingested by &lt;a href=&quot;http://www.greenplum.com&quot;&gt;Greenplum&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Node intégré à la plateforme cloud Microsoft Azure</title>
    <link href="http://www.adaltas.com/blog/2011/12/10/nodejs-microsoft-azure/"/>
    <updated>2011-12-10T17:50:00+01:00</updated>
    <id>http://www.adaltas.com/blog/2011/12/10/nodejs-microsoft-azure</id>
    <content type="html">&lt;p&gt;&lt;img class=&quot;right&quot; src=&quot;http://www.adaltas.com/images/blog/2011-12-11-nodejs-microsoft-azure/langages.png&quot; title=&quot;Langages disponibles sur Azure&quot; &gt;
&lt;a href=&quot;&quot;&gt;Node&lt;/a&gt; est désormais un citoyen de premier ordre dans l&amp;#8217;environnement  cloud de &lt;a href=&quot;&quot;&gt;Microsoft Azure&lt;/a&gt; au côté de &lt;a href=&quot;http://www.microsoft.com/net&quot;&gt;.Net&lt;/a&gt;, &lt;a href=&quot;http://www.java.com/fr/&quot;&gt;Java&lt;/a&gt; et &lt;a href=&quot;http://php.net/&quot;&gt;PHP&lt;/a&gt;. Cette intégration est la conséquence logique de l&amp;#8217;implication de Microsoft dans le développement de Node il y a maintenant un an. A l&amp;#8217;origine seulement disponible sur les plateformes de type Unix (Linux, OSX, …), la version 5 de Node fut principalement consacré au portage sur Windows sans impacter les performances de la version Unix.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;p&gt;Force est de constater que les performances ne se sont effectivement pas dégradées. A titre indicatif, notre générateur de séries temporelles développé pour EDF a doublé ses performance entre la version 0.4.11 et la version 0.6.1, essentiellement grâce à la monté en version du moteur &lt;a href=&quot;http://code.google.com/p/v8/&quot;&gt;Google V8&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Mais revenons à Microsoft. Il s&amp;#8217;agit d&amp;#8217;une nouvelle capitale. Personnellement, je ne suis pas intéressé par la possibilité de coder sur Windows, plateforme que je fuis comme la peste depuis une bonne douzaine d&amp;#8217;années. Mais de nombreux programmeurs le sont. Il ne faut pas négliger l&amp;#8217;importance de ceux-ci qui sont par légion. Certains sont Microsoft par amour, d&amp;#8217;autre se sont fait imposer cette plateforme par leur entreprise. Outre les développeurs professionnels, il y a aussi une large quantité de hacker du dimanche qui bidouille avec plaisir leurs sites Internet, maniant avec plus ou moins de brio HTML, CSS et &amp;#8230; Javascript après avoir téléchargé une version de WordPress, Drupal ou PrestaShop. Passé dans le côté obscure de la force était pour eux synonimes d&amp;#8217;apprendre un nouveau langage, le plus souvent PHP. On peut sans risque anticiper que certains de ceux là auront plus de facilité à manipuler le Javascript déjà présent dans le chapeau des technologies du Web. De plus comparativement à &lt;a href=&quot;http://en.wikipedia.org/wiki/WAMP&quot;&gt;WAMP&lt;/a&gt;, l&amp;#8217;environnement Node est bien plus simple à installer. Pas de serveur web à paramétrer et, avec NPM, un gestionnaire de modules ultra simple.&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;center&quot; src=&quot;http://www.adaltas.com/images/blog/2011-12-11-nodejs-microsoft-azure/azure.png&quot; title=&quot;[width] [height] Microsoft Azure&quot; &gt;&lt;/p&gt;

&lt;p&gt;La présence de Node au côté de .Net, Java et PHP est flatteuse. Pensez-y, Node n&amp;#8217;a que 2 ans, c&amp;#8217;est déjà un grand bébé. Autour de lui, le sénior du Web qu&amp;#8217;est PHP, celui du monde de l&amp;#8217;entreprise qu&amp;#8217;est Java et l&amp;#8217;enfant du boss qu&amp;#8217;est .Net façonné à partir du Java. Rien des autres, les Python, Ruby, Erlang, Go, Perl, … Cette présence est aussi synonyme des 3 choses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node est une plateforme mature. Son moteur &lt;a href=&quot;http://code.google.com/p/v8/&quot;&gt;Google V8&lt;/a&gt; est la fondation du navigateur du même nom. Il est installé par 200 millions d&amp;#8217;utilisateurs, ce qui en fait le second navigateur en terme de popularité après Microsoft Explorer.&lt;/li&gt;
&lt;li&gt;Node possède un large écosystème. La popularité de Node ces derniers mois ne s&amp;#8217;est pas uniquement traduit sur GitHub, en devenant de deuxième projet le plus populaire sur GitHub devant Ruby on Rails, mais aussi par un large choix de modules.&lt;/li&gt;
&lt;li&gt;Node est promit à un brillant avenir tant dans la communauté Web que dans le monde de l&amp;#8217;entreprise.&lt;/li&gt;
&lt;/ul&gt;

</content>
  </entry>
  
  <entry>
    <title>Chef : configuration et deploiement automatisé de Clusters</title>
    <link href="http://www.adaltas.com/blog/2010/12/10/deploiement-serveur-chef/"/>
    <updated>2010-12-10T17:50:00+01:00</updated>
    <id>http://www.adaltas.com/blog/2010/12/10/deploiement-serveur-chef</id>
    <content type="html">&lt;p&gt;L&amp;#8217;installation d&amp;#8217;un cluster de plusieurs machines est consommateur de temps. La même procédure de mise en place des logiciels et de leurs paramétrages doit être répétées à l&amp;#8217;identique. Au cours du temps, des mises à jours doivent être appliquées, certains logiciels doivent être supprimés quand d&amp;#8217;autres sont ajoutés et au final, les systèmes divergent les uns des autres.&lt;/p&gt;

&lt;p&gt;Pour répondre à ces problèmes, des logiciels gestion de configuration automatisent ces opérations. Un serveur s&amp;#8217;installe et se paramètre en une seule commande en fonction des rôles qu&amp;#8217;on souhaite lui alloué.&lt;/p&gt;

&lt;p&gt;Finalement, avec Chef, la mise en place d&amp;#8217;un système ce limite à 2 procédures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Installer un système de base sans logiciels préinstallé, juste ssh&lt;/li&gt;
&lt;li&gt;Lancer une commande indiquant l&amp;#8217;adresse du serveur et ses rôles (par exemple &amp;#8220;server, lamp&amp;#8221;)&lt;/li&gt;
&lt;/ul&gt;


&lt;!&#8211;more&#8211;&gt;


&lt;p&gt;Deux outils Open Source se chamaillent le leadership sur ce secteur, Puppet et Chef. Le débat entre chacun est houleux, tous les deux étant finalement de qualité comparable et dotés d&amp;#8217;un large éventail de configurations préétablies couvrant l&amp;#8217;ensemble des besoins d&amp;#8217;administration. Chef nous a paru légèrement plus flexible (paramétrage en Ruby au lieu d&amp;#8217;un langage sur-mesure).&lt;/p&gt;

&lt;p&gt;Parmi les fonctionnalités de Chef (et Puppet) :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Synchronisation automatique des nœuds avec l&amp;#8217;état de la configuration&lt;/li&gt;
&lt;li&gt;Support de plusieurs OS (spécialement Puppet)&lt;/li&gt;
&lt;li&gt;Nombreuses configurations disponibles&lt;/li&gt;
&lt;li&gt;Large communauté&lt;/li&gt;
&lt;li&gt;Interface web agréable&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Livres de recettes (Cookbooks)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://cookbooks.opscode.com/&quot;&gt;Recette publiées par la communauté&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://github.com/opscode/cookbooks&quot;&gt;Recettes crées par Opscode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://github.com/37signals/37s_cookbooks&quot;&gt;Dépôt maintenu par 37 Signals&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://github.com/engineyard/ey-cloud-recipes&quot;&gt;Dépôt maintenu par Engine Yard Cloud&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Des cookbooks relatifs à Hadoop sont présents aux endroits suivants:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/opscode/cookbooks/tree/master/hadoop/&quot;&gt;Opscode&lt;/a&gt;&lt;/strong&gt;&lt;br/&gt;
&lt;code&gt;hadoop::default&lt;/code&gt; : Installe le fichier apt du dépôt Cloudera et le paquet Hadoop&lt;br/&gt;
&lt;code&gt;hadoop::conf_pseudo&lt;/code&gt; : démarre les services Hadoop&lt;br/&gt;
&lt;code&gt;hadoop::doc&lt;/code&gt; : Installe le packet hadoop-doc&lt;br/&gt;
&lt;code&gt;hadoop::hive&lt;/code&gt; : Installe le packet hive&lt;br/&gt;
&lt;code&gt;hadoop::pig&lt;/code&gt; : Installe le packet pig&lt;br/&gt;
Conclusion, des fonctionnalités très limitées qui ne s&amp;#8217;appliquent pas à l&amp;#8217;installation complète d&amp;#8217;un cluster Hadoop.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/rberger/Runa-Public-Chef-Cookbooks.git&quot;&gt;Runa&lt;/a&gt;&lt;/strong&gt;&lt;br/&gt;
&lt;code&gt;hadoop_for_hbase::default&lt;/code&gt; : Télécharge hadoop sur depuis le site du créateur (version configurable)&lt;br/&gt;
Conclusion: Aucune garantie sur la source, peut de choix sur les version, limite a hadoop et hbase.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/infochimps/cluster_chef&quot;&gt;Infochimps Cluster Chef&lt;/a&gt;&lt;/strong&gt;&lt;br/&gt;
&lt;code&gt;hadoop_cluster::default&lt;/code&gt; : Enregistre la source apt du dépôt Cloudera, crée un groupe et un utilisateur Unix &lt;code&gt;hadoop&lt;/code&gt;, crée un supergroup Hadoop &lt;code&gt;supergroup&lt;/code&gt;&lt;br/&gt;
Conclusion, sans doute le meilleur point de départ sur lequel s&amp;#8217;appuiyer pour créer ses propres recettes.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Ressources externes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://wiki.opscode.com/display/chef/Home&quot;&gt;Chef Wiki&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.opscode.com/blog&quot;&gt;Blog d&amp;#8217;Opscode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://opscode.blip.tv/file/3757436/&quot;&gt;Video d&amp;#8217;introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://wiki.opscode.com/display/chef/Package+Installation+on+Debian+and+Ubuntu&quot;&gt;Installation via package manager&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://wiki.opscode.com/display/chef/Bootstrap+Chef+RubyGems+Installation&quot;&gt;Installation via gem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.themomorohoax.com/2010/07/31/ruby-chef-tutorial&quot;&gt;Tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.puppetlabs.com/puppet-3/introduction/&quot;&gt;Puppet&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
  </entry>
  
  <entry>
    <title>Installation sous OSX en mode pseudo-distribué</title>
    <link href="http://www.adaltas.com/blog/2010/12/01/installation-manuelle-hadoop-osx/"/>
    <updated>2010-12-01T19:58:00+01:00</updated>
    <id>http://www.adaltas.com/blog/2010/12/01/installation-manuelle-hadoop-osx</id>
    <content type="html">&lt;p&gt;Le système d&amp;#8217;exploitation choisi est OSX mais la procédure n&amp;#8217;est pas si différente pour tout environnement Unix car l&amp;#8217;essentiel des logiciels sont téléchargés depuis Internet, décompressés et paramétrés manuellement. Seuls quelques paquets sont installés par Macport mais ceux-ci sont aisément trouvables sur des outils équivalents comme Apt et Yum. Etant donné que les logiciels téléchargés sont en Java, il ne devrait pas y avoir de soucis quand à leur fonctionnement dans d&amp;#8217;autres environnements.&lt;/p&gt;

&lt;p&gt;Cette environnement est configuré en mode pseudo-distribué afin de simuler au mieux le comportement d&amp;#8217;un cluster si un poste unique. Dans ce mode, chaque processus Java tourne dans sa propre JVM.&lt;/p&gt;

&lt;p&gt;La procédure couvre l&amp;#8217;installation des logiciels suivant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://hadoop.apache.org/&quot;&gt;Hadoop&lt;/a&gt; (&lt;a href=&quot;http://hadoop.apache.org/common/&quot;&gt;common&lt;/a&gt;, &lt;a href=&quot;http://hadoop.apache.org/hdfs/&quot;&gt;hdfs&lt;/a&gt;, &lt;a href=&quot;http://hadoop.apache.org/mapreduce/&quot;&gt;mapreduce&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://pig.apache.org/&quot;&gt;Pig&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://hbase.apache.org/&quot;&gt;HBase&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://incubator.apache.org/projects/sqoop.html&quot;&gt;Sqoop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://cwiki.apache.org/FLUME&quot;&gt;Flume&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://cloudera.github.com/hue/&quot;&gt;Hue&lt;/a&gt; (Cloudera Desktop)&lt;/li&gt;
&lt;/ul&gt;


&lt;!&#8211;more&#8211;&gt;


&lt;h2&gt;Choix des versions&lt;/h2&gt;

&lt;p&gt;L&amp;#8217;installation des logiciels depuis les dépôts SVN s&amp;#8217;est confrontée à un problème d&amp;#8217;incompatibilité entre Hive qui requière la dernière version stable de Hadoop (2.20.2) et celle de Sqoop qui requière la version SVN de Hadoop. Pour cette raison, nous avons opté pour les versions distribuées par Cloudera. Basées sur des versions stables, elles incluent un grand nombre des patches présents dans les dépôts SVN et sont testés par certains des meilleurs experts de la communauté.&lt;/p&gt;

&lt;p&gt;Toutefois, certaines fonctionnalités ne sont pas encore présentes des la distribution, c&amp;#8217;est pourquoi certains d&amp;#8217;entre nous utilisent aussi des versions compilées depuis les dépôts SVN. Les logiciels en question sont HBase et Hive et leur installation manuelle n&amp;#8217;est pas couverte ci-dessous.&lt;/p&gt;

&lt;h2&gt;Installation&lt;/h2&gt;

&lt;p&gt;La procédure décrite part du postulat que XCode et MacPort sont déjà présent sur le système.&lt;/p&gt;

&lt;p&gt;La distribution de Cloudera est CDH3beta2 qui n&amp;#8217;est pas la plus récente mais le mécanisme est le même à condition de se rendre sur le site de Cloudera et de télécharger les versions les plus récentes.
Dépendances MacPort&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;bash&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;sudo port install wget p26-virtualenv libxml2 libxslt mysql5 mysql5-server  sqlite mysql
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;easyinstall simplejson
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Mise en place de SSH&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;bash&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# You need to able to ssh yourself with requiring a password&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# (using your public key)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# Next line only if &amp;quot;~/.ssh/id_rsa.pub&amp;quot; does not exists&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;ssh-keygen -C &lt;span class=&quot;s2&quot;&gt;&amp;quot;my@email.com&amp;quot;&lt;/span&gt; -t rsa
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;cat ~/.ssh/id_rsa.pub &amp;gt;&amp;gt; ~/.ssh/authorized_keys
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;chmod 600 ~/.ssh/authorized_keys
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# you should now be able to issue &amp;quot;ssh localhost&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# without entering your password&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Préparation du répertoire d&amp;#8217;installation&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;bash&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt; 
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# Replace {username}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;sudo mkdir /opt/cloudera
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;sudo chown &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;username&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;:staff /opt/cloudera
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /opt/cloudera
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Téléchargement des paquets&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;bash&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;wget http://archive.cloudera.com/cdh/3/hadoop-0.20.2+320.tar.gz
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;wget http://archive.cloudera.com/cdh/3/hive-0.5.0+20.tar.gz
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;wget http://archive.cloudera.com/cdh/3/pig-0.7.0+9.tar.gz
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;wget http://archive.cloudera.com/cdh/3/hbase-0.89.20100621+17.tar.gz
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;wget http://archive.cloudera.com/cdh/3/sqoop-1.0.0+3.tar.gz
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;wget http://archive.cloudera.com/cdh/3/flume-0.9.0+1.tar.gz
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;wget http://archive.cloudera.com/cdh/3/hue-common_0.9-2.tar.gz
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;wget http://archive.cloudera.com/cdh/3/zookeeper-3.3.1+10.tar.gz
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Extraction des paquets&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;13&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;14&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;15&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;16&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;17&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;18&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;19&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;20&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;bash&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt; 
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;tar -xzf hadoop-0.20.2+320.tar.gz
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;tar -xzf hive-0.5.0+20.tar.gz
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;tar -xzf pig-0.7.0+9.tar.gz
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;tar -xzf hbase-0.89.20100621+17.tar.gz
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;tar -xzf sqoop-1.0.0+3.tar.gz
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;tar -xzf flume-0.9.0+1.tar.gz
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;tar -xzf hue-common_0.9-2.tar.gz
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;tar -xzf zookeeper-3.3.1+10.tar.gz
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# Make symbolic links&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;ln -sf hadoop-0.20.2+320 hadoop
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;ln -sf hive-0.7.0-dev hive
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;ln -sf pig-0.7.0+9 pig
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;ln -sf hbase-0.89.20100621+17 hbase
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;ln -sf sqoop-1.0.0+3 sqoop
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;ln -sf flume-0.9.0+1 flume
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;ln -sf hue-common-0.9 hue
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;ln -sf zookeeper-3.3.1+10 zookeeper
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# Clean up&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;rm -rf *.tar.gz
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Configuration de l&amp;#8217;environnement&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;13&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;14&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;15&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;16&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;17&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;18&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;bash&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;export JAVA_HOME=/Library/Java/Home&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; ~/.profile
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;export HADOOP_HOME=/opt/cloudera/hadoop&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; ~/.profile
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;export HIVE_HOME=/opt/cloudera/hive&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; ~/.profile
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;export HIVE_CONF_DIR=/opt/cloudera/hive/conf&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; ~/.profile
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;export PIG_HOME=/opt/cloudera/pig&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; ~/.profile
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;export HBASE_HOME=/opt/cloudera/hbase&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; ~/.profile
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;export FLUME_HOME=/opt/cloudera/flume&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; ~/.profile
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;export SQOOP_HOME=/opt/cloudera/sqoop&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; ~/.profile
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;export ZOOKEEPER_HOME=/opt/cloudera/zookeeper&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; ~/.profile
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;export HUE_HOME=/opt/cloudera/hue&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; ~/.profile
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;export PATH=\$HADOOP_HOME/bin:\$PATH&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; ~/.profile
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;export PATH=\$HBASE_HOME/bin:\$PATH&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; ~/.profile
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;export PATH=\$PIG_HOME/bin:\$PATH&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; ~/.profile
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;export PATH=\$HIVE_HOME/bin:\$PATH&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; ~/.profile
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;export PATH=\$FLUME_HOME/bin:\$PATH&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; ~/.profile
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;export PATH=\$SQOOP_HOME/bin:\$PATH&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; ~/.profile
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;export PATH=\$ZOOKEEPER_HOME/bin:\$PATH&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; ~/.profile
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; ~/.profile
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Configuration des logiciels&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;13&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;14&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;15&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;16&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;17&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;18&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;19&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;20&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;21&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;22&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;23&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;24&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;25&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;26&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;27&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;28&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;29&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;30&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;31&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;32&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;33&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;34&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;35&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;36&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;37&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;38&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;39&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;40&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;41&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;bash&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# Configure Hive&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# Edit ./conf/hive-default.xml&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# and modify the property &amp;#39;javax.jdo.option.ConnectionURL&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# to &amp;#39;jdbc:derby:;databaseName=/opt/cloudera/data/hive/metastore_db;create=true&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# Edit ./conf/hive-log4j.properties&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# and modify the property &amp;#39;hive.log.file&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# to &amp;#39;/opt/cloudera/data/hive/hive.log&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# (SVN only) modify property &amp;#39;hive.stats.dbconnectionstring&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# to &amp;#39;jdbc:derby:;databaseName=/opt/cloudera/data/hive_temp_stats;create=true&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# For mysql,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# modify &amp;#39;javax.jdo.option.ConnectionURL&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# to &amp;#39;jdbc:mysql://127.0.0.1/hive?createDatabaseIfNotExist=true&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# and &amp;#39;javax.jdo.option.ConnectionDriverName&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# to &amp;#39;com.mysql.jdbc.Driver&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# and &amp;#39;javax.jdo.option.ConnectionUserName&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# to &amp;#39;your_username&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# and &amp;#39;javax.jdo.option.ConnectionPassword&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# to &amp;#39;your_password&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# Configure Hue&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# Note: from memory, you might also need mysql&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;sudo port install py26-setuptools
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;ln -sf /opt/local/bin/mysql_config5 /opt/local/bin/mysql_config
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;hue-common-0.9
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;make apps
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# EDIT $HUE_HOME/desktop/conf/hue.ini and&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# update the property &amp;quot;hadoop_home&amp;quot; from &amp;quot;/usr/lib/hadoop-0.20&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# to &amp;quot;/opt/cloudera/hadoop-0.20.2+320&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# Configure Hadoop&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$HADOOP_HOME&lt;/span&gt;/lib
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;ln -s &lt;span class=&quot;nv&quot;&gt;$HUE_HOME&lt;/span&gt;/desktop/libs/hadoop/java-lib/hue-plugins-0.9.jar
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;mv hadoop-0.20.2+320/conf hadoop-0.20.2+320/conf.bck
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;cp -rp hue/example-hadoop-confs/conf.pseudo-hue hadoop-0.20.2+320/conf
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# Edit the file $HADOOP_HOME/conf/core-site.xml and replace&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# the value &amp;quot;/var/lib/hadoop-0.20/cache/${user.name}&amp;quot; by&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# &amp;quot;/opt/cloudera/data/cache/${user.name}&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# Edit the file $HADOOP_HOME/conf/hdfs-site.xml and replace&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# the value &amp;quot;/var/lib/hadoop-0.20/cache/hadoop/dfs/name&amp;quot; by&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# &amp;quot;/opt/cloudera/data/cache/${user.name}/dfs/name&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;hadoop namenode -format
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h2&gt;Utilisation&lt;/h2&gt;

&lt;p&gt;Démarrage des services&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;bash&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# Start Hadoop&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;start-all.sh
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# Start HBase&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;start-hbase.sh
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;hbase-daemon.sh start rest
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# Start Hue&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$HUE_HOME&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;./build/env/bin/supervisor
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Arrêt des services&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;bash&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt; 
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# Start Hadoop&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;stop-all.sh
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c&quot;&gt;# Start HBase&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;hbase-daemon.sh stop rest
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;stop-hbase.sh
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h2&gt;Administration&lt;/h2&gt;

&lt;p&gt;Si l&amp;#8217;installation s&amp;#8217;est déroulée sans encombre, les URLs suivantes devrait être disponibles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hadoop Map/Reduce Administration: &lt;code&gt;http://localhost:50030&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Hadoop File System Browser: &lt;code&gt;http://localhost:50070&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Hadoop Task Tracker Status: &lt;code&gt;http://localhost:50060&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Hue: &lt;code&gt;http://localhost:8088&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
  </entry>
  
  <entry>
    <title>Stockage et traitement massif avec Hadoop</title>
    <link href="http://www.adaltas.com/blog/2010/11/26/hadoop-historique/"/>
    <updated>2010-11-26T00:40:00+01:00</updated>
    <id>http://www.adaltas.com/blog/2010/11/26/hadoop-historique</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;http://hadoop.apache.org/&quot;&gt;Apache Hadoop&lt;/a&gt; est un système pour construire des infrastructures de stockage partagé et d&amp;#8217;analyse adaptées à des volumes larges (plusieurs terabytes ou petabytes). Les clusters Hadoop sont utilisés par un large éventail de projets R&amp;amp;D pour un nombre croissant d&amp;#8217;acteurs du web (&lt;a href=&quot;http://www.yahoo.com/&quot;&gt;Yahoo!&lt;/a&gt;, &lt;a href=&quot;http://www.ebay.com/&quot;&gt;EBay&lt;/a&gt;, &lt;a href=&quot;http://www.facebook.com/&quot;&gt;Facebook&lt;/a&gt;, &lt;a href=&quot;http://www.linkedin.com/&quot;&gt;LinkedIn&lt;/a&gt;, &lt;a href=&quot;http://www.twitter.com/&quot;&gt;Twitter&lt;/a&gt;) et leur taille ne cesse d&amp;#8217;augmenter. Yahoo! regroupe 45000 machines dont le plus large cluster reuni 4000 serveurs et stocke 40 PB tandis que Facebook a rapporter stocker 20 PB sur un même cluster &lt;a href=&quot;http://hadoop.apache.org/hdfs/&quot;&gt;HDFS (pour Hadoop Distributed File System)&lt;/a&gt;.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;p&gt;Les dotcoms furent les premières sociétés à voir leur volume de données croître exponentiellement. Beaucoup ont fondé leur modèle économique sur le traitement de ces données. Autant Google que Facebook tirent l&amp;#8217;essentiel de leur revenu de l&amp;#8217;analyse de données à des fins publicitaires. Ne pouvant attendre les éditeurs traditionnels, ces sociétés ont lourdement investi dans le développement de nouveaux logiciels pour faire face à cette explosion tout en exploitant de nouveaux concepts. Aujourd’hui, grâce au model de l&amp;#8217;Open Source, ces technologies sont présentes dans un grand nombres d&amp;#8217;industries et deviennent un composant clé de plusieurs sociétés et services gouvernementaux.&lt;/p&gt;

&lt;p&gt;Hadoop, l&amp;#8217;implémentation Open Source de l&amp;#8217;infrastructure &lt;a href=&quot;http://google/&quot;&gt;Google&lt;/a&gt;, fait suite à la publication par Google de deux documents. Le premier, publié en 2003, décrit l&amp;#8217;architecture de &lt;a href=&quot;http://labs.google.com/papers/gfs.html&quot;&gt;GFS (pour Google Distributed Filesystem)&lt;/a&gt;. Le second, publié en 2004, introduit le paradigme Map-Reduce. A cet époque, Doug Cutting, aujourd&amp;#8217;hui chez &lt;a href=&quot;http://www.cloudera.com/&quot;&gt;Cloudera&lt;/a&gt;, travaillait sur &lt;a href=&quot;http://nutch.apache.org/&quot;&gt;Nutch&lt;/a&gt;, un logiciel Open Source de la fondation Apache incluant un aspirateur Internet et un moteur de recherche. Les besoins en stockage et capacité de calcul de Nutch ont conduit à l&amp;#8217;implémentation des travaux de Google en ce qui deviendra Hadoop.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Node HBase, client NodeJs pour Apache HBase</title>
    <link href="http://www.adaltas.com/blog/2010/11/01/hbase-nodejs/"/>
    <updated>2010-11-01T00:40:00+01:00</updated>
    <id>http://www.adaltas.com/blog/2010/11/01/hbase-nodejs</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;http://hbase.apache.org/&quot;&gt;HBase&lt;/a&gt; est la base de données de type &amp;#8220;column familly&amp;#8221; de l&amp;#8217;&lt;a href=&quot;http://hadoop.apache.org/&quot;&gt;écosystème Hadoop&lt;/a&gt; construit sur le modèle de &lt;a href=&quot;http://en.wikipedia.org/wiki/BigTable&quot;&gt;Google BigTable&lt;/a&gt;. HBase peut accueillir de très larges volumes de données (de l&amp;#8217;ordre du tera ou du peta) tout en maintenant une haute disponibilité et des temps de réponses rapides.&lt;/p&gt;

&lt;p&gt;Adaltas a mis en ligne un &lt;a href=&quot;http://github.com/wdavidw/node-hbase&quot;&gt;client Node pour HBase&lt;/a&gt; qui utilise les webservices REST (aussi appelés Stargate) et le mode de transport JSON. L&amp;#8217;intégration des services est complète et le code entièrement couvert par des tests unitaires.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;p&gt;De plus, j&amp;#8217;ai contribué le patch activant la mise à jour des schémas permettant ainsi de modifier la structure et la configuration d&amp;#8217;une table en utilisant les webservices.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Masson, build tool pour NodeJS</title>
    <link href="http://www.adaltas.com/blog/2010/10/05/nodejs-masson-build-tool/"/>
    <updated>2010-10-05T00:40:00+02:00</updated>
    <id>http://www.adaltas.com/blog/2010/10/05/nodejs-masson-build-tool</id>
    <content type="html">&lt;p&gt;Retrouvez Masson sur &lt;a href=&quot;http://github.com/&quot;&gt;Github&lt;/a&gt;:
&lt;a href=&quot;http://github.com/wdavidw/node-masson&quot;&gt;http://github.com/wdavidw/node-masson&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;J&amp;#8217;ai publié ces derniers jours plusieurs librairies pour Node. Je parlerai aujourd&amp;#8217;hui de Masson, un projet similaire à Make, Ant ou encore Rake. Masson est donc un projet JavaScript pour l&amp;#8217;environnement Node. Pour rappel, Node est basé sur le moteur V8 qui anime Google Chrome et fonctionnement de manière asynchronisé.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;h2&gt;Description&lt;/h2&gt;

&lt;p&gt;Masson est une librairie permettant d&amp;#8217;organiser et d&amp;#8217;exécuter des tâches. Une tâche est une ou plusieurs actions regroupées ensemble et identifié par un nom, c&amp;#8217;est-à-dire une clé. Chaque exécution de tâche peut dépendre de l&amp;#8217;exécution antérieure d&amp;#8217;autres tâches. Et puisque Node offre le bénéfice d&amp;#8217;être asynchrone, l&amp;#8217;API de Masson reflète ce model et il suffit d&amp;#8217;appeler la fonction &lt;code&gt;out&lt;/code&gt; pour marque la fin d&amp;#8217;une tâche et continuer l&amp;#8217;exécution du workflow.&lt;/p&gt;

&lt;h2&gt;Un rapide exemple&lt;/h2&gt;

&lt;p&gt;L&amp;#8217;exemple ci-dessous crée 3 tâches. La première, &amp;#8216;clean&amp;#8217;, nettoie le code source; la seconde, &amp;#8216;test&amp;#8217;, teste le code source; la troisième, &amp;#8216;build&amp;#8217;, lance les deux tâches précédentes et crée une archive.&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;13&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;14&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;15&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;16&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;17&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;18&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;19&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;20&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;21&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;js&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;   &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;masson&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;masson&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;nx&quot;&gt;masson&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;      &lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;clean&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;      &lt;span class=&quot;nx&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;          &lt;span class=&quot;cm&quot;&gt;/* do some cleaning */&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;          &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;p&quot;&gt;},{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;      &lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;test&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;      &lt;span class=&quot;nx&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;          &lt;span class=&quot;cm&quot;&gt;/* do some testing */&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;          &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;p&quot;&gt;},{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;      &lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;build&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;      &lt;span class=&quot;nx&quot;&gt;depends&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;prepare&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;clean&amp;#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;      &lt;span class=&quot;nx&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;          &lt;span class=&quot;cm&quot;&gt;/* do some archiving */&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;          &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;p&quot;&gt;}],&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;build&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;C&amp;#8217;est simple et complet. A noter aussi les points suivants:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Masson fournit plusieurs APIs alternatifs&lt;/li&gt;
&lt;li&gt;Les targets peuvent partager des arguments les unes avec les autres&lt;/li&gt;
&lt;li&gt;Méchanisme d&amp;#8217;évènements par extension de la class &lt;code&gt;EventEmitter&lt;/code&gt; de Node&lt;/li&gt;
&lt;li&gt;Intégration avec &lt;a href=&quot;http://github.com/wdavidw/node-masson&quot;&gt;NPM&lt;/a&gt; (Node Package Manager)&lt;/li&gt;
&lt;li&gt;100% Open Source (license MIT)&lt;/li&gt;
&lt;/ul&gt;

</content>
  </entry>
  
  <entry>
    <title>Présentation de MapReduce</title>
    <link href="http://www.adaltas.com/blog/2010/06/26/map-reduce-presentation/"/>
    <updated>2010-06-26T00:40:00+02:00</updated>
    <id>http://www.adaltas.com/blog/2010/06/26/map-reduce-presentation</id>
    <content type="html">&lt;p&gt;Les systèmes d&amp;#8217;information ont de plus en plus de données à stocker et à traiter. Des entreprises comme Google, Facebook, Twitter mais encore bien d&amp;#8217;autre stockent des quantités d&amp;#8217;information astronomiques en provenance de leurs clients et doivent être en mesure de les servir par les meilleurs recommandation tout en assurant la pérennité de leurs systèmes.&lt;/p&gt;

&lt;p&gt;MapReduce est un moyen de modéliser un programme pour traiter de large volume de donnée. Par large, on entend massif, par exemple de l&amp;#8217;ordre du petabytes. Orginallement créer par Google et décrit en détails dans la publication &amp;#8221;&lt;a href=&quot;http://labs.google.com/papers/mapreduce.html&quot;&gt;MapReduce: Simplified Data Processing on Large Clusters&lt;/a&gt;&amp;#8221; publiée en 2004, une implémentation Open Source existe  au travers d&amp;#8217;&lt;a href=&quot;http://hadoop.apache.org/&quot;&gt;Hadoop&lt;/a&gt; et de son écosystème de la fondation Apache.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;p&gt;Une tâche MapReduce est constituée de 2 phases. Le développeur implémente une fonction &amp;#8220;map&amp;#8221; qui décompose une donnée en clé/valeur et une autre fonction &amp;#8220;reduce&amp;#8221; qui fusionne toutes les valeurs associées à une même clé. Combinées entre elles, ce paradigme permet d&amp;#8217;exprimer un grand nombre de problématique.&lt;/p&gt;

&lt;p&gt;Le grand avantage de cette méthode est ça faculté de décomposer un processus en plusieurs tâches distribuables sur un très grand nombre de machines normales. Par machines normales, on entend des serveurs dont le prix peut varier entre 3000 et 5000 euros. Pour prendre un exemple concret, en 2010, nous avons commandé des serveurs à 4500 € constitués de 2 processors AMD Optéron à 8 coeurs, 32 Go de RAM et 4 disques de 1T à 7500 tours. Deux machines à 2000 euros chacune auraient très bien pu faire l&amp;#8217;affaire. Nous avons opté pour cette configuration à cause de l&amp;#8217;économie de place engendrée.&lt;/p&gt;

&lt;p&gt;Le traitement des données est réparti sur l&amp;#8217;ensemble des serveurs du cluster sans pénalité d&amp;#8217;échelle. Si vous données doublent, vous doublez le nombre de machines. Si vous avez besoins de plus de puissance de calcul, idem.&lt;/p&gt;

&lt;p&gt;Pour le programmeur, le travail se limite à la création de tâches MapReduce qui sont facile à comprendre et à écrire. Le système se charge des détails dont le partitionnement des données, l&amp;#8217;exécution et la coordination des tâches, la duplication des informations en cas de panne machine et la communication entre elles.&lt;/p&gt;

&lt;p&gt;Je vais terminer cet article par un exemple en JavaScript pour illustrer le concept. Le but de l&amp;#8217;exercice est de compter le nombre d&amp;#8217;utilisateur pour un même code postal, partant de données CSV comprenant 3 utilisateurs avec leur nom et leur code postal comme champs.&lt;/p&gt;

&lt;p&gt;Le fichier source (format CSV)&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;Hadoop,75006
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;Cassandra,75019
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;Hive,75006&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;La fonction &amp;#8220;map&amp;#8221; (en javascript)
L&amp;#8217;argument fournit, &amp;#8220;value&amp;#8221; correspond à une ligne de notre fichier source. Cette ligne est convertie sous forme d&amp;#8217;array comprend 2 éléments: le nom de l&amp;#8217;utilisateur et son code postal. Finalement, la fonction &amp;#8220;emit&amp;#8221; prend 2 arguments qui sont la clé à émettre et la valeur associée soit le code postal pour la clé et 1 pour signifier que ce code postal a été rencontré une fois.&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;js&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;nx&quot;&gt;row&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;,&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;emit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;La fonction &amp;#8220;reduce&amp;#8221; (en Javascript)
Les argument fournits sont une clé et les valuers associés à cette clé. Ils résultent de la fonction &amp;#8220;map&amp;#8221; appelée précédemment. L&amp;#8217;argument &amp;#8220;key&amp;#8221; est donc un code postal et l&amp;#8217;argument &amp;#8220;values&amp;#8221; une array de nombre. Attention toutefois, la function reduce peut être appelée plusieurs fois et son écriture doit prendre cela en compte. MapReduce étant destiné à de très larges volumes, values pourrait autrement prendre des proportions trop grandes. Ici, values est consituée de numéros &amp;#8220;1&amp;#8221; la première fois mais ce nombre sera différent si la méthode est appelée à nouveau.&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;js&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;previous&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;previous&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;current&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Le résultat final&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;75006, 2
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;75019, 1&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;



</content>
  </entry>
  
  <entry>
    <title>Node.js, JavaScript côté serveur</title>
    <link href="http://www.adaltas.com/blog/2010/06/12/nodejs-javascript-serveur/"/>
    <updated>2010-06-12T13:25:00+02:00</updated>
    <id>http://www.adaltas.com/blog/2010/06/12/nodejs-javascript-serveur</id>
    <content type="html">&lt;p&gt;En attente du prochain grand language (&lt;a href=&quot;http://typo3/http://steve-yegge.blogspot.com/2007/02/next-big-language.html&quot;&gt;NBL pour Next Big Language&lt;/a&gt;), cela fait maintenant 3 ans que je prédis à mes clients un bel avenir au JavaScript comme langue de programmation pour les applications serveurs. Mon argumentation se fondait essentiellement sur son esthétisme, sa simplicité et sa nature dynamique. Conçu en 1995 par &lt;a href=&quot;http://en.wikipedia.org/wiki/Sun_Microsystems&quot;&gt;Sun Microsystems&lt;/a&gt; (racheté par &lt;a href=&quot;http://www.oracle.com&quot;&gt;Oracle&lt;/a&gt;) et &lt;a href=&quot;http://en.wikipedia.org/wiki/Netscape&quot;&gt;Netscape&lt;/a&gt; (racheté par &lt;a href=&quot;http://www.aol.com/&quot;&gt;AOL&lt;/a&gt;), son intégration dans les navigateurs Internet a largement diffusé le language mais ce n&amp;#8217;est qu&amp;#8217;à partir de 2004 au travers de la génération AJAX et d&amp;#8217;applications Web telles que Gmail et Google Maps que le language a reçu ses lettres de noblesse et gagna l&amp;#8217;attention des professionnels.&lt;/p&gt;

&lt;!&#8211;more&#8211;&gt;


&lt;p&gt;Malgré quelques efforts infructueux, son utilisation était cantonnée aux postes clients, c&amp;#8217;est à dire aux navigateurs Internet dans lesquels il permet de dynamiser les pages Web. Depuis quelques années, des solutions sont apparues dans la communauté Open Source. Je pense notamment à &lt;a href=&quot;http://helma.org/&quot;&gt;Helma&lt;/a&gt;, d&amp;#8217;un fonctionnement traditionnel au sein d&amp;#8217;une &lt;a href=&quot;http://www.java.com/fr/download/manual.jsp&quot;&gt;machine virtuelle Java&lt;/a&gt; et donc aisément intégrable au large écosystème Java, mais aussi à des solutions plus innovantes comme &lt;a href=&quot;http://jaxer.org/&quot;&gt;Jaxer&lt;/a&gt;, dont la particularité et de créer un environnement de type navigateur (comme la manipulation du DOM) sur le serveur. De tous, c&amp;#8217;est sans doute &lt;a href=&quot;https://github.com/tlrobinson/narwhal&quot;&gt;Narwhal&lt;/a&gt; qui me laissa la plus forte impression par son architecture simple et la modularité de l&amp;#8217;interpréteur JavaScript.&lt;/p&gt;

&lt;p&gt;Durant ces dernières années, j&amp;#8217;ai suivi avec attention l&amp;#8217;actualité autour des solutions serveurs, testant chacune d’entre elles et analysant leurs approches. Au vu du trafic généré par chaque article traitant du sujet, je m&amp;#8217;aperçus à cette occasion que je n&amp;#8217;étais pas isolé. Mais aucun des projets n&amp;#8217;avait pu me convaincre d&amp;#8217;abandonner ce mauvais garçon qu’est PHP. Jusqu&amp;#8217;à il y a quelques mois avec l&amp;#8217;apparition de &lt;a href=&quot;http://typo3/http://nodejs.org/&quot;&gt;NodeJs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Revenons un peu en arrière. L&amp;#8217;&lt;a href=&quot;http://fr.wikipedia.org/wiki/Asynchronous_JavaScript_and_XML&quot;&gt;AJAX&lt;/a&gt; marqua l&amp;#8217;importance et le besoin de performance des navigateurs et l&amp;#8217;interpréteur JavaScript est une donnée essentielle des &lt;a href=&quot;http://fr.wikipedia.org/wiki/Rich_Internet_Application&quot;&gt;applications Internet dites riches (RIA pour Rich Internet Application)&lt;/a&gt;. Les éditeurs Mozilla et Microsoft rejoint par Apple avec Safari et plus récemment Google avec Chrome se sont lancé dans une course à l&amp;#8217;optimisation. Cette saine compétition a donné naissance à de nouvelles générations d&amp;#8217;interpréteurs que sont TraceMonkey pour Firefox 3.6, SquirrelFish pour Safari 5, Carakan pour Opera et V8 pour Chrome. Longtemps à la traîne, même Microsoft se prend au jeu dans la version 9 d&amp;#8217;Internet Explorer. Aujourd&amp;#8217;hui, le JavaScript est sans nul doute le language concentrant l&amp;#8217;essentiel des efforts de développement.&lt;/p&gt;

&lt;p&gt;Mais il y a une autre raison pour laquelle JavaScript est rapide et un excellent choix côté serveur. Par nature, c&amp;#8217;est un language orienté évènement en opposition aux serveurs orienté thread. Cette caractéristique du language vient de ses origines ou il était destiné à fonctionner à l&amp;#8217;intérieur des navigateurs Internet et il était essentiel de supporter les évènements utilisateurs sans saturer l&amp;#8217;ensemble du navigateur à chaque action. Traditionnellement, les applications serveurs sont écrites sous un mode thread dit bloquant. C&amp;#8217;est le cas pour les applications PHP et CGI et l&amp;#8217;essentiel des applications Python, Ruby ou Java.&lt;/p&gt;

&lt;p&gt;Je vais essayer d&amp;#8217;être aussi clair que possible. Lorsqu&amp;#8217;un serveur reçoit une requête, par exemple l&amp;#8217;envoi d&amp;#8217;un formulaire, le serveur met à disposition une thread et lance l&amp;#8217;application qui effectue ses opérations les une après les autres (connexion à une base de donnée afin de valider le nom et le mot passe de l&amp;#8217;utilisateur, écriture dans un fichier de log,&amp;#8230;) avant de finalement retourner la réponse au formulaire et de fermer la thread. Or le nombre de thread est limité et ces applications génèrent rapidement des erreurs lorsque celles-ci arrivent à saturation de la mémoire. Chaque thread est monopolisée jusqu&amp;#8217;à la fin de l&amp;#8217;ensemble des opérations. Ces opérations comme l&amp;#8217;écriture d&amp;#8217;un fichier prennent énormément de temps en comparaison de la vitesse d&amp;#8217;un CPU et ce n&amp;#8217;est que pur gâchis. Pour les applications avec de forts volumes de trafic, chaque requête doit être codée pour être la plus courte possible. Contrairement, dans un environnement évènementiel, ces mêmes opérations sont dites non bloquantes car en attendant de requêter sur une base de donnée ou d&amp;#8217;écrire dans un fichier, le serveur peut continuer à effectuer d&amp;#8217;autres taches dans une même thread.&lt;/p&gt;

&lt;p&gt;L&amp;#8217;absence d&amp;#8217;alternative non bloquante peut même devenir handicapante pour certains scénarios tels que le téléchargement de fichiers volumineux, le regroupement de résultats en provenance de plusieurs backends et, non des moindres, le support du protocole &lt;a href=&quot;http://typo3/http://svn.cometd.com/trunk/bayeux/bayeux.html&quot;&gt;Bayeux (Comet)&lt;/a&gt; ouvrant les voix du HTTP push.&lt;/p&gt;

&lt;p&gt;Partant du postulat que l&amp;#8217;essentiel du temps des applications serveurs est dépensé à attendre les résultats des opérations I/O (accès réseaux vers bases de données, lecture et écriture sur le système de fichier,&amp;#8230;), la programmation évènementiel est particulièrement adaptée à l&amp;#8217;environnement serveur. &lt;a href=&quot;http://twistedmatrix.com/&quot;&gt;Twisted&lt;/a&gt; en Python et &lt;a href=&quot;http://rubyeventmachine.com/&quot;&gt;EventMachine&lt;/a&gt; en Ruby répondent à cette problématique mais aucun ne bénéficie de la force d&amp;#8217;un language intégrant nativement ces fonctionnalités.&lt;/p&gt;

&lt;p&gt;Revenons à Node. Décrit par son auteur comme une excellente fondation au développement d&amp;#8217;applications Web, il est basé sur le moteur JavaScript V8 développé, utilisé et open-sourcé par Google pour son navigateur Chrome. Celui-ci est l&amp;#8217;un des plus rapide du marché (pour ne pas dire le plus rapide) et s&amp;#8217;améliore à chaque nouvelle version. Tout dans le développement de Node est construit et optimisé dans une optique évènementielle ce qui réduit considérablement les possibilités d&amp;#8217;écrire une application lente parce que faisant appel à des opérations I/O bloquantes. Rapidement, la communauté Open Source a reconnut le potentiel de cette plateforme et un riche éco système se construit autour comprenant drivers (&lt;a href=&quot;http://couchdb.apache.org&quot;&gt;CouchDB&lt;/a&gt;, &lt;a href=&quot;http://www.mongodb.org&quot;&gt;MongoDB&lt;/a&gt;, &lt;a href=&quot;http://redis.io&quot;&gt;Redis&lt;/a&gt;,&amp;#8230;), libraries (Haml, Sass, Expresso, &amp;#8230;) et frameworks (Connect, Express, &amp;#8230;).&lt;/p&gt;

&lt;p&gt;Pour le compte d&amp;#8217;un client, j&amp;#8217;ai prototypé une application et la prise en main est rapide, simple et intuitive. Le code est élégant, court et lisible. Tout ce que j&amp;#8217;attendais des promesses du JavaScript côté serveur. Pour la réalisation du proto et malgré la jeunesse de l&amp;#8217;écosystème, je n&amp;#8217;ai eu à manquer de rien. Voir cela m&amp;#8217;a permis d&amp;#8217;utiliser des concepts empruntés des univers Ruby et Python qui font défaut à celui de PHP (une pensée particulière pour SASS). Pour ceux familiers dans le développement d&amp;#8217;applications clients riches en JavaScript, la transition sera quasiment instantanée.&lt;/p&gt;

&lt;p&gt;Pour résumer Node en quelques phrases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript est fait pour l&amp;#8217;évènementiel: la programmation par callback est familière aux développeurs d&amp;#8217;applications AJAX et, pour se faire, la syntaxe des fonctions anonymes et le support des closures est adapté et élégant.&lt;/li&gt;
&lt;li&gt;Node est construit sur Javascript: de part sa présence dans les navigateurs, c&amp;#8217;est peut-être le language le plus programmé au monde et bénéficie de 15 ans d&amp;#8217;expérience.&lt;/li&gt;
&lt;li&gt;Node se stabilise: l&amp;#8217;API de Node gagne en maturité et est proche de se finaliser.&lt;/li&gt;
&lt;li&gt;Node a un écosystème: de nombreuses librairies sont disponibles, toutes en Open Source, de nouvelles apparaissent et toutes partagent une bonne qualité de réalisation.&lt;/li&gt;
&lt;li&gt;Node est simple et petit: la documentation se promène d&amp;#8217;un seul regard et permet de rapidement connaitre ses fonctionnalités.&lt;/li&gt;
&lt;li&gt;Node est rapide: le moteur V8 et l&amp;#8217;architecture non bloquante en font l&amp;#8217;une des architectures les plus puissante du marché, spécialement pour les requêtes longues et intensives en I/O.&lt;/li&gt;
&lt;/ul&gt;

</content>
  </entry>
  
</feed>

