<?xml version="1.0" encoding="UTF-8"?>
<!--Generated by Squarespace Site Server v5.9.2 (http://www.squarespace.com/) on Wed, 10 Mar 2010 08:53:52 GMT--><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rss="http://purl.org/rss/1.0/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:cc="http://web.resource.org/cc/"><rss:channel rdf:about="http://rklophaus.com/blog/"><rss:title>Blog</rss:title><rss:link>http://rklophaus.com/blog/</rss:link><rss:description></rss:description><dc:language>en-US</dc:language><dc:date>2010-03-10T08:53:52Z</dc:date><admin:generatorAgent rdf:resource="http://www.squarespace.com/">Squarespace Site Server v5.9.2 (http://www.squarespace.com/)</admin:generatorAgent><rss:items><rdf:Seq><rdf:li rdf:resource="http://rklophaus.com/blog/2010/1/24/submodules-and-subrepos-done-right.html"/><rdf:li rdf:resource="http://rklophaus.com/blog/2009/12/19/nitrogenriak-video-from-euc2009-stockholm.html"/><rdf:li rdf:resource="http://rklophaus.com/blog/2009/12/5/nitrogen-riak-and-1000-lines-of-erlang.html"/><rdf:li rdf:resource="http://rklophaus.com/blog/2009/12/3/blogging-to-squarespace-with-textmate.html"/><rdf:li rdf:resource="http://rklophaus.com/blog/2009/12/1/the-bilski-case-and-software-patents.html"/><rdf:li rdf:resource="http://rklophaus.com/blog/2009/9/16/gproc-erlang-global-process-registry.html"/><rdf:li rdf:resource="http://rklophaus.com/blog/2009/6/2/nitrogen-at-the-erlang-factory-across-the-pond.html"/><rdf:li rdf:resource="http://rklophaus.com/blog/2009/3/29/nitrogen-at-the-erlang-factory.html"/><rdf:li rdf:resource="http://rklophaus.com/blog/2009/2/25/youre-sitting-on-a-chair-in-the-sky.html"/><rdf:li rdf:resource="http://rklophaus.com/blog/2009/2/24/clara-needs-her-own-tv-show.html"/></rdf:Seq></rss:items></rss:channel><rss:item rdf:about="http://rklophaus.com/blog/2010/1/24/submodules-and-subrepos-done-right.html"><rss:title>Submodules and Subrepos Done Right</rss:title><rss:link>http://rklophaus.com/blog/2010/1/24/submodules-and-subrepos-done-right.html</rss:link><dc:creator>Rusty</dc:creator><dc:date>2010-01-24T19:45:08Z</dc:date><dc:subject></dc:subject><content:encoded><![CDATA[<p><em>An approach to managing Git or Mercurial sub-repos easily,
safely, and simply, while allowing you to embed Git projects in a
Mercurial repo and vice-versa.</em></p>

<p><span class="full-image-block ssNonEditable"><span><img src="http://rklophaus.com/storage/nestingdolls.jpg?__SQUARESPACE_CACHEVERSION=1264363142956" alt=""/></span></span></p>

<h2>Background</h2>

<p>Most software projects rely on other software projects to function.
For example, <a href="http://nitrogenproject.com">Nitrogen</a> depends on
<a href="http://github.com/rklophaus/SimpleBridge">SimpleBridge</a>,
<a href="http://github.com/mmullis/coverize">Coverize</a>, and
<a href="http://code.google.com/p/mochiweb/">Mochiweb</a> or
<a href="http://yaws.hyber.org/download/">Yaws</a>. Riak depends on
<a href="http://bitbucket.org/basho/webmachine/">Webmachine</a> and
<a href="http://code.google.com/p/mochiweb/">Mochiweb</a>.</p>

<p>In the name of simplicity and ease of use, it's generally a good idea for the
parent repo to contain the source code of any sub-projects it uses.</p>

<p>But then you are faced with a decision:</p>

<p><strong>Should the parent project include the full history of the
sub-project as well?</strong></p>

<p>You currently have three options, all with tradeoffs:</p>

<ol>
<li><p>Remove revision history in your sub-projects by deleting the <code>.git</code>/<code>.hg</code> directory, and
experience pain when you want to pull the latest updates or
commit a patch on the sub-project.</p></li>
<li><p>Track the entire <code>.git</code>/<code>.hg</code> directory for each sub-project,
and accept that the <code>.git</code>/<code>.hg</code> directory of your parent project will now
be huge.</p></li>
<li><p>Use
<a href="http://www.kernel.org/pub/software/scm/git/docs/git-submodule.html">Git submodules</a>
(or <a href="http://mercurial.selenic.com/wiki/subrepos">Mercurial subrepos</a>),
and hope that you never have to include a Git project inside of a
Mercurial project, or vice versa. Also, accept the unfortunate fact that your build
process now requires a working Internet connection.</p></li>
</ol>

<h2>The Search for a Better Way</h2>

<p>What do I really want out of sub-repo support? </p>

<ul>
<li><p>I want the sub-repos to seem like part of the parent project to
the user, while still seeming like distinct repositories to me.</p></li>
<li><p>I want to be able to work with the full history of the sub-repo,
but I don't want this included in the parent repo, or sent out to
anyone who downloads the code.</p></li>
<li><p>I want an easy process for contributors to get the history of the
sub-repos, so that they can commit patches.</p></li>
</ul>

<p>Furthermore:</p>

<ul>
<li><p>I only want to use tested, core features of Git or Mercurial.</p></li>
<li><p>I want the solution to be "cross platform", so that I can stick Git
repos in Mercurial and vice versa.</p></li>
<li><p>I want the solution to be simple to use and easy to understand for the
most common use case. (In other words, hide complexity from the non power-users.)</p></li>
</ul>

<h2>Introducing subgit and subhg</h2>

<p>After much thought and frustration, I think I've finally found a
solution that meets all of my needs. It lets me work with the parent
repo as I normally would, using the <code>git</code> or <code>hg</code>
command. Furthermore, it gives me a different command to work with the
sub-repos. Finally, it is cross platform, allowing me to mix and match
Git and Mercurial projects. The only downside is that a contributor
needs to jump through an extra hoop or two in order to get the history
of a sub-repo.</p>

<p>In practice, the solution looks like this:</p>

<p><em>Change to the directory of a sub-project...</em></p>

<pre><code>&gt; cd ParentProject/SubProject1
</code></pre>

<p><em>Operate on the parent project...</em></p>

<pre><code>&gt; git status
...status info...

&gt; git commit
...commit code...
</code></pre>

<p><em>Operate on the sub-project. Notice the use of the 'subgit' command...</em></p>

<pre><code>&gt; subgit status
...sub-project status info...

&gt; subgit commit
...commit sub-project code...
</code></pre>

<p>Best of all, the <code>subgit</code> and <code>subhg</code> commands are just thin wrappers
around <code>git</code> and <code>hg</code>. Each is about 25 lines of shell script.</p>

<h2>Installation</h2>

<p>To try this out on your computer:</p>

<ol>
<li><p>Save the following scripts to a location in your PATH: <a href="http://gist.github.com/285365">subgit</a>
and <a href="http://gist.github.com/285368">subhg</a>. (Remember to run <code>chmod
755</code> to make them executable.)</p></li>
<li><p>Create a global excludes file for both Git and Mercurial, and add <code>.subgit</code> and <code>.subhg</code> to
it.</p>

<p><em>~/.gitconfig</em></p>

<pre><code>[core]
excludesfile = "~/.gitignore"
</code></pre>

<p><em>~/.gitignore</em></p>

<pre><code>.subgit
.subhg
</code></pre>

<p><em>~/.hgrc</em></p>

<pre><code>[ui]
ignore=~/.hgignore
</code></pre>

<p><em>~/.hgignore</em></p>

<pre><code>.subgit
.subhg
</code></pre></li>
</ol>

<p>That's all!</p>

<h2>How Does It Work?</h2>

<p>The core concept behind this approach is to store the version history
of your sub-project in a non-standard directory, and then use special
wrapper scripts when you want Git or Mercurial to operate against that
directory.</p>

<p>In other words, your projects won't have a <code>.git</code> or <code>.hg</code> directory.
Instead, they will have a <code>.subgit</code> or <code>.subhg</code> directory, which is
not tracked by the parent repo.</p>

<pre><code>|--ParentProject    &lt;-- a Git repository
   |
   |--.git
   |
   |--SubProject1   &lt;-- a Git sub-repo
   |  |--.subgit    
   |
   |--SubProject2
   |  |--.subhg     &lt;-- a Mercurial sub-repo
   |
   |--src
</code></pre>

<p>This tricks Git or Mercurial into tracking the files inside of your
sub-repo, even though the files actually belong to a different
repository. (Normally Git won't track a Git repo nested inside of another Git
repo.)</p>

<p>The wrapper scripts--<code>subgit</code> and <code>subhg</code>--do the heavy lifting to
make Git or Mercurial use the <code>.subgit</code> and <code>.subhg</code> directories.</p>

<p><code>subgit</code> simply searches upward for the closest parent directory that
contains a <code>.subgit</code> directory. Once found, it calls <code>git</code>, telling
git to use the <code>.subgit</code> directory for repository information. <code>subhg</code>
works the same way.</p>

<h2>Usage</h2>

<p>To create a sub-repo that can be managed with <code>subgit</code> or <code>subhg</code>:</p>

<ol>
<li><p>Inside of an existing, clone a repository like normal:</p>

<pre><code>git clone git://hostname.com/repository.git sub_project
</code></pre></li>
<li><p>Then, change to the new repository's directory and run <code>subgit setup</code>. This
simply renames <code>.git</code> to <code>.subgit</code>:</p>

<pre><code>cd sub_project
subgit setup
</code></pre></li>
<li><p>Now, test that it worked by viewing the parent's Git log and the
sub-repo's git log:</p>

<pre><code>git log
...print out log for the parent project...


subgit log
...print out log for the sub-project...
</code></pre></li>
</ol>

<p><code>subhg</code> works the same way.</p>

<h2>Some Final Thoughts</h2>

<p>First, this approach is intended for all of the projects out there
using GitHub, BitBucket, Google Code, etc. as their main distribution
channel. Most of these projects have a small group of contributors,
and a much larger group of users. </p>

<p>If you distribute your project via a tar'd, gzip'd file, then this
blog post is not for you.</p>

<p>Second, in order for other contributors to submit patches to the sub-project
code, they will first need to obtain the full history of the
sub-project. (Which makes sense, because the whole point of this was
to NOT transfer the full history during a clone.)</p>

<p>As far as I know, the best approach to get the history is to just pull
it from the sub-project's remote URL into a <code>tmp</code> directory:</p>

<pre><code>git clone git://hostname.com/repository.git tmp
mv tmp/.git sub_project/.subgit
rm -rf tmp

-or-

hg clone http://hostname.com/repo/path/ tmp
mv tmp/.hg sub_project/.subhg
rm-rf tmp
</code></pre>

<p>Then, switch to the <code>sub_project</code> directory and checkout the right
version. (This assumes your sub-project is in a directory named <code>sub_project</code>.)</p>

<h2>Downloads:</h2>

<ul>
<li><a href="http://gist.github.com/285365">Source code</a> for <code>subgit</code>.</li>
<li><a href="http://gist.github.com/285368">Source code</a> for <code>subhg</code>.</li>
</ul>
]]></content:encoded></rss:item><rss:item rdf:about="http://rklophaus.com/blog/2009/12/19/nitrogenriak-video-from-euc2009-stockholm.html"><rss:title>Nitrogen/Riak Video from EUC2009, Stockholm</rss:title><rss:link>http://rklophaus.com/blog/2009/12/19/nitrogenriak-video-from-euc2009-stockholm.html</rss:link><dc:creator>Rusty</dc:creator><dc:date>2009-12-19T13:55:54Z</dc:date><dc:subject></dc:subject><content:encoded><![CDATA[<p>The fine folks over at <a href="http://www.erlang-consulting.com/">Erlang Solutions, Ltd.</a> just released the video of my talk "Nitrogen and Riak by Example" from Erlang User Conference 2009 in Stockholm.</p>

<ul>
<li><a href="http://vimeo.com/8258045">Watch the Video</a></li>
<li><a href="http://www.erlang-factory.com/upload/presentations/202/ErlangUserConference2009-RustyKlophaus.pdf">See the slides</a></li>
</ul>

<p><span class="full-image-block ssNonEditable"><span><img src="http://rklophaus.com/storage/euc2009_crowd.png?__SQUARESPACE_CACHEVERSION=1261519052018" alt=""/></span></span></p>

<p><span class="full-image-block ssNonEditable"><span><img src="http://rklophaus.com/storage/euc2009_Nitrogen.png?__SQUARESPACE_CACHEVERSION=1261232160771" alt=""/></span></span></p>

<p><span class="full-image-block ssNonEditable"><span><img src="http://rklophaus.com/storage/euc2009_riak.png?__SQUARESPACE_CACHEVERSION=1261232174277" alt=""/></span></span></p>

<p><span class="full-image-block ssNonEditable"><span><img src="http://rklophaus.com/storage/euc2009_code.png?__SQUARESPACE_CACHEVERSION=1261232185168" alt=""/></span></span></p>
]]></content:encoded></rss:item><rss:item rdf:about="http://rklophaus.com/blog/2009/12/5/nitrogen-riak-and-1000-lines-of-erlang.html"><rss:title>Nitrogen, Riak, and 1,000 Lines of Erlang</rss:title><rss:link>http://rklophaus.com/blog/2009/12/5/nitrogen-riak-and-1000-lines-of-erlang.html</rss:link><dc:creator>Rusty</dc:creator><dc:date>2009-12-05T15:37:24Z</dc:date><dc:subject></dc:subject><content:encoded><![CDATA[<p>UPDATE: <a href="http://rklophaus.com/blog/2009/12/19/nitrogenriak-video-from-euc2009-stockholm.html">See the video</a> of my talk on Nitrogen, Riak, and SlideBlast.com.</p>

<hr />

<p>Check out <a href="http://slideblast.com">SlideBlast.com</a>, a tool I created that lets you share and control a slide presentation on the web. SlideBlast was built using Nitrogen and Riak, and is an example of exactly how much you can do with the right tools and 1,000 lines of code. (Ok, it's more like 1,130 lines, but who's counting?) </p>

<p>The full source code is available on GitHub: <a href="http://github.com/rklophaus/SlideBlast">http://github.com/rklophaus/SlideBlast</a></p>

<p><center>
<a href="http://slideblast.com"><img border=0 src=http://slideblast.com/images/SlideBlastLogo.png /></a>
</center></p>

<h3>How it Works</h3>

<ol>
<li>Upload a .pdf or .zip file.</li>
<li>Share a link with your remote audience.</li>
<li>Start presenting. As you flip through slides, your attendees' slides change, too.</li>
</ol>

<h3>Components</h3>

<p>SlideBlast runs on <a href="http://erlang.org/">Erlang</a> and uses the following projects:</p>

<ul>
<li><a href="http://nitrogenproject.com">Nitrogen</a> to create a slick, <a href="http://en.wikipedia.org/wiki/Comet_%28programming%29">Comet-based</a> user interface. </li>
<li><a href="http://riak.basho.com">Riak</a> to store slide show data (including the images) with a flexible schema.</li>
<li><a href="http://code.google.com/p/mochiweb/">Mochiweb</a> as the underlying HTTP server.</li>
<li><a href="http://pages.cs.wisc.edu/~ghost/">Ghostscript</a> to split and convert .pdf files into images.</li>
<li><a href="http://www.imagemagick.org/script/index.php">Imagemagick</a> to create image thumbnails.</li>
<li><a href="http://alexgorbatchev.com/wiki/SyntaxHighlighter">SyntaxHighlighter</a> to transform uploaded code files into beautiful HTML.<br>(Try uploading an .erl, .cs, .cpp, .js, .java, .sh, or .sql file!)</li>
</ul>

<h3>Why I Built SlideBlast.com</h3>

<p>I built SlideBlast for my talk <a href="http://erlang-factory.com/conference/ErlangUserConference2009/speakers/RustyKlophaus">Nitrogen and Riak by Example</a>, presented at the Erlang User Conference 2009 in Stockholm, Sweden. In the presentation, I briefly cover both Nitrogen and Riak, and then describe some of the techniques used to build SlideBlast. The video should be online soon, check it out.</p>
]]></content:encoded></rss:item><rss:item rdf:about="http://rklophaus.com/blog/2009/12/3/blogging-to-squarespace-with-textmate.html"><rss:title>Blogging to SquareSpace with TextMate</rss:title><rss:link>http://rklophaus.com/blog/2009/12/3/blogging-to-squarespace-with-textmate.html</rss:link><dc:creator>Rusty</dc:creator><dc:date>2009-12-04T00:10:55Z</dc:date><dc:subject></dc:subject><content:encoded><![CDATA[<p>TextMate has a <a href="http://blog.macromates.com/2006/blogging-from-textmate/">Blogging Bundle</a>. It allows you to edit and update blog posts from within Textmate and works with any blog that uses the <a href="http://www.xmlrpc.com/metaWeblogApi">MetaWebLog API</a>. Unfortunately, it failed to work correctly with my <a href="http://squarespace.com">SquareSpace</a> blog, returning this cryptic error:</p>

<pre><code>    Error: Error parsing request: Malformed request: \
    com.squarespace.framework.ResourceNotFoundException: Invalid Object Reference (2)
</code></pre>

<p>After a little debugging, I realized that it works if you include the ID of your SquareSpace blog in the endpoint XML-RPC URL. For SquareSpace, your XML-RPC endpoint URL should look like this:</p>

<pre><code>    http://www.squarespace.com/do/process/external/PostInterceptor#BLOG_ID
</code></pre>

<p>To figure out the correct value for BLOG_ID, go to the url of your SquareSpace journal (for example, mine is http://rklophaus.com/blog), view source, and search for "CURRENT_MODULE_ID". You will see a line that says:</p>

<pre><code>    Squarespace.Constants.CURRENT_MODULE_ID = "&lt;YOUR BLOG ID&gt;";
</code></pre>

<p>This is the ID that you should use. The ID for this blog is 3142087, so my endpoint looks like this:</p>

<pre><code>    http://www.squarespace.com/do/process/external/PostInterceptor#3142087
</code></pre>]]></content:encoded></rss:item><rss:item rdf:about="http://rklophaus.com/blog/2009/12/1/the-bilski-case-and-software-patents.html"><rss:title>The Bilski Case and Software Patents</rss:title><rss:link>http://rklophaus.com/blog/2009/12/1/the-bilski-case-and-software-patents.html</rss:link><dc:creator>Rusty</dc:creator><dc:date>2009-12-02T00:40:00Z</dc:date><dc:subject>Blog Post patent</dc:subject><content:encoded><![CDATA[<p>Something happened in the second week of November that could forever change the face of the software industry. (No, I'm not referring to the release of <a href="http://golang.com">Go Lang</a>.)</p>

<p>On November 9th, the Supreme Court heard oral arguments <em>in re Bilski</em>. (<em>In re Bilski</em> means "in the matter of Bilski." I looked it up for you.) </p>

<p>The outcome of this case determines the future of software patents.</p>

<h3>What's a "Bilski"?</h3>

<p>Back in 1997, Bilski and Warsaw filed a patent for managing risk in commodities trading through hedging. Using their process, for example, an oil company would be able to offer a locked-in rate to customers, and do some fancy purchasing behind the scenes to cover their asses so that if oil prices spiked, they would still turn a reasonable profit.</p>

<p>The US Patent Office (USPTO) denied the patent because it did not pass the "machine-or-transformation" test. This test says that for a business process to be patentable, it must either be implemented with a particular machine designed or adapted to carry out the process, OR it must transform/reduce an article into a different state. </p>

<p>The problem with the USPTO's decision is that it contradicted precedent set by the Federal Circuit Court.</p>

<h3>"Ruh Roh"</h3>

<p>Ruh Roh indeed, Scoob. The Federal Circuit Court previously held in <a href="http://en.wikipedia.org/wiki/State_Street_Bank_v._Signature_Financial_Group">State Street</a>, that an invention is patentable if "it produces a useful, concrete and tangible result" and applies to a specific application, tests that Bilski's patent should have passed. </p>

<p>The Bilski team appealed to the Board of Patent Appeals, with no luck. So they appealed again to the Federal Circuit Court, who you would think would quickly overrule the Board's decision, citing State Street. The Circuit Court, however, agreed with the USPTO, saying in effect that they were wrong before, that the State Street ruling no longer applied, and that the machine-or-transformation test is now the one true test.</p>

<p>Interestingly, the Circuit Court included language in the decision stating more or less "holy crap guys, ever since the State Street decision we've been overwhelmed with business process patents, these damn patents are getting more and more abstract, and we need to streamline this process lest we get buried in paperwork."</p>

<h3>When all else fails, talk to "Los Jefes"</h3>

<p>Bilski appealed again, to the Supreme Court, which granted <em>certiorari</em> in June. (<em>Certiorari</em> means that they would hear the case. Again, I looked it up for you.) The surprisingly readable <a href="http://www.supremecourtus.gov/oral_arguments/argument_transcripts/08-964.pdf">oral arguments</a> occurred on November 9th, which brings us to the present day.</p>

<p>(See <a href="http://www.finnegan.com/files/Uploads/Documents/Bilski%20Timeline%20Final%20PDF.pdf">a timeline</a> of these events.)</p>

<h3>So, how does this relate to software?</h3>

<p>Software was seen as patentable as a business process because it produced a useful, concrete and tangible result. By discarding the State Street precedent, the Federal Circuit Court questioned the foundation upon which business process patents, and thus software patents, are built.</p>

<p>If the Supreme Court <em>upholds</em> the Federal Circuit Court's decision, it means that all existing US software patents will be very, very suspect, and <a href="http://stallman.org/">RMS</a> will be a happy, happy man.</p>

<p>If the Supreme Court <em>completely overrules</em> the Federal Circuit Court's decision, it will mean we keep the status quo, a continuation of the muddy quagmire that surrounds software patents today.</p>

<p>This is a black-and-white summary of the outcomes, of course. It is likely that the Supreme Court will shoot for the gray area in between.</p>

<h3>Don't Forget The Economy</h3>

<p>As exciting as it may be, the Supreme Court won't shake things up too much. Technology is one of the few industries in the United States that hasn't been gutted by the recession. At best, sweeping away software patents will plant some serious concerns in the minds of investors. At worst, their concerns will be justified. I suspect that of all of the factors the Supreme Court considers, the health of the economy will be what guides them the most.</p>

<h3>It's Broke, Fix It</h3>

<p>Rather than rehash all of the arguments for and against software patents, I'll provide you with a Google search for <a href="http://www.google.com/#q=software+patent+debate">software patent debate</a>.</p>

<p>To be honest, I'm still not sure which side I support on the issue. I do know that software patents--in their current form--are broken, because:</p>

<ul>
<li>Software patents alone don't do much. You need a patent plus gobs of money.</li>
<li>A good chunk of innovation in software industry comes from teams of smart people at startup companies.</li>
<li>Startup companies don't have gobs of money, and if they did, they'd prefer to spend it building things, not fiddling with patents.</li>
</ul>

<p>Can't wait to hear what the Supreme Court decides.</p>
]]></content:encoded></rss:item><rss:item rdf:about="http://rklophaus.com/blog/2009/9/16/gproc-erlang-global-process-registry.html"><rss:title>gproc - Erlang Global Process Registry</rss:title><rss:link>http://rklophaus.com/blog/2009/9/16/gproc-erlang-global-process-registry.html</rss:link><dc:creator>Rusty</dc:creator><dc:date>2009-09-16T12:29:00Z</dc:date><dc:subject></dc:subject><content:encoded><![CDATA[<p><i>
First blog post from my new position at <a href="http://www.basho.com">Basho Technologies</a>, home of <a href="http://riak.basho.com">Riak</a>, a fast, flexible, scalable, operationally-easy data store written in Erlang. 
In this post, I examine <a href="http://svn.ulf.wiger.net/gproc/">gproc</a>, an improved global process registry written in 2007 by <a href="http://ulf.wiger.net/weblog/">Ulf Wiger</a>, for possible use by <a href="http://riak.basho.com">Riak</a> and <a href="http://nitrogenproject.com">Nitrogen</a>.</p>

<h2></i></h2>

<h3>The Erlang Process Registry</h3>

<p>Very often in Erlang, you want to create a process and give it a name. This allows you to send messages to that process from other processes without passing the Pid around. Erlang supports named processes using erlang:register(Name, Pid), but there are limitations.</p>

<ul>
<li>The Name must be an atom.</li>
<li>A process can only have one, and a name can be associated with only one process.</li>
<li>The local and global registries are separate. (A process is registered globally via global:register_name(Name, Pid).)</li>
<li>There can be a lag between when a process is registered, and when it can receive messages under its registered name. ie: calling "register(myprocess, self())", and then immediately calling "myprocess ! message", can cause an error.</li>
</ul>

<p>These limitations constrain the way Erlang developers architect and debug applications. With a more robust process registry capable of storing additional metadata about each registered process, a developer can better decouple the responsibilities of an application, or gather information about running processes for debugging or reporting purposes.</p>

<p>Some concrete examples: </p>

<p>Riak spins off a new process for each get, put, and delete operation. There is currently no way to tell how many data operations are running at any one time, or to look inside a process once it is running to see what bucket it will modify. Ideally, this could be attached as metadata to the process, and a separate monitoring application could fetch this data and display it on the Riak Web dashboard.</p>

<p>Nitrogen spins off a process for a user's session. Ideally, on subsequent requests Nitrogen could look up the session process in the registry based on the user's cookie. For now, a separate lookup structure is used.</p>

<h3>GProc</h3>

<p><a href="http://ulf.wiger.net/weblog/">Ulf Wiger</a>, back in his days at Ericcson (he is currently the CTO of <a href="http://www.erlang-consulting.com/">Erlang Training and Consulting</a>, noticed that he and other engineers were repeatedly (re)creating their own process registry structures in the form of lists and lookup tables as a way of working around the limitations described above. </p>

<p>To solve the problem in a more general fashion, Ulf created gproc. (Well, he first created proc, and then--with the insight he gained--created gproc.)</p>

<p>gproc lets you:</p>

<ul>
<li>associate one or more names with a process, where a name can be any Erlang term</li>
<li>attach one or more arbitrary properties to a process, where the key or value can be any Erlang term</li>
<li>associate a counter with a process (with an optional rollup to aggregate counters across multiple processes), where the process name can be any Erlang term</li>
<li>retrieve any of these keys and values using ETS style wildcard matching</li>
</ul>

<p>gproc can be confusing at first because naming processes, applying properties, and creating counters are all accomplished using gproc:reg(GProcKey, Value). This was done in the name of speed, consistency, code-reuse -- all of these operations store data in the same ETS table, and so gproc makes functions double up. </p>

<p>Furthermore, to ensure thread safety, a process can only set it's own values. To put it another way, it's as if erlang:register(Name, Pid) became erlang:register(Name) and can only act on the current process.</p>

<p>Finally, it helps to think of "registering" a process as instead "the process sets a globally unique key". Similarly, "setting a property" means "the process sets a non-unique key". </p>

<p>You'll see what I mean in the examples below.</p>

<h3>Start a shell with GProc</h3>

<p>To get a gproc playground, run the following:</p>

<pre><code>    svn checkout http://svn.ulf.wiger.net/gproc/branches/experimental-0906/gproc
    cd gproc
    erlc -I include -o ebin src/*.erl
    erl -pa ebin
    &amp;gt; application:start(sasl).
    &amp;gt; application:start(gproc).
</code></pre>

<h3>Storing a value</h3>

<p>So let's play. To store a value in gproc, call "gproc:reg({n, l, Key}, Value)"</p>

<p>Again, both Key and Value can be any Erlang term. With a type of n (for name) you can only associate one value with a key. Try it again, and gproc will throw an exception. </p>

<h3>Removing a Value</h3>

<p>To remove something from gproc, call "gproc:unreg({n, l, Key})". Alternatively, kill the process. gproc monitors all processes that have stored values. When a process dies, gproc automatically removes any values associated with that process. This can lead to some confusion when testing gproc in the Erlang shell. If you store some values in gproc, and then run a gproc operation that throws an exception, Erlang restarts your shell process, so you lose any gproc values associated with that process.</p>

<p>Though this can be confusing in the shell, this is exactly the behaviour we want from a process registry. </p>

<h3>Retrieving a Value</h3>

<p>To get your stored value, call "gproc:get_value({n, l, Key})". Note that this will only retrieve values stored by the current process. You can also use "gproc:get_value({n, l, Key}, Pid)" to get values from another pid.</p>

<h3>Who put the cookie in the cookie jar?</h3>

<p>In addition to your value, gproc stores the Pid responsible for the value. You can retrieve this by calling "gproc:lookup_pid({n, l, Key})" or "gproc:lookup_pids({p, l, Key})". (You use the former when working with registered properties and aggregated counters, and the latter when working with properties and local counters.)</p>

<h3>Taking a step back</h3>

<p>So you are probably wondering about the significance of the 3-tuple that we are passing to these functions. This tuple, of the form {Type, Scope, Key} tells gproc a few things about your value:</p>

<ul>
<li>Type is either 'n', 'p', 'c', or 'a' (n = name, p = property,&nbsp; c = counter, a = aggregate counter)</li>
<li>Scope is either 'l' or 'g' ('l' = local, 'g' = global)</li>
<li>Key is any Erlang term.</li>
</ul>

<p>So far, we have been using a type of 'n', a globally unique key, which gives us a good mechanism for uniquely naming a process. This is similar to erlang:register/2.</p>

<p>Specifying 'p', for property, lets us set a key/value pair for a process, but other processes can also set a name and value of their own.</p>

<p>Specifying 'c', for counter, lets you set and increment a local counter for a process.</p>

<p>And specifying 'a' for aggregated counter, lets you access the sum of all local counters by the same name.</p>

<p>Note: we're always using 'l' for local scope. See the 'G is for Global' note below on why I haven't written anything about global scope.</p>

<h3>Registering a Process</h3>

<p>To register a process in gproc, call "gproc:reg({n, l, Key}, ignored)". The 'ignored' atom is irrelevant here, but could be used to store some extra metadata about the process. </p>

<p>Now you can use:</p>

<ul>
<li>gproc:lookup_pid({n, l, Key}) or gproc:where({n, l, Key}) to return the Pid of the process.</li>
<li>gproc:send({n, l, Key}, Msg) to send a message to the process.</li>
</ul>

<p>These functions are also available for registered processes, but less useful:</p>

<ul>
<li>gproc:get_value({n, l, Key}) gets the value from the process that set it.</li>
<li>gproc:select/1 to gets the value from any process (more below).</li>
</ul>

<h3>Setting a Property</h3>

<p>To set a property, call "gproc:reg({p, l, Key}, Value)".</p>

<p>Now, you can use:</p>

<ul>
<li>gproc:get_value({p, l, Key}) to get the value from the process that set it.</li>
<li>gproc:select/1 to get the value from any process&nbsp; (more below).</li>
<li>gproc:lookup_pids({p, l, Key}) to return a list of processes matching the key.</li>
<li>gproc:send{p, l, Key}) to send a message to all processes matching the key.</li>
</ul>

<h3>Creating a Local Counter</h3>

<p>To create a local counter, call "gproc:reg({c, l, Key}, Integer)".</p>

<p>Now, you can use:</p>

<ul>
<li>gproc:update_counter({c, l, Key}, Integer) to increment or decrement the counter.</li>
<li>gproc:select/1 to get the counter value from any process&nbsp; (more below).</li>
<li>gproc:lookup_pids({c, l, Key}) to return a list of processes matching the key.</li>
<li>gproc:send{c, l, Key}) to send a message to all processes matching the key.</li>
</ul>

<h3>Creating an Aggregated Counter</h3>

<p>To create an aggregated counter, call "gproc:reg({a, l, Key}, Ignored)</p>

<p>Now you can use:</p>

<ul>
<li>gproc:get_value({a, l, Key}) to get the counter value from the process that set it.</li>
<li>gproc:select/1 to get the counter value from any process (more below).</li>
<li>gproc:lookup_pid({n, l, Key}) or gproc:where({n, l, Key}) to return the Pid of the process that set the counter.</li>
<li>gproc:send({n, l, Key}, Msg) to send a message to the process that set the counter.</li>
</ul>

<h3>It's Really a Shared Dictionary</h3>

<p>As you can see, gproc is really a shared dictionary with some limitations on who can store what when. Again, this leads to some confusion at first, but means that gproc can be applied to a wider variety of problems. </p>

<h3>gproc:select/1</h3>

<p>So far, we've glossed over gproc:select/1, and for good reason: it's complicated. But, it's also where gproc derives most of its power, so it pays to understand it.</p>

<p>With gproc:select/1, you can query the gproc process registry using roughly the same semantics as an <a href="http://erlang.org/doc/apps/erts/match_spec.html">ETS MatchSpec</a>. Here is a quick (and far from complete) tutorial:</p>

<p>The basic form is gproc:select(Scope, MatchSpec).</p>

<p>Scope can either be 'all', 'names', 'props', 'counters', or 'aggr_counters'.
MatchSpec is of the form [{MatchHead, Guard, Result}]. (Yes, it must be wrapped within a list.)</p>

<p>The MatchHead is a 3-tuple of the form {GProcKey, Pid, Value}. GProcKey is the 3-tuple key we've seen earlier, ie: "{n, l, Key}". 
By leaving an empty Guard ([]) for now, and using a catch-all Result (['$$']), we can already do some interesting things.</p>

<p>This will pull out every record in the process registry:</p>

<pre><code>    MatchHead = '_',
    Guard = [],
    Result = ['$$'],
    gproc:select([{MatchHead, Guard, Result}]).
</code></pre>

<p>This will pull out every record where value == value1:</p>

<pre><code>    MatchHead = {'_', '_', value1},
    Guard = [],
    Result = ['$$'],
    gproc:select([{MatchHead, Guard, Result}]).
</code></pre>

<p>You can specify a more complicated keys. This example will pull out any entry whose key would match "{myrecord, _}"</p>

<pre><code>    Key = {myrecord, '_'},
    GProcKey = {'_', '_', Key}
    MatchHead = {GProcKey, '_', '_'},
    Guard = [],
    Result = ['$$'],
    gproc:select([{MatchHead, Guard, Result}]).
</code></pre>

<p>MatchHead can also use '$1' variables, which lets you start using guards to shape your select. For example, this will pull out any gproc entry whose key is a list:</p>

<pre><code>    GProcKey = {'_', '_', '$1'},
    MatchHead = {GProcKey, '_', '_'},
    Guard = [{is_list, '$1'}],
    Result = ['$$'],
    gproc:select([{MatchHead, Guard, Result}]).
</code></pre>

<p>See this gist for more examples. <a href="http://gist.github.com/188032">http://gist.github.com/188032</a>.</p>

<p>Normally, you would be able to use the Result property of the MatchSpec to select out a subset of the data you want to capture. In gproc this is slightly broken. You can choose which result you want to pull out by setting result to a '$1' variable (for example, ['$1']), but currently you can only pull out one result from each match. In other words, ['$1', '$2'] does not work. (It only returns '$2'.)</p>

<h3>GProc and QLC</h3>

<p>It appears that GProc began to have support for QLC, which is pretty friggin' sweet, but unfortunately I could not seem to make it work. </p>

<h3>G is for Global</h3>

<p>GProc automatically detects whether gen_leader is available on the system. If it is, then gproc will run in "global mode" meaning that all of the functions above work across your entire Erlang cluster rather than on a single node, which is also pretty friggin' sweet. Unfortunately, gproc currently uses an obsolete version of gen_leader, so running gproc in global mode is not recommended.</p>

<h3>Evaluation</h3>

<p>GProc is extremely powerful, but the interface could use simplification. Convenience methods around gproc:reg/2 specifically shaped for registering processes would go far to help smooth the learning curve for newcomers.</p>

<p>In addition, gproc:select/1 has a few small bugs. The MatchSpec must be passed as a list, even though it will only work with one MatchSpec, and the Result portion of the MatchSpec can only be used with one '$N' variable.</p>
]]></content:encoded></rss:item><rss:item rdf:about="http://rklophaus.com/blog/2009/6/2/nitrogen-at-the-erlang-factory-across-the-pond.html"><rss:title>Nitrogen at the Erlang Factory across the Pond</rss:title><rss:link>http://rklophaus.com/blog/2009/6/2/nitrogen-at-the-erlang-factory-across-the-pond.html</rss:link><dc:creator>Rusty</dc:creator><dc:date>2009-06-02T03:06:42Z</dc:date><dc:subject></dc:subject><content:encoded><![CDATA[<p>Have had too much to write about lately, and not enough time to write it.</p>
<p>In less than a month I'll be heading out to London to speak about <a href="http://nitrogenproject.com">Nitrogen</a> at the <a href="http://erlang-factory.com/conference/London2009">Erlang Factory</a>. I've booked a little extra time before and after the trip to go sip some tea, see Big Ben, high five the Queen, and <a href="http://news.bbc.co.uk/1/hi/sci/tech/677048.stm">ride in a London cab</a>.</p>
<p>In the meantime, Nitrogen is undergoing some big changes. The improvements were inspired by conversations and presentations at Erlang Factory San Francisco as well as <a href="http://www.brics.dk/~hosc/local/HOSC-12-3-pp221-236.pdf">Growing a Language</a> by Guy Steele.</p>
<p>The main goals are to:</p>
<ul>
<li>Allow Nitrogen to cooperate with--rather than compete against--some of the other great work out there, including <a href="http://bitbucket.org/justin/webmachine/wiki/Home">Webmachine</a>, <a href="http://www.erlang-web.org/">Erlang Web</a>, <a href="http://erlyweb.org/">ErlyWeb</a>, etc.</li>
<li>Make it easier for the Nitrogen community to customize caching, sessions, state management, and many of the other things that get more complicated as a site grows.</li>
</ul>
<p>Early prototypes are looking good. Hopefully I'll have some great stuff to show off by the time the 'Factory starts.</p>]]></content:encoded></rss:item><rss:item rdf:about="http://rklophaus.com/blog/2009/3/29/nitrogen-at-the-erlang-factory.html"><rss:title>Nitrogen at the Erlang Factory</rss:title><rss:link>http://rklophaus.com/blog/2009/3/29/nitrogen-at-the-erlang-factory.html</rss:link><dc:creator>Rusty</dc:creator><dc:date>2009-03-29T22:59:36Z</dc:date><dc:subject></dc:subject><content:encoded><![CDATA[<p>Very excited to be&nbsp;<a href="http://www.erlang-factory.com/conference/SFBayAreaErlangFactory2009/speakers">presenting</a> at the <a href="http://www.erlang-factory.com/">Erlang Factory</a> in Palo Alto, CA at the end of April. I will be giving an hour long talk about <a href="http://nitrogenproject.com/">Nitrogen</a>, a cutting-edge web framework that I created that is quickly building momentum in the <a href="http://erlang.org/">Erlang</a> community.</p>
<p>Some sample pages written in Nitrogen:</p>
<ul>
<li><a href="http://nitrogenproject.com/web/samples/ajax">Ajax</a> and <a href="http://nitrogenproject.com/web/samples/comet2">Comet</a> page updates</li>
<li><a href="http://nitrogenproject.com/web/samples/validation">Form Validation</a></li>
<li><a href="http://nitrogenproject.com/web/samples/upload">Streaming Http File Uploads</a></li>
<li><a href="http://nitrogenproject.com/web/samples/dragdrop">Dragging and Dropping</a></li>
<li><a href="http://nitrogenproject.com/web/samples/sorting1">Sorting</a></li>
</ul>]]></content:encoded></rss:item><rss:item rdf:about="http://rklophaus.com/blog/2009/2/25/youre-sitting-on-a-chair-in-the-sky.html"><rss:title>"You're sitting on a chair... in the sky."</rss:title><rss:link>http://rklophaus.com/blog/2009/2/25/youre-sitting-on-a-chair-in-the-sky.html</rss:link><dc:creator>Rusty</dc:creator><dc:date>2009-02-25T16:18:52Z</dc:date><dc:subject></dc:subject><content:encoded><![CDATA[<p>It's very rare that I laugh out loud while sitting alone.&nbsp;</p>
<p>This clip did the trick -&nbsp;<a style="text-decoration: none;" href="http://www.kk.org/thetechnium/archives/2009/02/so_amazing_but.php">http://www.kk.org/thetechnium/archives/2009/02/so_amazing_but.php</a></p>
<p>(By comedian Louis C.K.)</p>]]></content:encoded></rss:item><rss:item rdf:about="http://rklophaus.com/blog/2009/2/24/clara-needs-her-own-tv-show.html"><rss:title>Clara needs her own TV show.</rss:title><rss:link>http://rklophaus.com/blog/2009/2/24/clara-needs-her-own-tv-show.html</rss:link><dc:creator>Rusty</dc:creator><dc:date>2009-02-24T02:32:27Z</dc:date><dc:subject></dc:subject><content:encoded><![CDATA[<p>This is great: <a href="http://www.greatdepressioncooking.com/Depression_Cooking/Episodes.html">http://www.greatdepressioncooking.com</a></p>
<p>&nbsp;</p>]]></content:encoded></rss:item></rdf:RDF>