<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Erlang, Testing and TDD</title>
	<atom:link href="http://erlcode.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://erlcode.wordpress.com</link>
	<description>Dr Coverage says: &#34;80% a day, keeps the bugs away&#34;</description>
	<lastBuildDate>Wed, 02 May 2012 20:45:53 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='erlcode.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Erlang, Testing and TDD</title>
		<link>http://erlcode.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://erlcode.wordpress.com/osd.xml" title="Erlang, Testing and TDD" />
	<atom:link rel='hub' href='http://erlcode.wordpress.com/?pushpress=hub'/>
		<item>
		<title>&#8220;Weekly&#8221; exercise problems on GitHub</title>
		<link>http://erlcode.wordpress.com/2012/04/01/weekly-exercise-problems-on-github/</link>
		<comments>http://erlcode.wordpress.com/2012/04/01/weekly-exercise-problems-on-github/#comments</comments>
		<pubDate>Sun, 01 Apr 2012 09:53:34 +0000</pubDate>
		<dc:creator>gianfrancoalongi</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://erlcode.wordpress.com/?p=699</guid>
		<description><![CDATA[So, it was a while ago that I posted anything here, mostly because my eye or sauron has been fixed upon other stuff (me and my wife bought a flat, Bash and APL), but also because I am trying to build an open TDD Exercise repository with language agnostic problems. I will mainly update the [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=erlcode.wordpress.com&#038;blog=15510807&#038;post=699&#038;subd=erlcode&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>So, it was a while ago that I posted anything here, mostly because my eye or sauron has been fixed upon other stuff (me and my wife bought a flat, Bash and APL), but also because I am trying to build an <a title="TDD Exercises" href="https://github.com/Gianfrancoalongi/TDD-Exercises" target="_blank">open TDD Exercise repository</a> with language agnostic problems.</p>
<p>I will mainly update the repo but also try to post here more frequently when I come across something interesting.</p>
<p>The repo solutions have been Makefile and non-OTP centric to keep it simple and on a level comprehensible for all.<br />
However, I will be including more and more of the standard production level tools and components.</p>
<p>As for now, the aim is to keep it weekly or bi-weekly if I notice that I don&#8217;t have the time. Right now it&#8217;s that way.</p>
<p>/G</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/erlcode.wordpress.com/699/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/erlcode.wordpress.com/699/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=erlcode.wordpress.com&#038;blog=15510807&#038;post=699&#038;subd=erlcode&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://erlcode.wordpress.com/2012/04/01/weekly-exercise-problems-on-github/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/861b8f824c3cd15c17ac6aa1b902e029?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">gianfrancoalongi</media:title>
		</media:content>
	</item>
		<item>
		<title>Erlang TDD hand on project &#8211; WorkerNet part 8</title>
		<link>http://erlcode.wordpress.com/2011/03/05/erlang-tdd-hand-on-project-workernet-part-8/</link>
		<comments>http://erlcode.wordpress.com/2011/03/05/erlang-tdd-hand-on-project-workernet-part-8/#comments</comments>
		<pubDate>Sat, 05 Mar 2011 15:46:09 +0000</pubDate>
		<dc:creator>gianfrancoalongi</dc:creator>
				<category><![CDATA[WorkerNet]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[workernet]]></category>

		<guid isPermaLink="false">http://erlcode.wordpress.com/?p=685</guid>
		<description><![CDATA[Last story to play  on the workernet job layer, “I want to be able to delete a job once it’s done, through any node.” To design this &#8211; the test is written first (as usual) done_job_deleted() -&#62; wn_resource_layer:register(#wn_resource{name = "Laptop", type = [{perl,1}], resides = node() }), Path = create_file_at(?NODE_ROOT), File1 = #wn_file{id = "File1",file [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=erlcode.wordpress.com&#038;blog=15510807&#038;post=685&#038;subd=erlcode&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Last story to play  on the workernet job layer,</p>
<p>“<em>I want to be able to delete a job once it’s done, through any node</em>.”</p>
<p>To design this &#8211; the test is written first (as usual)</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">done_job_deleted</span>() -&gt;
    <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(#<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"Laptop"</span>,
                                     <span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">perl</span>,1}],
                                     <span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()
                                    }),
    <span style="color:#eedd82;">Path</span> = <span style="color:#98fb98;">create_file_at</span>(?<span style="color:#b0c4de;">NODE_ROOT</span>),
    <span style="color:#eedd82;">File1</span> = #<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"File1"</span>,<span style="color:#7fffd4;">file</span> = <span style="color:#eedd82;">Path</span>,<span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()},
    <span style="color:#eedd82;">Job1</span> = #<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId"</span>,
                   <span style="color:#7fffd4;">files</span> = [<span style="color:#eedd82;">File1</span>],
                   <span style="color:#7fffd4;">resources</span> = [<span style="color:#7fffd4;">perl</span>],
                   <span style="color:#7fffd4;">commands</span> = [<span style="color:#ffa07a;">"perl -e 'print(\"HelloWorld\n\")'"</span>],
                   <span style="color:#7fffd4;">timeout</span> = 1000
                  },
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">Job1</span>),
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">stream</span>(<span style="color:#7fffd4;">user</span>,<span style="color:#ffa07a;">"JobId"</span>),
    <span style="color:#98fb98;">timer</span>:<span style="color:#98fb98;">sleep</span>(500),
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#ffa07a;">"JobId"</span>),
    ?<span style="color:#b0c4de;">assertMatch</span>([#<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span>=<span style="color:#ffa07a;">"File1"</span>}],<span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">list_files</span>()),
    ?<span style="color:#b0c4de;">assertEqual</span>([],<span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">list_all_jobs</span>()),
    <span style="color:#7fffd4;">ok</span>.</pre>
<p><!-- End Of Snippet --></p>
<p>As usual, this will not even compile first as stuff is missing and dialyzer should get a headache about it. Now, everything is there except the <em>wn_job_layer:delete/1</em> function.</p>
<p>Therefore, the first implementation goes into <em>wn_job_layer.erl</em></p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">delete</span>(<span style="color:#98fb98;">string</span>()) -&gt; <span style="color:#7fffd4;">ok</span> | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).
<span style="color:#87cefa;">delete</span>(<span style="color:#eedd82;">Id</span>) -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,{<span style="color:#7fffd4;">delete</span>,<span style="color:#eedd82;">Id</span>}).</pre>
<p><!--- End Of Snippet --></p>
<p>next the internal handle_call/3 clause for handling the delete request</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_call</span>({<span style="color:#7fffd4;">delete</span>,<span style="color:#eedd82;">Id</span>},<span style="color:#eedd82;">_</span>,<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#eedd82;">Result</span> = <span style="color:#98fb98;">try_delete</span>(<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">State</span>),
    {<span style="color:#7fffd4;">reply</span>,<span style="color:#eedd82;">Result</span>,<span style="color:#eedd82;">State</span>};</pre>
<p><!--- End Of Snippet --></p>
<p>this raises the need to implement the internal try_delete/2 function</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">try_delete</span>(<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">lookup</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">jobs</span>,<span style="color:#eedd82;">Id</span>) <span style="color:#00ffff;">of</span>
        [{<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">_</span>}] -&gt;
            <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">get_stored_result</span>(<span style="color:#eedd82;">JobKeeperPid</span>) <span style="color:#00ffff;">of</span>
                {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">Result</span>} -&gt;
                    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">JobKeeperPid</span>),
                    <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">jobs</span>,<span style="color:#eedd82;">Id</span>),
                    <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">delete_file</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#eedd82;">Result</span>);
                <span style="color:#eedd82;">X</span> -&gt; <span style="color:#eedd82;">X</span>
            <span style="color:#00ffff;">end</span>;
        [] -&gt;
            {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">no_such_job</span>}
    <span style="color:#00ffff;">end</span>.</pre>
<p><!--- End Of Snippet --></p>
<p>That was all the code needed inside <em> wn_job_layer.erl </em>.  However, the last internal function brought up the need for a new function; <em>wn_job_keeper:delete/1</em> so the function is to be implemented next!</p>
<p>In <em> wn_job_keeper.erl</em></p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">delete</span>(<span style="color:#b0c4de;">pid</span>()) -&gt; <span style="color:#7fffd4;">ok</span> | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).
<span style="color:#87cefa;">delete</span>(<span style="color:#eedd82;">Pid</span>) -&gt;
    <span style="color:#98fb98;">gen_fsm</span>:<span style="color:#98fb98;">sync_send_all_state_event</span>(<span style="color:#eedd82;">Pid</span>,<span style="color:#7fffd4;">delete</span>).</pre>
<p><!--- End Of Snippet --></p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">try_delete</span>(<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">lookup</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">jobs</span>,<span style="color:#eedd82;">Id</span>) <span style="color:#00ffff;">of</span>
        [{<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">_</span>}] -&gt;
            <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">get_stored_result</span>(<span style="color:#eedd82;">JobKeeperPid</span>) <span style="color:#00ffff;">of</span>
                {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">Result</span>} -&gt;
                    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">JobKeeperPid</span>),
                    <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">jobs</span>,<span style="color:#eedd82;">Id</span>),
                    <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">delete_file</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#eedd82;">Result</span>);
                <span style="color:#eedd82;">X</span> -&gt; <span style="color:#eedd82;">X</span>
            <span style="color:#00ffff;">end</span>;
        [] -&gt;
            {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">no_such_job</span>}
    <span style="color:#00ffff;">end</span>.</pre>
<p><!--- End Of Snippet --></p>
<p>With a handle_call clause inside it for the delete request</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_sync_event</span>(<span style="color:#7fffd4;">delete</span>,<span style="color:#eedd82;">_</span>,<span style="color:#7fffd4;">done</span>,<span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">stop</span>,<span style="color:#7fffd4;">normal</span>,<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">State</span>};
<span style="color:#87cefa;">handle_sync_event</span>(<span style="color:#7fffd4;">delete</span>,<span style="color:#eedd82;">_</span>,<span style="color:#eedd82;">X</span>,<span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">reply</span>,{<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">not_done</span>},<span style="color:#eedd82;">X</span>,<span style="color:#eedd82;">State</span>};</pre>
<p><!--- End Of Snippet --></p>
<p>That would be all! Since so much had already been written in prior tests, this one turned out to be quite a breeze. Of course this passes both compilation, dialyzation and testing. The judge &#8216;make full&#8217; turns it&#8217;s mighty eye on this</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#7fffd4;">zen</span>:<span style="color:#7fffd4;">worker_net</span>-0.1 <span style="color:#7fffd4;">zenon</span><span style="color:#ffa07a;">$ </span><span style="color:#7fffd4;">make</span> <span style="color:#7fffd4;">full</span>
<span style="color:#7fffd4;">erlc</span> -<span style="color:#7fffd4;">pa</span> . -<span style="color:#7fffd4;">o</span> <span style="color:#7fffd4;">ebin</span>/  <span style="color:#7fffd4;">src</span>/*.<span style="color:#7fffd4;">erl</span> <span style="color:#7fffd4;">test</span>/*.<span style="color:#7fffd4;">erl</span>
<span style="color:#7fffd4;">erl</span> -<span style="color:#7fffd4;">pa</span> <span style="color:#7fffd4;">ebin</span>/ -<span style="color:#7fffd4;">eval</span> 'eunit:<span style="color:#98fb98;">test</span>(<span style="color:#7fffd4;">wn_resource_layer</span>,[<span style="color:#7fffd4;">verbose</span>]), <span style="color:#98fb98;">init</span>:<span style="color:#98fb98;">stop</span>().'
<span style="color:#eedd82;">Erlang</span> <span style="color:#eedd82;">R14B</span> (<span style="color:#7fffd4;">erts</span>-5.8.1) [<span style="color:#7fffd4;">source</span>] [<span style="color:#7fffd4;">smp</span>:4:4] [<span style="color:#7fffd4;">rq</span>:4] [<span style="color:#7fffd4;">async</span>-<span style="color:#7fffd4;">threads</span>:0] [<span style="color:#7fffd4;">hipe</span>] [<span style="color:#7fffd4;">kernel</span>-<span style="color:#7fffd4;">poll</span>:<span style="color:#7fffd4;">false</span>]

<span style="color:#eedd82;">Eshell</span> <span style="color:#eedd82;">V5</span>.8.1  (<span style="color:#7fffd4;">abort</span> <span style="color:#7fffd4;">with</span> ^<span style="color:#eedd82;">G</span>)
1&gt; ======================== <span style="color:#eedd82;">EUnit</span> ========================
<span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_resource_layer'</span>
  <span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_resource_layer_tests'</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">local_resource_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">register</span> <span style="color:#7fffd4;">resources</span> <span style="color:#7fffd4;">locally</span>)...[0.001 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">register_distributed</span> (<span style="color:#eedd82;">Can</span> <span style="color:#eedd82;">Register</span> <span style="color:#eedd82;">Distributed</span>)...[0.006 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">register_restart_register</span> (<span style="color:#eedd82;">Can</span> <span style="color:#eedd82;">Register</span>, <span style="color:#eedd82;">Restart</span> <span style="color:#7fffd4;">and</span> <span style="color:#eedd82;">Register</span>)...[0.015 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">register_deregister</span> (<span style="color:#eedd82;">Can</span> <span style="color:#eedd82;">Register</span>, <span style="color:#eedd82;">Deregister</span> <span style="color:#7fffd4;">and</span> <span style="color:#eedd82;">Register</span>)...[0.013 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 6.324 <span style="color:#7fffd4;">s</span>]
  [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 6.325 <span style="color:#7fffd4;">s</span>]
=======================================================
  <span style="color:#eedd82;">All</span> 4 <span style="color:#7fffd4;">tests</span> <span style="color:#7fffd4;">passed</span>.
<span style="color:#7fffd4;">erl</span> -<span style="color:#7fffd4;">pa</span> <span style="color:#7fffd4;">ebin</span>/ -<span style="color:#7fffd4;">eval</span> 'eunit:<span style="color:#98fb98;">test</span>(<span style="color:#7fffd4;">wn_file_layer</span>,[<span style="color:#7fffd4;">verbose</span>]), <span style="color:#98fb98;">init</span>:<span style="color:#98fb98;">stop</span>().'
<span style="color:#eedd82;">Erlang</span> <span style="color:#eedd82;">R14B</span> (<span style="color:#7fffd4;">erts</span>-5.8.1) [<span style="color:#7fffd4;">source</span>] [<span style="color:#7fffd4;">smp</span>:4:4] [<span style="color:#7fffd4;">rq</span>:4] [<span style="color:#7fffd4;">async</span>-<span style="color:#7fffd4;">threads</span>:0] [<span style="color:#7fffd4;">hipe</span>] [<span style="color:#7fffd4;">kernel</span>-<span style="color:#7fffd4;">poll</span>:<span style="color:#7fffd4;">false</span>]

<span style="color:#eedd82;">Eshell</span> <span style="color:#eedd82;">V5</span>.8.1  (<span style="color:#7fffd4;">abort</span> <span style="color:#7fffd4;">with</span> ^<span style="color:#eedd82;">G</span>)
1&gt; ======================== <span style="color:#eedd82;">EUnit</span> ========================
<span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_file_layer'</span>
  <span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_file_layer_tests'</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">file_layer_local_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">store</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">locally</span>)...[0.326 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">file_layer_local_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">retrieve</span> <span style="color:#7fffd4;">files</span> <span style="color:#7fffd4;">locally</span>)...[0.003 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">file_layer_local_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">delete</span> <span style="color:#7fffd4;">files</span> <span style="color:#7fffd4;">locally</span>)...[0.002 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">can_store_distributed</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">store</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">distributed</span>)...[0.024 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">can_retrieve_distributed</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">retrieve</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">distributed</span>)...[0.018 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">can_delete_distributed</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">delete</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">distributed</span>)...[0.020 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">must_retain</span> (<span style="color:#eedd82;">Must</span> <span style="color:#7fffd4;">retain</span> <span style="color:#7fffd4;">information</span> <span style="color:#7fffd4;">between</span> <span style="color:#7fffd4;">node</span> <span style="color:#7fffd4;">kill</span> <span style="color:#7fffd4;">and</span> <span style="color:#7fffd4;">node</span> <span style="color:#7fffd4;">restart</span>)...[0.391 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 2.348 <span style="color:#7fffd4;">s</span>]
  [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 2.348 <span style="color:#7fffd4;">s</span>]
=======================================================
  <span style="color:#eedd82;">All</span> 7 <span style="color:#7fffd4;">tests</span> <span style="color:#7fffd4;">passed</span>.
<span style="color:#7fffd4;">erl</span> -<span style="color:#7fffd4;">pa</span> <span style="color:#7fffd4;">ebin</span>/ -<span style="color:#7fffd4;">eval</span> 'eunit:<span style="color:#98fb98;">test</span>(<span style="color:#7fffd4;">wn_job_layer</span>,[<span style="color:#7fffd4;">verbose</span>]), <span style="color:#98fb98;">init</span>:<span style="color:#98fb98;">stop</span>().'
<span style="color:#eedd82;">Erlang</span> <span style="color:#eedd82;">R14B</span> (<span style="color:#7fffd4;">erts</span>-5.8.1) [<span style="color:#7fffd4;">source</span>] [<span style="color:#7fffd4;">smp</span>:4:4] [<span style="color:#7fffd4;">rq</span>:4] [<span style="color:#7fffd4;">async</span>-<span style="color:#7fffd4;">threads</span>:0] [<span style="color:#7fffd4;">hipe</span>] [<span style="color:#7fffd4;">kernel</span>-<span style="color:#7fffd4;">poll</span>:<span style="color:#7fffd4;">false</span>]

<span style="color:#eedd82;">Eshell</span> <span style="color:#eedd82;">V5</span>.8.1  (<span style="color:#7fffd4;">abort</span> <span style="color:#7fffd4;">with</span> ^<span style="color:#eedd82;">G</span>)
1&gt; ======================== <span style="color:#eedd82;">EUnit</span> ========================
<span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_job_layer'</span>
  <span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_job_layer_tests'</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">register</span> <span style="color:#7fffd4;">locally</span>)...[0.005 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Executed</span> <span style="color:#7fffd4;">locally</span>)...{1299,338969,204767} : <span style="color:#7fffd4;">file_fetching_done</span>
{1299,338969,204771} : <span style="color:#7fffd4;">executing_commands</span>
{1299,338969,218209} : {<span style="color:#7fffd4;">executing</span>,<span style="color:#ffa07a;">"more EUnitFile"</span>}
{1299,338969,225651} : <span style="color:#ffa07a;">"1,2,3"</span>
{1299,338969,226358} : <span style="color:#7fffd4;">no_more_commands</span>
{1299,338969,226362} : <span style="color:#7fffd4;">building_result_tgz</span>
{1299,338969,226462} : <span style="color:#7fffd4;">done</span>
[1.018 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Executed</span> <span style="color:#7fffd4;">queue</span>)...{1299,338970,229138} : <span style="color:#7fffd4;">file_fetching_done</span>
{1299,338970,229141} : <span style="color:#7fffd4;">executing_commands</span>
{1299,338970,229539} : {<span style="color:#7fffd4;">executing</span>,<span style="color:#ffa07a;">"file EunitFile"</span>}
{1299,338970,239052} : <span style="color:#ffa07a;">"EunitFile: ASCII text"</span>
{1299,338970,239301} : <span style="color:#7fffd4;">no_more_commands</span>
{1299,338970,239304} : <span style="color:#7fffd4;">building_result_tgz</span>
{1299,338970,239476} : <span style="color:#7fffd4;">done</span>
{1299,338970,243238} : <span style="color:#7fffd4;">file_fetching_done</span>
{1299,338970,243250} : <span style="color:#7fffd4;">executing_commands</span>
{1299,338970,243360} : {<span style="color:#7fffd4;">executing</span>,<span style="color:#ffa07a;">"cat EUnitFile"</span>}
{1299,338970,250730} : <span style="color:#ffa07a;">"1,2,3"</span>
{1299,338970,250782} : <span style="color:#7fffd4;">no_more_commands</span>
{1299,338970,250785} : <span style="color:#7fffd4;">building_result_tgz</span>
{1299,338970,250856} : <span style="color:#7fffd4;">done</span>
[1.105 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Queueus</span> <span style="color:#7fffd4;">on</span> <span style="color:#7fffd4;">resource</span> <span style="color:#7fffd4;">type</span> <span style="color:#7fffd4;">amount</span>)...[0.001 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Canceled</span> <span style="color:#7fffd4;">in</span> <span style="color:#7fffd4;">queue</span>)...[0.001 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Done</span> <span style="color:#eedd82;">Job</span> <span style="color:#eedd82;">Stored</span> <span style="color:#7fffd4;">in</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">layer</span>)...[0.606 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Done</span> <span style="color:#eedd82;">Job</span> <span style="color:#7fffd4;">canceled</span>)...{1299,338971,966369} : <span style="color:#7fffd4;">file_fetching_done</span>
{1299,338971,966377} : <span style="color:#7fffd4;">executing_commands</span>
{1299,338971,966651} : {<span style="color:#7fffd4;">executing</span>,<span style="color:#ffa07a;">"perl -e 'print(\"HelloWorld\n\")'"</span>}
{1299,338972,3168} : <span style="color:#ffa07a;">"HelloWorld"</span>
{1299,338972,3405} : <span style="color:#7fffd4;">no_more_commands</span>
{1299,338972,3408} : <span style="color:#7fffd4;">building_result_tgz</span>
{1299,338972,3508} : <span style="color:#7fffd4;">done</span>
[0.504 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 3.305 <span style="color:#7fffd4;">s</span>]
  [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 3.305 <span style="color:#7fffd4;">s</span>]
=======================================================
  <span style="color:#eedd82;">All</span> 7 <span style="color:#7fffd4;">tests</span> <span style="color:#7fffd4;">passed</span>.
<span style="color:#7fffd4;">dialyzer</span> <span style="color:#7fffd4;">src</span>/*.<span style="color:#7fffd4;">erl</span> <span style="color:#7fffd4;">test</span>/*.<span style="color:#7fffd4;">erl</span>
  <span style="color:#eedd82;">Checking</span> <span style="color:#7fffd4;">whether</span> <span style="color:#7fffd4;">the</span> <span style="color:#eedd82;">PLT</span> /<span style="color:#eedd82;">Users</span>/<span style="color:#7fffd4;">zenon</span>/.<span style="color:#7fffd4;">dialyzer_plt</span> <span style="color:#7fffd4;">is</span> <span style="color:#7fffd4;">up</span>-<span style="color:#7fffd4;">to</span>-<span style="color:#7fffd4;">date</span>... <span style="color:#7fffd4;">yes</span>
  <span style="color:#eedd82;">Proceeding</span> <span style="color:#7fffd4;">with</span> <span style="color:#7fffd4;">analysis</span>...
<span style="color:#eedd82;">Unknown</span> <span style="color:#7fffd4;">functions</span>:
  <span style="color:#7fffd4;">eunit</span>:<span style="color:#87cefa;">test/1</span>
 <span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0m6.92s
<span style="color:#87cefa;">done</span> (<span style="color:#7fffd4;">passed</span> <span style="color:#7fffd4;">successfully</span>)
<span style="color:#7fffd4;">zen</span>:<span style="color:#7fffd4;">worker_net</span>-0.1 <span style="color:#7fffd4;">zenon</span><span style="color:#ffa07a;">$ </span></pre>
<p><!--- End Of Snippet --></p>
<h3>The end</h3>
<h3>This concludes the TDD hands on project for the WorkerNet &#8211; the source can now be found through my github repository for this.</h3>
<p>git://github.com/Gianfrancoalongi/WorkerNet.git</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/erlcode.wordpress.com/685/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/erlcode.wordpress.com/685/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=erlcode.wordpress.com&#038;blog=15510807&#038;post=685&#038;subd=erlcode&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://erlcode.wordpress.com/2011/03/05/erlang-tdd-hand-on-project-workernet-part-8/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/861b8f824c3cd15c17ac6aa1b902e029?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">gianfrancoalongi</media:title>
		</media:content>
	</item>
		<item>
		<title>Erlang TDD hands on project &#8211; part 7</title>
		<link>http://erlcode.wordpress.com/2011/03/01/erlang-tdd-hands-on-project-part-7/</link>
		<comments>http://erlcode.wordpress.com/2011/03/01/erlang-tdd-hands-on-project-part-7/#comments</comments>
		<pubDate>Tue, 01 Mar 2011 21:07:42 +0000</pubDate>
		<dc:creator>gianfrancoalongi</dc:creator>
				<category><![CDATA[WorkerNet]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[workernet]]></category>

		<guid isPermaLink="false">http://erlcode.wordpress.com/?p=633</guid>
		<description><![CDATA[This evenings entertainment is “Once a job is done, the result should be stored in the file layer,  together with the logs.“ A new test needs to be devised to prove the result is stored in the file layer once a job is done. Of course the test is put in  wn_job_layer_tests.erl . The test [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=erlcode.wordpress.com&#038;blog=15510807&#038;post=633&#038;subd=erlcode&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>This evenings entertainment is</p>
<p>“<em>Once a job is done, the result should be stored in the file layer,  together with the logs.</em>“</p>
<p>A new test needs to be devised to prove the result is stored in the file layer once a job is done. Of course the test is put in  <em>wn_job_layer_tests.erl . </em>The test  can be seen below &#8211; and as always &#8211; the test is written  <em>first. </em></p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">stored_in_file_layer</span>() -&gt;
    <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">(1)
</span>    <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(#<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"Laptop"</span>,
                                     <span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">laptop</span>,1}],
                                     <span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()
                                    }),
    <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">(2)
</span>    <span style="color:#eedd82;">Path</span> = <span style="color:#98fb98;">create_file_at</span>(?<span style="color:#b0c4de;">NODE_ROOT</span>),
    <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">(3)
</span>    <span style="color:#eedd82;">File1</span> = #<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"File1"</span>,<span style="color:#7fffd4;">file</span> = <span style="color:#eedd82;">Path</span>,<span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()},
    <span style="color:#eedd82;">Job1</span> = #<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId"</span>,
                   <span style="color:#7fffd4;">files</span> = [<span style="color:#eedd82;">File1</span>],
                   <span style="color:#7fffd4;">resources</span> = [<span style="color:#7fffd4;">laptop</span>],
                   <span style="color:#7fffd4;">commands</span> = [<span style="color:#ffa07a;">"cat EunitFile"</span>,<span style="color:#ffa07a;">"touch MadeFile"</span>],
                   <span style="color:#7fffd4;">timeout</span> = 100
                  },
    <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">(4)
</span>    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">Job1</span>),
    <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">(5)
</span>    <span style="color:#98fb98;">timer</span>:<span style="color:#98fb98;">sleep</span>(500),

    <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">(6)
</span>    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">T</span>} = <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">finished_at</span>(<span style="color:#ffa07a;">"JobId"</span>),

    <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">(7)
</span>    <span style="color:#eedd82;">TimeSuffix</span> = <span style="color:#98fb98;">wn_util</span>:<span style="color:#98fb98;">time_marker_to_string</span>(<span style="color:#eedd82;">T</span>),
    <span style="color:#eedd82;">ExpectedFileName</span> = <span style="color:#ffa07a;">"JobId_result_"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">TimeSuffix</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">".tgz"</span>,
    <span style="color:#eedd82;">ExpectedFileId</span> = <span style="color:#ffa07a;">"JobId_result"</span>,
    <span style="color:#eedd82;">ExpectedFiles</span> = [<span style="color:#eedd82;">F1</span>,<span style="color:#eedd82;">F2</span>,<span style="color:#eedd82;">F3</span>] = [<span style="color:#ffa07a;">"EUnitFile"</span>,<span style="color:#ffa07a;">"MadeFile"</span>,<span style="color:#ffa07a;">"Log.txt"</span>],

    <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">(8)
</span>    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">ResultId</span>} = <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">stored_result</span>(<span style="color:#ffa07a;">"JobId"</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#eedd82;">ExpectedFileId</span>,<span style="color:#eedd82;">ResultId</span>),

    <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">(9)
</span>    [<span style="color:#eedd82;">_</span>,<span style="color:#eedd82;">Res</span>] = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">list_files</span>(),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#eedd82;">ExpectedFileName</span>,<span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Res</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">file</span>)),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#eedd82;">ExpectedFileId</span>,<span style="color:#eedd82;">Res</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">id</span>),

    <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">(10)
</span>    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">Tar</span>} = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">retrieve_file</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#eedd82;">ResultId</span>),
    ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">ExpectedFiles</span>},<span style="color:#98fb98;">erl_tar</span>:<span style="color:#98fb98;">table</span>(<span style="color:#eedd82;">Tar</span>,[<span style="color:#7fffd4;">compressed</span>])),

    <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">(11)
</span>    <span style="color:#98fb98;">erl_tar</span>:<span style="color:#98fb98;">extract</span>(<span style="color:#eedd82;">Tar</span>,[{<span style="color:#7fffd4;">files</span>,[<span style="color:#eedd82;">F3</span>]},<span style="color:#7fffd4;">compressed</span>]),
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">IoDev</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">open</span>(<span style="color:#ffa07a;">"local_stream.txt"</span>,[<span style="color:#7fffd4;">write</span>]),
    <span style="color:#7fffd4;">ok</span>  = <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">stream</span>(<span style="color:#eedd82;">IoDev</span>,<span style="color:#ffa07a;">"JobId"</span>),
    <span style="color:#98fb98;">timer</span>:<span style="color:#98fb98;">sleep</span>(100),
    <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">close</span>(<span style="color:#eedd82;">IoDev</span>),
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">LocalStreamBin</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">read_file</span>(<span style="color:#ffa07a;">"local_stream.txt"</span>),
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">JobLogBin</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">read_file</span>(<span style="color:#eedd82;">F3</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#eedd82;">LocalStreamBin</span>,<span style="color:#eedd82;">JobLogBin</span>),    

    <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">(12)
</span>    <span style="color:#98fb98;">erl_tar</span>:<span style="color:#98fb98;">extract</span>(<span style="color:#eedd82;">Tar</span>,[{<span style="color:#7fffd4;">files</span>,[<span style="color:#eedd82;">F1</span>]},<span style="color:#7fffd4;">compressed</span>]),
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">LocalEunitBin</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">read_file</span>(<span style="color:#eedd82;">Path</span>),
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">JobEunitBin</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">read_file</span>(<span style="color:#eedd82;">F1</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#eedd82;">LocalEunitBin</span>,<span style="color:#eedd82;">JobEunitBin</span>),

    <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">(13)
</span>    <span style="color:#98fb98;">erl_tar</span>:<span style="color:#98fb98;">extract</span>(<span style="color:#eedd82;">Tar</span>,[{<span style="color:#7fffd4;">files</span>,[<span style="color:#eedd82;">F2</span>]},<span style="color:#7fffd4;">compressed</span>]),
    ?<span style="color:#b0c4de;">assertEqual</span>({<span style="color:#7fffd4;">ok</span>,&lt;&lt;&gt;&gt;},<span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">read_file</span>(<span style="color:#eedd82;">F2</span>)),

    <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">(14)
</span>    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#ffa07a;">"local_stream.txt"</span>),
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">F1</span>),
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">F2</span>),
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">F3</span>),
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">Tar</span>).</pre>
<p><!--- End Of Snippet --></p>
<p>This test is one of the bigger ones, and deserves some guidance. From the top to bottom: (1) resource registration, (2) creation of the file I wish to send as part of the job, (3) file and job declaration, (4) job registration, (5) waiting for the job to finish (one of the structural weaknesses of this test) and (6) job finish checking by getting the timestamp at the moment of finish. (7) Setting up the expected result values for comparison, (8) getting the result-id and comparing it with the expected result. (9) Listing all files in the file layer and comparing with expected result (note that there SHOULD be two files in the layer &#8211; [1] First EunitFile, [2] the result package). (10) Retrieving the expected tgz file and checking that it should contain only two specific files (the log and the sent file). (11) Extraction of the payload logfile and checking with a streamed version that it&#8217;s the same. (12) Extraction of the job file to see that it&#8217;s there, and comparison to see it&#8217;s the same content. (13) Testing that the created file is the one which we sent back, (14) Cleanup of the extracted files and the tgz result.</p>
<p>So, of to write the code &#8211; first the wn_util:time_marker_to_string/1 function.  One important aspect is that this utility function <em>should not be allowed to exists</em> for the <em>sole purpose of the testing</em> &#8211; however as we shall see, this function does have other applications and thus survives.</p>
<p>In <em>wn_util.erl</em>, (skipping to show the export, <em>that </em>part should be bread and butter by now)</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">time_marker_to_string</span>(<span style="color:#98fb98;">time_marker</span>()) -&gt; <span style="color:#98fb98;">string</span>()).
<span style="color:#87cefa;">time_marker_to_string</span>({<span style="color:#eedd82;">Date</span>,<span style="color:#eedd82;">Time</span>,<span style="color:#eedd82;">Now</span>}) -&gt;
    <span style="color:#eedd82;">F</span> = <span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">X</span>) -&gt; <span style="color:#98fb98;">string</span>:<span style="color:#98fb98;">join</span>([<span style="color:#b0c4de;">integer_to_list</span>(<span style="color:#eedd82;">Y</span>)<span style="color:#00ffff;">||</span><span style="color:#eedd82;">Y</span><span style="color:#00ffff;">&lt;-</span><span style="color:#b0c4de;">tuple_to_list</span>(<span style="color:#eedd82;">X</span>)],<span style="color:#ffa07a;">"_"</span>)
        <span style="color:#00ffff;">end</span>,
    <span style="color:#eedd82;">F</span>(<span style="color:#eedd82;">Date</span>)<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"_"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">F</span>(<span style="color:#eedd82;">Time</span>)<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"_"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">F</span>(<span style="color:#eedd82;">Now</span>).</pre>
<p><!--- End Of Snippet --></p>
<p>following the test-code, the expected filename is already given in (7), and it&#8217;s time to write up the <em>wn_job_layer:stored_result/1</em> function, taking the JobId as parameter and giving the file-name.</p>
<p>Next the missing part in (8), in <em>wn_job_layer.erl</em> , the API function</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">stored_result</span>(<span style="color:#98fb98;">string</span>()) -&gt; {<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">string</span>()} | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).
<span style="color:#87cefa;">stored_result</span>(<span style="color:#eedd82;">Id</span>) -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,{<span style="color:#7fffd4;">stored_result</span>,<span style="color:#eedd82;">Id</span>}).</pre>
<p><!--- End Of Snippet --></p>
<p>and internal logic for handling it</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_call</span>({<span style="color:#7fffd4;">stored_result</span>,<span style="color:#eedd82;">Id</span>},<span style="color:#eedd82;">_</span>,<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#eedd82;">Result</span> = <span style="color:#98fb98;">try_get_stored</span>(<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">State</span>),
    {<span style="color:#7fffd4;">reply</span>,<span style="color:#eedd82;">Result</span>,<span style="color:#eedd82;">State</span>};</pre>
<p><!--- End Of Snippet --></p>
<p>and the seen helper function for stored result retrieval.</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">try_get_stored</span>(<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">lookup</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">jobs</span>,<span style="color:#eedd82;">Id</span>) <span style="color:#00ffff;">of</span>
        [{<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">_</span>}] -&gt;
            <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">get_stored_result</span>(<span style="color:#eedd82;">JobKeeperPid</span>);
        [] -&gt; {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">no_such_job</span>}
    <span style="color:#00ffff;">end</span>.</pre>
<p><!--- End Of Snippet --></p>
<p>This directly leads to the need in fleshing out the wn_job_keeper code. Thus, time to write the <em>wn_job_keeper:get_stored_result/1</em> function. However, as you are not inside my head (thanks for that!) I might need to give a quick explanation. The idea is that the job keeper holds the <em>name</em> of the stored result, not the result itself. So it&#8217;s not the actual tgz we get here. Remember that <em>all</em> files should be handled through the wn_file_layer.</p>
<p>In <em> wn_job_keeper.erl: </em>In order to maintain the stored result in the state, a new field has to be added (and while doing so I took the liberty of making the state type-declarations nicer)</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-record</span>(<span style="color:#b0c4de;">state</span>, {<span style="color:#7fffd4;">job</span> :: #<span style="color:#b0c4de;">wn_job</span>{},
             <span style="color:#7fffd4;">info</span> :: [{<span style="color:#b0c4de;">time</span>(),<span style="color:#98fb98;">term</span>()}],
             <span style="color:#7fffd4;">result</span> :: [{<span style="color:#b0c4de;">time</span>(),<span style="color:#98fb98;">term</span>()}],
             <span style="color:#7fffd4;">stored_result</span> :: <span style="color:#98fb98;">string</span>(),
             <span style="color:#7fffd4;">stream</span> :: [<span style="color:#b0c4de;">pid</span>()],
             <span style="color:#7fffd4;">done_at</span> :: <span style="color:#7fffd4;">undefined</span> | <span style="color:#98fb98;">time_marker</span>()
               }).</pre>
<p><!--- End Of Snippet --></p>
<p>onward and downwards (in the source file), the API function</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">get_stored_result</span>(<span style="color:#b0c4de;">pid</span>()) -&gt; {<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">string</span>()} | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).
<span style="color:#87cefa;">get_stored_result</span>(<span style="color:#eedd82;">Pid</span>) -&gt;
    <span style="color:#98fb98;">gen_fsm</span>:<span style="color:#98fb98;">sync_send_all_state_event</span>(<span style="color:#eedd82;">Pid</span>,<span style="color:#7fffd4;">get_stored_result</span>).</pre>
<p><!--- End Of Snippet --></p>
<p>alongside the internal function for handling the call</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_sync_event</span>(<span style="color:#7fffd4;">get_stored_result</span>,<span style="color:#eedd82;">_</span>,<span style="color:#eedd82;">X</span>,<span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">reply</span>,
     <span style="color:#00ffff;">case</span> <span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">stored_result</span> <span style="color:#00ffff;">of</span>
         <span style="color:#7fffd4;">undefined</span> -&gt; {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">no_result</span>};
         <span style="color:#eedd82;">R</span> -&gt; {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">R</span>}
     <span style="color:#00ffff;">end</span>,<span style="color:#eedd82;">X</span>,<span style="color:#eedd82;">State</span>};</pre>
<p><!--- End Of Snippet --></p>
<p>while working my way through this I noticed a bug in the get_done clause of handle_sync_event with done as StateName, and fixed it (should now be what is seen below)</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_sync_event</span>(<span style="color:#7fffd4;">get_done</span>,<span style="color:#eedd82;">_From</span>,<span style="color:#7fffd4;">done</span>,<span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">reply</span>,{<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">done_at</span>},<span style="color:#7fffd4;">done</span>,<span style="color:#eedd82;">State</span>};</pre>
<p><!--- End Of Snippet --></p>
<p>The natural question is now &#8211; <em>who</em> called <em>some</em> API function to put the value we are retrieving? The wn_job_worker would seem to be a good place to do this from since the job_worker knows when it&#8217;s finished and hence can generate the resulting file, put it into the file layer and signal the wn_job_keeper.</p>
<p>So, going to <em>wn_job_worker.erl, </em>to the part when all commands have been executed, (the handle_info clause of the gen_server) &#8211; this is what I put there (<em>not working</em> &#8211; needs to be implemented)</p>
<p><!-- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_info</span>({<span style="color:#eedd82;">Port</span>,<span style="color:#7fffd4;">eof</span>},#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">port</span> = <span style="color:#eedd82;">Port</span>} = <span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#00ffff;">case</span> <span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">commands</span> <span style="color:#00ffff;">of</span>
        [] -&gt;
            <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">info</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">pid</span>,<span style="color:#7fffd4;">no_more_commands</span>),
            <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">info</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">pid</span>,<span style="color:#7fffd4;">building_result_tgz</span>),
            <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">set_cwd</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">olddir</span>),
            <span style="color:#eedd82;">Keeper</span> = <span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">pid</span>,
            <span style="color:#eedd82;">TimeMarker</span> = <span style="color:#98fb98;">wn_util</span>:<span style="color:#98fb98;">time_marker</span>(),
            <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">done</span>(<span style="color:#eedd82;">Keeper</span>,<span style="color:#eedd82;">TimeMarker</span>),
            <span style="color:#eedd82;">Job</span> = <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">get_job</span>(<span style="color:#eedd82;">Keeper</span>),
            <span style="color:#eedd82;">Logs</span> = <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">logs</span>(<span style="color:#eedd82;">Keeper</span>),
            {<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">Name</span>} = <span style="color:#98fb98;">make_tgz_result</span>(<span style="color:#eedd82;">TimeMarker</span>,
                                        <span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">workdir</span>,
                                        <span style="color:#eedd82;">Job</span>,<span style="color:#eedd82;">Logs</span>),
            <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">add_file</span>(#<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#eedd82;">Id</span>,
                                                 <span style="color:#7fffd4;">file</span> = <span style="color:#eedd82;">Name</span>,
                                                 <span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()}),
            <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">Name</span>),
            <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">set_stored_result</span>(<span style="color:#eedd82;">Keeper</span>,<span style="color:#eedd82;">Id</span>),
            {<span style="color:#7fffd4;">stop</span>,<span style="color:#7fffd4;">normal</span>,<span style="color:#eedd82;">State</span>};
        [<span style="color:#eedd82;">C</span>|<span style="color:#eedd82;">Commands</span>] -&gt;
            <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">info</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">pid</span>,{<span style="color:#7fffd4;">executing</span>,<span style="color:#eedd82;">C</span>}),
            <span style="color:#eedd82;">NewPort</span> = <span style="color:#b0c4de;">erlang</span>:<span style="color:#b0c4de;">open_port</span>({<span style="color:#7fffd4;">spawn</span>,<span style="color:#eedd82;">C</span>},[<span style="color:#7fffd4;">eof</span>,{<span style="color:#7fffd4;">line</span>,2048}]),
            {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">commands</span> = <span style="color:#eedd82;">Commands</span>,<span style="color:#7fffd4;">port</span> = <span style="color:#eedd82;">NewPort</span>}}
    <span style="color:#00ffff;">end</span>;</pre>
<p><!--- End Of Snippet --></p>
<p>This block of code jumps out of the current worker-dir, creates a resulting <em>tgz</em>, adds all files in the worker-dir to it, signals done to the wn_job_keeper and puts the <em>tgz</em> file into the file layer. Of course this is designing as we go and hence there are some functions missing. Finishing off the stuff here first,  the local make_tgz_result/4 function</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">make_tgz_result</span>(<span style="color:#eedd82;">TimeMarker</span>,<span style="color:#eedd82;">Dir</span>,<span style="color:#eedd82;">WnJob</span>,<span style="color:#eedd82;">Logs</span>) -&gt;
    <span style="color:#eedd82;">Id</span> = <span style="color:#eedd82;">WnJob</span>#<span style="color:#b0c4de;">wn_job</span>.<span style="color:#7fffd4;">id</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"_result"</span>,
    <span style="color:#eedd82;">Name</span> = <span style="color:#eedd82;">Id</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"_"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#98fb98;">wn_util</span>:<span style="color:#98fb98;">time_marker_to_string</span>(<span style="color:#eedd82;">TimeMarker</span>)<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">".tgz"</span>,
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">TarFile</span>} = <span style="color:#98fb98;">erl_tar</span>:<span style="color:#98fb98;">open</span>(<span style="color:#eedd82;">Name</span>,[<span style="color:#7fffd4;">write</span>,<span style="color:#7fffd4;">compressed</span>]),
    <span style="color:#eedd82;">Files</span> = <span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">wildcard</span>(<span style="color:#eedd82;">Dir</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"*"</span>),
    <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foreach</span>(
      <span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">File</span>) -&gt;
              <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">erl_tar</span>:<span style="color:#98fb98;">add</span>(<span style="color:#eedd82;">TarFile</span>,<span style="color:#eedd82;">File</span>,<span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">File</span>),[])
      <span style="color:#00ffff;">end</span>,<span style="color:#eedd82;">Files</span>),
    <span style="color:#eedd82;">LogStr</span> = <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foldl</span>(
               <span style="color:#00ffff;">fun</span>({<span style="color:#eedd82;">TimeMark</span>,<span style="color:#eedd82;">Entry</span>},<span style="color:#eedd82;">Str</span>) -&gt;
                       <span style="color:#eedd82;">Str</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#98fb98;">io_lib</span>:<span style="color:#98fb98;">format</span>(<span style="color:#ffa07a;">"~p : ~p~n"</span>,[<span style="color:#eedd82;">TimeMark</span>,<span style="color:#eedd82;">Entry</span>])
               <span style="color:#00ffff;">end</span>,<span style="color:#ffa07a;">""</span>,<span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">sort</span>(<span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">append</span>([<span style="color:#eedd82;">Lines</span> <span style="color:#00ffff;">||</span> {<span style="color:#eedd82;">_</span>,<span style="color:#eedd82;">Lines</span>} <span style="color:#00ffff;">&lt;-</span> <span style="color:#eedd82;">Logs</span>]))),
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">erl_tar</span>:<span style="color:#98fb98;">add</span>(<span style="color:#eedd82;">TarFile</span>,<span style="color:#b0c4de;">erlang</span>:<span style="color:#b0c4de;">list_to_binary</span>(<span style="color:#eedd82;">LogStr</span>),<span style="color:#ffa07a;">"Log.txt"</span>,[]),
    <span style="color:#98fb98;">erl_tar</span>:<span style="color:#98fb98;">close</span>(<span style="color:#eedd82;">TarFile</span>),
    {<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">Name</span>}.</pre>
<p><!--- End Of List --></p>
<p>luckily this one does not rely on any more internal / external functions. So that closes this branch of the dev. Backtracking to the handle_info clause, there are some new external functions which has to be developed, one of them is the <em>wn_util:time_marker/0</em><br />
function.</p>
<p>In <em> wn_util.erl </em>i add the following</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">time_marker</span>() -&gt; <span style="color:#98fb98;">time_marker</span>()).
<span style="color:#87cefa;">time_marker</span>() -&gt;
    {<span style="color:#b0c4de;">date</span>(),<span style="color:#b0c4de;">time</span>(),<span style="color:#98fb98;">now</span>()}.</pre>
<p><!--- End Of Snippet --></p>
<p>the way of signalling that a job is done has now changed, and the second argument is the time_marker of when this happened &#8211; this as the wn_job_worker must create the resulting tgz file with the correct time-stamp in the filename.</p>
<p>So, to change the done-signaling, the new lines in <em>wn_job_keeper.erl </em> are</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">done</span>(<span style="color:#b0c4de;">pid</span>(),<span style="color:#98fb98;">time_marker</span>()) -&gt; <span style="color:#7fffd4;">ok</span>).
<span style="color:#87cefa;">done</span>(<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">TimeMarker</span>) -&gt;
    <span style="color:#98fb98;">gen_fsm</span>:<span style="color:#98fb98;">send_all_state_event</span>(<span style="color:#eedd82;">Pid</span>,{<span style="color:#7fffd4;">done</span>,<span style="color:#eedd82;">TimeMarker</span>}).</pre>
<p><!--- End Of Snippet --></p>
<p>the internal clause for the handle_event to process this change is</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_event</span>({<span style="color:#7fffd4;">done</span>,<span style="color:#eedd82;">TimeMarker</span>}, <span style="color:#7fffd4;">working</span>, #<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">info</span> = <span style="color:#eedd82;">Info</span>} = <span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#eedd82;">Now</span> = <span style="color:#98fb98;">now</span>(),
    <span style="color:#98fb98;">stream_msg</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">stream</span>,{<span style="color:#eedd82;">Now</span>,<span style="color:#7fffd4;">done</span>}),
    {<span style="color:#7fffd4;">next_state</span>, <span style="color:#7fffd4;">done</span>, <span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">info</span> = [{<span style="color:#eedd82;">Now</span>,<span style="color:#7fffd4;">done</span>}|<span style="color:#eedd82;">Info</span>],
                                   <span style="color:#7fffd4;">done_at</span> = <span style="color:#eedd82;">TimeMarker</span>
                                  }};</pre>
<p><!--- End Of Snippet --></p>
<p>Next &#8211; still handle_info of <em>wn_job_worker.erl</em> there is a new function to be implemented, <em>wn_job_keeper:logs/1</em> which will retrieve the stdout result of the processing to be put into the Log.txt file that was seen in <em>make_tgz_result/4. </em></p>
<p><em> </em>Going into <em>wn_job_keeper.erl </em>, i add the following type-spec and function</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">logs</span>(<span style="color:#b0c4de;">pid</span>()) -&gt; [{<span style="color:#7fffd4;">info</span>|<span style="color:#7fffd4;">result</span>,[{<span style="color:#b0c4de;">time</span>(),<span style="color:#98fb98;">term</span>()}]}]).
<span style="color:#87cefa;">logs</span>(<span style="color:#eedd82;">Pid</span>) -&gt;
    <span style="color:#98fb98;">gen_fsm</span>:<span style="color:#98fb98;">sync_send_all_state_event</span>(<span style="color:#eedd82;">Pid</span>,<span style="color:#7fffd4;">get_logs</span>).</pre>
<p><!--- End Of Snippet --></p>
<p>and the function clause to handle the log retrieval request</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_sync_event</span>(<span style="color:#7fffd4;">get_logs</span>,<span style="color:#eedd82;">_From</span>,<span style="color:#eedd82;">X</span>,<span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">reply</span>,[{<span style="color:#7fffd4;">info</span>,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">info</span>},
            {<span style="color:#7fffd4;">result</span>,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">result</span>}],<span style="color:#eedd82;">X</span>,<span style="color:#eedd82;">State</span>};</pre>
<p><!--- End Of Snippet --></p>
<p>Going <em>back</em> to the <em>handle_info</em> clause in <em>wn_job_worker.erl</em>, the next new thing to implement is the function for setting the result inside the wn_job_keeper. The implementation is thus naturally put in <em>wn_job_keeper.erl.</em></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">set_stored_result</span>(<span style="color:#b0c4de;">pid</span>(),<span style="color:#98fb98;">string</span>()) -&gt; <span style="color:#7fffd4;">ok</span>).
<span style="color:#87cefa;">set_stored_result</span>(<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">Id</span>) -&gt;
    <span style="color:#98fb98;">gen_fsm</span>:<span style="color:#98fb98;">sync_send_all_state_event</span>(<span style="color:#eedd82;">Pid</span>,{<span style="color:#7fffd4;">stored_result</span>,<span style="color:#eedd82;">Id</span>}).</pre>
<p><!--- End Of Snippet --></p>
<p>Of course we also need the clause to handle this synchronous request</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_sync_event</span>({<span style="color:#7fffd4;">stored_result</span>,<span style="color:#eedd82;">Id</span>},<span style="color:#eedd82;">_</span>,<span style="color:#eedd82;">X</span>,<span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">reply</span>,<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">X</span>,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">stored_result</span> = <span style="color:#eedd82;">Id</span>}};</pre>
<p><!--- End Of Snippet --></p>
<p>very straight forward and nothing fishy on that sandwich. Ending the wn_job_worker&#8217;s <em>handle_info</em> clause, some changes where made in the <em>wn_resource_process.erl</em>. The wn_resource_process should now no longer signal done to the wn_job_keeper as the wn_job_worker does it herself.</p>
<p>As the right of done-signalling has been revoked from the wn_resource_process, some code modification had to be done to the <em>handle_info</em> clause in <em>wn_resource_process.erl </em></p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_info</span>({<span style="color:#7fffd4;">'EXIT'</span>,<span style="color:#eedd82;">WorkerPid</span>,<span style="color:#eedd82;">_</span>}, <span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">noreply</span>,
     <span style="color:#00ffff;">begin</span>
      [{<span style="color:#eedd82;">WorkerPid</span>,<span style="color:#eedd82;">_</span>,<span style="color:#eedd82;">QueueType</span>}] = <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">lookup</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">working</span>,<span style="color:#eedd82;">WorkerPid</span>),
      <span style="color:#7fffd4;">true</span> = <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">working</span>,<span style="color:#eedd82;">WorkerPid</span>),

      <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">keytake</span>(<span style="color:#eedd82;">QueueType</span>,1,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">queues</span>) <span style="color:#00ffff;">of</span>
        {<span style="color:#7fffd4;">value</span>,{<span style="color:#eedd82;">_</span>,[]},<span style="color:#eedd82;">_</span>} -&gt;
          <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">lookup</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">slots</span>,<span style="color:#eedd82;">QueueType</span>) <span style="color:#00ffff;">of</span>
             [{<span style="color:#eedd82;">QueueType</span>,<span style="color:#7fffd4;">infinity</span>}] -&gt; <span style="color:#7fffd4;">ignore</span>;
             [{<span style="color:#eedd82;">QueueType</span>,<span style="color:#eedd82;">X</span>}] -&gt; <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">insert</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">slots</span>,{<span style="color:#eedd82;">QueueType</span>,<span style="color:#eedd82;">X</span>+1})
          <span style="color:#00ffff;">end</span>,
          <span style="color:#eedd82;">State</span>;
        {<span style="color:#7fffd4;">value</span>,{<span style="color:#eedd82;">Type</span>,[<span style="color:#eedd82;">QueuedPid</span>|<span style="color:#eedd82;">R</span>]},<span style="color:#eedd82;">Queues</span>} -&gt;
          <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">try_dispatch_job</span>(<span style="color:#eedd82;">QueuedPid</span>,<span style="color:#eedd82;">State</span>,<span style="color:#eedd82;">QueueType</span>) <span style="color:#00ffff;">of</span>
             <span style="color:#7fffd4;">ok</span> -&gt;
               <span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">queues</span> = [{<span style="color:#eedd82;">Type</span>,<span style="color:#eedd82;">R</span>}|<span style="color:#eedd82;">Queues</span>]};
            {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">taken</span>} -&gt;
               <span style="color:#eedd82;">State</span>
          <span style="color:#00ffff;">end</span>
         <span style="color:#00ffff;">end</span>
     <span style="color:#00ffff;">end</span>}.</pre>
<p><!--- End Of Snippet --></p>
<p>As the <em>wn_job_worker:make_tgz_result/4</em> dictated, the input in the Log.txt file changed what the streamer should get &#8211; in unison with (11) in the test. Thus this format change has to be accommodated in the <em> wn_job_layer:</em>stream/2 function</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">stream</span>(<span style="color:#98fb98;">term</span>(),<span style="color:#98fb98;">string</span>()) -&gt; <span style="color:#7fffd4;">ok</span> | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).
<span style="color:#87cefa;">stream</span>(<span style="color:#eedd82;">IoDev</span>,<span style="color:#eedd82;">Id</span>) -&gt;
    <span style="color:#eedd82;">Stream</span> = <span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">F</span>) -&gt; <span style="color:#00ffff;">receive</span> {<span style="color:#eedd82;">T</span>,<span style="color:#eedd82;">E</span>} -&gt; <span style="color:#98fb98;">io</span>:<span style="color:#98fb98;">format</span>(<span style="color:#eedd82;">IoDev</span>,<span style="color:#ffa07a;">"~p : ~p~n"</span>,[<span style="color:#eedd82;">T</span>,<span style="color:#eedd82;">E</span>]) <span style="color:#00ffff;">end</span>, <span style="color:#eedd82;">F</span>(<span style="color:#eedd82;">F</span>) <span style="color:#00ffff;">end</span>,
    <span style="color:#eedd82;">StreamPid</span> = <span style="color:#b0c4de;">spawn_link</span>(<span style="color:#00ffff;">fun</span>() -&gt; <span style="color:#eedd82;">Stream</span>(<span style="color:#eedd82;">Stream</span>) <span style="color:#00ffff;">end</span>),
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,{<span style="color:#7fffd4;">stream</span>,<span style="color:#eedd82;">StreamPid</span>,<span style="color:#eedd82;">Id</span>}) <span style="color:#00ffff;">of</span>
        <span style="color:#7fffd4;">ok</span> -&gt; <span style="color:#7fffd4;">ok</span>;
        <span style="color:#eedd82;">Err</span> -&gt;
            <span style="color:#b0c4de;">exit</span>(<span style="color:#eedd82;">StreamPid</span>,<span style="color:#eedd82;">Err</span>),
            <span style="color:#eedd82;">Err</span>
    <span style="color:#00ffff;">end</span>.</pre>
<p><!--- End Of Snippet --></p>
<p>Also, the <em>wn_job_layer:replay/2</em> function had to be changed</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">replay</span>(<span style="color:#eedd82;">Pid</span>,#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">info</span> = <span style="color:#eedd82;">Info</span>,<span style="color:#7fffd4;">result</span>=<span style="color:#eedd82;">Result</span>}) -&gt;
    <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foreach</span>(<span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">Entry</span>) -&gt; <span style="color:#eedd82;">Pid</span> ! <span style="color:#eedd82;">Entry</span> <span style="color:#00ffff;">end</span>,
                  <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">sort</span>(<span style="color:#eedd82;">Info</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">Result</span>)).</pre>
<p><!--- End Of Snippet --></p>
<p>Finally! This satisfies the test! However, there is one point of concern. One of the previous tests can cause this one to fail! The culprit is</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"> {<span style="color:#ffa07a;">"Queueus on resource type amount"</span>, <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">queues_on_resource_types_amount/0</span>},</pre>
<p><!--- End Of Snippet --></p>
<p>That culprit-test queued several jobs but never removed them properly &#8211; causing some interesting effects on the current working directory of the processes. The effect of having this intermediate test <em>interfering</em> is a good example of <span style="text-decoration:underline;"><em>bad test behaviour</em></span>. In the best case &#8211; we would be expecting each test to be set up in it&#8217;s own clean universe, and to die in that same universe as well, without overspilling into other parallel realities!</p>
<p>As can be seen &#8211; the make test shows the failure</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;">1&gt; ======================== <span style="color:#eedd82;">EUnit</span> ========================
<span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_job_layer'</span>
  <span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_job_layer_tests'</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">register</span> <span style="color:#7fffd4;">locally</span>)...[0.004 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Executed</span> <span style="color:#7fffd4;">locally</span>)...{1298,929708,203063} : <span style="color:#7fffd4;">file_fetching_done</span>
{1298,929708,203067} : <span style="color:#7fffd4;">executing_commands</span>
{1298,929708,203217} : {<span style="color:#7fffd4;">executing</span>,<span style="color:#ffa07a;">"more EUnitFile"</span>}
{1298,929708,210033} : <span style="color:#ffa07a;">"1,2,3"</span>
{1298,929708,210134} : <span style="color:#7fffd4;">no_more_commands</span>
{1298,929708,210137} : <span style="color:#7fffd4;">building_result_tgz</span>
{1298,929708,210187} : <span style="color:#7fffd4;">done</span>
[1.004 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Executed</span> <span style="color:#7fffd4;">queue</span>)...{1298,929709,215132} : <span style="color:#7fffd4;">file_fetching_done</span>
{1298,929709,215134} : <span style="color:#7fffd4;">executing_commands</span>
{1298,929709,215221} : {<span style="color:#7fffd4;">executing</span>,<span style="color:#ffa07a;">"file EunitFile"</span>}
{1298,929709,222661} : <span style="color:#ffa07a;">"EunitFile: ASCII text"</span>
{1298,929709,222721} : <span style="color:#7fffd4;">no_more_commands</span>
{1298,929709,222725} : <span style="color:#7fffd4;">building_result_tgz</span>
{1298,929709,222801} : <span style="color:#7fffd4;">done</span>
{1298,929709,225999} : <span style="color:#7fffd4;">file_fetching_done</span>
{1298,929709,226001} : <span style="color:#7fffd4;">executing_commands</span>
{1298,929709,226189} : {<span style="color:#7fffd4;">executing</span>,<span style="color:#ffa07a;">"cat EUnitFile"</span>}
{1298,929709,231033} : <span style="color:#ffa07a;">"1,2,3"</span>
{1298,929709,231087} : <span style="color:#7fffd4;">no_more_commands</span>
{1298,929709,231090} : <span style="color:#7fffd4;">building_result_tgz</span>
{1298,929709,231149} : <span style="color:#7fffd4;">done</span>
[1.104 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Queueus</span> <span style="color:#7fffd4;">on</span> <span style="color:#7fffd4;">resource</span> <span style="color:#7fffd4;">type</span> <span style="color:#7fffd4;">amount</span>)...[0.001 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
<span style="color:#7fffd4;">shell</span>-<span style="color:#7fffd4;">init</span>: <span style="color:#7fffd4;">error</span> <span style="color:#7fffd4;">retrieving</span> <span style="color:#7fffd4;">current</span> <span style="color:#7fffd4;">directory</span>: <span style="color:#7fffd4;">getcwd</span>: <span style="color:#7fffd4;">cannot</span> <span style="color:#7fffd4;">access</span> <span style="color:#7fffd4;">parent</span> <span style="color:#7fffd4;">directories</span>: <span style="color:#eedd82;">No</span> <span style="color:#7fffd4;">such</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">or</span> <span style="color:#7fffd4;">directory</span>
                                                                                                                       <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Canceled</span> <span style="color:#7fffd4;">in</span> <span style="color:#7fffd4;">queue</span>)...<span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Done</span> <span style="color:#eedd82;">Job</span> <span style="color:#eedd82;">Stored</span> <span style="color:#7fffd4;">in</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">layer</span>)...
=<span style="color:#eedd82;">ERROR</span> <span style="color:#eedd82;">REPORT</span>==== 28-<span style="color:#eedd82;">Feb</span>-2011::21:48:30 ===
** <span style="color:#eedd82;">Generic</span> <span style="color:#7fffd4;">server</span> &lt;0.174.0&gt; <span style="color:#7fffd4;">terminating</span>
** <span style="color:#eedd82;">Last</span> <span style="color:#7fffd4;">message</span> <span style="color:#7fffd4;">in</span> <span style="color:#7fffd4;">was</span> {<span style="color:#7fffd4;">'$gen_cast'</span>,{<span style="color:#7fffd4;">signal</span>,&lt;0.178.0&gt;,<span style="color:#7fffd4;">a</span>}}
** <span style="color:#eedd82;">When</span> <span style="color:#eedd82;">Server</span> <span style="color:#7fffd4;">state</span> == {<span style="color:#7fffd4;">state</span>,<span style="color:#ffa07a;">"/Users/zenon/ErlangBlog/worker_net-0.1/node_root/"</span>,
                               [{<span style="color:#7fffd4;">a</span>,[]}],
                               127001,122904}
** <span style="color:#eedd82;">Reason</span> <span style="color:#7fffd4;">for</span> <span style="color:#7fffd4;">termination</span> ==
** {{<span style="color:#7fffd4;">badmatch</span>,
        {<span style="color:#7fffd4;">error</span>,
            {<span style="color:#7fffd4;">function_clause</span>,
                [{<span style="color:#7fffd4;">wn_job_worker</span>,'-<span style="color:#87cefa;">init/1</span>-<span style="color:#00ffff;">fun</span>-0-',[{<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">enoent</span>}]},
                 {<span style="color:#7fffd4;">wn_job_worker</span>,<span style="color:#7fffd4;">init</span>,1},
                 {<span style="color:#7fffd4;">gen_server</span>,<span style="color:#7fffd4;">init_it</span>,6},
                 {<span style="color:#7fffd4;">proc_lib</span>,<span style="color:#7fffd4;">init_p_do_apply</span>,3}]}}},
    [{<span style="color:#7fffd4;">wn_resource_process</span>,<span style="color:#7fffd4;">try_dispatch_job</span>,3},
     {<span style="color:#7fffd4;">wn_resource_process</span>,<span style="color:#7fffd4;">handle_cast</span>,2},
     {<span style="color:#7fffd4;">gen_server</span>,<span style="color:#7fffd4;">handle_msg</span>,5},
     {<span style="color:#7fffd4;">proc_lib</span>,<span style="color:#7fffd4;">init_p_do_apply</span>,3}]}
*<span style="color:#7fffd4;">failed</span>*
::<span style="color:#7fffd4;">error</span>:{<span style="color:#7fffd4;">badmatch</span>,{<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">not_done</span>}}
  <span style="color:#7fffd4;">in</span> <span style="color:#7fffd4;">function</span> <span style="color:#7fffd4;">wn_job_layer_tests</span>:<span style="color:#87cefa;">stored_in_file_layer/0</span>

    [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 2.687 <span style="color:#7fffd4;">s</span>]
  [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 2.687 <span style="color:#7fffd4;">s</span>]
=======================================================
  <span style="color:#eedd82;">Failed</span>: 1.  <span style="color:#eedd82;">Skipped</span>: 0.  <span style="color:#eedd82;">Passed</span>: 5.
<span style="color:#7fffd4;">zen</span>:<span style="color:#7fffd4;">worker_net</span>-0.1 <span style="color:#7fffd4;">zenon</span><span style="color:#ffa07a;">$ </span></pre>
<p><!--- End Of Snippet --></p>
<p>While the version in where we comment out the test in question succeeds quite nice</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;">1&gt; ======================== <span style="color:#eedd82;">EUnit</span> ========================
<span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_job_layer'</span>
  <span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_job_layer_tests'</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">register</span> <span style="color:#7fffd4;">locally</span>)...[0.005 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Executed</span> <span style="color:#7fffd4;">locally</span>)...{1298,929858,474814} : <span style="color:#7fffd4;">file_fetching_done</span>
{1298,929858,474817} : <span style="color:#7fffd4;">executing_commands</span>
{1298,929858,474949} : {<span style="color:#7fffd4;">executing</span>,<span style="color:#ffa07a;">"more EUnitFile"</span>}
{1298,929858,481366} : <span style="color:#ffa07a;">"1,2,3"</span>
{1298,929858,481451} : <span style="color:#7fffd4;">no_more_commands</span>
{1298,929858,481454} : <span style="color:#7fffd4;">building_result_tgz</span>
{1298,929858,481489} : <span style="color:#7fffd4;">done</span>
[1.005 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Executed</span> <span style="color:#7fffd4;">queue</span>)...{1298,929859,486690} : <span style="color:#7fffd4;">file_fetching_done</span>
{1298,929859,486693} : <span style="color:#7fffd4;">executing_commands</span>
{1298,929859,486733} : {<span style="color:#7fffd4;">executing</span>,<span style="color:#ffa07a;">"file EunitFile"</span>}
{1298,929859,493820} : <span style="color:#ffa07a;">"EunitFile: ASCII text"</span>
{1298,929859,493937} : <span style="color:#7fffd4;">no_more_commands</span>
{1298,929859,493939} : <span style="color:#7fffd4;">building_result_tgz</span>
{1298,929859,494065} : <span style="color:#7fffd4;">done</span>
{1298,929859,497623} : <span style="color:#7fffd4;">file_fetching_done</span>
{1298,929859,497627} : <span style="color:#7fffd4;">executing_commands</span>
{1298,929859,497716} : {<span style="color:#7fffd4;">executing</span>,<span style="color:#ffa07a;">"cat EUnitFile"</span>}
{1298,929859,503066} : <span style="color:#ffa07a;">"1,2,3"</span>
{1298,929859,503118} : <span style="color:#7fffd4;">no_more_commands</span>
{1298,929859,503120} : <span style="color:#7fffd4;">building_result_tgz</span>
{1298,929859,503188} : <span style="color:#7fffd4;">done</span>
[1.105 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Canceled</span> <span style="color:#7fffd4;">in</span> <span style="color:#7fffd4;">queue</span>)...<span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Done</span> <span style="color:#eedd82;">Job</span> <span style="color:#eedd82;">Stored</span> <span style="color:#7fffd4;">in</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">layer</span>)...[0.607 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 2.766 <span style="color:#7fffd4;">s</span>]
  [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 2.766 <span style="color:#7fffd4;">s</span>]
=======================================================
  <span style="color:#eedd82;">All</span> 5 <span style="color:#7fffd4;">tests</span> <span style="color:#7fffd4;">passed</span>.</pre>
<p><!--- End Of Snippet --></p>
<p>This was fixed by constraining the previous test (and making it more actual to what it should test)</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">queues_on_resource_types_amount</span>() -&gt;
    <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(#<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"Laptop"</span>,
                                            <span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">a</span>,0},{<span style="color:#7fffd4;">b</span>,0}],
                                            <span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()
                                           }),
    <span style="color:#eedd82;">Queued</span> = <span style="color:#00ffff;">fun</span>() -&gt; <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">queued</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#ffa07a;">"Laptop"</span>) <span style="color:#00ffff;">end</span>,
    <span style="color:#eedd82;">Job1</span> = #<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId"</span>,<span style="color:#7fffd4;">files</span> = [],<span style="color:#7fffd4;">resources</span> = [<span style="color:#7fffd4;">a</span>]},
    <span style="color:#eedd82;">Job2</span> = <span style="color:#eedd82;">Job1</span>#<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId2"</span>, <span style="color:#7fffd4;">resources</span> = [<span style="color:#7fffd4;">a</span>]},
    <span style="color:#eedd82;">Job3</span> = <span style="color:#eedd82;">Job1</span>#<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId3"</span>, <span style="color:#7fffd4;">resources</span> = [<span style="color:#7fffd4;">a</span>,<span style="color:#7fffd4;">b</span>]},

    <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">Job1</span>),
    ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,[{<span style="color:#7fffd4;">a</span>,[<span style="color:#eedd82;">Job1</span>]},{<span style="color:#7fffd4;">b</span>,[]}]},<span style="color:#eedd82;">Queued</span>()),

    <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">Job2</span>),
    ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,[{<span style="color:#7fffd4;">a</span>,[<span style="color:#eedd82;">Job1</span>, <span style="color:#eedd82;">Job2</span>]},{<span style="color:#7fffd4;">b</span>,[]}]},<span style="color:#eedd82;">Queued</span>()),

    <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">Job3</span>),
    ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,[{<span style="color:#7fffd4;">b</span>,[<span style="color:#eedd82;">Job3</span>]},
                      {<span style="color:#7fffd4;">a</span>,[<span style="color:#eedd82;">Job1</span>,<span style="color:#eedd82;">Job2</span>,<span style="color:#eedd82;">Job3</span>]}
                     ]},<span style="color:#eedd82;">Queued</span>()).</pre>
<p><!--- End Of Snippet --></p>
<p>This story has now ended &#8211; with the following output of <em> &#8216;make full&#8217; </em></p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#7fffd4;">zen</span>:<span style="color:#7fffd4;">worker_net</span>-0.1 <span style="color:#7fffd4;">zenon</span><span style="color:#ffa07a;">$ </span><span style="color:#7fffd4;">make</span> <span style="color:#7fffd4;">full</span>
<span style="color:#7fffd4;">erlc</span> -<span style="color:#7fffd4;">pa</span> . -<span style="color:#7fffd4;">o</span> <span style="color:#7fffd4;">ebin</span>/  <span style="color:#7fffd4;">src</span>/*.<span style="color:#7fffd4;">erl</span> <span style="color:#7fffd4;">test</span>/*.<span style="color:#7fffd4;">erl</span>
<span style="color:#7fffd4;">erl</span> -<span style="color:#7fffd4;">pa</span> <span style="color:#7fffd4;">ebin</span>/ -<span style="color:#7fffd4;">eval</span> 'eunit:<span style="color:#98fb98;">test</span>(<span style="color:#7fffd4;">wn_resource_layer</span>,[<span style="color:#7fffd4;">verbose</span>]), <span style="color:#98fb98;">init</span>:<span style="color:#98fb98;">stop</span>().'
<span style="color:#eedd82;">Erlang</span> <span style="color:#eedd82;">R14B</span> (<span style="color:#7fffd4;">erts</span>-5.8.1) [<span style="color:#7fffd4;">source</span>] [<span style="color:#7fffd4;">smp</span>:4:4] [<span style="color:#7fffd4;">rq</span>:4] [<span style="color:#7fffd4;">async</span>-<span style="color:#7fffd4;">threads</span>:0] [<span style="color:#7fffd4;">hipe</span>] [<span style="color:#7fffd4;">kernel</span>-<span style="color:#7fffd4;">poll</span>:<span style="color:#7fffd4;">false</span>]

<span style="color:#eedd82;">Eshell</span> <span style="color:#eedd82;">V5</span>.8.1  (<span style="color:#7fffd4;">abort</span> <span style="color:#7fffd4;">with</span> ^<span style="color:#eedd82;">G</span>)
1&gt; ======================== <span style="color:#eedd82;">EUnit</span> ========================
<span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_resource_layer'</span>
  <span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_resource_layer_tests'</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">local_resource_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">register</span> <span style="color:#7fffd4;">resources</span> <span style="color:#7fffd4;">locally</span>)...[0.001 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">register_distributed</span> (<span style="color:#eedd82;">Can</span> <span style="color:#eedd82;">Register</span> <span style="color:#eedd82;">Distributed</span>)...[0.004 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">register_restart_register</span> (<span style="color:#eedd82;">Can</span> <span style="color:#eedd82;">Register</span>, <span style="color:#eedd82;">Restart</span> <span style="color:#7fffd4;">and</span> <span style="color:#eedd82;">Register</span>)...[0.010 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">register_deregister</span> (<span style="color:#eedd82;">Can</span> <span style="color:#eedd82;">Register</span>, <span style="color:#eedd82;">Deregister</span> <span style="color:#7fffd4;">and</span> <span style="color:#eedd82;">Register</span>)...[0.008 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0.894 <span style="color:#7fffd4;">s</span>]
  [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0.894 <span style="color:#7fffd4;">s</span>]
=======================================================
  <span style="color:#eedd82;">All</span> 4 <span style="color:#7fffd4;">tests</span> <span style="color:#7fffd4;">passed</span>.
<span style="color:#7fffd4;">erl</span> -<span style="color:#7fffd4;">pa</span> <span style="color:#7fffd4;">ebin</span>/ -<span style="color:#7fffd4;">eval</span> 'eunit:<span style="color:#98fb98;">test</span>(<span style="color:#7fffd4;">wn_file_layer</span>,[<span style="color:#7fffd4;">verbose</span>]), <span style="color:#98fb98;">init</span>:<span style="color:#98fb98;">stop</span>().'
<span style="color:#eedd82;">Erlang</span> <span style="color:#eedd82;">R14B</span> (<span style="color:#7fffd4;">erts</span>-5.8.1) [<span style="color:#7fffd4;">source</span>] [<span style="color:#7fffd4;">smp</span>:4:4] [<span style="color:#7fffd4;">rq</span>:4] [<span style="color:#7fffd4;">async</span>-<span style="color:#7fffd4;">threads</span>:0] [<span style="color:#7fffd4;">hipe</span>] [<span style="color:#7fffd4;">kernel</span>-<span style="color:#7fffd4;">poll</span>:<span style="color:#7fffd4;">false</span>]

<span style="color:#eedd82;">Eshell</span> <span style="color:#eedd82;">V5</span>.8.1  (<span style="color:#7fffd4;">abort</span> <span style="color:#7fffd4;">with</span> ^<span style="color:#eedd82;">G</span>)
1&gt; ======================== <span style="color:#eedd82;">EUnit</span> ========================
<span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_file_layer'</span>
  <span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_file_layer_tests'</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">file_layer_local_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">store</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">locally</span>)...[0.001 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">file_layer_local_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">retrieve</span> <span style="color:#7fffd4;">files</span> <span style="color:#7fffd4;">locally</span>)...[0.002 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">file_layer_local_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">delete</span> <span style="color:#7fffd4;">files</span> <span style="color:#7fffd4;">locally</span>)...[0.001 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">can_store_distributed</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">store</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">distributed</span>)...[0.016 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">can_retrieve_distributed</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">retrieve</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">distributed</span>)...[0.017 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">can_delete_distributed</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">delete</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">distributed</span>)...[0.018 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">must_retain</span> (<span style="color:#eedd82;">Must</span> <span style="color:#7fffd4;">retain</span> <span style="color:#7fffd4;">information</span> <span style="color:#7fffd4;">between</span> <span style="color:#7fffd4;">node</span> <span style="color:#7fffd4;">kill</span> <span style="color:#7fffd4;">and</span> <span style="color:#7fffd4;">node</span> <span style="color:#7fffd4;">restart</span>)...[0.321 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 1.667 <span style="color:#7fffd4;">s</span>]
  [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 1.667 <span style="color:#7fffd4;">s</span>]
=======================================================
  <span style="color:#eedd82;">All</span> 7 <span style="color:#7fffd4;">tests</span> <span style="color:#7fffd4;">passed</span>.
<span style="color:#7fffd4;">erl</span> -<span style="color:#7fffd4;">pa</span> <span style="color:#7fffd4;">ebin</span>/ -<span style="color:#7fffd4;">eval</span> 'eunit:<span style="color:#98fb98;">test</span>(<span style="color:#7fffd4;">wn_job_layer</span>,[<span style="color:#7fffd4;">verbose</span>]), <span style="color:#98fb98;">init</span>:<span style="color:#98fb98;">stop</span>().'
<span style="color:#eedd82;">Erlang</span> <span style="color:#eedd82;">R14B</span> (<span style="color:#7fffd4;">erts</span>-5.8.1) [<span style="color:#7fffd4;">source</span>] [<span style="color:#7fffd4;">smp</span>:4:4] [<span style="color:#7fffd4;">rq</span>:4] [<span style="color:#7fffd4;">async</span>-<span style="color:#7fffd4;">threads</span>:0] [<span style="color:#7fffd4;">hipe</span>] [<span style="color:#7fffd4;">kernel</span>-<span style="color:#7fffd4;">poll</span>:<span style="color:#7fffd4;">false</span>]

<span style="color:#eedd82;">Eshell</span> <span style="color:#eedd82;">V5</span>.8.1  (<span style="color:#7fffd4;">abort</span> <span style="color:#7fffd4;">with</span> ^<span style="color:#eedd82;">G</span>)
1&gt; ======================== <span style="color:#eedd82;">EUnit</span> ========================
<span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_job_layer'</span>
  <span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_job_layer_tests'</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">register</span> <span style="color:#7fffd4;">locally</span>)...[0.004 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Executed</span> <span style="color:#7fffd4;">locally</span>)...{1299,10791,575180} : <span style="color:#7fffd4;">file_fetching_done</span>
{1299,10791,575182} : <span style="color:#7fffd4;">executing_commands</span>
{1299,10791,575370} : {<span style="color:#7fffd4;">executing</span>,<span style="color:#ffa07a;">"more EUnitFile"</span>}
{1299,10791,582067} : <span style="color:#ffa07a;">"1,2,3"</span>
{1299,10791,582181} : <span style="color:#7fffd4;">no_more_commands</span>
{1299,10791,582183} : <span style="color:#7fffd4;">building_result_tgz</span>
{1299,10791,582278} : <span style="color:#7fffd4;">done</span>
[1.005 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Executed</span> <span style="color:#7fffd4;">queue</span>)...{1299,10792,587205} : <span style="color:#7fffd4;">file_fetching_done</span>
{1299,10792,587208} : <span style="color:#7fffd4;">executing_commands</span>
{1299,10792,587299} : {<span style="color:#7fffd4;">executing</span>,<span style="color:#ffa07a;">"file EunitFile"</span>}
{1299,10792,594990} : <span style="color:#ffa07a;">"EunitFile: ASCII text"</span>
{1299,10792,595034} : <span style="color:#7fffd4;">no_more_commands</span>
{1299,10792,595037} : <span style="color:#7fffd4;">building_result_tgz</span>
{1299,10792,595117} : <span style="color:#7fffd4;">done</span>
{1299,10792,598436} : <span style="color:#7fffd4;">file_fetching_done</span>
{1299,10792,598446} : <span style="color:#7fffd4;">executing_commands</span>
{1299,10792,598525} : {<span style="color:#7fffd4;">executing</span>,<span style="color:#ffa07a;">"cat EUnitFile"</span>}
{1299,10792,603488} : <span style="color:#ffa07a;">"1,2,3"</span>
{1299,10792,603533} : <span style="color:#7fffd4;">no_more_commands</span>
{1299,10792,603536} : <span style="color:#7fffd4;">building_result_tgz</span>
{1299,10792,603593} : <span style="color:#7fffd4;">done</span>
[1.104 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Queueus</span> <span style="color:#7fffd4;">on</span> <span style="color:#7fffd4;">resource</span> <span style="color:#7fffd4;">type</span> <span style="color:#7fffd4;">amount</span>)...<span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Canceled</span> <span style="color:#7fffd4;">in</span> <span style="color:#7fffd4;">queue</span>)...<span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Done</span> <span style="color:#eedd82;">Job</span> <span style="color:#eedd82;">Stored</span> <span style="color:#7fffd4;">in</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">layer</span>)...[0.609 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 2.773 <span style="color:#7fffd4;">s</span>]
  [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 2.773 <span style="color:#7fffd4;">s</span>]
=======================================================
  <span style="color:#eedd82;">All</span> 6 <span style="color:#7fffd4;">tests</span> <span style="color:#7fffd4;">passed</span>.
<span style="color:#7fffd4;">dialyzer</span> <span style="color:#7fffd4;">src</span>/*.<span style="color:#7fffd4;">erl</span> <span style="color:#7fffd4;">test</span>/*.<span style="color:#7fffd4;">erl</span>
  <span style="color:#eedd82;">Checking</span> <span style="color:#7fffd4;">whether</span> <span style="color:#7fffd4;">the</span> <span style="color:#eedd82;">PLT</span> /<span style="color:#eedd82;">Users</span>/<span style="color:#7fffd4;">zenon</span>/.<span style="color:#7fffd4;">dialyzer_plt</span> <span style="color:#7fffd4;">is</span> <span style="color:#7fffd4;">up</span>-<span style="color:#7fffd4;">to</span>-<span style="color:#7fffd4;">date</span>... <span style="color:#7fffd4;">yes</span>
  <span style="color:#eedd82;">Proceeding</span> <span style="color:#7fffd4;">with</span> <span style="color:#7fffd4;">analysis</span>...
<span style="color:#eedd82;">Unknown</span> <span style="color:#7fffd4;">functions</span>:
  <span style="color:#7fffd4;">eunit</span>:<span style="color:#87cefa;">test/1</span>
 <span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0m5.21s
<span style="color:#87cefa;">done</span> (<span style="color:#7fffd4;">passed</span> <span style="color:#7fffd4;">successfully</span>)</pre>
<p><!--- End Of Snippet --></p>
<p>The status of the stories is now</p>
<h2>Done stories</h2>
<p>“<em>I want to be able to describe a job as</em></p>
<ul>
<li><em>A set of Files [#wn_file{}]</em></li>
<li><em>The possible resource types needed (disjunction)</em></li>
<li><em>A list of commands for running the job</em></li>
<li><em>A timeout the job is given while running (in seconds)</em></li>
<li><em>A job id – primary key for the job</em><em>“</em></li>
</ul>
<p>“<em>I want to be able to register a job in the job layer,  through  any node.</em>“</p>
<p>“<em>Several jobs should be queued on the same resource type(s),  being processed one and one in order as they where queued</em>“</p>
<p>“<em>I want to be able to list all jobs in the system, through any node</em>.”</p>
<p>“<em>The output generated by a job should be possible to see in realtime,  through any node and stored to logfiles</em>.”</p>
<p>“<em>A job must be possible to cancel before it starts running, through any node.</em>“</p>
<p>“<em>Once a job is done, the result should be stored in the file layer,  together with the logs.</em>“</p>
<h2>Not done stories</h2>
<p>“<em>I want to be able to delete a job once it’s done, through any node</em>.”</p>
<p>In the next post, I shall write the test and implementation of the current final story on the job layer &#8211; to delete a job from any node &#8211; once it&#8217;s done.</p>
<p>Cheers</p>
<p>/G</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/erlcode.wordpress.com/633/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/erlcode.wordpress.com/633/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=erlcode.wordpress.com&#038;blog=15510807&#038;post=633&#038;subd=erlcode&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://erlcode.wordpress.com/2011/03/01/erlang-tdd-hands-on-project-part-7/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/861b8f824c3cd15c17ac6aa1b902e029?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">gianfrancoalongi</media:title>
		</media:content>
	</item>
		<item>
		<title>Erlang TDD hands on project &#8211; WorkerNet part 6</title>
		<link>http://erlcode.wordpress.com/2011/02/17/erlang-tdd-hands-on-project-workernet-part-6/</link>
		<comments>http://erlcode.wordpress.com/2011/02/17/erlang-tdd-hands-on-project-workernet-part-6/#comments</comments>
		<pubDate>Thu, 17 Feb 2011 21:48:33 +0000</pubDate>
		<dc:creator>gianfrancoalongi</dc:creator>
				<category><![CDATA[WorkerNet]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[workernet]]></category>

		<guid isPermaLink="false">http://erlcode.wordpress.com/?p=610</guid>
		<description><![CDATA[In the previous post, two tests where introduced &#8211; one of them to design and test the API for job cancelation &#8211; for this, proper per-type queueing was needed. So a queueing test was introduced. new test was finished and some architectural changes introduced &#8211; one of them was to change the wn_resource_process from a [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=erlcode.wordpress.com&#038;blog=15510807&#038;post=610&#038;subd=erlcode&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>In the previous post, two tests where introduced &#8211; one of them to design and test the API for job cancelation &#8211; for this, proper per-type queueing was needed. So a queueing test was introduced. new test was finished and some architectural changes introduced &#8211; one of them was to change the <em>wn_resource_process </em>from a gen_fsm to a gen_server &#8211; turns out the initial assumption did not hold.</p>
<p>So, I present the new listing of <strong><em>wn_resource_process.erl</em></strong></p>
<p><!--- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">-------------------------------------------------------------------
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@author Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@copyright (C) 2011, Gianfranco
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">Created : 14 Feb 2011 by Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">-------------------------------------------------------------------
</span><span style="color:#b0c4de;">-module</span>(<span style="color:#7fffd4;">wn_resource_process</span>).
<span style="color:#b0c4de;">-behaviour</span>(<span style="color:#7fffd4;">gen_server</span>).
<span style="color:#b0c4de;">-include</span>(<span style="color:#ffa07a;">"include/worker_net.hrl"</span>).
<span style="color:#b0c4de;">-define</span>(<span style="color:#b0c4de;">TIMEOUT</span>,3000).
<span style="color:#b0c4de;">-record</span>(<span style="color:#b0c4de;">state</span>,{<span style="color:#7fffd4;">node_root</span> :: <span style="color:#98fb98;">string</span>(),
               <span style="color:#7fffd4;">queues</span> :: [{<span style="color:#7fffd4;">atom</span>,[<span style="color:#b0c4de;">pid</span>()]}],
               <span style="color:#7fffd4;">working</span>, <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">ets {pid(),pid(),atom()}
</span>               <span style="color:#7fffd4;">slots</span>    <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">ets {atom,non_neg_integer()|infinity}
</span>              }).

<span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">API
</span><span style="color:#b0c4de;">-export</span>([<span style="color:#87cefa;">start_link/2</span>,<span style="color:#87cefa;">signal/3</span>,<span style="color:#87cefa;">queued/1</span>]).

<span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">gen_server callbacks
</span><span style="color:#b0c4de;">-export</span>([<span style="color:#87cefa;">init/1</span>, <span style="color:#87cefa;">handle_call/3</span>, <span style="color:#87cefa;">handle_cast/2</span>, <span style="color:#87cefa;">handle_info/2</span>,
         <span style="color:#87cefa;">terminate/2</span>, <span style="color:#87cefa;">code_change/3</span>]).

<span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">==========================================================
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">API
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">==========================================================
</span><span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">start_link</span>(<span style="color:#98fb98;">string</span>(),[<span style="color:#98fb98;">resource_spec</span>()]) -&gt; {<span style="color:#7fffd4;">ok</span>,<span style="color:#b0c4de;">pid</span>()} | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).
<span style="color:#87cefa;">start_link</span>(<span style="color:#eedd82;">NodeRoot</span>,<span style="color:#eedd82;">TypeSpec</span>) -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">start_link</span>(?<span style="color:#b0c4de;">MODULE</span>, {<span style="color:#eedd82;">NodeRoot</span>,<span style="color:#eedd82;">TypeSpec</span>}, []).

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">signal</span>(<span style="color:#b0c4de;">pid</span>(),<span style="color:#b0c4de;">pid</span>(),<span style="color:#b0c4de;">atom</span>()) -&gt; <span style="color:#7fffd4;">ok</span>).
<span style="color:#87cefa;">signal</span>(<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">QueueType</span>) -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">cast</span>(<span style="color:#eedd82;">Pid</span>,{<span style="color:#7fffd4;">signal</span>,<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">QueueType</span>}).

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">queued</span>(<span style="color:#b0c4de;">pid</span>()) -&gt; [{<span style="color:#b0c4de;">atom</span>(),[#<span style="color:#b0c4de;">wn_job</span>{}]}]).
<span style="color:#87cefa;">queued</span>(<span style="color:#eedd82;">Pid</span>) -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">Pid</span>,<span style="color:#7fffd4;">queued</span>).

<span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">==========================================================
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">gen_server callbacks
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">==========================================================
</span><span style="color:#87cefa;">init</span>({<span style="color:#eedd82;">NodeRoot</span>,<span style="color:#eedd82;">TypeSpec</span>}) -&gt;
    <span style="color:#eedd82;">Slots</span> = <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">new</span>(<span style="color:#7fffd4;">available</span>,[<span style="color:#7fffd4;">set</span>]),
    <span style="color:#eedd82;">Working</span> = <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">new</span>(<span style="color:#7fffd4;">working</span>,[<span style="color:#7fffd4;">set</span>]),
    <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foreach</span>(<span style="color:#00ffff;">fun</span>({<span style="color:#eedd82;">Type</span>,<span style="color:#eedd82;">Amount</span>}) -&gt;
                          <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">insert</span>(<span style="color:#eedd82;">Slots</span>,{<span style="color:#eedd82;">Type</span>,<span style="color:#eedd82;">Amount</span>}),
                          <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">insert</span>(<span style="color:#eedd82;">Working</span>,{<span style="color:#eedd82;">Type</span>,[]})
                  <span style="color:#00ffff;">end</span>,<span style="color:#eedd82;">TypeSpec</span>),
    {<span style="color:#7fffd4;">ok</span>,#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">node_root</span> = <span style="color:#eedd82;">NodeRoot</span>,
               <span style="color:#7fffd4;">queues</span> = [{<span style="color:#eedd82;">Type</span>,[]} <span style="color:#00ffff;">||</span> {<span style="color:#eedd82;">Type</span>,<span style="color:#eedd82;">_</span>} <span style="color:#00ffff;">&lt;-</span> <span style="color:#eedd82;">TypeSpec</span>],
               <span style="color:#7fffd4;">slots</span> = <span style="color:#eedd82;">Slots</span>,
               <span style="color:#7fffd4;">working</span> = <span style="color:#eedd82;">Working</span>
              }}.

<span style="color:#87cefa;">handle_call</span>(<span style="color:#7fffd4;">queued</span>, <span style="color:#eedd82;">_From</span>, <span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#eedd82;">Reply</span> = <span style="color:#98fb98;">collect_jobs</span>(<span style="color:#eedd82;">State</span>),
    {<span style="color:#7fffd4;">reply</span>, <span style="color:#eedd82;">Reply</span>, <span style="color:#eedd82;">State</span>}.

<span style="color:#87cefa;">handle_cast</span>({<span style="color:#7fffd4;">signal</span>,<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">QueueType</span>}, <span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">noreply</span>,
     <span style="color:#00ffff;">case</span> {<span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">lookup</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">slots</span>,<span style="color:#eedd82;">QueueType</span>),
           <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">keytake</span>(<span style="color:#eedd82;">QueueType</span>,1,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">queues</span>)} <span style="color:#00ffff;">of</span>
         {[{<span style="color:#eedd82;">QueueType</span>,<span style="color:#7fffd4;">infinity</span>}], <span style="color:#eedd82;">_</span> } -&gt;
             <span style="color:#98fb98;">try_dispatch_job</span>(<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">State</span>,<span style="color:#eedd82;">QueueType</span>),
             <span style="color:#eedd82;">State</span>;
         {[{<span style="color:#eedd82;">QueueType</span>,<span style="color:#eedd82;">Available</span>}], {<span style="color:#7fffd4;">value</span>,{<span style="color:#eedd82;">_</span>,[]},<span style="color:#eedd82;">_</span>}} <span style="color:#00ffff;">when</span> <span style="color:#eedd82;">Available</span> &gt; 0 -&gt;
             <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">try_dispatch_job</span>(<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">State</span>,<span style="color:#eedd82;">QueueType</span>) <span style="color:#00ffff;">of</span>
                 <span style="color:#7fffd4;">ok</span> -&gt; <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">insert</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">slots</span>,{<span style="color:#eedd82;">QueueType</span>,<span style="color:#eedd82;">Available</span>-1});
                 {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">taken</span>} -&gt; <span style="color:#7fffd4;">ignore</span>
             <span style="color:#00ffff;">end</span>,
             <span style="color:#eedd82;">State</span>;
         {[{<span style="color:#eedd82;">QueueType</span>,<span style="color:#eedd82;">_</span>}], {<span style="color:#7fffd4;">value</span>,{<span style="color:#eedd82;">Type</span>,<span style="color:#eedd82;">Queue</span>},<span style="color:#eedd82;">Queues</span>}} -&gt;
             <span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">queues</span> = [{<span style="color:#eedd82;">Type</span>,<span style="color:#eedd82;">Queue</span><span style="color:#ffc0cb;font-weight:bold;">++</span>[<span style="color:#eedd82;">JobKeeperPid</span>]}|<span style="color:#eedd82;">Queues</span>]}
     <span style="color:#00ffff;">end</span>}.

<span style="color:#87cefa;">handle_info</span>({<span style="color:#7fffd4;">'EXIT'</span>,<span style="color:#eedd82;">WorkerPid</span>,<span style="color:#eedd82;">Reason</span>}, <span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">noreply</span>,
     <span style="color:#00ffff;">begin</span>
      [{<span style="color:#eedd82;">WorkerPid</span>,<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">QueueType</span>}] = <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">lookup</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">working</span>,<span style="color:#eedd82;">WorkerPid</span>),
      <span style="color:#7fffd4;">true</span> = <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">working</span>,<span style="color:#eedd82;">WorkerPid</span>),
      <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">done</span>(<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">Reason</span>),
      <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">keytake</span>(<span style="color:#eedd82;">QueueType</span>,1,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">queues</span>) <span style="color:#00ffff;">of</span>
         {<span style="color:#7fffd4;">value</span>,{<span style="color:#eedd82;">_</span>,[]},<span style="color:#eedd82;">_</span>} -&gt;
            <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">lookup</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">slots</span>,<span style="color:#eedd82;">QueueType</span>) <span style="color:#00ffff;">of</span>
                [{<span style="color:#eedd82;">QueueType</span>,<span style="color:#7fffd4;">infinity</span>}] -&gt; <span style="color:#7fffd4;">ignore</span>;
                [{<span style="color:#eedd82;">QueueType</span>,<span style="color:#eedd82;">X</span>}] -&gt; <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">insert</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">slots</span>,{<span style="color:#eedd82;">QueueType</span>,<span style="color:#eedd82;">X</span>+1})
           <span style="color:#00ffff;">end</span>,
           <span style="color:#eedd82;">State</span>;
         {<span style="color:#7fffd4;">value</span>,{<span style="color:#eedd82;">Type</span>,[<span style="color:#eedd82;">QueuedPid</span>|<span style="color:#eedd82;">R</span>]},<span style="color:#eedd82;">Queues</span>} -&gt;
            <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">try_dispatch_job</span>(<span style="color:#eedd82;">QueuedPid</span>,<span style="color:#eedd82;">State</span>,<span style="color:#eedd82;">QueueType</span>) <span style="color:#00ffff;">of</span>
                <span style="color:#7fffd4;">ok</span> -&gt;
                   <span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">queues</span> = [{<span style="color:#eedd82;">Type</span>,<span style="color:#eedd82;">R</span>}|<span style="color:#eedd82;">Queues</span>]};
                {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">taken</span>} -&gt;
                   <span style="color:#eedd82;">State</span>
           <span style="color:#00ffff;">end</span>
      <span style="color:#00ffff;">end</span>
     <span style="color:#00ffff;">end</span>}.

<span style="color:#87cefa;">terminate</span>(<span style="color:#eedd82;">_Reason</span>, <span style="color:#eedd82;">_State</span>) -&gt;
    <span style="color:#7fffd4;">ok</span>.

<span style="color:#87cefa;">code_change</span>(<span style="color:#eedd82;">_OldVsn</span>, <span style="color:#eedd82;">State</span>, <span style="color:#eedd82;">_Extra</span>) -&gt;
    {<span style="color:#7fffd4;">ok</span>, <span style="color:#eedd82;">State</span>}.

<span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">==========================================================
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">Internal functions
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">==========================================================
</span><span style="color:#87cefa;">try_dispatch_job</span>(<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">State</span>,<span style="color:#eedd82;">QueueType</span>) -&gt;
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">signal</span>(<span style="color:#eedd82;">JobKeeperPid</span>) <span style="color:#00ffff;">of</span>
        {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">WnJob</span>} -&gt;
            <span style="color:#b0c4de;">process_flag</span>(<span style="color:#7fffd4;">trap_exit</span>,<span style="color:#7fffd4;">true</span>),
            {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">WorkerPid</span>}  = <span style="color:#98fb98;">wn_job_worker</span>:<span style="color:#98fb98;">start_link</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">node_root</span>,
                                                <span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">WnJob</span>),
            <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">insert</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">working</span>,{<span style="color:#eedd82;">WorkerPid</span>,<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">QueueType</span>}),
            <span style="color:#7fffd4;">ok</span>;
        {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">taken</span>} -&gt;
            {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">taken</span>}
    <span style="color:#00ffff;">end</span>.

<span style="color:#87cefa;">collect_jobs</span>(<span style="color:#eedd82;">State</span>) -&gt;
    [{<span style="color:#eedd82;">Type</span>,[ <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">get_job</span>(<span style="color:#eedd82;">Pid</span>) <span style="color:#00ffff;">||</span> <span style="color:#eedd82;">Pid</span> <span style="color:#00ffff;">&lt;-</span> <span style="color:#eedd82;">Queue</span>]}
     <span style="color:#00ffff;">||</span> {<span style="color:#eedd82;">Type</span>,<span style="color:#eedd82;">Queue</span>} <span style="color:#00ffff;">&lt;-</span> <span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">queues</span>].</pre>
<p><!--- End Of Snippet -!&gt; --></p>
<p>This new code was accompanied with an additional change in the <em><strong>worker_net.hrl </strong></em>header</p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-type</span> <span style="color:#98fb98;">resource_spec</span>() :: [{<span style="color:#b0c4de;">atom</span>(),<span style="color:#7fffd4;">infinity</span>| <span style="color:#98fb98;">non_neg_integer</span>()}].

<span style="color:#b0c4de;">-record</span>(<span style="color:#b0c4de;">wn_resource</span>,
        {<span style="color:#7fffd4;">name</span> :: <span style="color:#98fb98;">string</span>(),
         <span style="color:#7fffd4;">type</span> :: <span style="color:#98fb98;">resource_spec</span>(),
         <span style="color:#7fffd4;">resides</span> :: <span style="color:#b0c4de;">node</span>(),
         <span style="color:#7fffd4;">pid</span> :: <span style="color:#b0c4de;">pid</span>() | <span style="color:#7fffd4;">undefined</span>
        }).</pre>
<p><!--- End Of Snippet --></p>
<p>and some additional changes in the <em><strong>wn_resource_layer.erl</strong></em> module.</p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">try_register</span>(<span style="color:#eedd82;">State</span>,<span style="color:#eedd82;">Resource</span>) -&gt;
    #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span>=<span style="color:#eedd82;">Name</span>} = <span style="color:#eedd82;">Resource</span>,
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">lookup</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">resources</span>,<span style="color:#eedd82;">Name</span>) <span style="color:#00ffff;">of</span>
        [] -&gt;
            <span style="color:#b0c4de;">process_flag</span>(<span style="color:#7fffd4;">trap_exit</span>,<span style="color:#7fffd4;">true</span>),
            <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">NEW CODE
</span>            {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">Pid</span>} = <span style="color:#98fb98;">wn_resource_process</span>:<span style="color:#98fb98;">start_link</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">node_root</span>,
                                             <span style="color:#eedd82;">Resource</span>#<span style="color:#b0c4de;">wn_resource</span>.<span style="color:#7fffd4;">type</span>),
            <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">insert</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">resources</span>,
                       {<span style="color:#eedd82;">Name</span>,<span style="color:#eedd82;">Resource</span>#<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">pid</span>=<span style="color:#eedd82;">Pid</span>}}),
            <span style="color:#7fffd4;">ok</span>;
        <span style="color:#eedd82;">_</span> -&gt;
            {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">already_exists</span>}
    <span style="color:#00ffff;">end</span>.</pre>
<p><!--- End Of Snippet --></p>
<p>Further on, I noticed my blunder in the test for this, and replaced the #wn_job{} records in the ?assertEquals with the actual jobs, so the test would look like this in <em><strong>wn_job_layer_tests.erl</strong></em></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">queues_on_resource_types_amount</span>() -&gt;
    <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(#<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"Laptop"</span>,
                                            <span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">a</span>,0},{<span style="color:#7fffd4;">b</span>,1}],
                                            <span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()
                                           }),
    <span style="color:#eedd82;">Queued</span> = <span style="color:#00ffff;">fun</span>() -&gt; <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">queued</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#ffa07a;">"Laptop"</span>) <span style="color:#00ffff;">end</span>,
    <span style="color:#eedd82;">Job1</span> = #<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId"</span>,
                   <span style="color:#7fffd4;">files</span> = [],
                   <span style="color:#7fffd4;">resources</span> = [<span style="color:#7fffd4;">a</span>],
                   <span style="color:#7fffd4;">commands</span> = [<span style="color:#ffa07a;">"sleep 5"</span>]},
    <span style="color:#eedd82;">Job2</span> = <span style="color:#eedd82;">Job1</span>#<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId2"</span>, <span style="color:#7fffd4;">resources</span> = [<span style="color:#7fffd4;">a</span>]},
    <span style="color:#eedd82;">Job3</span> = <span style="color:#eedd82;">Job1</span>#<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId3"</span>, <span style="color:#7fffd4;">resources</span> = [<span style="color:#7fffd4;">a</span>,<span style="color:#7fffd4;">b</span>]},
    <span style="color:#eedd82;">Job4</span> = <span style="color:#eedd82;">Job1</span>#<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId4"</span>, <span style="color:#7fffd4;">resources</span> = [<span style="color:#7fffd4;">b</span>]},

    <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">Job1</span>),
    ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,[{<span style="color:#7fffd4;">a</span>,[<span style="color:#eedd82;">Job1</span>]},{<span style="color:#7fffd4;">b</span>,[]}]},<span style="color:#eedd82;">Queued</span>()),

    <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">Job2</span>),
    ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,[{<span style="color:#7fffd4;">a</span>,[<span style="color:#eedd82;">Job1</span>, <span style="color:#eedd82;">Job2</span>]},{<span style="color:#7fffd4;">b</span>,[]}]},<span style="color:#eedd82;">Queued</span>()),

    <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">This job will be executed by b with 1 slot - do not expect
</span>    <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">it to be queued
</span>    <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">Job3</span>),
    ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,[{<span style="color:#7fffd4;">a</span>,[<span style="color:#eedd82;">Job1</span>,<span style="color:#eedd82;">Job2</span>,<span style="color:#eedd82;">Job3</span>]},
                      {<span style="color:#7fffd4;">b</span>,[]}]},<span style="color:#eedd82;">Queued</span>()),

    <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">Job4</span>),
    ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,[{<span style="color:#7fffd4;">b</span>,[<span style="color:#eedd82;">Job4</span>]},{<span style="color:#7fffd4;">a</span>,[<span style="color:#eedd82;">Job1</span>,<span style="color:#eedd82;">Job2</span>,<span style="color:#eedd82;">Job3</span>]}]},<span style="color:#eedd82;">Queued</span>()).</pre>
<p>Running the tests &#8211; and it worked! All tests except cancel would now work &#8211; proof below<br />
<!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#7fffd4;">zen</span>:<span style="color:#7fffd4;">worker_net</span>-0.1 <span style="color:#7fffd4;">zenon</span><span style="color:#ffa07a;">$ </span><span style="color:#7fffd4;">make</span> <span style="color:#7fffd4;">full</span>
<span style="color:#7fffd4;">erlc</span> -<span style="color:#7fffd4;">pa</span> . -<span style="color:#7fffd4;">o</span> <span style="color:#7fffd4;">ebin</span>/  <span style="color:#7fffd4;">src</span>/*.<span style="color:#7fffd4;">erl</span> <span style="color:#7fffd4;">test</span>/*.<span style="color:#7fffd4;">erl</span>
<span style="color:#7fffd4;">erl</span> -<span style="color:#7fffd4;">pa</span> <span style="color:#7fffd4;">ebin</span>/ -<span style="color:#7fffd4;">eval</span> 'eunit:<span style="color:#98fb98;">test</span>(<span style="color:#7fffd4;">wn_resource_layer</span>,[<span style="color:#7fffd4;">verbose</span>]), <span style="color:#98fb98;">init</span>:<span style="color:#98fb98;">stop</span>().'
<span style="color:#eedd82;">Erlang</span> <span style="color:#eedd82;">R14B</span> (<span style="color:#7fffd4;">erts</span>-5.8.1) [<span style="color:#7fffd4;">source</span>] [<span style="color:#7fffd4;">smp</span>:4:4] [<span style="color:#7fffd4;">rq</span>:4] [<span style="color:#7fffd4;">async</span>-<span style="color:#7fffd4;">threads</span>:0] [<span style="color:#7fffd4;">hipe</span>] [<span style="color:#7fffd4;">kernel</span>-<span style="color:#7fffd4;">poll</span>:<span style="color:#7fffd4;">false</span>]

<span style="color:#eedd82;">Eshell</span> <span style="color:#eedd82;">V5</span>.8.1  (<span style="color:#7fffd4;">abort</span> <span style="color:#7fffd4;">with</span> ^<span style="color:#eedd82;">G</span>)
1&gt; ======================== <span style="color:#eedd82;">EUnit</span> ========================
<span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_resource_layer'</span>
  <span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_resource_layer_tests'</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">local_resource_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">register</span> <span style="color:#7fffd4;">resources</span> <span style="color:#7fffd4;">locally</span>)...[0.001 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">register_distributed</span> (<span style="color:#eedd82;">Can</span> <span style="color:#eedd82;">Register</span> <span style="color:#eedd82;">Distributed</span>)...[0.004 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">register_restart_register</span> (<span style="color:#eedd82;">Can</span> <span style="color:#eedd82;">Register</span>, <span style="color:#eedd82;">Restart</span> <span style="color:#7fffd4;">and</span> <span style="color:#eedd82;">Register</span>)...[0.010 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">register_deregister</span> (<span style="color:#eedd82;">Can</span> <span style="color:#eedd82;">Register</span>, <span style="color:#eedd82;">Deregister</span> <span style="color:#7fffd4;">and</span> <span style="color:#eedd82;">Register</span>)...[0.007 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0.902 <span style="color:#7fffd4;">s</span>]
  [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0.902 <span style="color:#7fffd4;">s</span>]
=======================================================
  <span style="color:#eedd82;">All</span> 4 <span style="color:#7fffd4;">tests</span> <span style="color:#7fffd4;">passed</span>.
<span style="color:#7fffd4;">erl</span> -<span style="color:#7fffd4;">pa</span> <span style="color:#7fffd4;">ebin</span>/ -<span style="color:#7fffd4;">eval</span> 'eunit:<span style="color:#98fb98;">test</span>(<span style="color:#7fffd4;">wn_file_layer</span>,[<span style="color:#7fffd4;">verbose</span>]), <span style="color:#98fb98;">init</span>:<span style="color:#98fb98;">stop</span>().'
<span style="color:#eedd82;">Erlang</span> <span style="color:#eedd82;">R14B</span> (<span style="color:#7fffd4;">erts</span>-5.8.1) [<span style="color:#7fffd4;">source</span>] [<span style="color:#7fffd4;">smp</span>:4:4] [<span style="color:#7fffd4;">rq</span>:4] [<span style="color:#7fffd4;">async</span>-<span style="color:#7fffd4;">threads</span>:0] [<span style="color:#7fffd4;">hipe</span>] [<span style="color:#7fffd4;">kernel</span>-<span style="color:#7fffd4;">poll</span>:<span style="color:#7fffd4;">false</span>]

<span style="color:#eedd82;">Eshell</span> <span style="color:#eedd82;">V5</span>.8.1  (<span style="color:#7fffd4;">abort</span> <span style="color:#7fffd4;">with</span> ^<span style="color:#eedd82;">G</span>)
1&gt; ======================== <span style="color:#eedd82;">EUnit</span> ========================
<span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_file_layer'</span>
  <span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_file_layer_tests'</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">file_layer_local_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">store</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">locally</span>)...[0.001 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">file_layer_local_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">retrieve</span> <span style="color:#7fffd4;">files</span> <span style="color:#7fffd4;">locally</span>)...[0.002 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">file_layer_local_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">delete</span> <span style="color:#7fffd4;">files</span> <span style="color:#7fffd4;">locally</span>)...[0.002 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">can_store_distributed</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">store</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">distributed</span>)...[0.017 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">can_retrieve_distributed</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">retrieve</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">distributed</span>)...[0.014 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">can_delete_distributed</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">delete</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">distributed</span>)...[0.015 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">must_retain</span> (<span style="color:#eedd82;">Must</span> <span style="color:#7fffd4;">retain</span> <span style="color:#7fffd4;">information</span> <span style="color:#7fffd4;">between</span> <span style="color:#7fffd4;">node</span> <span style="color:#7fffd4;">kill</span> <span style="color:#7fffd4;">and</span> <span style="color:#7fffd4;">node</span> <span style="color:#7fffd4;">restart</span>)...[0.299 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 1.495 <span style="color:#7fffd4;">s</span>]
  [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 1.496 <span style="color:#7fffd4;">s</span>]
=======================================================
  <span style="color:#eedd82;">All</span> 7 <span style="color:#7fffd4;">tests</span> <span style="color:#7fffd4;">passed</span>.
<span style="color:#7fffd4;">erl</span> -<span style="color:#7fffd4;">pa</span> <span style="color:#7fffd4;">ebin</span>/ -<span style="color:#7fffd4;">eval</span> 'eunit:<span style="color:#98fb98;">test</span>(<span style="color:#7fffd4;">wn_job_layer</span>,[<span style="color:#7fffd4;">verbose</span>]), <span style="color:#98fb98;">init</span>:<span style="color:#98fb98;">stop</span>().'
<span style="color:#eedd82;">Erlang</span> <span style="color:#eedd82;">R14B</span> (<span style="color:#7fffd4;">erts</span>-5.8.1) [<span style="color:#7fffd4;">source</span>] [<span style="color:#7fffd4;">smp</span>:4:4] [<span style="color:#7fffd4;">rq</span>:4] [<span style="color:#7fffd4;">async</span>-<span style="color:#7fffd4;">threads</span>:0] [<span style="color:#7fffd4;">hipe</span>] [<span style="color:#7fffd4;">kernel</span>-<span style="color:#7fffd4;">poll</span>:<span style="color:#7fffd4;">false</span>]

<span style="color:#eedd82;">Eshell</span> <span style="color:#eedd82;">V5</span>.8.1  (<span style="color:#7fffd4;">abort</span> <span style="color:#7fffd4;">with</span> ^<span style="color:#eedd82;">G</span>)
1&gt; ======================== <span style="color:#eedd82;">EUnit</span> ========================
<span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_job_layer'</span>
  <span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_job_layer_tests'</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">register</span> <span style="color:#7fffd4;">locally</span>)...[0.004 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Executed</span> <span style="color:#7fffd4;">locally</span>)...<span style="color:#7fffd4;">file_fetching_done</span>
<span style="color:#7fffd4;">executing_commands</span>
{<span style="color:#7fffd4;">executing</span>,<span style="color:#ffa07a;">"more EUnitFile"</span>}
<span style="color:#ffa07a;">"1,2,3"</span>
<span style="color:#7fffd4;">no_more_commands</span>
<span style="color:#7fffd4;">done</span>
<span style="color:#7fffd4;">normal</span>
[1.004 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Executed</span> <span style="color:#7fffd4;">queue</span>)...<span style="color:#7fffd4;">file_fetching_done</span>
<span style="color:#7fffd4;">executing_commands</span>
{<span style="color:#7fffd4;">executing</span>,<span style="color:#ffa07a;">"file EunitFile"</span>}
<span style="color:#ffa07a;">"EunitFile: ASCII text"</span>
<span style="color:#7fffd4;">no_more_commands</span>
<span style="color:#7fffd4;">done</span>
<span style="color:#7fffd4;">normal</span>
<span style="color:#7fffd4;">file_fetching_done</span>
<span style="color:#7fffd4;">executing_commands</span>
{<span style="color:#7fffd4;">executing</span>,<span style="color:#ffa07a;">"cat EUnitFile"</span>}
<span style="color:#ffa07a;">"1,2,3"</span>
<span style="color:#7fffd4;">no_more_commands</span>
<span style="color:#7fffd4;">done</span>
<span style="color:#7fffd4;">normal</span>
[1.105 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Queueus</span> <span style="color:#7fffd4;">on</span> <span style="color:#7fffd4;">resource</span> <span style="color:#7fffd4;">type</span> <span style="color:#7fffd4;">amount</span>)...[0.001 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>

                                                                                                                       <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Canceled</span> <span style="color:#7fffd4;">in</span> <span style="color:#7fffd4;">queue</span>)...
=<span style="color:#eedd82;">ERROR</span> <span style="color:#eedd82;">REPORT</span>==== 16-<span style="color:#eedd82;">Feb</span>-2011::21:18:37 ===
** <span style="color:#eedd82;">Generic</span> <span style="color:#7fffd4;">server</span> <span style="color:#7fffd4;">wn_job_layer</span> <span style="color:#7fffd4;">terminating</span>
** <span style="color:#eedd82;">Last</span> <span style="color:#7fffd4;">message</span> <span style="color:#7fffd4;">in</span> <span style="color:#7fffd4;">was</span> {<span style="color:#7fffd4;">cancel</span>,<span style="color:#ffa07a;">"JobId"</span>}
** <span style="color:#eedd82;">When</span> <span style="color:#eedd82;">Server</span> <span style="color:#7fffd4;">state</span> == {<span style="color:#7fffd4;">state</span>,98322}
** <span style="color:#eedd82;">Reason</span> <span style="color:#7fffd4;">for</span> <span style="color:#7fffd4;">termination</span> ==
** {<span style="color:#7fffd4;">'function not exported'</span>,[{<span style="color:#7fffd4;">wn_job_keeper</span>,<span style="color:#7fffd4;">cancel</span>,[&lt;0.148.0&gt;]},
                             {<span style="color:#7fffd4;">wn_job_layer</span>,<span style="color:#7fffd4;">try_cancel</span>,2},
                             {<span style="color:#7fffd4;">wn_job_layer</span>,<span style="color:#7fffd4;">handle_call</span>,3},
                             {<span style="color:#7fffd4;">gen_server</span>,<span style="color:#7fffd4;">handle_msg</span>,5},
                             {<span style="color:#7fffd4;">proc_lib</span>,<span style="color:#7fffd4;">init_p_do_apply</span>,3}]}
*<span style="color:#7fffd4;">skipped</span>*
<span style="color:#7fffd4;">undefined</span>
*<span style="color:#7fffd4;">unexpected</span> <span style="color:#7fffd4;">termination</span> <span style="color:#00ffff;">of</span> <span style="color:#7fffd4;">test</span> <span style="color:#7fffd4;">process</span>*
::{<span style="color:#7fffd4;">undef</span>,[{<span style="color:#7fffd4;">wn_job_keeper</span>,<span style="color:#7fffd4;">cancel</span>,[&lt;0.148.0&gt;]},
          {<span style="color:#7fffd4;">wn_job_layer</span>,<span style="color:#7fffd4;">try_cancel</span>,2},
          {<span style="color:#7fffd4;">wn_job_layer</span>,<span style="color:#7fffd4;">handle_call</span>,3},
          {<span style="color:#7fffd4;">gen_server</span>,<span style="color:#7fffd4;">handle_msg</span>,5},
          {<span style="color:#7fffd4;">proc_lib</span>,<span style="color:#7fffd4;">init_p_do_apply</span>,3}]}

=======================================================
  <span style="color:#eedd82;">Failed</span>: 0.  <span style="color:#eedd82;">Skipped</span>: 0.  <span style="color:#eedd82;">Passed</span>: 4.
<span style="color:#eedd82;">One</span> <span style="color:#7fffd4;">or</span> <span style="color:#7fffd4;">more</span> <span style="color:#7fffd4;">tests</span> <span style="color:#7fffd4;">were</span> <span style="color:#7fffd4;">cancelled</span>.

=<span style="color:#eedd82;">ERROR</span> <span style="color:#eedd82;">REPORT</span>==== 16-<span style="color:#eedd82;">Feb</span>-2011::21:18:37 ===
** <span style="color:#eedd82;">Generic</span> <span style="color:#7fffd4;">server</span> <span style="color:#7fffd4;">wn_resource_layer</span> <span style="color:#7fffd4;">terminating</span>
** <span style="color:#eedd82;">Last</span> <span style="color:#7fffd4;">message</span> <span style="color:#7fffd4;">in</span> <span style="color:#7fffd4;">was</span> {<span style="color:#7fffd4;">'EXIT'</span>,&lt;0.37.0&gt;,
                               {<span style="color:#7fffd4;">undef</span>,[{<span style="color:#7fffd4;">wn_job_keeper</span>,<span style="color:#7fffd4;">cancel</span>,[&lt;0.148.0&gt;]},
                                       {<span style="color:#7fffd4;">wn_job_layer</span>,<span style="color:#7fffd4;">try_cancel</span>,2},
                                       {<span style="color:#7fffd4;">wn_job_layer</span>,<span style="color:#7fffd4;">handle_call</span>,3},
                                       {<span style="color:#7fffd4;">gen_server</span>,<span style="color:#7fffd4;">handle_msg</span>,5},
                                       {<span style="color:#7fffd4;">proc_lib</span>,<span style="color:#7fffd4;">init_p_do_apply</span>,3}]}}
** <span style="color:#eedd82;">When</span> <span style="color:#eedd82;">Server</span> <span style="color:#7fffd4;">state</span> == {<span style="color:#7fffd4;">state</span>,94228,
                               <span style="color:#ffa07a;">"/Users/zenon/ErlangBlog/worker_net-0.1/node_root/"</span>,
                               <span style="color:#7fffd4;">undefined</span>}
** <span style="color:#eedd82;">Reason</span> <span style="color:#7fffd4;">for</span> <span style="color:#7fffd4;">termination</span> ==
** {<span style="color:#7fffd4;">'function not exported'</span>,[{<span style="color:#7fffd4;">wn_job_keeper</span>,<span style="color:#7fffd4;">cancel</span>,[&lt;0.148.0&gt;]},
                             {<span style="color:#7fffd4;">wn_job_layer</span>,<span style="color:#7fffd4;">try_cancel</span>,2},
                             {<span style="color:#7fffd4;">wn_job_layer</span>,<span style="color:#7fffd4;">handle_call</span>,3},
                             {<span style="color:#7fffd4;">gen_server</span>,<span style="color:#7fffd4;">handle_msg</span>,5},
                             {<span style="color:#7fffd4;">proc_lib</span>,<span style="color:#7fffd4;">init_p_do_apply</span>,3}]}
<span style="color:#7fffd4;">dialyzer</span> <span style="color:#7fffd4;">src</span>/*.<span style="color:#7fffd4;">erl</span> <span style="color:#7fffd4;">test</span>/*.<span style="color:#7fffd4;">erl</span>
  <span style="color:#eedd82;">Checking</span> <span style="color:#7fffd4;">whether</span> <span style="color:#7fffd4;">the</span> <span style="color:#eedd82;">PLT</span> /<span style="color:#eedd82;">Users</span>/<span style="color:#7fffd4;">zenon</span>/.<span style="color:#7fffd4;">dialyzer_plt</span> <span style="color:#7fffd4;">is</span> <span style="color:#7fffd4;">up</span>-<span style="color:#7fffd4;">to</span>-<span style="color:#7fffd4;">date</span>... <span style="color:#7fffd4;">yes</span>
  <span style="color:#eedd82;">Proceeding</span> <span style="color:#7fffd4;">with</span> <span style="color:#7fffd4;">analysis</span>...
<span style="color:#7fffd4;">wn_job_layer</span>.<span style="color:#7fffd4;">erl</span>:162: <span style="color:#eedd82;">Call</span> <span style="color:#7fffd4;">to</span> <span style="color:#7fffd4;">missing</span> <span style="color:#7fffd4;">or</span> <span style="color:#7fffd4;">unexported</span> <span style="color:#7fffd4;">function</span> <span style="color:#7fffd4;">wn_job_keeper</span>:<span style="color:#87cefa;">cancel/1</span>
<span style="color:#eedd82;">Unknown</span> <span style="color:#7fffd4;">functions</span>:
  <span style="color:#7fffd4;">eunit</span>:<span style="color:#87cefa;">test/1</span>
 <span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0m4.59s
<span style="color:#87cefa;">done</span> (<span style="color:#7fffd4;">warnings</span> <span style="color:#7fffd4;">were</span> <span style="color:#7fffd4;">emitted</span>)
<span style="color:#7fffd4;">make</span>: *** [<span style="color:#7fffd4;">dialyze</span>] <span style="color:#eedd82;">Error</span> 2
<span style="color:#7fffd4;">zen</span>:<span style="color:#7fffd4;">worker_net</span>-0.1 <span style="color:#7fffd4;">zenon</span><span style="color:#ffa07a;">$ </span></pre>
<p><!--- End Of Snippet --></p>
<p>Moving on and finishing the cancelation. The test is there in <em><strong>wn_job_layer_tests.erl</strong></em> &#8211; with a minor modification</p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">cancel_before_running</span>() -&gt;
    <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(#<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"Laptop"</span>,
                                     <span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">'os-x'</span>,0}],
                                     <span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()
                                    }),
    <span style="color:#eedd82;">Job1</span> = #<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId"</span>,
                  <span style="color:#7fffd4;">files</span> = [],
                  <span style="color:#7fffd4;">resources</span> = [<span style="color:#7fffd4;">'os-x'</span>],
                  <span style="color:#7fffd4;">commands</span> = [<span style="color:#ffa07a;">"echo hello"</span>]},
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">Job1</span>)),
    ?<span style="color:#b0c4de;">assertEqual</span>({<span style="color:#7fffd4;">ok</span>,[{<span style="color:#7fffd4;">'os-x'</span>,[<span style="color:#eedd82;">Job1</span>]}]},<span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">queued</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#ffa07a;">"Laptop"</span>)),
    [<span style="color:#eedd82;">Res</span>] = <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">list_all_jobs</span>(),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#ffa07a;">"JobId"</span>,<span style="color:#eedd82;">Res</span>#<span style="color:#b0c4de;">wn_job</span>.<span style="color:#7fffd4;">id</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#7fffd4;">'os-x'</span>],<span style="color:#eedd82;">Res</span>#<span style="color:#b0c4de;">wn_job</span>.<span style="color:#7fffd4;">resources</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>([],<span style="color:#eedd82;">Res</span>#<span style="color:#b0c4de;">wn_job</span>.<span style="color:#7fffd4;">files</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#ffa07a;">"echo hello"</span>],<span style="color:#eedd82;">Res</span>#<span style="color:#b0c4de;">wn_job</span>.<span style="color:#7fffd4;">commands</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">cancel</span>(<span style="color:#ffa07a;">"JobId"</span>)),
    [] = <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">list_all_jobs</span>(),
    ?<span style="color:#b0c4de;">assertEqual</span>({<span style="color:#7fffd4;">ok</span>,[{<span style="color:#7fffd4;">'os-x'</span>,[]}]},<span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">queued</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#ffa07a;">"Laptop"</span>)).</pre>
<p><!--- End Of Snippet --></p>
<p>First, the usual (export + api) in  <em><strong>wn_job_layer.erl</strong></em></p>
<p><!--- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">API
</span><span style="color:#b0c4de;">-export</span>([<span style="color:#87cefa;">start_link/0</span>,<span style="color:#87cefa;">register/1</span>,<span style="color:#87cefa;">list_all_jobs/0</span>,
         <span style="color:#87cefa;">stop/0</span>,<span style="color:#87cefa;">stream/2</span>,<span style="color:#87cefa;">result/1</span>,<span style="color:#87cefa;">finished_at/1</span>,
         <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">NEW CODE vvvv
</span>         <span style="color:#87cefa;">cancel/1</span>]).</pre>
<p><!--- End Of Snippet -!&gt;--></p>
<p><!--- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">cancel</span>(<span style="color:#98fb98;">string</span>()) -&gt; <span style="color:#7fffd4;">ok</span> | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).
<span style="color:#87cefa;">cancel</span>(<span style="color:#eedd82;">Id</span>) -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,{<span style="color:#7fffd4;">cancel</span>,<span style="color:#eedd82;">Id</span>}).</pre>
<p>This lends itself to a similar approach as other wn_job_layer requests and a try_cancel could be in order</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_call</span>({<span style="color:#7fffd4;">cancel</span>,<span style="color:#eedd82;">Id</span>},<span style="color:#eedd82;">_</span>,<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#eedd82;">Reply</span> = <span style="color:#98fb98;">try_cancel</span>(<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">State</span>),
    {<span style="color:#7fffd4;">reply</span>,<span style="color:#eedd82;">Reply</span>,<span style="color:#eedd82;">State</span>};</pre>
<p><!--- End Of Snippet --></p>
<p>Now the most of the work is to implement try_cancel and the behaviour of the wn_resource_process and wn_job_keeper. The try_cancel/2 in wn_job_layer.erl can be seen below</p>
<p><!--- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">try_cancel</span>(<span style="color:#eedd82;">Id</span>, <span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">lookup</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">jobs</span>,<span style="color:#eedd82;">Id</span>) <span style="color:#00ffff;">of</span>
        [{<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">WnJob</span>}] -&gt;
            <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">jobs</span>,<span style="color:#eedd82;">Id</span>),
            <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">cancel</span>(<span style="color:#eedd82;">JobKeeperPid</span>),
            <span style="color:#98fb98;">cancel_resources</span>(<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">WnJob</span>),
            <span style="color:#7fffd4;">ok</span>;
        [] -&gt;
            {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">no_such_job</span>}
    <span style="color:#00ffff;">end</span>.</pre>
<p><!--- End Of Snippet --></p>
<p>the required support function cancel_resources/2</p>
<p><!--- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">cancel_resources</span>(<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">WnJob</span>) -&gt;
    <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foreach</span>(
      <span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">WnResource</span>) -&gt;
              <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">resource_is_sufficient</span>(<span style="color:#eedd82;">WnJob</span>,<span style="color:#eedd82;">WnResource</span>) <span style="color:#00ffff;">of</span>
                  {<span style="color:#7fffd4;">true</span>,<span style="color:#eedd82;">Possibles</span>} -&gt;
                      <span style="color:#eedd82;">WnPid</span> = <span style="color:#eedd82;">WnResource</span>#<span style="color:#b0c4de;">wn_resource</span>.<span style="color:#7fffd4;">pid</span>,
                      <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foreach</span>(
                        <span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">Type</span>) -&gt;
                          <span style="color:#98fb98;">wn_resource_process</span>:<span style="color:#98fb98;">cancel</span>(<span style="color:#eedd82;">WnPid</span>,
                                                <span style="color:#eedd82;">JobKeeperPid</span>,
                                                <span style="color:#eedd82;">Type</span>)
                        <span style="color:#00ffff;">end</span>,
                        <span style="color:#eedd82;">Possibles</span>);
                  <span style="color:#7fffd4;">false</span> -&gt; <span style="color:#7fffd4;">ignore</span>
              <span style="color:#00ffff;">end</span>
      <span style="color:#00ffff;">end</span>,
      <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">list_resources</span>()).</pre>
<p><!--- End Of Snippet -!&gt;--></p>
<p>And the corresponding function in wn_resource_process.erl &#8211; export</p>
<p><!--- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">API
</span><span style="color:#b0c4de;">-export</span>([<span style="color:#87cefa;">start_link/2</span>,<span style="color:#87cefa;">signal/3</span>,<span style="color:#87cefa;">queued/1</span>,
         <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">NEW CODE
</span>         <span style="color:#87cefa;">cancel/3</span>
        ]).</pre>
<p><!--- End Of Snippet -!&gt;--></p>
<p>and function</p>
<p><!--- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">cancel</span>(<span style="color:#b0c4de;">pid</span>(),<span style="color:#b0c4de;">pid</span>(),<span style="color:#b0c4de;">atom</span>()) -&gt; <span style="color:#7fffd4;">ok</span> | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).
<span style="color:#87cefa;">cancel</span>(<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">Type</span>) -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">Pid</span>,{<span style="color:#7fffd4;">cancel</span>,<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">Type</span>}).</pre>
<p><!--- End Of SNippet -!&gt;--></p>
<p>as well as the handle_call clause</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_call</span>({<span style="color:#7fffd4;">cancel</span>,<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">Type</span>},<span style="color:#eedd82;">_From</span>,<span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">value</span>,{<span style="color:#eedd82;">_</span>,<span style="color:#eedd82;">TypeQueue</span>},<span style="color:#eedd82;">Q</span>} = <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">keytake</span>(<span style="color:#eedd82;">Type</span>,1,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">queues</span>),
    <span style="color:#00ffff;">case</span> <span style="color:#eedd82;">TypeQueue</span> -- [<span style="color:#eedd82;">JobKeeperPid</span>] <span style="color:#00ffff;">of</span>
        <span style="color:#eedd82;">TypeQueue</span> -&gt;
            {<span style="color:#7fffd4;">reply</span>,{<span style="color:#7fffd4;">error</span>,{<span style="color:#7fffd4;">not_in_queue</span>,<span style="color:#eedd82;">Type</span>}},<span style="color:#eedd82;">State</span>};
        <span style="color:#eedd82;">X</span> -&gt;
            {<span style="color:#7fffd4;">reply</span>,<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">queues</span> = [{<span style="color:#eedd82;">Type</span>,<span style="color:#eedd82;">X</span>}|<span style="color:#eedd82;">Q</span>]}}
    <span style="color:#00ffff;">end</span>;</pre>
<p><!--- End Of SNippet -!&gt;--></p>
<p>Next the needed change in wn_job_keeper.erl (export)</p>
<p><!-- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">API
</span><span style="color:#b0c4de;">-export</span>([<span style="color:#87cefa;">start_link/1</span>,<span style="color:#87cefa;">done/2</span>,<span style="color:#87cefa;">progress/2</span>,<span style="color:#87cefa;">info/2</span>,<span style="color:#87cefa;">stream/2</span>,
         <span style="color:#87cefa;">signal/1</span>,<span style="color:#87cefa;">get_result/1</span>,<span style="color:#87cefa;">get_done/1</span>,<span style="color:#87cefa;">get_job/1</span>,
         <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">NEW CODE
</span>         <span style="color:#87cefa;">cancel/1</span>]).</pre>
<p><!-- End Of Snippet -!&gt;--></p>
<p>and the function itself of course</p>
<p><!--- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">cancel</span>(<span style="color:#b0c4de;">pid</span>()) -&gt; <span style="color:#7fffd4;">ok</span> | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).
<span style="color:#87cefa;">cancel</span>(<span style="color:#eedd82;">Pid</span>) -&gt;
    <span style="color:#98fb98;">gen_fsm</span>:<span style="color:#98fb98;">sync_send_all_state_event</span>(<span style="color:#eedd82;">Pid</span>,<span style="color:#7fffd4;">cancel</span>).</pre>
<p><!--- End Of Snippet -!&gt;--></p>
<p>with the internal handle_sync_event</p>
<p><!-- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_sync_event</span>(<span style="color:#7fffd4;">cancel</span>,<span style="color:#eedd82;">_From</span>,<span style="color:#7fffd4;">waiting</span>,<span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">stop</span>,<span style="color:#7fffd4;">normal</span>,<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">State</span>};
<span style="color:#87cefa;">handle_sync_event</span>(<span style="color:#7fffd4;">cancel</span>,<span style="color:#eedd82;">_From</span>,<span style="color:#eedd82;">X</span>,<span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">reply</span>,{<span style="color:#7fffd4;">error</span>,<span style="color:#eedd82;">X</span>},<span style="color:#eedd82;">X</span>,<span style="color:#eedd82;">State</span>};</pre>
<p><!--- End Of Snippet -!&gt;--></p>
<p>That&#8217;s all &#8211; and the proof is the &#8216;make test&#8217; of course<br />
<!-- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#7fffd4;">zen</span>:<span style="color:#7fffd4;">worker_net</span>-0.1 <span style="color:#7fffd4;">zenon</span><span style="color:#ffa07a;">$ </span><span style="color:#7fffd4;">make</span> <span style="color:#7fffd4;">test</span>
......
<span style="color:#eedd82;">Eshell</span> <span style="color:#eedd82;">V5</span>.8.1  (<span style="color:#7fffd4;">abort</span> <span style="color:#7fffd4;">with</span> ^<span style="color:#eedd82;">G</span>)
1&gt; ======================== <span style="color:#eedd82;">EUnit</span> ========================
<span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_job_layer'</span>
  <span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_job_layer_tests'</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">register</span> <span style="color:#7fffd4;">locally</span>)...[0.004 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Executed</span> <span style="color:#7fffd4;">locally</span>)...[1.004 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Executed</span> <span style="color:#7fffd4;">queue</span>)...[1.105 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Queueus</span> <span style="color:#7fffd4;">on</span> <span style="color:#7fffd4;">resource</span> <span style="color:#7fffd4;">type</span> <span style="color:#7fffd4;">amount</span>)...[0.002 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Canceled</span> <span style="color:#7fffd4;">in</span> <span style="color:#7fffd4;">queue</span>)...<span style="color:#7fffd4;">ok</span>
    [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 2.158 <span style="color:#7fffd4;">s</span>]
  [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 2.158 <span style="color:#7fffd4;">s</span>]
=======================================================
  <span style="color:#eedd82;">All</span> 5 <span style="color:#7fffd4;">tests</span> <span style="color:#7fffd4;">passed</span>.
<span style="color:#7fffd4;">zen</span>:<span style="color:#7fffd4;">worker_net</span>-0.1 <span style="color:#7fffd4;">zenon</span><span style="color:#ffa07a;">$ </span></pre>
<p><!--- End Of Snippet -!&gt;--></p>
<p>I chose to hide the output of the other tests and the execution of the job tests which print out stuff to stdout.<br />
Anyway &#8211; the current list of done and not done stories is now</p>
<h2>Done stories</h2>
<p>“<em>I want to be able to describe a job as</em></p>
<ul>
<li><em>A set of Files [#wn_file{}]</em></li>
<li><em>The possible resource types needed (disjunction)</em></li>
<li><em>A list of commands for running the job</em></li>
<li><em>A timeout the job is given while running (in seconds)</em></li>
<li><em>A job id – primary key for the job</em><em>“</em></li>
</ul>
<p>“<em>I want to be able to register a job in the job layer,  through  any node.</em>“</p>
<p>“<em>Several jobs should be queued on the same resource type(s),  being processed one and one in order as they where queued</em>“</p>
<p>“<em>I want to be able to list all jobs in the system, through any node</em>.”</p>
<p>“<em>The output generated by a job should be possible to see in realtime,  through any node and stored to logfiles</em>.”</p>
<p>“<em>A job must be possible to cancel before it starts running, through any node.</em>“</p>
<h2>Not done stories</h2>
<p>“<em>Once a job is done, the result should be stored in the file layer,  together with the logs.</em>“</p>
<p>“<em>I want to be able to delete a job once it’s done, through any node</em>.”</p>
<p>In the next post, I shall write the test and implementation of</p>
<p>“<em>Once a job is done, the result should be stored in the file layer,  together with the logs.</em>“</p>
<p>Cheers</p>
<p>/G</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/erlcode.wordpress.com/610/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/erlcode.wordpress.com/610/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=erlcode.wordpress.com&#038;blog=15510807&#038;post=610&#038;subd=erlcode&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://erlcode.wordpress.com/2011/02/17/erlang-tdd-hands-on-project-workernet-part-6/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/861b8f824c3cd15c17ac6aa1b902e029?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">gianfrancoalongi</media:title>
		</media:content>
	</item>
		<item>
		<title>Erlang TDD hands on project &#8211; WorkerNet part 5</title>
		<link>http://erlcode.wordpress.com/2011/02/13/erlang-tdd-hands-on-project-workernet-part-5/</link>
		<comments>http://erlcode.wordpress.com/2011/02/13/erlang-tdd-hands-on-project-workernet-part-5/#comments</comments>
		<pubDate>Sun, 13 Feb 2011 23:04:57 +0000</pubDate>
		<dc:creator>gianfrancoalongi</dc:creator>
				<category><![CDATA[WorkerNet]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[workernet]]></category>

		<guid isPermaLink="false">http://erlcode.wordpress.com/?p=546</guid>
		<description><![CDATA[Last time we left of, there was no real proof that the jobs are being processed one and one in the order they are queued. In order to prove that and satisfy the story “Several jobs should be queued on the same resource type(s),  being processed one and one in order as they where queued“ [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=erlcode.wordpress.com&#038;blog=15510807&#038;post=546&#038;subd=erlcode&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Last time we left of, there was no real proof that the jobs are being processed one and one in the order they are queued. In order to prove that and satisfy the story</p>
<p>“<em>Several jobs should be queued on the same resource type(s),  being processed one and one in order as they where queued</em>“</p>
<p>What we need to prove this is some form of timestamps which we will use in the tests. Question is &#8211; where do we put them &#8211; or more interesting &#8211; do we need them? One particularly bad thing that we must not do is to start contaminating the API and logic for the sake of being able to prove tests in an easy way.</p>
<p>Just food for thought.</p>
<p>However, in this case we want to see <em>when </em>something was finished, no harm in that, so the test (which fails) can be seen below</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">executed_queue</span>() -&gt;
    <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(#<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"Laptop"</span>,
                                     <span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">'os-x'</span>,1}],
                                     <span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()
                                     }),
    <span style="color:#eedd82;">Path</span> = <span style="color:#98fb98;">create_file_at</span>(?<span style="color:#b0c4de;">NODE_ROOT</span>),
    <span style="color:#eedd82;">File1</span> = #<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"File1"</span>,<span style="color:#7fffd4;">file</span> = <span style="color:#eedd82;">Path</span>,<span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()},
    <span style="color:#eedd82;">Job1</span> = #<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId"</span>,
                   <span style="color:#7fffd4;">files</span> = [<span style="color:#eedd82;">File1</span>],
                   <span style="color:#7fffd4;">resources</span> = [<span style="color:#7fffd4;">'os-x'</span>],
                   <span style="color:#7fffd4;">commands</span> = [<span style="color:#ffa07a;">"file EunitFile"</span>],
                   <span style="color:#7fffd4;">timeout</span> = 100
                  },
    <span style="color:#eedd82;">Job2</span> = <span style="color:#eedd82;">Job1</span>#<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId2"</span>,
                       <span style="color:#7fffd4;">files</span> = [<span style="color:#eedd82;">File1</span>#<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span>=<span style="color:#ffa07a;">"File"</span>}],
                       <span style="color:#7fffd4;">commands</span> = [<span style="color:#ffa07a;">"cat EUnitFile"</span>]},
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">Job1</span>)),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">Job2</span>)),
    <span style="color:#7fffd4;">ok</span>  = <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">stream</span>(<span style="color:#7fffd4;">user</span>,<span style="color:#ffa07a;">"JobId"</span>),
    <span style="color:#7fffd4;">ok</span>  = <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">stream</span>(<span style="color:#7fffd4;">user</span>,<span style="color:#ffa07a;">"JobId2"</span>),
    <span style="color:#98fb98;">timer</span>:<span style="color:#98fb98;">sleep</span>(100),
    ?<span style="color:#b0c4de;">assertEqual</span>({<span style="color:#7fffd4;">ok</span>,[<span style="color:#ffa07a;">"EunitFile: ASCII text"</span>]},<span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">result</span>(<span style="color:#ffa07a;">"JobId"</span>)),
    <span style="color:#98fb98;">timer</span>:<span style="color:#98fb98;">sleep</span>(1000),
    ?<span style="color:#b0c4de;">assertEqual</span>({<span style="color:#7fffd4;">ok</span>,[<span style="color:#ffa07a;">"1,2,3"</span>]},<span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">result</span>(<span style="color:#ffa07a;">"JobId2"</span>)),
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">T1</span>} = <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">finished_at</span>(<span style="color:#ffa07a;">"JobId"</span>),
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">T2</span>} = <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">finished_at</span>(<span style="color:#ffa07a;">"JobId2"</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">true</span>,<span style="color:#eedd82;">T1</span> &lt; <span style="color:#eedd82;">T2</span>).</pre>
<p><!--- End Of Snippet --></p>
<p>Seems pretty self explanatory, it&#8217;s like the first test, but with two jobs, and some function called <em>finished_at/1</em> returning <em>{<strong>ok</strong>,Timestamp}</em> great, and we check that the first job was done before the other one.  As we have a failing case agin (yay!) there is something to implement, first the extra code in <em>wn_job_layer.erl</em></p>
<p>The added  API function export (last element in the list)</p>
<p><!-- -Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">API
</span><span style="color:#b0c4de;">-export</span>([<span style="color:#87cefa;">start_link/0</span>,<span style="color:#87cefa;">register/1</span>,<span style="color:#87cefa;">list_all_jobs/0</span>,
        <span style="color:#87cefa;">stop/0</span>,<span style="color:#87cefa;">stream/2</span>,<span style="color:#87cefa;">result/1</span>,<span style="color:#87cefa;">finished_at/1</span>]).</pre>
<p><!--- End Of Snippet --></p>
<p>Then the added API function implementation</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">finished_at</span>(<span style="color:#98fb98;">string</span>()) -&gt; {<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">time_marker</span>()} | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).
<span style="color:#87cefa;">finished_at</span>(<span style="color:#eedd82;">Id</span>) -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,{<span style="color:#7fffd4;">finished_at</span>,<span style="color:#eedd82;">Id</span>}).</pre>
<p><!--- End Of Snippet --></p>
<p>The added handle_call clause, sending on the signal via a new wn_job_keeper function</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_call</span>({<span style="color:#7fffd4;">finished_at</span>,<span style="color:#eedd82;">Id</span>},<span style="color:#eedd82;">_From</span>,<span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">reply</span>,
     <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">lookup</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">jobs</span>,<span style="color:#eedd82;">Id</span>) <span style="color:#00ffff;">of</span>
         [] -&gt; {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">no_such_job</span>};
         [{<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">_</span>}] -&gt;
             {<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">get_done</span>(<span style="color:#eedd82;">Pid</span>)}
     <span style="color:#00ffff;">end</span>,<span style="color:#eedd82;">State</span>};</pre>
<p><!--- End Of Snippet --></p>
<p>Over to <em>wn_job_keeper.erl</em> and the changes on it, of course, first the added export (last element)</p>
<p><!-- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-export</span>([<span style="color:#87cefa;">start_link/1</span>,<span style="color:#87cefa;">done/2</span>,<span style="color:#87cefa;">progress/2</span>,<span style="color:#87cefa;">info/2</span>,<span style="color:#87cefa;">stream/2</span>,
         <span style="color:#87cefa;">signal/1</span>,<span style="color:#87cefa;">get_result/1,get_done/1</span>]).</pre>
<p><!--- End Of Snippet --></p>
<p>Then the actual API function</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">get_done</span>(<span style="color:#b0c4de;">pid</span>()) -&gt; {<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">time_marker</span>()} | {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">not_done</span>}).
<span style="color:#87cefa;">get_done</span>(<span style="color:#eedd82;">Pid</span>) -&gt;
    <span style="color:#98fb98;">gen_fsm</span>:<span style="color:#98fb98;">sync_send_all_state_event</span>(<span style="color:#eedd82;">Pid</span>,<span style="color:#7fffd4;">get_done</span>).</pre>
<p><!--- End Of Snippet --></p>
<p>with the added new clauses in the handle_sync_event function</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_sync_event</span>(<span style="color:#7fffd4;">get_done</span>,<span style="color:#eedd82;">_From</span>,<span style="color:#7fffd4;">done</span>,<span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">reply</span>,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">done_at</span>,<span style="color:#7fffd4;">done</span>,<span style="color:#eedd82;">State</span>};
<span style="color:#87cefa;">handle_sync_event</span>(<span style="color:#7fffd4;">get_done</span>,<span style="color:#eedd82;">_From</span>,<span style="color:#eedd82;">X</span>,<span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">reply</span>,{<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">not_done</span>},<span style="color:#eedd82;">X</span>,<span style="color:#eedd82;">State</span>}.</pre>
<p><!--- End Of Snippet --></p>
<p>On top of that, we need to set the done_at state record field, presumably with the done signal</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_event</span>({<span style="color:#7fffd4;">done</span>,<span style="color:#eedd82;">X</span>}, <span style="color:#7fffd4;">working</span>, #<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">info</span> = <span style="color:#eedd82;">Info</span>} = <span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#98fb98;">stream_msg</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">stream</span>,<span style="color:#eedd82;">X</span>),
    {<span style="color:#7fffd4;">next_state</span>, <span style="color:#7fffd4;">done</span>, <span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">info</span> = [{<span style="color:#98fb98;">now</span>(),{<span style="color:#7fffd4;">done</span>,<span style="color:#eedd82;">X</span>}}|<span style="color:#eedd82;">Info</span>],
                              <span style="color:#7fffd4;">done_at</span> = {<span style="color:#b0c4de;">date</span>(),<span style="color:#b0c4de;">time</span>(),<span style="color:#98fb98;">now</span>()}
                             }};</pre>
<p><!--- End Of Snippet --></p>
<p>The attentive reader now sees the time_marker() type spec and wonders where it comes from? Well, <em>worker_net.hrl </em>of course, the added lines are seen below</p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-type</span> <span style="color:#b0c4de;">date</span>() :: {<span style="color:#b0c4de;">integer</span>(),<span style="color:#b0c4de;">integer</span>(),<span style="color:#b0c4de;">integer</span>()}.
<span style="color:#b0c4de;">-type</span> <span style="color:#b0c4de;">time</span>() :: {<span style="color:#b0c4de;">integer</span>(),<span style="color:#b0c4de;">integer</span>(),<span style="color:#b0c4de;">integer</span>()}.
<span style="color:#b0c4de;">-type</span> <span style="color:#98fb98;">now</span>() :: {<span style="color:#b0c4de;">integer</span>(),<span style="color:#b0c4de;">integer</span>(),<span style="color:#b0c4de;">integer</span>()}.
<span style="color:#b0c4de;">-type</span> <span style="color:#98fb98;">time_marker</span>() :: {<span style="color:#b0c4de;">date</span>(),<span style="color:#b0c4de;">time</span>(),<span style="color:#98fb98;">now</span>()}.</pre>
<p><!--- End Of Snippet --></p>
<p>Greatness, so little for so much added value, fire up the console and &#8216;make full&#8217;. At this point I found some bugs and fixed them. Fast forward *ahem*. One of the more serious changes I made during the bug fix was to make sure the<em> wn_resource_process </em>would actually signal done to the job keeper and not the job worker.</p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_event</span>({<span style="color:#7fffd4;">signal</span>,<span style="color:#eedd82;">JobKeeperPid</span>}, <span style="color:#7fffd4;">free</span>, <span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#eedd82;">Ns</span>,<span style="color:#eedd82;">Nld</span>} =
        <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">signal</span>(<span style="color:#eedd82;">JobKeeperPid</span>) <span style="color:#00ffff;">of</span>
            {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">WnJob</span>} -&gt;
                <span style="color:#b0c4de;">process_flag</span>(<span style="color:#7fffd4;">trap_exit</span>,<span style="color:#7fffd4;">true</span>),
                {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">WorkerPid</span>} =
                    <span style="color:#98fb98;">wn_job_worker</span>:<span style="color:#98fb98;">start_link</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">node_root</span>,
                                             <span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">WnJob</span>),
                {<span style="color:#7fffd4;">taken</span>,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">job</span> = <span style="color:#eedd82;">WorkerPid</span>,
                                   <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">This was missing vvvvvvv
</span>                                   <span style="color:#7fffd4;">job_keeper</span> = <span style="color:#eedd82;">JobKeeperPid</span>}};
            {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">taken</span>} -&gt;
                {<span style="color:#7fffd4;">free</span>,<span style="color:#eedd82;">State</span>}
        <span style="color:#00ffff;">end</span>,
    {<span style="color:#7fffd4;">next_state</span>,<span style="color:#eedd82;">Ns</span>,<span style="color:#eedd82;">Nld</span>};</pre>
<p><!--- End Of Snippet --></p>
<p>and the second part of this fix here</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_info</span>({<span style="color:#7fffd4;">'EXIT'</span>,<span style="color:#eedd82;">WorkerPid</span>,<span style="color:#eedd82;">Reason</span>},
            <span style="color:#7fffd4;">taken</span>,#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">job</span> = <span style="color:#eedd82;">WorkerPid</span>,<span style="color:#7fffd4;">job_keeper</span> = <span style="color:#eedd82;">JobKeeperPid</span>}= <span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">Part of fix here vvvvvvvvvv and here ^^^^^^^^^^
</span>    <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">done</span>(<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">Reason</span>),
    {<span style="color:#eedd82;">Ns</span>,<span style="color:#eedd82;">Nld</span>} =
    <span style="color:#00ffff;">case</span> <span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">queue</span> <span style="color:#00ffff;">of</span>
       [] -&gt; {<span style="color:#7fffd4;">free</span>, <span style="color:#eedd82;">State</span>};
       [<span style="color:#eedd82;">X</span>|<span style="color:#eedd82;">Q</span>] -&gt;
         <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">signal</span>(<span style="color:#eedd82;">X</span>) <span style="color:#00ffff;">of</span>
             {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">WnJob</span>} -&gt;
                <span style="color:#b0c4de;">process_flag</span>(<span style="color:#7fffd4;">trap_exit</span>,<span style="color:#7fffd4;">true</span>),
                {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">NewWorkerPid</span>} =
                    <span style="color:#98fb98;">wn_job_worker</span>:<span style="color:#98fb98;">start_link</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">node_root</span>,<span style="color:#eedd82;">X</span>,<span style="color:#eedd82;">WnJob</span>),
                {<span style="color:#7fffd4;">taken</span>,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">job</span> = <span style="color:#eedd82;">NewWorkerPid</span>,
                               <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">And here vvv
</span>                               <span style="color:#7fffd4;">job_keeper</span> = <span style="color:#eedd82;">X</span>,
                               <span style="color:#7fffd4;">queue</span> = <span style="color:#eedd82;">Q</span>}};
             {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">taken</span>} -&gt;
                {<span style="color:#7fffd4;">free</span>,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">queue</span>=<span style="color:#eedd82;">Q</span>}}
       <span style="color:#00ffff;">end</span>
    <span style="color:#00ffff;">end</span>,
    {<span style="color:#7fffd4;">next_state</span>,<span style="color:#eedd82;">Ns</span>,<span style="color:#eedd82;">Nld</span>}.</pre>
<p><!--- End Of Snippet  --></p>
<p>After the fix, and removing the output from the paste a make full &#8211; the output of the job tests is now okay</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;">1&gt; ======================== <span style="color:#eedd82;">EUnit</span> ========================
<span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_job_layer'</span>
  <span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_job_layer_tests'</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">register</span> <span style="color:#7fffd4;">locally</span>)...[0.004 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Executed</span> <span style="color:#7fffd4;">locally</span>)...[1.003 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Executed</span> <span style="color:#7fffd4;">queue</span>)...[1.104 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 2.143 <span style="color:#7fffd4;">s</span>]
  [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 2.143 <span style="color:#7fffd4;">s</span>]
=======================================================
  <span style="color:#eedd82;">All</span> 3 <span style="color:#7fffd4;">tests</span> <span style="color:#7fffd4;">passed</span>.
<span style="color:#7fffd4;">dialyzer</span> <span style="color:#7fffd4;">src</span>/*.<span style="color:#7fffd4;">erl</span> <span style="color:#7fffd4;">test</span>/*.<span style="color:#7fffd4;">erl</span>
  <span style="color:#eedd82;">Checking</span> <span style="color:#7fffd4;">whether</span> <span style="color:#7fffd4;">the</span> <span style="color:#eedd82;">PLT</span> /<span style="color:#eedd82;">Users</span>/<span style="color:#7fffd4;">zenon</span>/.<span style="color:#7fffd4;">dialyzer_plt</span> <span style="color:#7fffd4;">is</span> <span style="color:#7fffd4;">up</span>-<span style="color:#7fffd4;">to</span>-<span style="color:#7fffd4;">date</span>... <span style="color:#7fffd4;">yes</span>
  <span style="color:#eedd82;">Proceeding</span> <span style="color:#7fffd4;">with</span> <span style="color:#7fffd4;">analysis</span>...
<span style="color:#eedd82;">Unknown</span> <span style="color:#7fffd4;">functions</span>:
  <span style="color:#7fffd4;">eunit</span>:<span style="color:#87cefa;">test/1</span>
 <span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0m3.87s
<span style="color:#87cefa;">done</span> (<span style="color:#7fffd4;">passed</span> <span style="color:#7fffd4;">successfully</span>)
<span style="color:#7fffd4;">zen</span>:<span style="color:#7fffd4;">worker_net</span>-0.1 <span style="color:#7fffd4;">zenon</span><span style="color:#ffa07a;">$ </span></pre>
<p><!--- End Of Snippet --></p>
<p>A quick look back in history with a sort of what is done and not could be in order</p>
<h2>Done stories</h2>
<p>“<em>I want to be able to describe a job as</em></p>
<ul>
<li><em>A set of Files [#wn_file{}]</em></li>
<li><em>The possible resource types needed (disjunction)</em></li>
<li><em>A list of commands for running the job</em></li>
<li><em>A timeout the job is given while running (in seconds)</em></li>
<li><em>A job id – primary key for the job</em><em>“</em></li>
</ul>
<p>“<em>I want to be able to register a job in the job layer,  through  any node.</em>“</p>
<p>“<em>Several jobs should be queued on the same resource type(s),  being processed one and one in order as they where queued</em>“</p>
<p>“<em>I want to be able to list all jobs in the system, through any node</em>.”</p>
<p>“<em>The output generated by a job should be possible to see in realtime,  through any node and stored to logfiles</em>.”</p>
<h2>Not done stories</h2>
<p>“<em>A job must be possible to cancel before it starts running, through any node.</em>“</p>
<p>“<em>Once a job is done, the result should be stored in the file layer,  together with the logs.</em>“</p>
<p>“<em>I want to be able to delete a job once it’s done, through any node</em>.”</p>
<p><strong>Onward with the next chosen </strong>stories &#8211; the cancelation (first story in the Not done stories  seen above)</p>
<p>“<em>A job must be possible to cancel before it starts running, through any node.</em>“</p>
<p>The test (and design of intended use) can be seen below</p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">cancel_queued</span>() -&gt;
    <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(#<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"Laptop"</span>,
                                     <span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">'os-x'</span>,0}],
                                     <span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()
                                     }),
    <span style="color:#eedd82;">Job1</span> = #<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId"</span>, <span style="color:#7fffd4;">files</span> = [],<span style="color:#7fffd4;">resources</span> = [<span style="color:#7fffd4;">'non-existent'</span>],
                   <span style="color:#7fffd4;">commands</span> = [<span style="color:#ffa07a;">"echo hello"</span>]},
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">Job1</span>)),
    [<span style="color:#eedd82;">Res</span>] = <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">list_all_jobs</span>(),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#ffa07a;">"JobId"</span>,<span style="color:#eedd82;">Res</span>#<span style="color:#b0c4de;">wn_job</span>.<span style="color:#7fffd4;">id</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#7fffd4;">'non-existent'</span>],<span style="color:#eedd82;">Res</span>#<span style="color:#b0c4de;">wn_job</span>.<span style="color:#7fffd4;">resources</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>([],<span style="color:#eedd82;">Res</span>#<span style="color:#b0c4de;">wn_job</span>.<span style="color:#7fffd4;">files</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#ffa07a;">"echo hello"</span>],<span style="color:#eedd82;">Res</span>#<span style="color:#b0c4de;">wn_job</span>.<span style="color:#7fffd4;">commands</span>),
    <span style="color:#98fb98;">timer</span>:<span style="color:#98fb98;">sleep</span>(1000),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">cancel</span>(<span style="color:#ffa07a;">"JobId"</span>)),
    [] = <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">list_all_jobs</span>().</pre>
<p><!--- Enf Of Snippet  --></p>
<p>A good think to notice here is that I intentionally set the amount of available &#8216;os-x&#8217; resources to zero. The intended effect is that the job should we waiting until it get&#8217;s a signal from an available resource process. So this job <em>should not be executed</em>.  However, this is not implemented yet! So this &#8220;ticket&#8221; system will have to be implemented in some way.</p>
<p>A question is &#8211; how do we do this easily? Remember that a resource can be of several types at the same time &#8211; with different available numbers of slots for each type. The intended use of the types from the Job&#8217;s point of view was that a Job should be able to require one of<em> several Resource types</em>.</p>
<p>It would now be prudent to add such a test &#8211; and make it pass if it does not already! I chose to add the test in<em> wn_job_layer_tests.erl</em></p>
<p><!-- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">queues_on_resource_types_amount</span>() -&gt;
    <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(#<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"Laptop"</span>,
                                     <span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">a</span>,0},{<span style="color:#7fffd4;">b</span>,1}],
                                     <span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()
                                    }),
    <span style="color:#eedd82;">Queued</span> = <span style="color:#00ffff;">fun</span>() -&gt; <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">queued</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#ffa07a;">"Laptop"</span>) <span style="color:#00ffff;">end</span>,
    <span style="color:#eedd82;">Job1</span> = #<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId"</span>,
                   <span style="color:#7fffd4;">files</span> = [],
                   <span style="color:#7fffd4;">resources</span> = [<span style="color:#7fffd4;">a</span>],
                   <span style="color:#7fffd4;">commands</span> = [<span style="color:#ffa07a;">"sleep 5"</span>]},
    <span style="color:#eedd82;">Job2</span> = <span style="color:#eedd82;">Job1</span>#<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId2"</span>, <span style="color:#7fffd4;">resources</span> = [<span style="color:#7fffd4;">a</span>]},
    <span style="color:#eedd82;">Job3</span> = <span style="color:#eedd82;">Job1</span>#<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId3"</span>, <span style="color:#7fffd4;">resources</span> = [<span style="color:#7fffd4;">a</span>,<span style="color:#7fffd4;">b</span>]},
    <span style="color:#eedd82;">Job4</span> = <span style="color:#eedd82;">Job1</span>#<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId4"</span>, <span style="color:#7fffd4;">resources</span> = [<span style="color:#7fffd4;">b</span>]},

    <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">Job1</span>),
    ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,[{<span style="color:#7fffd4;">a</span>,[#<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId"</span>}]}]},<span style="color:#eedd82;">Queued</span>()),

    <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">Job2</span>),
    ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,[{<span style="color:#7fffd4;">a</span>,[#<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId"</span>},
                         #<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId2"</span>}]}]},
                <span style="color:#eedd82;">Queued</span>()),

    <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">Job3</span>),
    ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,[{<span style="color:#7fffd4;">a</span>,[#<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId"</span>},
                         #<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId2"</span>},
                         #<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId3"</span>}]},
                     {<span style="color:#7fffd4;">b</span>,[#<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId3"</span>}]}
                    ]},<span style="color:#eedd82;">Queued</span>()),

    <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">Job4</span>),
    ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,[{<span style="color:#7fffd4;">a</span>,[#<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId"</span>},
                         #<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId2"</span>},
                         #<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId3"</span>}]},
                     {<span style="color:#7fffd4;">b</span>,[#<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId3"</span>},
                         #<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId4"</span>}]}
                    ]},<span style="color:#eedd82;">Queued</span>()).</pre>
<p><!-- End Of Snippet -!&gt;--></p>
<p>Now the first priority is to make the latest test work, so we start developing the queued/2 function in<em> wn_resource_layer.erl</em>, first the usual added API export  (last element in list)</p>
<p><!--- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-export</span>([<span style="color:#87cefa;">start_link/1</span>,
         <span style="color:#87cefa;">register/1</span>,<span style="color:#87cefa;">list_resources/0</span>,<span style="color:#87cefa;">stop/0</span>,
         <span style="color:#87cefa;">deregister/2</span>,<span style="color:#87cefa;">queued/2</span>]).</pre>
<p><!--- End Of Snippet -!&gt;--></p>
<p>After that, the actual API function</p>
<p><!--- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">queued</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#98fb98;">string</span>()) -&gt; {<span style="color:#7fffd4;">ok</span>,[{<span style="color:#b0c4de;">atom</span>(),[#<span style="color:#b0c4de;">wn_job</span>{}]}]} | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).
<span style="color:#87cefa;">queued</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Name</span>) -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,{<span style="color:#7fffd4;">queued</span>,<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Name</span>}).</pre>
<p><!--- End Of Snippet -!&gt;--></p>
<p>The added handle_call clause</p>
<p><!--- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_call</span>({<span style="color:#7fffd4;">queued</span>,<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Name</span>},<span style="color:#eedd82;">_From</span>,<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#00ffff;">case</span> {<span style="color:#eedd82;">Node</span> == <span style="color:#b0c4de;">node</span>(), <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">member</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#b0c4de;">nodes</span>())} <span style="color:#00ffff;">of</span>
        {<span style="color:#7fffd4;">true</span>,<span style="color:#eedd82;">_</span>} -&gt;
            <span style="color:#eedd82;">Reply</span> = <span style="color:#98fb98;">try_get_queued</span>(<span style="color:#eedd82;">State</span>,<span style="color:#eedd82;">Resource</span>),
            {<span style="color:#7fffd4;">reply</span>,<span style="color:#eedd82;">Reply</span>,<span style="color:#eedd82;">State</span>};
        {<span style="color:#7fffd4;">false</span>,<span style="color:#7fffd4;">true</span>} -&gt;
            <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">cast</span>({?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#eedd82;">Node</span>},{<span style="color:#7fffd4;">queued</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Name</span>}),
            {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>};
          {<span style="color:#7fffd4;">false</span>,<span style="color:#7fffd4;">false</span>} -&gt;
            {<span style="color:#7fffd4;">reply</span>,{<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">noresides</span>},<span style="color:#eedd82;">State</span>}
    <span style="color:#00ffff;">end</span>;</pre>
<p><!-- End Of Snippet -!&gt;--></p>
<p>The try_get_queued/2</p>
<p><!--- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">try_get_queued</span>(<span style="color:#eedd82;">State</span>,<span style="color:#eedd82;">Name</span>) -&gt;
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">lookup</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">resources</span>,<span style="color:#eedd82;">Name</span>) <span style="color:#00ffff;">of</span>
        [] -&gt; {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">noexists</span>};
        [{<span style="color:#eedd82;">Name</span>,<span style="color:#eedd82;">WnResource</span>}] -&gt;
            <span style="color:#eedd82;">Pid</span> = <span style="color:#eedd82;">WnResource</span>#<span style="color:#b0c4de;">wn_resource</span>.<span style="color:#7fffd4;">pid</span>,
            <span style="color:#98fb98;">wn_resource_process</span>:<span style="color:#98fb98;">queued</span>(<span style="color:#eedd82;">Pid</span>)
    <span style="color:#00ffff;">end</span>.</pre>
<p><!-- End Of Snippet -!&gt;--></p>
<p>the necessary handle_cast clause as well (if on remote node)</p>
<p><!-- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_cast</span>({<span style="color:#7fffd4;">queued</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Name</span>},<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">reply</span>(<span style="color:#eedd82;">From</span>,<span style="color:#98fb98;">try_get_queued</span>(<span style="color:#eedd82;">State</span>,<span style="color:#eedd82;">Name</span>)),
    {<span style="color:#7fffd4;">noreply</span>, <span style="color:#eedd82;">State</span>};</pre>
<p><!--- End Of Snippet -!&gt;--></p>
<p>In <em>wn_resource_process.erl</em> we need to add the API export for the queued/1 function</p>
<p><!--- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">API
</span><span style="color:#b0c4de;">-export</span>([<span style="color:#87cefa;">start_link/1</span>,<span style="color:#87cefa;">signal/2</span>,<span style="color:#87cefa;">queued/1</span>]).</pre>
<p><!--- End Of Snippet -!&gt;--></p>
<p>And the API function</p>
<p><!--- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">queued</span>(<span style="color:#b0c4de;">pid</span>()) -&gt; [{<span style="color:#b0c4de;">atom</span>(),[#<span style="color:#b0c4de;">wn_job</span>{}]}]).
<span style="color:#87cefa;">queued</span>(<span style="color:#eedd82;">Pid</span>) -&gt;
    <span style="color:#98fb98;">gen_fsm</span>:<span style="color:#98fb98;">sync_send_all_state_event</span>(<span style="color:#eedd82;">Pid</span>,<span style="color:#7fffd4;">queued</span>).</pre>
<p><!--- End Of Snippet -!&gt;--></p>
<p>With the synchronized all state event handler</p>
<p><!-- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_sync_event</span>(<span style="color:#7fffd4;">queued</span>, <span style="color:#eedd82;">_From</span>, <span style="color:#eedd82;">StateName</span>, <span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#eedd82;">Reply</span> = <span style="color:#98fb98;">collect_jobs</span>(<span style="color:#eedd82;">State</span>),
    {<span style="color:#7fffd4;">reply</span>, <span style="color:#eedd82;">Reply</span>, <span style="color:#eedd82;">StateName</span>, <span style="color:#eedd82;">State</span>}.</pre>
<p><!--- End Of Snippet -!&gt;--></p>
<p>And the internal collect_jobs/1 function, the implementation of the collect_jobs/1 suggests that we need to make another change of the current design. Whenever a job registers one the types it wishes to use, it has to tell which one of the types it wants to queue on! This atom will be used for the internal queues of the resource process from now on.</p>
<p><!--- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">collect_jobs</span>(<span style="color:#eedd82;">State</span>) -&gt;
    [{<span style="color:#eedd82;">Type</span>,[ <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">get_job</span>(<span style="color:#eedd82;">Pid</span>) <span style="color:#00ffff;">||</span> <span style="color:#eedd82;">Pid</span> <span style="color:#00ffff;">&lt;-</span> <span style="color:#eedd82;">Queue</span>]}
     <span style="color:#00ffff;">||</span> {<span style="color:#eedd82;">Type</span>,<span style="color:#eedd82;">Queue</span>} <span style="color:#00ffff;">&lt;-</span> <span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">queues</span>].</pre>
<p><!--- End Of Snippet -!&gt;--></p>
<p>Lastly the type spec changes in <em>wn_resource_process.erl</em></p>
<p><!--- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-record</span>(<span style="color:#b0c4de;">state</span>,{<span style="color:#7fffd4;">node_root</span> :: <span style="color:#98fb98;">string</span>(),
            <span style="color:#7fffd4;">queues</span> :: [{<span style="color:#7fffd4;">atom</span>,[<span style="color:#b0c4de;">pid</span>()]}],
            <span style="color:#7fffd4;">job</span> :: <span style="color:#b0c4de;">pid</span>(),
            <span style="color:#7fffd4;">job_keeper</span> :: <span style="color:#b0c4de;">pid</span>()
           }).</pre>
<p><!--- End Of Snippet -!&gt;--></p>
<p>and signalling changes to the <em>wn_resource_process.erl</em>.</p>
<p><!--- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">signal</span>(<span style="color:#b0c4de;">pid</span>(),<span style="color:#b0c4de;">pid</span>(),<span style="color:#b0c4de;">atom</span>()) -&gt; <span style="color:#7fffd4;">ok</span>).
<span style="color:#87cefa;">signal</span>(<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">QueueType</span>) -&gt;
    <span style="color:#98fb98;">gen_fsm</span>:<span style="color:#98fb98;">send_all_state_event</span>(<span style="color:#eedd82;">Pid</span>,{<span style="color:#7fffd4;">signal</span>,<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">QueueType</span>}).</pre>
<p><!--- End Of Snippet -!&gt;--></p>
<p><em>and</em> the internal changes for the signalling (in the other signal clause, we just ignore the QueueType)</p>
<p><!--- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_event</span>({<span style="color:#7fffd4;">signal</span>,<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">QueueType</span>}, <span style="color:#7fffd4;">taken</span>, <span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#eedd82;">Queues</span> =  <span style="color:#98fb98;">add_to_queues</span>(<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">QueueType</span>,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">queues</span>),
    {<span style="color:#7fffd4;">next_state</span>,<span style="color:#7fffd4;">taken</span>,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">queues</span> = <span style="color:#eedd82;">Queues</span>}}.</pre>
<p><!--- End Of Snippet -!&gt;--></p>
<p>along with the necessary internal add_to_queues function (also rename all instances of the field queue to queues)</p>
<p><!--- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">add_to_queues</span>(<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">Type</span>,[{<span style="color:#eedd82;">Type</span>,<span style="color:#eedd82;">Queue</span>}|<span style="color:#eedd82;">Rest</span>]) -&gt;
    [{<span style="color:#eedd82;">Type</span>,<span style="color:#eedd82;">Queue</span><span style="color:#ffc0cb;font-weight:bold;">++</span>[<span style="color:#eedd82;">JobKeeperPid</span>]}|<span style="color:#eedd82;">Rest</span>];
<span style="color:#87cefa;">add_to_queues</span>(<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">Type</span>,[<span style="color:#eedd82;">E</span>|<span style="color:#eedd82;">Rest</span>]) -&gt;
    [<span style="color:#eedd82;">E</span>|<span style="color:#98fb98;">add_to_queues</span>(<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">Type</span>,<span style="color:#eedd82;">Rest</span>)];
<span style="color:#87cefa;">add_to_queues</span>(<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">Type</span>,[]) -&gt; [{<span style="color:#eedd82;">Type</span>,[<span style="color:#eedd82;">JobKeeperPid</span>]}].</pre>
<p><!--- End Of Snippet -!&gt;--></p>
<p>The handle_info &#8216;EXIT&#8217; clause needs to be changed as well since we need to pop all type-queues now, this is handled with an internal helper function</p>
<p><!--- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_info</span>({<span style="color:#7fffd4;">'EXIT'</span>,<span style="color:#eedd82;">WorkerPid</span>,<span style="color:#eedd82;">Reason</span>},
            <span style="color:#7fffd4;">taken</span>,#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">job</span> = <span style="color:#eedd82;">WorkerPid</span>,<span style="color:#7fffd4;">job_keeper</span> = <span style="color:#eedd82;">JobKeeperPid</span>} = <span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">done</span>(<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">Reason</span>),
    {<span style="color:#eedd82;">Ns</span>,<span style="color:#eedd82;">Nld</span>} =
        <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">waiting_in</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">queues</span>) <span style="color:#00ffff;">of</span>
            <span style="color:#7fffd4;">undefined</span> -&gt; {<span style="color:#7fffd4;">free</span>,<span style="color:#eedd82;">State</span>};
            {<span style="color:#eedd82;">WaitingKeeperPid</span>,<span style="color:#eedd82;">NewQs</span>} -&gt;
                <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">signal</span>(<span style="color:#eedd82;">WaitingKeeperPid</span>) <span style="color:#00ffff;">of</span>
                    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">WnJob</span>} -&gt;
                        <span style="color:#b0c4de;">process_flag</span>(<span style="color:#7fffd4;">trap_exit</span>,<span style="color:#7fffd4;">true</span>),
                        {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">NewWorkerPid</span>} =
                           <span style="color:#98fb98;">wn_job_worker</span>:<span style="color:#98fb98;">start_link</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">node_root</span>,
                                                <span style="color:#eedd82;">WaitingKeeperPid</span>,
                                                <span style="color:#eedd82;">WnJob</span>),
                        {<span style="color:#7fffd4;">taken</span>,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">job</span> = <span style="color:#eedd82;">NewWorkerPid</span>,
                                           <span style="color:#7fffd4;">job_keeper</span> = <span style="color:#eedd82;">WaitingKeeperPid</span>,
                                           <span style="color:#7fffd4;">queues</span> = <span style="color:#eedd82;">NewQs</span>}};
                    {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">taken</span>} -&gt;
                        {<span style="color:#7fffd4;">free</span>,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">queues</span> = <span style="color:#eedd82;">NewQs</span>}}
                <span style="color:#00ffff;">end</span>
        <span style="color:#00ffff;">end</span>,
    {<span style="color:#7fffd4;">next_state</span>,<span style="color:#eedd82;">Ns</span>,<span style="color:#eedd82;">Nld</span>}.</pre>
<p><!--- End Of Snippet -!&gt;--></p>
<p>and the helper function waiting_in/1</p>
<p><!--- Snippet  --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">waiting_in</span>([{<span style="color:#eedd82;">_</span>,[<span style="color:#eedd82;">Pid</span>]}|<span style="color:#eedd82;">Q</span>]) -&gt; {<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">Q</span>};
<span style="color:#87cefa;">waiting_in</span>([{<span style="color:#eedd82;">Type</span>,[<span style="color:#eedd82;">Pid</span>|<span style="color:#eedd82;">R</span>]}|<span style="color:#eedd82;">Q</span>]) -&gt; {<span style="color:#eedd82;">Pid</span>,[{<span style="color:#eedd82;">Type</span>,<span style="color:#eedd82;">R</span>}|<span style="color:#eedd82;">Q</span>]};
<span style="color:#87cefa;">waiting_in</span>([]) -&gt; <span style="color:#7fffd4;">none</span>.</pre>
<p><!--- End Of Snippet  --></p>
<p>All that remains here is the change in how we signal to the wn_resource_process from the wn_job_layer and the necessary minimal logic in the wn_job_keeper to send the #wn_job record. First the necessary signalling change from the <em>wn_job_layer.erl</em></p>
<p>The job_layer should now try and signal the job on each possible type which is in the intersection of the possible job types and the designated resource types.  First change is the add_job clause in wn_job_layer.erl</p>
<p><!--- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_call</span>({<span style="color:#7fffd4;">add_job</span>,<span style="color:#eedd82;">WnJob</span>}, <span style="color:#eedd82;">_From</span>, <span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#eedd82;">JobId</span> = <span style="color:#eedd82;">WnJob</span>#<span style="color:#b0c4de;">wn_job</span>.<span style="color:#7fffd4;">id</span>,
    {<span style="color:#7fffd4;">reply</span>,
     <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">lookup</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">jobs</span>,<span style="color:#eedd82;">JobId</span>) <span style="color:#00ffff;">of</span>
         [] -&gt; {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">Pid</span>} = <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">start_link</span>(<span style="color:#eedd82;">WnJob</span>),
               <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">insert</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">jobs</span>,{<span style="color:#eedd82;">JobId</span>,<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">WnJob</span>}),
               <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foreach</span>(
                 <span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">WnResource</span>)  -&gt;
                    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">resource_is_sufficient</span>(<span style="color:#eedd82;">WnJob</span>,<span style="color:#eedd82;">WnResource</span>) <span style="color:#00ffff;">of</span>
                        {<span style="color:#7fffd4;">true</span>,<span style="color:#eedd82;">Possibles</span>} -&gt;
                            <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foreach</span>(
                               <span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">Type</span>) -&gt;
                                   <span style="color:#98fb98;">signal_resource</span>(<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">WnResource</span>,<span style="color:#eedd82;">Type</span>)
                               <span style="color:#00ffff;">end</span>,<span style="color:#eedd82;">Possibles</span>);
                        <span style="color:#7fffd4;">false</span> -&gt; <span style="color:#7fffd4;">ignore</span>
                   <span style="color:#00ffff;">end</span>
               <span style="color:#00ffff;">end</span>,<span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">list_resources</span>()),
               <span style="color:#7fffd4;">ok</span>;
         [<span style="color:#eedd82;">_</span>] -&gt;
             <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foreach</span>(
               <span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">File</span>) -&gt;
                       <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">delete_file</span>(<span style="color:#eedd82;">File</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">resides</span>,
                                           <span style="color:#eedd82;">File</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">id</span>)
               <span style="color:#00ffff;">end</span>,<span style="color:#eedd82;">WnJob</span>#<span style="color:#b0c4de;">wn_job</span>.<span style="color:#7fffd4;">files</span>),
             {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">already_exists</span>}
     <span style="color:#00ffff;">end</span>, <span style="color:#eedd82;">State</span>}.</pre>
<p><!--- End Of Snippet -!&gt;--></p>
<p>the implied changes in the helper functions by this</p>
<p><!--- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">resource_is_sufficient</span>(<span style="color:#eedd82;">WnJob</span>,<span style="color:#eedd82;">WnResource</span>) -&gt;
    <span style="color:#00ffff;">case</span> [ <span style="color:#eedd82;">T</span> <span style="color:#00ffff;">||</span> {<span style="color:#eedd82;">T</span>,<span style="color:#eedd82;">_</span>} <span style="color:#00ffff;">&lt;-</span> <span style="color:#eedd82;">WnResource</span>#<span style="color:#b0c4de;">wn_resource</span>.<span style="color:#7fffd4;">type</span>,
                <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">member</span>(<span style="color:#eedd82;">T</span>,<span style="color:#eedd82;">WnJob</span>#<span style="color:#b0c4de;">wn_job</span>.<span style="color:#7fffd4;">resources</span>)] <span style="color:#00ffff;">of</span>
        [] -&gt; <span style="color:#7fffd4;">false</span>;
        <span style="color:#eedd82;">L</span> -&gt; {<span style="color:#7fffd4;">true</span>,<span style="color:#eedd82;">L</span>}
    <span style="color:#00ffff;">end</span>.

<span style="color:#87cefa;">signal_resource</span>(<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">WnResource</span>,<span style="color:#eedd82;">Type</span>) -&gt;
    <span style="color:#98fb98;">wn_resource_process</span>:<span style="color:#98fb98;">signal</span>(<span style="color:#eedd82;">WnResource</span>#<span style="color:#b0c4de;">wn_resource</span>.<span style="color:#7fffd4;">pid</span>,
                               <span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">Type</span>).</pre>
<p><!--- End Of Snippet --></p>
<p>and finally, the requested get_job/1 function can be added to <em>wn_job_keeper.erl</em>, starting by the usual two &#8211; export</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">resource_is_sufficient</span>(<span style="color:#eedd82;">WnJob</span>,<span style="color:#eedd82;">WnResource</span>) -&gt;
    <span style="color:#eedd82;">JobResourceType</span> = <span style="color:#eedd82;">WnJob</span>#<span style="color:#b0c4de;">wn_job</span>.<span style="color:#7fffd4;">resources</span>,
    <span style="color:#00ffff;">case</span> [ <span style="color:#eedd82;">T</span> <span style="color:#00ffff;">||</span> {<span style="color:#eedd82;">T</span>,<span style="color:#eedd82;">_</span>} <span style="color:#00ffff;">&lt;-</span> <span style="color:#eedd82;">WnResource</span>#<span style="color:#b0c4de;">wn_resource</span>.<span style="color:#7fffd4;">type</span>,
                <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">member</span>(<span style="color:#eedd82;">T</span>,<span style="color:#eedd82;">WnJob</span>#<span style="color:#b0c4de;">wn_job</span>.<span style="color:#7fffd4;">resources</span>)] <span style="color:#00ffff;">of</span>
        [] -&gt; <span style="color:#7fffd4;">false</span>;
        <span style="color:#eedd82;">L</span> -&gt; {<span style="color:#7fffd4;">true</span>,<span style="color:#eedd82;">L</span>}
    <span style="color:#00ffff;">end</span>.

<span style="color:#87cefa;">signal_resource</span>(<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">WnResource</span>,<span style="color:#eedd82;">Type</span>) -&gt;
    <span style="color:#98fb98;">wn_resource_process</span>:<span style="color:#98fb98;">signal</span>(<span style="color:#eedd82;">WnResource</span>#<span style="color:#b0c4de;">wn_resource</span>.<span style="color:#7fffd4;">pid</span>,
                               <span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">Type</span>).</pre>
<p><!--- End Of Snippet --></p>
<p>and API function implementation</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">get_job</span>(<span style="color:#b0c4de;">pid</span>()) -&gt; #<span style="color:#b0c4de;">wn_job</span>{}).
<span style="color:#87cefa;">get_job</span>(<span style="color:#eedd82;">Pid</span>) -&gt;
    <span style="color:#98fb98;">gen_fsm</span>:<span style="color:#98fb98;">sync_send_all_state_event</span>(<span style="color:#eedd82;">Pid</span>,<span style="color:#7fffd4;">get_job</span>).</pre>
<p><!--- End Of Snippet --></p>
<p>and the handle_sync_event clause for this trivial signalling</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_sync_event</span>(<span style="color:#7fffd4;">get_job</span>,<span style="color:#eedd82;">_From</span>, <span style="color:#eedd82;">X</span>, <span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">reply</span>,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">job</span>,<span style="color:#eedd82;">X</span>,<span style="color:#eedd82;">State</span>};</pre>
<p><!--- End Of Snippet --></p>
<p>After all this, it seems like we have the full queueing in place &#8211; just the ticket counters to be fixed as well. Now &#8211; with &#8220;ticket behaviour&#8221; I mean the semaphoric behaviour &#8211; the counter on available resource slots for each declared type.</p>
<p>The change is small &#8211; let each resource_process keep an internal counter for each type and reduce it for each started process and increase it for each &#8216;EXIT&#8217;:ed. If the counter is &#8216;infinity&#8217; we don&#8217;t care counting for it.<br />
First the state record change for the <em>wn_resource_process.erl</em></p>
<p><!--- Snippet  --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;">-record(<span style="color:#b0c4de;">state</span>,{<span style="color:#7fffd4;">node_root</span> :: <span style="color:#98fb98;">string</span>(),
               <span style="color:#7fffd4;">queues</span> :: [{<span style="color:#7fffd4;">atom</span>,[<span style="color:#b0c4de;">pid</span>()]}],
               <span style="color:#7fffd4;">slots</span> <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">ets {atom,non_neg_integer()|infinity,
</span>                     <span style="color:#ff7f24;">%%           </span><span style="color:#ff7f24;">non_neg_integer()|infinity}
</span>               <span style="color:#7fffd4;">job</span> :: <span style="color:#b0c4de;">pid</span>(),
               <span style="color:#7fffd4;">job_keeper</span> :: <span style="color:#b0c4de;">pid</span>()
              }).</pre>
<p><!--- End Of Snippet -!&gt;--></p>
<p>Then the change so each wn_resource_process knows from the beginning how many slots they ought to have (passing an extra parameter in start_link/2)</p>
<p><!--- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">start_link</span>(<span style="color:#98fb98;">string</span>(),[{<span style="color:#b0c4de;">atom</span>(),<span style="color:#98fb98;">non_neg_integer</span>()|<span style="color:#7fffd4;">infinity</span>}]) -&gt;
             {<span style="color:#7fffd4;">ok</span>,<span style="color:#b0c4de;">pid</span>()} | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).
<span style="color:#87cefa;">start_link</span>(<span style="color:#eedd82;">NodeRoot</span>,<span style="color:#eedd82;">TypeSpec</span>) -&gt;
    <span style="color:#98fb98;">gen_fsm</span>:<span style="color:#98fb98;">start_link</span>(?<span style="color:#b0c4de;">MODULE</span>, {<span style="color:#eedd82;">NodeRoot</span>,<span style="color:#eedd82;">TypeSpec</span>}, []).</pre>
<p><!--- End Of Snippet -!&gt;--></p>
<p>the wn_resource_process init function is then modified to initiate the slot entries</p>
<p><!--- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">init</span>({<span style="color:#eedd82;">NodeRoot</span>,<span style="color:#eedd82;">TypeSpec</span>}) -&gt;
    <span style="color:#eedd82;">Ets</span> = <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">new</span>(<span style="color:#7fffd4;">available</span>,[<span style="color:#7fffd4;">set</span>]),
    <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foreach</span>(<span style="color:#00ffff;">fun</span>({<span style="color:#eedd82;">Type</span>,<span style="color:#eedd82;">Amount</span>}) -&gt; <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">insert</span>(<span style="color:#eedd82;">Ets</span>,{<span style="color:#eedd82;">Type</span>,<span style="color:#eedd82;">Amount</span>,<span style="color:#eedd82;">Amount</span>})
                  <span style="color:#00ffff;">end</span>,<span style="color:#eedd82;">TypeSpec</span>),
    {<span style="color:#7fffd4;">ok</span>, <span style="color:#7fffd4;">free</span>, #<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">node_root</span> = <span style="color:#eedd82;">NodeRoot</span>,
                      <span style="color:#7fffd4;">queues</span> = [],
                      <span style="color:#7fffd4;">slots</span> = <span style="color:#eedd82;">Ets</span>
                     }}.</pre>
<p><!--- End Of Snippet -!&gt;--></p>
<p>It now seems like a single wn_resource_process does not in fact have one single free/taken state any more. What decides whether a wn_resource_process can or can not take a job is the amount of available slots for each type.</p>
<p>Aha &#8211; so, do we remove the free / taken states? Do we rewrite the wn_resource_process as a gen_server perhaps? It would seem more fitting! And I shall, that will be the continuation for the next post (which will come quite soon &#8211; this post was getting too big &#8211; tune in, in 2 days or so for the next one).</p>
<p>Cheers<br />
/G</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/erlcode.wordpress.com/546/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/erlcode.wordpress.com/546/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=erlcode.wordpress.com&#038;blog=15510807&#038;post=546&#038;subd=erlcode&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://erlcode.wordpress.com/2011/02/13/erlang-tdd-hands-on-project-workernet-part-5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/861b8f824c3cd15c17ac6aa1b902e029?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">gianfrancoalongi</media:title>
		</media:content>
	</item>
		<item>
		<title>Erlang TDD hands on project – WorkerNet part 4</title>
		<link>http://erlcode.wordpress.com/2011/01/30/erlang-tdd-hands-on-project-%e2%80%93-workernet-part-4/</link>
		<comments>http://erlcode.wordpress.com/2011/01/30/erlang-tdd-hands-on-project-%e2%80%93-workernet-part-4/#comments</comments>
		<pubDate>Sun, 30 Jan 2011 22:11:43 +0000</pubDate>
		<dc:creator>gianfrancoalongi</dc:creator>
				<category><![CDATA[WorkerNet]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[workernet]]></category>

		<guid isPermaLink="false">http://erlcode.wordpress.com/?p=495</guid>
		<description><![CDATA[Continuing the job layer which had a whole lot of stories &#8211; we will now device and flesh out the test &#38; implementation sets. A word of warning first, the following test looks simple by design, but it only a tip of the iceberg that begs for implementation. First, a small change to the create_file_at/1 [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=erlcode.wordpress.com&#038;blog=15510807&#038;post=495&#038;subd=erlcode&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Continuing the job layer which had a whole lot of stories &#8211; we will now device and flesh out the test &amp; implementation sets. A word of warning first, the following test looks simple by design, but it only a tip of the iceberg that begs for implementation. First, a small change to the create_file_at/1 function in <em>wn_job_layer_tests.erl</em></p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">create_file_at</span>(<span style="color:#eedd82;">X</span>) -&gt;
    <span style="color:#eedd82;">Path</span> = <span style="color:#eedd82;">X</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"EUnitFile"</span>,
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">ensure_dir</span>(<span style="color:#eedd82;">X</span>),
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">write_file</span>(<span style="color:#eedd82;">Path</span>,<span style="color:#ffa07a;">"1,2,3\n"</span>),
    <span style="color:#eedd82;">Path</span>.</pre>
<p><!--- End Of Snippet --></p>
<p>The first written job-executing test in <em>wn_job_layer_tests.erl</em> is thus</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">executed_locally</span>() -&gt;
    <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(#<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"Laptop"</span>,
                                     <span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">'os-x'</span>,<span style="color:#7fffd4;">infinity</span>}],
                                     <span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()
                                     }),
    <span style="color:#eedd82;">Path</span> = <span style="color:#98fb98;">create_file_at</span>(?<span style="color:#b0c4de;">NODE_ROOT</span>),
    <span style="color:#eedd82;">File1</span> = #<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"File1"</span>,<span style="color:#7fffd4;">file</span> = <span style="color:#eedd82;">Path</span>,<span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()},
    <span style="color:#eedd82;">Job1</span> = #<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId"</span>,
                   <span style="color:#7fffd4;">files</span> = [<span style="color:#eedd82;">File1</span>],
                   <span style="color:#7fffd4;">resources</span> = [<span style="color:#7fffd4;">'os-x'</span>],
                   <span style="color:#7fffd4;">commands</span> = [<span style="color:#ffa07a;">"more EUnitFile"</span>],
                   <span style="color:#7fffd4;">timeout</span> = 100
                  },
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">Job1</span>)),
    <span style="color:#7fffd4;">ok</span>  = <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">stream</span>(<span style="color:#7fffd4;">user</span>,<span style="color:#ffa07a;">"JobId"</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>({<span style="color:#7fffd4;">ok</span>,[<span style="color:#ffa07a;">"1,2,3"</span>]},<span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">result</span>(<span style="color:#ffa07a;">"JobId"</span>)).</pre>
<p><!--- End Of Snippet --></p>
<p>Pretty tidy, small and easily understandable. Now off to implement the code needed for this design. First of all we need to have a clear picture of how to implement the internals of this. For me at least, a conceptual image always goes a long way (the previous image seen in part 3 was a rougher outline)</p>
<p><a href="http://erlcode.files.wordpress.com/2011/01/conceptual_work_design1.png"><img class="alignnone size-large wp-image-513" title="conceptual_work_design" src="http://erlcode.files.wordpress.com/2011/01/conceptual_work_design1.png?w=599&#038;h=1024" alt="" width="599" height="1024" /></a></p>
<p>Seems good enough for now, the rough corners are there, what else, how would we want to iron out? Yeah, one thing that needs consideration as we broke the seal on it already (circled in green on step (3)). How should the directory structure be designed properly? We want something scalable and isolated for each isolated piece of data, this should do it</p>
<p><a href="http://erlcode.files.wordpress.com/2011/01/dirstruct.png"><img class="alignnone size-full wp-image-517" title="dirstruct" src="http://erlcode.files.wordpress.com/2011/01/dirstruct.png?w=600" alt=""   /></a></p>
<p>The green-circled text is the  path on an example File stored in the file-layer on node n2@zen. Phew &#8211; that was a lot of &#8220;conceptual imaging&#8221; before we get to coding.  First of, the new meat of the resource_process depicted in the first image (let&#8217;s call it Fig-1) ,</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">-------------------------------------------------------------------
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@author Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@copyright (C) 2011, Gianfranco
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">Created : 11 Jan 2011 by Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">-------------------------------------------------------------------
</span><span style="color:#b0c4de;">-module</span>(<span style="color:#7fffd4;">wn_resource_process</span>).
<span style="color:#b0c4de;">-behaviour</span>(<span style="color:#7fffd4;">gen_fsm</span>).
<span style="color:#b0c4de;">-include</span>(<span style="color:#ffa07a;">"include/worker_net.hrl"</span>).
<span style="color:#b0c4de;">-define</span>(<span style="color:#b0c4de;">TIMEOUT</span>,3000).
<span style="color:#b0c4de;">-record</span>(<span style="color:#b0c4de;">state</span>,{<span style="color:#7fffd4;">node_root</span> :: <span style="color:#98fb98;">string</span>(),
            <span style="color:#7fffd4;">queue</span> :: [<span style="color:#b0c4de;">pid</span>()],
            <span style="color:#7fffd4;">job</span> :: <span style="color:#b0c4de;">pid</span>()
           }).

<span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">API
</span><span style="color:#b0c4de;">-export</span>([<span style="color:#87cefa;">start_link/1</span>,<span style="color:#87cefa;">signal/2</span>]).

<span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">gen_fsm callbacks
</span><span style="color:#b0c4de;">-export</span>([<span style="color:#87cefa;">init/1</span>, <span style="color:#87cefa;">handle_event/3</span>, <span style="color:#87cefa;">handle_sync_event/4</span>,
         <span style="color:#87cefa;">handle_info/3</span>, <span style="color:#87cefa;">terminate/3</span>, <span style="color:#87cefa;">code_change/4</span>]).

<span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">========================================================
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">API
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">========================================================
</span><span style="color:#87cefa;">start_link</span>(<span style="color:#eedd82;">NodeRoot</span>) -&gt;
    <span style="color:#98fb98;">gen_fsm</span>:<span style="color:#98fb98;">start_link</span>(?<span style="color:#b0c4de;">MODULE</span>, <span style="color:#eedd82;">NodeRoot</span>, []).

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">signal</span>(<span style="color:#b0c4de;">pid</span>(),<span style="color:#b0c4de;">pid</span>()) -&gt; <span style="color:#7fffd4;">ok</span>).
<span style="color:#87cefa;">signal</span>(<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">JobKeeperPid</span>) -&gt;
    <span style="color:#98fb98;">gen_fsm</span>:<span style="color:#98fb98;">send_all_state_event</span>(<span style="color:#eedd82;">Pid</span>,{<span style="color:#7fffd4;">signal</span>,<span style="color:#eedd82;">JobKeeperPid</span>}).

<span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">========================================================
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">gen_fsm callbacks
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">========================================================
</span><span style="color:#87cefa;">init</span>(<span style="color:#eedd82;">NodeRoot</span>) -&gt;
    {<span style="color:#7fffd4;">ok</span>, <span style="color:#7fffd4;">free</span>, #<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">node_root</span> = <span style="color:#eedd82;">NodeRoot</span>,<span style="color:#7fffd4;">queue</span> = []}}.

<span style="color:#87cefa;">handle_event</span>({<span style="color:#7fffd4;">signal</span>,<span style="color:#eedd82;">JobKeeperPid</span>}, <span style="color:#7fffd4;">free</span>, <span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#eedd82;">Ns</span>,<span style="color:#eedd82;">Nld</span>} =
        <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">signal</span>(<span style="color:#eedd82;">JobKeeperPid</span>) <span style="color:#00ffff;">of</span>
            {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">WnJob</span>} -&gt;
                <span style="color:#b0c4de;">process_flag</span>(<span style="color:#7fffd4;">trap_exit</span>,<span style="color:#7fffd4;">true</span>),
                {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">WorkerPid</span>} =
                    <span style="color:#98fb98;">wn_job_worker</span>:<span style="color:#98fb98;">start_link</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">node_root</span>,
                                             <span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">WnJob</span>),
                {<span style="color:#7fffd4;">taken</span>,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">job</span> = <span style="color:#eedd82;">WorkerPid</span>}};
            {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">taken</span>} -&gt;
                {<span style="color:#7fffd4;">free</span>,<span style="color:#eedd82;">State</span>}
        <span style="color:#00ffff;">end</span>,
    {<span style="color:#7fffd4;">next_state</span>,<span style="color:#eedd82;">Ns</span>,<span style="color:#eedd82;">Nld</span>};

<span style="color:#87cefa;">handle_event</span>({<span style="color:#7fffd4;">signal</span>,<span style="color:#eedd82;">JobKeeperPid</span>}, <span style="color:#7fffd4;">taken</span>, <span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">nex_state</span>,<span style="color:#7fffd4;">taken</span>,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">queue</span> = <span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">queue</span> <span style="color:#ffc0cb;font-weight:bold;">++</span> [<span style="color:#eedd82;">JobKeeperPid</span>]}}.

<span style="color:#87cefa;">handle_sync_event</span>(<span style="color:#eedd82;">_Event</span>, <span style="color:#eedd82;">_From</span>, <span style="color:#eedd82;">StateName</span>, <span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">reply</span>, <span style="color:#7fffd4;">ok</span>, <span style="color:#eedd82;">StateName</span>, <span style="color:#eedd82;">State</span>}.

<span style="color:#87cefa;">handle_info</span>({<span style="color:#7fffd4;">'EXIT'</span>,<span style="color:#eedd82;">WorkerPid</span>,<span style="color:#eedd82;">Reason</span>},<span style="color:#7fffd4;">taken</span>,#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">job</span> = <span style="color:#eedd82;">WorkerPid</span>} = <span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">done</span>(<span style="color:#eedd82;">WorkerPid</span>,<span style="color:#eedd82;">Reason</span>),
    {<span style="color:#eedd82;">Ns</span>,<span style="color:#eedd82;">Nld</span>} =
    <span style="color:#00ffff;">case</span> <span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">queue</span> <span style="color:#00ffff;">of</span>
        [] -&gt; {<span style="color:#7fffd4;">free</span>, <span style="color:#eedd82;">State</span>};
        [<span style="color:#eedd82;">X</span>|<span style="color:#eedd82;">Q</span>] -&gt;
            <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">signal</span>(<span style="color:#eedd82;">X</span>) <span style="color:#00ffff;">of</span>
                {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">WnJob</span>} -&gt;
                    <span style="color:#b0c4de;">process_flag</span>(<span style="color:#7fffd4;">trap_exit</span>,<span style="color:#7fffd4;">true</span>),
                    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">WorkerPid</span>} =
                    <span style="color:#98fb98;">wn_job_worker</span>:<span style="color:#98fb98;">start_link</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">node_root</span>,<span style="color:#eedd82;">X</span>,<span style="color:#eedd82;">WnJob</span>),
                    {<span style="color:#7fffd4;">taken</span>,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">job</span> = <span style="color:#eedd82;">WorkerPid</span>,<span style="color:#7fffd4;">queue</span> = <span style="color:#eedd82;">Q</span>}};
                {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">taken</span>} -&gt;
                    {<span style="color:#7fffd4;">free</span>,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">queue</span>=<span style="color:#eedd82;">Q</span>}}
            <span style="color:#00ffff;">end</span>
    <span style="color:#00ffff;">end</span>,
    {<span style="color:#7fffd4;">next_state</span>,<span style="color:#eedd82;">Ns</span>,<span style="color:#eedd82;">Nld</span>}.

<span style="color:#87cefa;">terminate</span>(<span style="color:#eedd82;">_Reason</span>, <span style="color:#eedd82;">_StateName</span>, <span style="color:#eedd82;">_State</span>) -&gt;
    <span style="color:#7fffd4;">ok</span>.

<span style="color:#87cefa;">code_change</span>(<span style="color:#eedd82;">_OldVsn</span>, <span style="color:#eedd82;">StateName</span>, <span style="color:#eedd82;">State</span>, <span style="color:#eedd82;">_Extra</span>) -&gt;
    {<span style="color:#7fffd4;">ok</span>, <span style="color:#eedd82;">StateName</span>, <span style="color:#eedd82;">State</span>}.

<span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">========================================================
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">Internal functions
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">========================================================
</span></pre>
<p><!--- End Of Snippet --></p>
<p>Previously the wn_resource_process.erl held the implementation of a minimal server, but the need for more logic made it easier to implement with standard OTP nuts and bolts. Next up the new meat  of the <em>wn_job_keeper.erl, </em>previously just the minimal possible code, but now with more requirements on it.</p>
<p><!--- Snippet -!&gt;--></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">-------------------------------------------------------------------
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@author Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@copyright (C) 2011, Gianfranco
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">Created : 13 Jan 2011 by Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">-------------------------------------------------------------------
</span><span style="color:#b0c4de;">-module</span>(<span style="color:#7fffd4;">wn_job_keeper</span>).
<span style="color:#b0c4de;">-behaviour</span>(<span style="color:#7fffd4;">gen_fsm</span>).
<span style="color:#b0c4de;">-include</span>(<span style="color:#ffa07a;">"include/worker_net.hrl"</span>).

<span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">API
</span><span style="color:#b0c4de;">-export</span>([<span style="color:#87cefa;">start_link/1</span>,<span style="color:#87cefa;">done/2</span>,<span style="color:#87cefa;">progress/2</span>,<span style="color:#87cefa;">info/2</span>,<span style="color:#87cefa;">stream/2</span>,
         <span style="color:#87cefa;">signal/1</span>,<span style="color:#87cefa;">get_result/1</span>]).

<span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">gen_fsm callbacks
</span><span style="color:#b0c4de;">-export</span>([<span style="color:#87cefa;">init/1</span>, <span style="color:#87cefa;">handle_event/3</span>, <span style="color:#87cefa;">handle_sync_event/4</span>,
         <span style="color:#87cefa;">handle_info/3</span>, <span style="color:#87cefa;">terminate/3</span>, <span style="color:#87cefa;">code_change/4</span>]).

<span style="color:#b0c4de;">-record</span>(<span style="color:#b0c4de;">state</span>, {<span style="color:#7fffd4;">job</span> :: #<span style="color:#b0c4de;">wn_job</span>{},
                <span style="color:#7fffd4;">info</span> :: [{{<span style="color:#b0c4de;">integer</span>(),<span style="color:#b0c4de;">integer</span>(),<span style="color:#b0c4de;">integer</span>()},<span style="color:#98fb98;">term</span>()}],
                <span style="color:#7fffd4;">result</span> :: [{{<span style="color:#b0c4de;">integer</span>(),<span style="color:#b0c4de;">integer</span>(),<span style="color:#b0c4de;">integer</span>()},<span style="color:#98fb98;">term</span>()}],
                <span style="color:#7fffd4;">stream</span> :: [<span style="color:#b0c4de;">pid</span>()]
               }).

<span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">==========================================================
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">API
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">==========================================================
</span><span style="color:#87cefa;">start_link</span>(<span style="color:#eedd82;">WnJob</span>) -&gt;
    <span style="color:#98fb98;">gen_fsm</span>:<span style="color:#98fb98;">start_link</span>(?<span style="color:#b0c4de;">MODULE</span>, <span style="color:#eedd82;">WnJob</span>, []).

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">done</span>(<span style="color:#b0c4de;">pid</span>(),<span style="color:#98fb98;">term</span>()) -&gt; <span style="color:#7fffd4;">ok</span>).
<span style="color:#87cefa;">done</span>(<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">X</span>) -&gt;
    <span style="color:#98fb98;">gen_fsm</span>:<span style="color:#98fb98;">send_all_state_event</span>(<span style="color:#eedd82;">Pid</span>,{<span style="color:#7fffd4;">done</span>,<span style="color:#eedd82;">X</span>}).

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">progress</span>(<span style="color:#b0c4de;">pid</span>(),<span style="color:#98fb98;">term</span>()) -&gt; <span style="color:#7fffd4;">ok</span>).
<span style="color:#87cefa;">progress</span>(<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">X</span>) -&gt;
    <span style="color:#98fb98;">gen_fsm</span>:<span style="color:#98fb98;">send_all_state_event</span>(<span style="color:#eedd82;">Pid</span>,{<span style="color:#7fffd4;">progress</span>,<span style="color:#eedd82;">X</span>}).

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">info</span>(<span style="color:#b0c4de;">pid</span>(),<span style="color:#98fb98;">term</span>()) -&gt; <span style="color:#7fffd4;">ok</span>).
<span style="color:#87cefa;">info</span>(<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">X</span>) -&gt;
    <span style="color:#98fb98;">gen_fsm</span>:<span style="color:#98fb98;">send_all_state_event</span>(<span style="color:#eedd82;">Pid</span>,{<span style="color:#7fffd4;">info</span>,<span style="color:#eedd82;">X</span>}).

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">stream</span>(<span style="color:#b0c4de;">pid</span>(),<span style="color:#b0c4de;">pid</span>()) -&gt; <span style="color:#7fffd4;">ok</span>).
<span style="color:#87cefa;">stream</span>(<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">StreamPid</span>) -&gt;
    <span style="color:#98fb98;">gen_fsm</span>:<span style="color:#98fb98;">send_all_state_event</span>(<span style="color:#eedd82;">Pid</span>,{<span style="color:#7fffd4;">stream</span>,<span style="color:#eedd82;">StreamPid</span>}).

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">signal</span>(<span style="color:#b0c4de;">pid</span>()) -&gt; {<span style="color:#7fffd4;">ok</span>,#<span style="color:#b0c4de;">wn_job</span>{}} | {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">taken</span>}).
<span style="color:#87cefa;">signal</span>(<span style="color:#eedd82;">Pid</span>) -&gt;
    <span style="color:#98fb98;">gen_fsm</span>:<span style="color:#98fb98;">sync_send_all_state_event</span>(<span style="color:#eedd82;">Pid</span>,<span style="color:#7fffd4;">signal</span>).

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">get_result</span>(<span style="color:#b0c4de;">pid</span>()) -&gt; [<span style="color:#98fb98;">string</span>()]).
<span style="color:#87cefa;">get_result</span>(<span style="color:#eedd82;">Pid</span>) -&gt;
    <span style="color:#98fb98;">gen_fsm</span>:<span style="color:#98fb98;">sync_send_all_state_event</span>(<span style="color:#eedd82;">Pid</span>,<span style="color:#7fffd4;">get_result</span>).

<span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">==========================================================
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">gen_fsm callbacks
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">==========================================================
</span><span style="color:#87cefa;">init</span>(<span style="color:#eedd82;">WnJob</span>) -&gt;
    {<span style="color:#7fffd4;">ok</span>, <span style="color:#7fffd4;">waiting</span>, #<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">job</span> = <span style="color:#eedd82;">WnJob</span>,
                         <span style="color:#7fffd4;">info</span> = [],
                         <span style="color:#7fffd4;">result</span> = [],
                         <span style="color:#7fffd4;">stream</span> = []
                        }}.

<span style="color:#87cefa;">handle_event</span>({<span style="color:#7fffd4;">done</span>,<span style="color:#eedd82;">X</span>}, <span style="color:#7fffd4;">working</span>, #<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">info</span> = <span style="color:#eedd82;">Info</span>} = <span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#98fb98;">stream_msg</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">stream</span>,<span style="color:#eedd82;">X</span>),
    {<span style="color:#7fffd4;">next_state</span>, <span style="color:#7fffd4;">done</span>, <span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">info</span> = [{<span style="color:#98fb98;">now</span>(),{<span style="color:#7fffd4;">done</span>,<span style="color:#eedd82;">X</span>}}|<span style="color:#eedd82;">Info</span>]}};
<span style="color:#87cefa;">handle_event</span>({<span style="color:#7fffd4;">progress</span>,<span style="color:#eedd82;">X</span>},<span style="color:#7fffd4;">working</span>,#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">result</span> = <span style="color:#eedd82;">Result</span>} = <span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#98fb98;">stream_msg</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">stream</span>,<span style="color:#eedd82;">X</span>),
    {<span style="color:#7fffd4;">next_state</span>,<span style="color:#7fffd4;">working</span>,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">result</span> = [{<span style="color:#98fb98;">now</span>(),<span style="color:#eedd82;">X</span>}|<span style="color:#eedd82;">Result</span>]}};
<span style="color:#87cefa;">handle_event</span>({<span style="color:#7fffd4;">info</span>,<span style="color:#eedd82;">X</span>},<span style="color:#7fffd4;">working</span>,#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">info</span> = <span style="color:#eedd82;">Info</span>} = <span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#98fb98;">stream_msg</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">stream</span>,<span style="color:#eedd82;">X</span>),
    {<span style="color:#7fffd4;">next_state</span>,<span style="color:#7fffd4;">working</span>,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">info</span> = [{<span style="color:#98fb98;">now</span>(),<span style="color:#eedd82;">X</span>}|<span style="color:#eedd82;">Info</span>]}};
<span style="color:#87cefa;">handle_event</span>({<span style="color:#7fffd4;">stream</span>,<span style="color:#eedd82;">Pid</span>},<span style="color:#eedd82;">X</span>,#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">stream</span> = <span style="color:#eedd82;">Stream</span>} = <span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#98fb98;">replay</span>(<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">State</span>),
    {<span style="color:#7fffd4;">next_state</span>,<span style="color:#eedd82;">X</span>,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">stream</span>=[<span style="color:#eedd82;">Pid</span>|<span style="color:#eedd82;">Stream</span>]}}.

<span style="color:#87cefa;">handle_sync_event</span>(<span style="color:#7fffd4;">signal</span>, <span style="color:#eedd82;">_From</span>, <span style="color:#7fffd4;">waiting</span>, <span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">reply</span>,{<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">job</span>}, <span style="color:#7fffd4;">working</span>, <span style="color:#eedd82;">State</span>};
<span style="color:#87cefa;">handle_sync_event</span>(<span style="color:#7fffd4;">signal</span>,<span style="color:#eedd82;">_From</span>,<span style="color:#eedd82;">X</span>,<span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">reply</span>,{<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">taken</span>},<span style="color:#eedd82;">X</span>,<span style="color:#eedd82;">State</span>};
<span style="color:#87cefa;">handle_sync_event</span>(<span style="color:#7fffd4;">get_result</span>,<span style="color:#eedd82;">_From</span>,<span style="color:#eedd82;">X</span>,<span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">reply</span>,[ <span style="color:#eedd82;">Z</span> <span style="color:#00ffff;">||</span> {<span style="color:#eedd82;">_</span>,<span style="color:#eedd82;">Z</span>} <span style="color:#00ffff;">&lt;-</span> <span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">result</span>],<span style="color:#eedd82;">X</span>,<span style="color:#eedd82;">State</span>}.

<span style="color:#87cefa;">handle_info</span>(<span style="color:#eedd82;">_Info</span>, <span style="color:#eedd82;">StateName</span>, <span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">next_state</span>, <span style="color:#eedd82;">StateName</span>, <span style="color:#eedd82;">State</span>}.

<span style="color:#87cefa;">terminate</span>(<span style="color:#eedd82;">_Reason</span>, <span style="color:#eedd82;">_StateName</span>, <span style="color:#eedd82;">_State</span>) -&gt;
    <span style="color:#7fffd4;">ok</span>.

<span style="color:#87cefa;">code_change</span>(<span style="color:#eedd82;">_OldVsn</span>, <span style="color:#eedd82;">StateName</span>, <span style="color:#eedd82;">State</span>, <span style="color:#eedd82;">_Extra</span>) -&gt;
    {<span style="color:#7fffd4;">ok</span>, <span style="color:#eedd82;">StateName</span>, <span style="color:#eedd82;">State</span>}.

<span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">==========================================================
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">Internal functions
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">==========================================================
</span><span style="color:#87cefa;">replay</span>(<span style="color:#eedd82;">Pid</span>,#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">info</span> = <span style="color:#eedd82;">Info</span>,<span style="color:#7fffd4;">result</span>=<span style="color:#eedd82;">Result</span>}) -&gt;
    <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foreach</span>(<span style="color:#00ffff;">fun</span>({<span style="color:#eedd82;">_Now</span>,<span style="color:#eedd82;">X</span>}) -&gt; <span style="color:#eedd82;">Pid</span> ! <span style="color:#eedd82;">X</span> <span style="color:#00ffff;">end</span>,
                  <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">sort</span>(<span style="color:#eedd82;">Info</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">Result</span>)).

<span style="color:#87cefa;">stream_msg</span>(<span style="color:#eedd82;">List</span>,<span style="color:#eedd82;">X</span>) -&gt;
    <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foreach</span>(<span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">Pid</span>) -&gt; <span style="color:#eedd82;">Pid</span> ! <span style="color:#eedd82;">X</span> <span style="color:#00ffff;">end</span>,<span style="color:#eedd82;">List</span>).</pre>
<p><!--- End Of Snippet -!&gt;--></p>
<p>This new implementation also used the standard parts of the OTP toolbox, nothing crazy. Final part to be implemented to pull this stunt is the wn_job_worker.erl<br />
<!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">-------------------------------------------------------------------
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@author Gianfranco &lt;<a href="mailto:zenon@zen.home">zenon@zen.home</a>&gt;
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@copyright (C) 2011, Gianfranco
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">Created : 20 Jan 2011 by Gianfranco &lt;<a href="mailto:zenon@zen.home">zenon@zen.home</a>&gt;
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">-------------------------------------------------------------------
</span><span style="color:#b0c4de;">-module</span>(<span style="color:#7fffd4;">wn_job_worker</span>).
<span style="color:#b0c4de;">-behaviour</span>(<span style="color:#7fffd4;">gen_server</span>).
<span style="color:#b0c4de;">-include</span>(<span style="color:#ffa07a;">"include/worker_net.hrl"</span>).

<span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">API
</span><span style="color:#b0c4de;">-export</span>([<span style="color:#87cefa;">start_link/3</span>]).

<span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">gen_server callbacks
</span><span style="color:#b0c4de;">-export</span>([<span style="color:#87cefa;">init/1</span>, <span style="color:#87cefa;">handle_call/3</span>, <span style="color:#87cefa;">handle_cast/2</span>, <span style="color:#87cefa;">handle_info/2</span>,
         <span style="color:#87cefa;">terminate/2</span>, <span style="color:#87cefa;">code_change/3</span>]).

<span style="color:#b0c4de;">-record</span>(<span style="color:#b0c4de;">state</span>, {<span style="color:#7fffd4;">pid</span> :: <span style="color:#b0c4de;">pid</span>(),
             <span style="color:#7fffd4;">job</span> :: #<span style="color:#b0c4de;">wn_job</span>{},
             <span style="color:#7fffd4;">workdir</span> :: <span style="color:#98fb98;">string</span>(),
             <span style="color:#7fffd4;">olddir</span> :: <span style="color:#98fb98;">string</span>(),
             <span style="color:#7fffd4;">commands</span> :: [<span style="color:#98fb98;">string</span>()],
             <span style="color:#7fffd4;">port</span> :: <span style="color:#b0c4de;">port</span>()
             }).

<span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">==========================================================
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">API
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">==========================================================
</span><span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">start_link</span>(<span style="color:#98fb98;">string</span>(),<span style="color:#b0c4de;">pid</span>(),#<span style="color:#b0c4de;">wn_job</span>{}) -&gt; {<span style="color:#7fffd4;">ok</span>,<span style="color:#b0c4de;">pid</span>()} | <span style="color:#98fb98;">term</span>()).
<span style="color:#87cefa;">start_link</span>(<span style="color:#eedd82;">NodeRoot</span>,<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">WnJob</span>) -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">start_link</span>(?<span style="color:#b0c4de;">MODULE</span>, {<span style="color:#eedd82;">NodeRoot</span>,<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">WnJob</span>}, []).

<span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">==========================================================
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">gen_server callbacks
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">==========================================================
</span><span style="color:#87cefa;">init</span>({<span style="color:#eedd82;">NodeRoot</span>,<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">WnJob</span>}) -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">cast</span>(<span style="color:#b0c4de;">self</span>(),<span style="color:#7fffd4;">start</span>),
    {<span style="color:#7fffd4;">ok</span>, #<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">pid</span> = <span style="color:#eedd82;">Pid</span>,
              <span style="color:#7fffd4;">job</span> = <span style="color:#eedd82;">WnJob</span>,
              <span style="color:#7fffd4;">olddir</span> = (<span style="color:#00ffff;">fun</span>({<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">Curr</span>}) -&gt; <span style="color:#eedd82;">Curr</span> <span style="color:#00ffff;">end</span>)(<span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">get_cwd</span>()),
              <span style="color:#7fffd4;">workdir</span> = <span style="color:#98fb98;">wn_util</span>:<span style="color:#98fb98;">work_dir</span>(<span style="color:#eedd82;">NodeRoot</span>,<span style="color:#eedd82;">WnJob</span>)}}.

<span style="color:#87cefa;">handle_call</span>(<span style="color:#eedd82;">_Request</span>, <span style="color:#eedd82;">_From</span>, <span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">reply</span>, <span style="color:#7fffd4;">ok</span>, <span style="color:#eedd82;">State</span>}.

<span style="color:#87cefa;">handle_cast</span>(<span style="color:#7fffd4;">start</span>, <span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">ensure_dir</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">workdir</span>),
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">set_cwd</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">workdir</span>),
    <span style="color:#eedd82;">WnJob</span> = <span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">job</span>,
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">get_work_files</span>(<span style="color:#eedd82;">WnJob</span>) <span style="color:#00ffff;">of</span>
        {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>} -&gt;
            <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">info</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">pid</span>,<span style="color:#7fffd4;">file_fetching_done</span>),
            <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">info</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">pid</span>,<span style="color:#7fffd4;">executing_commands</span>),
            <span style="color:#98fb98;">timer</span>:<span style="color:#98fb98;">send_after</span>(<span style="color:#eedd82;">WnJob</span>#<span style="color:#b0c4de;">wn_job</span>.<span style="color:#7fffd4;">timeout</span>,<span style="color:#b0c4de;">self</span>(),<span style="color:#7fffd4;">timeout</span>),
            [<span style="color:#eedd82;">C</span>|<span style="color:#eedd82;">Commands</span>] = (<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">job</span>)#<span style="color:#b0c4de;">wn_job</span>.<span style="color:#7fffd4;">commands</span>,
            <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">info</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">pid</span>,{<span style="color:#7fffd4;">executing</span>,<span style="color:#eedd82;">C</span>}),
            <span style="color:#eedd82;">Port</span> = <span style="color:#b0c4de;">erlang</span>:<span style="color:#b0c4de;">open_port</span>({<span style="color:#7fffd4;">spawn</span>,<span style="color:#eedd82;">C</span>},[<span style="color:#7fffd4;">eof</span>,{<span style="color:#7fffd4;">line</span>,2048}]),
            {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">commands</span> = <span style="color:#eedd82;">Commands</span>,<span style="color:#7fffd4;">port</span> = <span style="color:#eedd82;">Port</span>}};
        <span style="color:#eedd82;">Err</span> -&gt;
            <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">set_cwd</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">olddir</span>),
            <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_util</span>:<span style="color:#98fb98;">clean_up</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">workdir</span>),
            <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">info</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">pid</span>,{<span style="color:#7fffd4;">file_fetching_failed</span>,<span style="color:#eedd82;">Err</span>}),
            <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">info</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">pid</span>,<span style="color:#7fffd4;">ending</span>),
            {<span style="color:#7fffd4;">stop</span>,<span style="color:#7fffd4;">file_fetching_failed</span>,<span style="color:#eedd82;">State</span>}
    <span style="color:#00ffff;">end</span>.

<span style="color:#87cefa;">handle_info</span>({<span style="color:#eedd82;">Port</span>,{<span style="color:#7fffd4;">data</span>,{<span style="color:#7fffd4;">eol</span>,<span style="color:#eedd82;">D</span>}}},#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">port</span> = <span style="color:#eedd82;">Port</span>} = <span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">progress</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">pid</span>,<span style="color:#eedd82;">D</span>),
    {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>};
<span style="color:#87cefa;">handle_info</span>({<span style="color:#eedd82;">Port</span>,<span style="color:#7fffd4;">eof</span>},#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">port</span> = <span style="color:#eedd82;">Port</span>} = <span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#00ffff;">case</span> <span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">commands</span> <span style="color:#00ffff;">of</span>
        [] -&gt;
            <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">info</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">pid</span>,<span style="color:#7fffd4;">no_more_commands</span>),
            <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">info</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">pid</span>,<span style="color:#7fffd4;">done</span>),
            {<span style="color:#7fffd4;">stop</span>,<span style="color:#7fffd4;">normal</span>,<span style="color:#eedd82;">State</span>};
        [<span style="color:#eedd82;">C</span>|<span style="color:#eedd82;">Commands</span>] -&gt;
            <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">info</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">pid</span>,{<span style="color:#7fffd4;">executing</span>,<span style="color:#eedd82;">C</span>}),
            <span style="color:#eedd82;">NewPort</span> = <span style="color:#b0c4de;">erlang</span>:<span style="color:#b0c4de;">open_port</span>({<span style="color:#7fffd4;">spawn</span>,<span style="color:#eedd82;">C</span>},[<span style="color:#7fffd4;">eof</span>,{<span style="color:#7fffd4;">line</span>,2048}]),
            {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">commands</span> = <span style="color:#eedd82;">Commands</span>,<span style="color:#7fffd4;">port</span> = <span style="color:#eedd82;">NewPort</span>}}
    <span style="color:#00ffff;">end</span>;
<span style="color:#87cefa;">handle_info</span>(<span style="color:#7fffd4;">timeout</span>, <span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">info</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">pid</span>,<span style="color:#7fffd4;">timeout_on_job</span>),
    {<span style="color:#7fffd4;">stop</span>,<span style="color:#7fffd4;">timeout</span>,<span style="color:#eedd82;">State</span>}.

<span style="color:#87cefa;">terminate</span>(<span style="color:#eedd82;">_Reason</span>, <span style="color:#eedd82;">_State</span>) -&gt;
    <span style="color:#7fffd4;">ok</span>.

<span style="color:#87cefa;">code_change</span>(<span style="color:#eedd82;">_OldVsn</span>, <span style="color:#eedd82;">State</span>, <span style="color:#eedd82;">_Extra</span>) -&gt;
    {<span style="color:#7fffd4;">ok</span>, <span style="color:#eedd82;">State</span>}.

<span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">==========================================================
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">Internal functions
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">==========================================================
</span><span style="color:#87cefa;">get_work_files</span>(<span style="color:#eedd82;">WnJob</span>) -&gt;
    <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foldl</span>(
      <span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">_WnFile</span>,{<span style="color:#7fffd4;">error</span>,<span style="color:#eedd82;">X</span>}) -&gt; {<span style="color:#7fffd4;">error</span>,<span style="color:#eedd82;">X</span>};
         (<span style="color:#eedd82;">WnFile</span>,{<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>}) -&gt;
              <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">retrieve_file</span>(<span style="color:#eedd82;">WnFile</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">resides</span>,
                                          <span style="color:#eedd82;">WnFile</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">id</span>)
      <span style="color:#00ffff;">end</span>,{<span style="color:#7fffd4;">ok</span>,1},<span style="color:#eedd82;">WnJob</span>#<span style="color:#b0c4de;">wn_job</span>.<span style="color:#7fffd4;">files</span>).</pre>
<p><!--- End Of Snippet --></p>
<p>Also, last but not least, this code relies on the use of a ne utility lib module <em>wn_util.erl</em></p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@author Gianfranco &lt;<a href="mailto:zenon@zen.home">zenon@zen.home</a>&gt;
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@copyright (C) 2011, Gianfranco
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">Created : 19 Jan 2011 by Gianfranco &lt;<a href="mailto:zenon@zen.home">zenon@zen.home</a>&gt;
</span><span style="color:#b0c4de;">-module</span>(<span style="color:#7fffd4;">wn_util</span>).
<span style="color:#b0c4de;">-include</span>(<span style="color:#ffa07a;">"include/worker_net.hrl"</span>).
<span style="color:#b0c4de;">-export</span>([<span style="color:#87cefa;">file_dir/2</span>,
         <span style="color:#87cefa;">work_dir/2</span>,
         <span style="color:#87cefa;">clean_up/1</span>,
         <span style="color:#87cefa;">file_root/1</span>
        ]).

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">clean_up</span>(<span style="color:#98fb98;">string</span>()) -&gt; <span style="color:#7fffd4;">ok</span> | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).
<span style="color:#87cefa;">clean_up</span>(<span style="color:#eedd82;">Path</span>) -&gt;
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_dir</span>(<span style="color:#eedd82;">Path</span>) <span style="color:#00ffff;">of</span>
        <span style="color:#7fffd4;">true</span> -&gt;
            {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">Files</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">list_dir</span>(<span style="color:#eedd82;">Path</span>),
            <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foreach</span>(
              <span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">File</span>) -&gt;
                      <span style="color:#98fb98;">clean_up</span>(<span style="color:#eedd82;">Path</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">File</span>)
              <span style="color:#00ffff;">end</span>,<span style="color:#eedd82;">Files</span>),
            <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">del_dir</span>(<span style="color:#eedd82;">Path</span>);
        <span style="color:#7fffd4;">false</span> -&gt;
            <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">Path</span>)
    <span style="color:#00ffff;">end</span>.

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">work_dir</span>(<span style="color:#98fb98;">string</span>(),#<span style="color:#b0c4de;">wn_job</span>{}) -&gt; <span style="color:#98fb98;">string</span>()).
<span style="color:#87cefa;">work_dir</span>(<span style="color:#eedd82;">NodeRoot</span>,<span style="color:#eedd82;">WnJob</span>) -&gt;
    <span style="color:#98fb98;">work_root</span>(<span style="color:#eedd82;">NodeRoot</span>)<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">WnJob</span>#<span style="color:#b0c4de;">wn_job</span>.<span style="color:#7fffd4;">id</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span>.

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">file_dir</span>(<span style="color:#98fb98;">string</span>(),#<span style="color:#b0c4de;">wn_file</span>{}) -&gt; <span style="color:#98fb98;">string</span>()).
<span style="color:#87cefa;">file_dir</span>(<span style="color:#eedd82;">NodeRoot</span>,<span style="color:#eedd82;">WnFile</span>) -&gt;
    <span style="color:#98fb98;">file_root</span>(<span style="color:#eedd82;">NodeRoot</span>)<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">WnFile</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">id</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span>.

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">file_root</span>(<span style="color:#98fb98;">string</span>()) -&gt; <span style="color:#98fb98;">string</span>()).
<span style="color:#87cefa;">file_root</span>(<span style="color:#eedd82;">NodeRoot</span>) -&gt;
    <span style="color:#eedd82;">NodeRoot</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#b0c4de;">atom_to_list</span>(<span style="color:#b0c4de;">node</span>())<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/Files/"</span>.

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">work_root</span>(<span style="color:#98fb98;">string</span>()) -&gt; <span style="color:#98fb98;">string</span>()).
<span style="color:#87cefa;">work_root</span>(<span style="color:#eedd82;">NodeRoot</span>) -&gt;
    <span style="color:#eedd82;">NodeRoot</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#b0c4de;">atom_to_list</span>(<span style="color:#b0c4de;">node</span>())<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/Jobs/"</span>.</pre>
<p><!--- End Of Snippet --></p>
<p>The rationale behind this module is to keep the code clean, tidy and maintainable. Hiding the implementation details of the structure.  Running the &#8216;full&#8217; make target with this code in hand should now produce the following heartwarming output</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#7fffd4;">zen</span>:<span style="color:#7fffd4;">worker_net</span>-0.1 <span style="color:#7fffd4;">zenon</span><span style="color:#ffa07a;">$ </span><span style="color:#7fffd4;">make</span> <span style="color:#7fffd4;">full</span>
<span style="color:#7fffd4;">erlc</span> -<span style="color:#7fffd4;">pa</span> . -<span style="color:#7fffd4;">o</span> <span style="color:#7fffd4;">ebin</span>/  <span style="color:#7fffd4;">src</span>/*.<span style="color:#7fffd4;">erl</span> <span style="color:#7fffd4;">test</span>/*.<span style="color:#7fffd4;">erl</span>
<span style="color:#7fffd4;">erl</span> -<span style="color:#7fffd4;">pa</span> <span style="color:#7fffd4;">ebin</span>/ -<span style="color:#7fffd4;">eval</span> 'eunit:<span style="color:#98fb98;">test</span>(<span style="color:#7fffd4;">wn_resource_layer</span>,[<span style="color:#7fffd4;">verbose</span>]), <span style="color:#98fb98;">init</span>:<span style="color:#98fb98;">stop</span>().'
<span style="color:#eedd82;">Erlang</span> <span style="color:#eedd82;">R14B</span> (<span style="color:#7fffd4;">erts</span>-5.8.1) [<span style="color:#7fffd4;">source</span>] [<span style="color:#7fffd4;">smp</span>:4:4] [<span style="color:#7fffd4;">rq</span>:4] [<span style="color:#7fffd4;">async</span>-<span style="color:#7fffd4;">threads</span>:0] [<span style="color:#7fffd4;">hipe</span>]
[<span style="color:#7fffd4;">kernel</span>-<span style="color:#7fffd4;">poll</span>:<span style="color:#7fffd4;">false</span>]

<span style="color:#eedd82;">Eshell</span> <span style="color:#eedd82;">V5</span>.8.1  (<span style="color:#7fffd4;">abort</span> <span style="color:#7fffd4;">with</span> ^<span style="color:#eedd82;">G</span>)
1&gt; ======================== <span style="color:#eedd82;">EUnit</span> ========================
<span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_resource_layer'</span>
  <span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_resource_layer_tests'</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">local_resource_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">register</span> <span style="color:#7fffd4;">resources</span> <span style="color:#7fffd4;">locally</span>)...[0.003 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">register_distributed</span> (<span style="color:#eedd82;">Can</span> <span style="color:#eedd82;">Register</span> <span style="color:#eedd82;">Distributed</span>)...[0.007 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">register_restart_register</span> (<span style="color:#eedd82;">Can</span> <span style="color:#eedd82;">Register</span>, <span style="color:#eedd82;">Restart</span> <span style="color:#7fffd4;">and</span> <span style="color:#eedd82;">Register</span>)...[0.012 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">register_deregister</span> (<span style="color:#eedd82;">Can</span> <span style="color:#eedd82;">Register</span>, <span style="color:#eedd82;">Deregister</span> <span style="color:#7fffd4;">and</span> <span style="color:#eedd82;">Register</span>)...[0.011 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0.911 <span style="color:#7fffd4;">s</span>]
  [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0.911 <span style="color:#7fffd4;">s</span>]
=======================================================
  <span style="color:#eedd82;">All</span> 4 <span style="color:#7fffd4;">tests</span> <span style="color:#7fffd4;">passed</span>.
<span style="color:#7fffd4;">erl</span> -<span style="color:#7fffd4;">pa</span> <span style="color:#7fffd4;">ebin</span>/ -<span style="color:#7fffd4;">eval</span> 'eunit:<span style="color:#98fb98;">test</span>(<span style="color:#7fffd4;">wn_file_layer</span>,[<span style="color:#7fffd4;">verbose</span>]), <span style="color:#98fb98;">init</span>:<span style="color:#98fb98;">stop</span>().'
<span style="color:#eedd82;">Erlang</span> <span style="color:#eedd82;">R14B</span> (<span style="color:#7fffd4;">erts</span>-5.8.1) [<span style="color:#7fffd4;">source</span>] [<span style="color:#7fffd4;">smp</span>:4:4] [<span style="color:#7fffd4;">rq</span>:4] [<span style="color:#7fffd4;">async</span>-<span style="color:#7fffd4;">threads</span>:0] [<span style="color:#7fffd4;">hipe</span>] [<span style="color:#7fffd4;">kernel</span>-<span style="color:#7fffd4;">poll</span>:<span style="color:#7fffd4;">false</span>]

<span style="color:#eedd82;">Eshell</span> <span style="color:#eedd82;">V5</span>.8.1  (<span style="color:#7fffd4;">abort</span> <span style="color:#7fffd4;">with</span> ^<span style="color:#eedd82;">G</span>)
1&gt; ======================== <span style="color:#eedd82;">EUnit</span> ========================
<span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_file_layer'</span>
  <span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_file_layer_tests'</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">file_layer_local_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">store</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">locally</span>)...[0.011 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">file_layer_local_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">retrieve</span> <span style="color:#7fffd4;">files</span> <span style="color:#7fffd4;">locally</span>)...[0.001 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">file_layer_local_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">delete</span> <span style="color:#7fffd4;">files</span> <span style="color:#7fffd4;">locally</span>)...[0.011 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">can_store_distributed</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">store</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">distributed</span>)...[0.097 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">can_retrieve_distributed</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">retrieve</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">distributed</span>)...[0.014 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">can_delete_distributed</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">delete</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">distributed</span>)...[0.044 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">must_retain</span> (<span style="color:#eedd82;">Must</span> <span style="color:#7fffd4;">retain</span> <span style="color:#7fffd4;">information</span> <span style="color:#7fffd4;">between</span> <span style="color:#7fffd4;">node</span> <span style="color:#7fffd4;">kill</span> <span style="color:#7fffd4;">and</span> <span style="color:#7fffd4;">node</span> <span style="color:#7fffd4;">restart</span>)...[0.362 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 1.689 <span style="color:#7fffd4;">s</span>]
  [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 1.689 <span style="color:#7fffd4;">s</span>]
=======================================================
  <span style="color:#eedd82;">All</span> 7 <span style="color:#7fffd4;">tests</span> <span style="color:#7fffd4;">passed</span>.
<span style="color:#7fffd4;">erl</span> -<span style="color:#7fffd4;">pa</span> <span style="color:#7fffd4;">ebin</span>/ -<span style="color:#7fffd4;">eval</span> 'eunit:<span style="color:#98fb98;">test</span>(<span style="color:#7fffd4;">wn_job_layer</span>,[<span style="color:#7fffd4;">verbose</span>]), <span style="color:#98fb98;">init</span>:<span style="color:#98fb98;">stop</span>().'
<span style="color:#eedd82;">Erlang</span> <span style="color:#eedd82;">R14B</span> (<span style="color:#7fffd4;">erts</span>-5.8.1) [<span style="color:#7fffd4;">source</span>] [<span style="color:#7fffd4;">smp</span>:4:4] [<span style="color:#7fffd4;">rq</span>:4] [<span style="color:#7fffd4;">async</span>-<span style="color:#7fffd4;">threads</span>:0] [<span style="color:#7fffd4;">hipe</span>] [<span style="color:#7fffd4;">kernel</span>-<span style="color:#7fffd4;">poll</span>:<span style="color:#7fffd4;">false</span>]

<span style="color:#eedd82;">Eshell</span> <span style="color:#eedd82;">V5</span>.8.1  (<span style="color:#7fffd4;">abort</span> <span style="color:#7fffd4;">with</span> ^<span style="color:#eedd82;">G</span>)
1&gt; ======================== <span style="color:#eedd82;">EUnit</span> ========================
<span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_job_layer'</span>
  <span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_job_layer_tests'</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">register</span> <span style="color:#7fffd4;">locally</span>)...[0.003 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_job_layer_tests</span>: <span style="color:#98fb98;">local_test_</span> (<span style="color:#eedd82;">Executed</span> <span style="color:#7fffd4;">locally</span>)...<span style="color:#7fffd4;">file_fetching_done</span>
<span style="color:#7fffd4;">executing_commands</span>
{<span style="color:#7fffd4;">executing</span>,<span style="color:#ffa07a;">"more EUnitFile"</span>}
<span style="color:#ffa07a;">"1,2,3"</span>
<span style="color:#7fffd4;">no_more_commands</span>
<span style="color:#7fffd4;">done</span>
[1.004 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 1.030 <span style="color:#7fffd4;">s</span>]
  [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 1.030 <span style="color:#7fffd4;">s</span>]
=======================================================
  <span style="color:#eedd82;">All</span> 2 <span style="color:#7fffd4;">tests</span> <span style="color:#7fffd4;">passed</span>.
<span style="color:#7fffd4;">dialyzer</span> <span style="color:#7fffd4;">src</span>/*.<span style="color:#7fffd4;">erl</span> <span style="color:#7fffd4;">test</span>/*.<span style="color:#7fffd4;">erl</span>
  <span style="color:#eedd82;">Checking</span> <span style="color:#7fffd4;">whether</span> <span style="color:#7fffd4;">the</span> <span style="color:#eedd82;">PLT</span> /<span style="color:#eedd82;">Users</span>/<span style="color:#7fffd4;">zenon</span>/.<span style="color:#7fffd4;">dialyzer_plt</span> <span style="color:#7fffd4;">is</span> <span style="color:#7fffd4;">up</span>-<span style="color:#7fffd4;">to</span>-<span style="color:#7fffd4;">date</span>... <span style="color:#7fffd4;">yes</span>
  <span style="color:#eedd82;">Proceeding</span> <span style="color:#7fffd4;">with</span> <span style="color:#7fffd4;">analysis</span>...
<span style="color:#eedd82;">Unknown</span> <span style="color:#7fffd4;">functions</span>:
  <span style="color:#7fffd4;">eunit</span>:<span style="color:#87cefa;">test/1</span>
 <span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0m3.60s
<span style="color:#87cefa;">done</span> (<span style="color:#7fffd4;">passed</span> <span style="color:#7fffd4;">successfully</span>)
<span style="color:#7fffd4;">zen</span>:<span style="color:#7fffd4;">worker_net</span>-0.1 <span style="color:#7fffd4;">zenon</span><span style="color:#ffa07a;">$ </span></pre>
<p><!--- End Of Snippet -->We can see the output from the stream/2 in the console as well. Nice!<br />
The seen implementation was the heaviest part and we have now fulfilled the requirements for</p>
<p>“<em>The output generated by a job should be possible to see in realtime,  through any node and stored to logfiles</em>.”</p>
<p>This is possible with the stream/2 function as it will put the result to whatever iodevice we choose. File or screen. However, there is not yet total proof for</p>
<p>“<em>Several jobs should be queued on the same resource type(s),  being processed one and one in order as they where queued</em>“</p>
<p>We need a method for retrieving the timestamps of each job, proving the order of execution. A test for this will be devised next time. Usually I always supply code listings at the end of each post, and this one would get really long if I did so, as you have already seen the code above.</p>
<p>Therefore, no such listing this time, if it is requested &#8211; I will post it immediately for the requested modules. There are som unseen changes to <em>wn_file_layer.erl </em>since it now uses the <em>wn_util.erl </em>of course, these changes also change <em>wn_file_layer_tests.erl</em>. I leave it as an exercise to figure it out.</p>
<p>The current directory structure is now</p>
<p><!--- Snippet  --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#7fffd4;">zen</span>:<span style="color:#7fffd4;">worker_net</span>-0.1 <span style="color:#7fffd4;">zenon</span><span style="color:#ffa07a;">$ </span><span style="color:#7fffd4;">tree</span> .
.
├── <span style="color:#eedd82;">Makefile</span>
├── <span style="color:#7fffd4;">ebin</span>
├── <span style="color:#7fffd4;">include</span>
│   └── <span style="color:#7fffd4;">worker_net</span>.<span style="color:#7fffd4;">hrl</span>
├── <span style="color:#7fffd4;">src</span>
│   ├── <span style="color:#7fffd4;">wn_file_layer</span>.<span style="color:#7fffd4;">erl</span>
│   ├── <span style="color:#7fffd4;">wn_job_keeper</span>.<span style="color:#7fffd4;">erl</span>
│   ├── <span style="color:#7fffd4;">wn_job_layer</span>.<span style="color:#7fffd4;">erl</span>
│   ├── <span style="color:#7fffd4;">wn_job_worker</span>.<span style="color:#7fffd4;">erl</span>
│   ├── <span style="color:#7fffd4;">wn_resource_layer</span>.<span style="color:#7fffd4;">erl</span>
│   ├── <span style="color:#7fffd4;">wn_resource_process</span>.<span style="color:#7fffd4;">erl</span>
│   └── <span style="color:#7fffd4;">wn_util</span>.<span style="color:#7fffd4;">erl</span>
└── <span style="color:#7fffd4;">test</span>
    ├── <span style="color:#7fffd4;">wn_file_layer_tests</span>.<span style="color:#7fffd4;">erl</span>
    ├── <span style="color:#7fffd4;">wn_job_layer_tests</span>.<span style="color:#7fffd4;">erl</span>
    └── <span style="color:#7fffd4;">wn_resource_layer_tests</span>.<span style="color:#7fffd4;">erl</span></pre>
<p><!--- End Of Snippet --></p>
<p>Cheers<br />
/G</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/erlcode.wordpress.com/495/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/erlcode.wordpress.com/495/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=erlcode.wordpress.com&#038;blog=15510807&#038;post=495&#038;subd=erlcode&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://erlcode.wordpress.com/2011/01/30/erlang-tdd-hands-on-project-%e2%80%93-workernet-part-4/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/861b8f824c3cd15c17ac6aa1b902e029?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">gianfrancoalongi</media:title>
		</media:content>

		<media:content url="http://erlcode.files.wordpress.com/2011/01/conceptual_work_design1.png?w=599" medium="image">
			<media:title type="html">conceptual_work_design</media:title>
		</media:content>

		<media:content url="http://erlcode.files.wordpress.com/2011/01/dirstruct.png" medium="image">
			<media:title type="html">dirstruct</media:title>
		</media:content>
	</item>
		<item>
		<title>Erlang peculiarities</title>
		<link>http://erlcode.wordpress.com/2011/01/18/erlang-peculiarities/</link>
		<comments>http://erlcode.wordpress.com/2011/01/18/erlang-peculiarities/#comments</comments>
		<pubDate>Tue, 18 Jan 2011 21:18:37 +0000</pubDate>
		<dc:creator>gianfrancoalongi</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[gen_server]]></category>
		<category><![CDATA[trap_exit]]></category>

		<guid isPermaLink="false">http://erlcode.wordpress.com/?p=497</guid>
		<description><![CDATA[While working on my WorkerNet post, I stumbled across a weird behaviour with start_links, trap_exit and slave nodes. Long Story (sorry, there is no short one) As I was setting up a distributed test with slaves, I also wanted one gen_server to trap_exit&#8217;s for the offsprings sake which I did not wish to be put [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=erlcode.wordpress.com&#038;blog=15510807&#038;post=497&#038;subd=erlcode&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>While working on my WorkerNet post, I stumbled across a weird behaviour with start_links, trap_exit and slave nodes.</p>
<h2>Long Story (sorry, there is no short one)</h2>
<p>As I was setting up a distributed test with slaves, I also wanted one gen_server to trap_exit&#8217;s for the offsprings sake which I did not wish to be put under a supervisor (shame on me <img src='http://s1.wp.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> , suddenly &#8211; all of the tests stopped working! All of them where either timing out or reporting direct noprocs. Bewildered and wide eyed at 23:40 I gave it a go with the dbg tracer and even went through some of the gen_server source.</p>
<p>No answer.</p>
<p>I chalked it up to the rpc calls for the remote nodes, tried printing out the process numbers in each step. But no &#8211; it was a fact. My gen_servers died the instant they where created&#8230; Brooding over it, I tried some more but finally went to sleep. Up to then, I knew that the problem was caused by the following two snippets in combination with rpc calls to my local slave nodes</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">start_link</span>() -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">start_link</span>({<span style="color:#7fffd4;">local</span>,?<span style="color:#b0c4de;">MODULE</span>},?<span style="color:#b0c4de;">MODULE</span>,[],[]).    

<span style="color:#87cefa;">init</span>([]) -&gt;
    <span style="color:#b0c4de;">process_flag</span>(<span style="color:#7fffd4;">trap_exit</span>,<span style="color:#7fffd4;">true</span>),
    {<span style="color:#7fffd4;">ok</span>, <span style="color:#7fffd4;">ok</span>}.</pre>
<p><!--- End Of Snippet --></p>
<p>While the non trap_exit&#8217;d version worked like a charm. Not wanting to waste more time on it, I just circumvented it like a cheap rug on a very dark and very deep embarrassing hole in the floor with</p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">start_link</span>(<span style="color:#7fffd4;">succeed</span>) -&gt;
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">Pid</span>} = <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">start</span>({<span style="color:#7fffd4;">local</span>, ?<span style="color:#b0c4de;">MODULE</span>}, ?<span style="color:#b0c4de;">MODULE</span>, [], []),
    <span style="color:#b0c4de;">link</span>(<span style="color:#eedd82;">Pid</span>),
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">Pid</span>}.
<span style="color:#87cefa;">init</span>([]) -&gt;
    <span style="color:#b0c4de;">process_flag</span>(<span style="color:#7fffd4;">trap_exit</span>,<span style="color:#7fffd4;">true</span>),
    {<span style="color:#7fffd4;">ok</span>, <span style="color:#7fffd4;">ok</span>}.</pre>
<p>But I couldn&#8217;t leave it at just that. I had to seek help, and so I showed it to my senior colleague <a href="http://charpi.net/blog/">Nicolas</a>, I had then devised a test which would reproduce this neatly. He cut it down a bit, and I boiled it to the broth you see here and can compile and run for yourself.</p>
<p><strong>Just for the record</strong>: The <em>seemingly expected</em> behaviour would be to see the exit signals appear in the handle_info/2 &#8211; not causing the process to crash.</p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">-------------------------------------------------------------------
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@author Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@copyright (C) 2011, Gianfranco
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">Created : 17 Jan 2011 by Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">-------------------------------------------------------------------
</span><span style="color:#b0c4de;">-module</span>(<span style="color:#7fffd4;">test</span>).

<span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">API
</span><span style="color:#b0c4de;">-export</span>([<span style="color:#87cefa;">start_link/1</span>]).
<span style="color:#b0c4de;">-export</span>([<span style="color:#87cefa;">test/1</span>,<span style="color:#87cefa;">init/1</span>,<span style="color:#87cefa;">handle_info/2</span>,<span style="color:#87cefa;">terminate/2</span>]).

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">test</span>(<span style="color:#7fffd4;">fail</span>|<span style="color:#7fffd4;">succeed</span>) -&gt; <span style="color:#98fb98;">term</span>()).
<span style="color:#87cefa;">test</span>(<span style="color:#eedd82;">Mode</span>) -&gt;
    <span style="color:#98fb98;">io</span>:<span style="color:#98fb98;">format</span>(<span style="color:#ffa07a;">"Current 0 ~p~n"</span>,[<span style="color:#b0c4de;">self</span>()]),
    <span style="color:#b0c4de;">spawn</span>(<span style="color:#00ffff;">fun</span>() -&gt; <span style="color:#98fb98;">io</span>:<span style="color:#98fb98;">format</span>(<span style="color:#ffa07a;">"Current 1 ~p~n"</span>,[<span style="color:#b0c4de;">self</span>()]),
                  {<span style="color:#7fffd4;">ok</span>, <span style="color:#eedd82;">_P</span>} = ?<span style="color:#b0c4de;">MODULE</span>:<span style="color:#98fb98;">start_link</span>(<span style="color:#eedd82;">Mode</span>)
          <span style="color:#00ffff;">end</span>).

<span style="color:#87cefa;">start_link</span>(<span style="color:#7fffd4;">fail</span>) -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">start_link</span>({<span style="color:#7fffd4;">local</span>,?<span style="color:#b0c4de;">MODULE</span>},?<span style="color:#b0c4de;">MODULE</span>,[],[]);
<span style="color:#87cefa;">start_link</span>(<span style="color:#7fffd4;">succeed</span>) -&gt;
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">Pid</span>} = <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">start</span>({<span style="color:#7fffd4;">local</span>, ?<span style="color:#b0c4de;">MODULE</span>}, ?<span style="color:#b0c4de;">MODULE</span>, [], []),
    <span style="color:#b0c4de;">link</span>(<span style="color:#eedd82;">Pid</span>),
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">Pid</span>}.    

<span style="color:#87cefa;">init</span>([]) -&gt;
    <span style="color:#b0c4de;">process_flag</span>(<span style="color:#7fffd4;">trap_exit</span>,<span style="color:#7fffd4;">true</span>),
    {<span style="color:#7fffd4;">ok</span>, <span style="color:#7fffd4;">ok</span>}.

<span style="color:#87cefa;">handle_info</span>(<span style="color:#7fffd4;">timeout</span>,<span style="color:#eedd82;">State</span>) -&gt; {<span style="color:#7fffd4;">stop</span>,<span style="color:#7fffd4;">normal</span>,<span style="color:#eedd82;">State</span>};
<span style="color:#87cefa;">handle_info</span>(<span style="color:#eedd82;">_Info</span>, <span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#98fb98;">io</span>:<span style="color:#98fb98;">format</span>(<span style="color:#ffa07a;">"info ~p~n"</span>,[<span style="color:#eedd82;">_Info</span>]),
    {<span style="color:#7fffd4;">noreply</span>, <span style="color:#eedd82;">State</span>,5000}.

<span style="color:#87cefa;">terminate</span>(<span style="color:#eedd82;">_Reason</span>, <span style="color:#eedd82;">_State</span>) -&gt;
    <span style="color:#98fb98;">io</span>:<span style="color:#98fb98;">format</span>(<span style="color:#ffa07a;">"reason ~p~n"</span>,[<span style="color:#eedd82;">_Reason</span>]),
    <span style="color:#7fffd4;">ok</span>.</pre>
<p><!--- End Of Snippet --></p>
<p>Compiling and running we see the expected and unexpected, I chose to call it succeed and fail, based on that the process dies (fails) and succeeds (succeed) in trapping</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#7fffd4;">zen</span>:<span style="color:#eedd82;">Downloads</span> <span style="color:#7fffd4;">zenon</span><span style="color:#ffa07a;">$ </span><span style="color:#7fffd4;">erlc</span> <span style="color:#7fffd4;">test</span>.<span style="color:#7fffd4;">erl</span>
<span style="color:#7fffd4;">zen</span>:<span style="color:#eedd82;">Downloads</span> <span style="color:#7fffd4;">zenon</span><span style="color:#ffa07a;">$ </span><span style="color:#7fffd4;">erl</span>
<span style="color:#eedd82;">Erlang</span> <span style="color:#eedd82;">R14B</span> (<span style="color:#7fffd4;">erts</span>-5.8.1) [<span style="color:#7fffd4;">source</span>] [<span style="color:#7fffd4;">smp</span>:4:4] [<span style="color:#7fffd4;">rq</span>:4] [<span style="color:#7fffd4;">async</span>-<span style="color:#7fffd4;">threads</span>:0] [<span style="color:#7fffd4;">hipe</span>]
[<span style="color:#7fffd4;">kernel</span>-<span style="color:#7fffd4;">poll</span>:<span style="color:#7fffd4;">false</span>]

<span style="color:#eedd82;">Eshell</span> <span style="color:#eedd82;">V5</span>.8.1  (<span style="color:#7fffd4;">abort</span> <span style="color:#7fffd4;">with</span> ^<span style="color:#eedd82;">G</span>)
1&gt; <span style="color:#98fb98;">test</span>:<span style="color:#98fb98;">test</span>(<span style="color:#7fffd4;">fail</span>).
<span style="color:#eedd82;">Current</span> 0 &lt;0.31.0&gt;
<span style="color:#eedd82;">Current</span> 1 &lt;0.33.0&gt;
&lt;0.33.0&gt;
<span style="color:#7fffd4;">reason</span> <span style="color:#7fffd4;">normal</span>
2&gt; <span style="color:#98fb98;">test</span>:<span style="color:#98fb98;">test</span>(<span style="color:#7fffd4;">succeed</span>).
<span style="color:#eedd82;">Current</span> 0 &lt;0.31.0&gt;
<span style="color:#eedd82;">Current</span> 1 &lt;0.36.0&gt;
&lt;0.36.0&gt;
<span style="color:#7fffd4;">info</span> {<span style="color:#7fffd4;">'EXIT'</span>,&lt;0.36.0&gt;,<span style="color:#7fffd4;">normal</span>}
                             (5 seconds later)
<span style="color:#7fffd4;">reason</span> <span style="color:#7fffd4;">normal</span>
3&gt;</pre>
<p><!--- End Of Snippet --></p>
<p>As you see, the process did not die after initialization. It trapped the spawner&#8217;s end.  One possible explanation could be the one stated is in the module  <em>gen_server.erl (read the source Luke!)</em></p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">---------------------------------------------------
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">The idea behind THIS server is that the user module
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">provides (different) functions to handle different
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">kind of inputs.
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">If the Parent process terminates the Module:terminate/2
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">function is called.
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">
</span></pre>
<p><!--- End Of Snippet --></p>
<p>Some more digging into this, Nicolas came with the idea of sys:get_status/1 ing the processes. What was revealed can be seen below! The <strong>parent</strong> of the gen_server:start/1-ed process <strong>is itself</strong>!</p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#eedd82;">Sys</span>:<span style="color:#98fb98;">get_status</span>(&lt;0.37.0&gt;) = {<span style="color:#7fffd4;">status</span>,&lt;0.37.0&gt;,
                               {<span style="color:#7fffd4;">module</span>,<span style="color:#7fffd4;">gen_server</span>},
                               [[{<span style="color:#7fffd4;">'$ancestors'</span>,[&lt;0.36.0&gt;]},
                                 {<span style="color:#7fffd4;">'$initial_call'</span>,{<span style="color:#7fffd4;">test</span>,<span style="color:#7fffd4;">init</span>,1}}],
                                <span style="color:#7fffd4;">running</span>,&lt;0.37.0&gt;,[],
                                [{<span style="color:#7fffd4;">header</span>,<span style="color:#ffa07a;">"Status for generic server test"</span>},
                                 {<span style="color:#7fffd4;">data</span>,
                                     [{<span style="color:#ffa07a;">"Status"</span>,<span style="color:#7fffd4;">running</span>},
                                      {<span style="color:#ffa07a;">"Parent"</span>,&lt;0.37.0&gt;},
                                      {<span style="color:#ffa07a;">"Logged events"</span>,[]}]},
                                 {<span style="color:#7fffd4;">data</span>,[{<span style="color:#ffa07a;">"State"</span>,<span style="color:#7fffd4;">ok</span>}]}]]}</pre>
<p><!--- End Of Snippet -->/G</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/erlcode.wordpress.com/497/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/erlcode.wordpress.com/497/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=erlcode.wordpress.com&#038;blog=15510807&#038;post=497&#038;subd=erlcode&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://erlcode.wordpress.com/2011/01/18/erlang-peculiarities/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/861b8f824c3cd15c17ac6aa1b902e029?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">gianfrancoalongi</media:title>
		</media:content>
	</item>
		<item>
		<title>Erlang TDD hands on project – WorkerNet part 3</title>
		<link>http://erlcode.wordpress.com/2011/01/17/erlang-tdd-hands-on-project-%e2%80%93-workernet-part-3/</link>
		<comments>http://erlcode.wordpress.com/2011/01/17/erlang-tdd-hands-on-project-%e2%80%93-workernet-part-3/#comments</comments>
		<pubDate>Mon, 17 Jan 2011 23:13:49 +0000</pubDate>
		<dc:creator>gianfrancoalongi</dc:creator>
				<category><![CDATA[WorkerNet]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[workernet]]></category>

		<guid isPermaLink="false">http://erlcode.wordpress.com/?p=449</guid>
		<description><![CDATA[The third part will unveil the job layer, the part of the Worker Net &#8220;stack&#8221; that handles the jobs of the network.  Just as before, it is easy to express the functionality through stories. &#8220;I want to be able to describe a job as A set of Files [#wn_file{}] The possible resource types needed (disjunction) [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=erlcode.wordpress.com&#038;blog=15510807&#038;post=449&#038;subd=erlcode&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>The third part will unveil the job layer, the part of the Worker Net &#8220;stack&#8221; that handles the jobs of the network.  Just as before, it is easy to express the functionality through stories.</p>
<p>&#8220;<em>I want to be able to describe a job as</em></p>
<ul>
<li><em>A set of Files [#wn_file{}] </em></li>
<li><em>The possible resource types needed (disjunction)</em></li>
<li><em>A list of commands for running the job </em></li>
<li><em>A timeout the job is given while running (in seconds) </em></li>
<li><em>A job id &#8211; primary key for the job</em><em>&#8220;</em></li>
</ul>
<p>&#8220;<em>I want to be able to register a job in the job layer,  through  any node.</em>&#8220;</p>
<p>&#8220;<em>Several jobs should be queued on the same resource type(s),  being processed one and one in order as they where queued</em>&#8220;</p>
<p>&#8220;<em>A job must be possible to cancel before it starts running, through any node.</em>&#8220;</p>
<p>&#8220;<em>The output generated by a job should be possible to see in realtime,  through any node and stored to logfiles</em>.&#8221;</p>
<p>&#8220;<em>Once a job is done, the result should be stored in the file layer,  together with the logs.</em>&#8220;</p>
<p>&#8220;<em>I want to be able to delete a job once it&#8217;s done, through any node</em>.&#8221;</p>
<p>&#8220;<em>I want to be able to list all jobs in the system, through any node</em>.&#8221;</p>
<p>These tests require a lot more setup than the old ones, as the job layer must be able to transfer, add and delete files. The job layer must also be able to list the available resources. Also, what remains is to design the functionality of the layers involved, I have prepared such a design which can be seen in the picture below</p>
<p><a href="http://erlcode.files.wordpress.com/2011/01/job_layer_design.png"><img class="size-large wp-image-473 aligncenter" title="job_layer_design" src="http://erlcode.files.wordpress.com/2011/01/job_layer_design.png?w=412&#038;h=1024" alt="Job layer design in rough outline" width="412" height="1024" /></a> <a href="http://erlcode.files.wordpress.com/2010/12/job_layer_design.png"></a>The text which is in bold denote certain parts of interest that need fleshing out or be considered some extra times. The parts which require some more consideration are</p>
<ul>
<li>The requirements for the resource process</li>
<li>How is the job process going to aquire the Pid of all the resource processes?</li>
<li>How is the negotiation going to be implemented? (timeouts etc)</li>
<li>How will the job be executed?</li>
</ul>
<p>Once these parts are answered, wer&#8217;e almost done! And since we are doing TDD here, we are expecting answers in the form of tests. As first thing, add a new line to the Makefile for testing the job_layer</p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">all</span>:
      erlc -pa . -o ebin/  src/*.erl test/*.erl

<span style="color:#87cefa;">test</span>:  all
      erl -pa ebin/ -eval <span style="color:#ffa07a;">'eunit:test(wn_resource_layer,[verbose]), init:stop().'</span>
      erl -pa ebin/ -eval <span style="color:#ffa07a;">'eunit:test(wn_file_layer,[verbose]), init:stop().'</span>
      erl -pa ebin/ -eval <span style="color:#ffa07a;">'eunit:test(wn_job_layer,[verbose]), init:stop().'</span>  

<span style="color:#87cefa;">dialyze</span>:
      dialyzer src/*.erl test/*.erl

<span style="color:#87cefa;">full</span>: all test dialyze</pre>
<p><!--- End Of Snippet -->Pick the low hanging fruit first, so, a test with registration of a job and listing of the job, should be nice.</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@author Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@copyright (C) 2010, Gianfranco
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">Created : 26 Dec 2010 by Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#b0c4de;">-module</span>(<span style="color:#7fffd4;">wn_job_layer_tests</span>).
<span style="color:#b0c4de;">-include_lib</span>(<span style="color:#ffa07a;">"eunit/include/eunit.hrl"</span>).
<span style="color:#b0c4de;">-include</span>(<span style="color:#ffa07a;">"include/worker_net.hrl"</span>).
<span style="color:#b0c4de;">-define</span>(<span style="color:#b0c4de;">NODE_ROOT</span>,
        <span style="color:#ffa07a;">"/Users/zenon/ErlangBlog/worker_net-0.1/node_root/"</span>).

<span style="color:#87cefa;">local_test_</span>() -&gt;
    {<span style="color:#7fffd4;">foreach</span>,
     <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">setup/0</span>,
     <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">cleanup/1</span>,
     [
      {<span style="color:#ffa07a;">"Can register locally"</span>, <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">register_locally/0</span>}
      ]}.

<span style="color:#87cefa;">register_locally</span>() -&gt;
    <span style="color:#eedd82;">Path</span> = <span style="color:#98fb98;">create_file_at</span>(?<span style="color:#b0c4de;">NODE_ROOT</span>),
    <span style="color:#eedd82;">File1</span> = #<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"File1"</span>,<span style="color:#7fffd4;">file</span> = <span style="color:#eedd82;">Path</span>,<span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()},
    <span style="color:#eedd82;">File2</span> = #<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"File2"</span>,<span style="color:#7fffd4;">file</span> = <span style="color:#eedd82;">Path</span>,<span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()},
    <span style="color:#eedd82;">Job</span> = #<span style="color:#b0c4de;">wn_job</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"JobId"</span>,
                  <span style="color:#7fffd4;">files</span> = [<span style="color:#eedd82;">File1</span>,<span style="color:#eedd82;">File2</span>],
                  <span style="color:#7fffd4;">resources</span> = [<span style="color:#7fffd4;">'non-existent'</span>],
                  <span style="color:#7fffd4;">commands</span> = [<span style="color:#ffa07a;">"ls -l"</span>]
                 },
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">Job</span>)),
    [<span style="color:#eedd82;">Res</span>] = <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">list_all_jobs</span>(),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#ffa07a;">"JobId"</span>,<span style="color:#eedd82;">Res</span>#<span style="color:#b0c4de;">wn_job</span>.<span style="color:#7fffd4;">id</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#7fffd4;">'non-existent'</span>],<span style="color:#eedd82;">Res</span>#<span style="color:#b0c4de;">wn_job</span>.<span style="color:#7fffd4;">resources</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">File1</span>,<span style="color:#eedd82;">File2</span>],<span style="color:#eedd82;">Res</span>#<span style="color:#b0c4de;">wn_job</span>.<span style="color:#7fffd4;">files</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#ffa07a;">"ls -l"</span>],<span style="color:#eedd82;">Res</span>#<span style="color:#b0c4de;">wn_job</span>.<span style="color:#7fffd4;">commands</span>).

<span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">-----------------------------------------------------------------
</span><span style="color:#87cefa;">setup</span>() -&gt;
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>} = <span style="color:#98fb98;">net_kernel</span>:<span style="color:#98fb98;">start</span>([<span style="color:#7fffd4;">eunit_resource</span>,<span style="color:#7fffd4;">shortnames</span>]),
    <span style="color:#98fb98;">erlang</span>:<span style="color:#98fb98;">set_cookie</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#7fffd4;">eunit</span>),
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>} = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">start_link</span>(?<span style="color:#b0c4de;">NODE_ROOT</span>),
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>} = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">start_link</span>(),
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>} = <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">start_link</span>(),
    <span style="color:#7fffd4;">ok</span>.

<span style="color:#87cefa;">cleanup</span>(<span style="color:#eedd82;">_</span>) -&gt;
    <span style="color:#98fb98;">clean_up</span>(?<span style="color:#b0c4de;">NODE_ROOT</span>),
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">net_kernel</span>:<span style="color:#98fb98;">stop</span>(),
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">stop</span>(),
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">stop</span>(),
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_job_layer</span>:<span style="color:#98fb98;">stop</span>().

<span style="color:#87cefa;">create_file_at</span>(<span style="color:#eedd82;">X</span>) -&gt;
    <span style="color:#eedd82;">Path</span> = <span style="color:#eedd82;">X</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"EUnitFile"</span>,
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">ensure_dir</span>(<span style="color:#eedd82;">X</span>),
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">write_file</span>(<span style="color:#eedd82;">Path</span>,&lt;&lt;1,2,3&gt;&gt;),
    <span style="color:#eedd82;">Path</span>.

<span style="color:#87cefa;">clean_up</span>(<span style="color:#eedd82;">X</span>) -&gt;
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_dir</span>(<span style="color:#eedd82;">X</span>) <span style="color:#00ffff;">of</span>
        <span style="color:#7fffd4;">true</span> -&gt;
            {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">Files</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">list_dir</span>(<span style="color:#eedd82;">X</span>),
            <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foreach</span>(
              <span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">File</span>) -&gt;
                      <span style="color:#98fb98;">clean_up</span>(<span style="color:#eedd82;">X</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">File</span>)
              <span style="color:#00ffff;">end</span>,<span style="color:#eedd82;">Files</span>),
            <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">del_dir</span>(<span style="color:#eedd82;">X</span>);
        <span style="color:#7fffd4;">false</span> -&gt;
            <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">X</span>)
    <span style="color:#00ffff;">end</span>.</pre>
<p><!--- End Of Snippet -->This first test is quite basic and shows how a job has files that may be located on any node, a job id (JID) and a list of resource types (disjunction).  To make this test pass, we need to start implementing the record type. So the new entry in worker_net.hrl is</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-record</span>(<span style="color:#b0c4de;">wn_job</span>,
        {<span style="color:#7fffd4;">id</span> :: <span style="color:#98fb98;">string</span>(),
         <span style="color:#7fffd4;">files</span> :: [#<span style="color:#b0c4de;">wn_file</span>{}],
         <span style="color:#7fffd4;">resources</span> :: [<span style="color:#b0c4de;">atom</span>()],
         <span style="color:#7fffd4;">commands</span> :: [<span style="color:#98fb98;">string</span>()]
         }).</pre>
<p><!--- End Of Snippet -->Next, the actual logic module needs to be implemented, it seems like gen_server fits the bill quite nicely here for the job_layer. For each part, it is good practice to make it as simple as possible, &#8220;you ain&#8217;t gonna need it&#8221; (YAGNI) is a good thing to remember. Without further ado, the implementation that passes the first test, of denoting and registering a job through any node. Take note that two new modules had to be introduced</p>
<ul>
<li><em>wn_job_keeper.erl</em> the job process started by the job_layer, sends the pid to the appropriate resource processes. Started after registration.</li>
<li>wn_resource_process.erl the resource process started whenever a new resource is registered</li>
</ul>
<p>As the design requires a resource process to be started for each newly registered process, we need to test the new functionality. The side effect of registering a new resource must be checked. So first out, the modifications to the wn_resource record</p>
<p><!-- End Of Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-record</span>(<span style="color:#b0c4de;">wn_resource</span>,
        {<span style="color:#7fffd4;">name</span> :: <span style="color:#98fb98;">string</span>(),
         <span style="color:#7fffd4;">type</span> :: [{<span style="color:#b0c4de;">atom</span>(), <span style="color:#98fb98;">non_neg_integer</span>() | <span style="color:#7fffd4;">infinity</span>}],
         <span style="color:#7fffd4;">resides</span> :: <span style="color:#b0c4de;">node</span>(),
         <span style="color:#7fffd4;">pid</span> :: <span style="color:#b0c4de;">pid</span>()
        }).</pre>
<p><!--- Snippet -->as well as the modification to the existing tests in the <em>wn_resource_layer_tests.erl</em> module</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">resource_processes_are_alive</span>([],<span style="color:#eedd82;">_</span>) -&gt; <span style="color:#7fffd4;">ok</span>;
<span style="color:#87cefa;">resource_processes_are_alive</span>([<span style="color:#eedd82;">Expected</span>|<span style="color:#eedd82;">Tail</span>],<span style="color:#eedd82;">List</span>) -&gt;
    #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#eedd82;">Name</span>, <span style="color:#7fffd4;">type</span> = <span style="color:#eedd82;">Type</span>, <span style="color:#7fffd4;">resides</span> = <span style="color:#eedd82;">Resides</span>} = <span style="color:#eedd82;">Expected</span>,
    <span style="color:#eedd82;">Filtered</span> =
        <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">filter</span>(
           <span style="color:#00ffff;">fun</span>(#<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span>=<span style="color:#eedd82;">N</span>,<span style="color:#7fffd4;">type</span>=<span style="color:#eedd82;">T</span>,<span style="color:#7fffd4;">resides</span>=<span style="color:#eedd82;">R</span>}) -&gt;
                   <span style="color:#eedd82;">N</span> == <span style="color:#eedd82;">Name</span> <span style="color:#00ffff;">andalso</span> <span style="color:#eedd82;">T</span> == <span style="color:#eedd82;">Type</span> <span style="color:#00ffff;">andalso</span> <span style="color:#eedd82;">R</span> == <span style="color:#eedd82;">Resides</span>
           <span style="color:#00ffff;">end</span>,<span style="color:#eedd82;">List</span>),
    ?<span style="color:#b0c4de;">assertMatch</span>([<span style="color:#eedd82;">_X</span>],<span style="color:#eedd82;">Filtered</span>),
    [<span style="color:#eedd82;">T</span>] = <span style="color:#eedd82;">Filtered</span>,
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">true</span>,<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#b0c4de;">node</span>(<span style="color:#eedd82;">T</span>#<span style="color:#b0c4de;">wn_resource</span>.<span style="color:#7fffd4;">pid</span>),<span style="color:#7fffd4;">erlang</span>,<span style="color:#7fffd4;">is_process_alive</span>,
                               [<span style="color:#eedd82;">T</span>#<span style="color:#b0c4de;">wn_resource</span>.<span style="color:#7fffd4;">pid</span>])),
    <span style="color:#98fb98;">resource_processes_are_alive</span>(<span style="color:#eedd82;">Tail</span>,<span style="color:#eedd82;">List</span>).</pre>
<p><!--- End Of Snippet -->The function resource_processes_are_alive/2 was added to each test in appropriate places where a resource is registered.  Once this modification was made, the change was imposed on the<em> wn_resource_layer.erl</em> module. The changes are shown with the %% Change comment</p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">try_deregister</span>(<span style="color:#eedd82;">State</span>,<span style="color:#eedd82;">Name</span>) -&gt;
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">lookup</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">resources</span>,<span style="color:#eedd82;">Name</span>) <span style="color:#00ffff;">of</span>
        [] -&gt; {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">noexists</span>};
        <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">Changed
</span>        [{<span style="color:#eedd82;">Name</span>,<span style="color:#eedd82;">WnResource</span>}] -&gt;
            <span style="color:#b0c4de;">exit</span>(<span style="color:#eedd82;">WnResource</span>#<span style="color:#b0c4de;">wn_resource</span>.<span style="color:#7fffd4;">pid</span>,<span style="color:#7fffd4;">deregistered</span>),
            <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">resources</span>,<span style="color:#eedd82;">Name</span>),
            <span style="color:#7fffd4;">ok</span>
    <span style="color:#00ffff;">end</span>.

<span style="color:#87cefa;">try_register</span>(<span style="color:#eedd82;">State</span>,<span style="color:#eedd82;">Resource</span>) -&gt;
    #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span>=<span style="color:#eedd82;">Name</span>} = <span style="color:#eedd82;">Resource</span>,
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">lookup</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">resources</span>,<span style="color:#eedd82;">Name</span>) <span style="color:#00ffff;">of</span>
        [] -&gt;
            <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">Changed
</span>            <span style="color:#eedd82;">Pid</span> = <span style="color:#98fb98;">wn_resource_process</span>:<span style="color:#98fb98;">start</span>(),
            <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">insert</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">resources</span>,
                       {<span style="color:#eedd82;">Name</span>,<span style="color:#eedd82;">Resource</span>#<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">pid</span>=<span style="color:#eedd82;">Pid</span>}}),
            <span style="color:#7fffd4;">ok</span>;
        <span style="color:#eedd82;">_</span> -&gt;
            {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">already_exists</span>}
    <span style="color:#00ffff;">end</span>.</pre>
<p><!--- End Of Snippet -->Of course, the minimal new module <em>wn_resource_process.erl</em> is shown</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">-------------------------------------------------------------------
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@author Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@copyright (C) 2011, Gianfranco
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">Created : 11 Jan 2011 by Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">-------------------------------------------------------------------
</span><span style="color:#b0c4de;">-module</span>(<span style="color:#7fffd4;">wn_resource_process</span>).
<span style="color:#b0c4de;">-export</span>([<span style="color:#87cefa;">start/0</span>, <span style="color:#87cefa;">init/1</span>]).

<span style="color:#87cefa;">start</span>() -&gt; <span style="color:#b0c4de;">spawn</span>(<span style="color:#7fffd4;">wn_resource_process</span>, <span style="color:#7fffd4;">init</span>, [<span style="color:#7fffd4;">free</span>]).

<span style="color:#87cefa;">init</span>(<span style="color:#eedd82;">X</span>) -&gt;
    <span style="color:#98fb98;">loop</span>(<span style="color:#eedd82;">X</span>).

<span style="color:#87cefa;">loop</span>(<span style="color:#eedd82;">X</span>) -&gt;
    <span style="color:#00ffff;">receive</span>
        <span style="color:#eedd82;">_</span> -&gt; <span style="color:#7fffd4;">ok</span>
    <span style="color:#00ffff;">end</span>
    <span style="color:#98fb98;">loop</span>(<span style="color:#eedd82;">X</span>).</pre>
<p><!--- End Of Snippet -->Even though the module is trivial, it is all that is needed for the moment. Keep it simple. Now the job_layer implementation that will make the test pass (and a bit more)</p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">-------------------------------------------------------------------
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@author Gianfranco &lt;<a href="mailto:zenon@zen.home">zenon@zen.home</a>&gt;
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@copyright (C) 2011, Gianfranco
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">Created :  4 Jan 2011 by Gianfranco &lt;<a href="mailto:zenon@zen.home">zenon@zen.home</a>&gt;
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">-------------------------------------------------------------------
</span><span style="color:#b0c4de;">-module</span>(<span style="color:#7fffd4;">wn_job_layer</span>).
<span style="color:#b0c4de;">-behaviour</span>(<span style="color:#7fffd4;">gen_server</span>).
<span style="color:#b0c4de;">-include</span>(<span style="color:#ffa07a;">"include/worker_net.hrl"</span>).

<span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">API
</span><span style="color:#b0c4de;">-export</span>([<span style="color:#87cefa;">start_link/0</span>,<span style="color:#87cefa;">register/1</span>,<span style="color:#87cefa;">list_all_jobs/0</span>,
        <span style="color:#87cefa;">stop/0</span>]).

<span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">gen_server callbacks
</span><span style="color:#b0c4de;">-export</span>([<span style="color:#87cefa;">init/1</span>, <span style="color:#87cefa;">handle_call/3</span>, <span style="color:#87cefa;">handle_cast/2</span>, <span style="color:#87cefa;">handle_info/2</span>,
         <span style="color:#87cefa;">terminate/2</span>, <span style="color:#87cefa;">code_change/3</span>]).

<span style="color:#b0c4de;">-record</span>(<span style="color:#b0c4de;">state</span>, {<span style="color:#7fffd4;">jobs</span> <span style="color:#ff7f24;">% </span><span style="color:#ff7f24;">ets table {Name,Pid,WnJob}
</span>             }).

<span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">==========================================================
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">API
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">==========================================================
</span><span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">start_link</span>() -&gt; {<span style="color:#7fffd4;">ok</span>,<span style="color:#b0c4de;">pid</span>()} | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).
<span style="color:#87cefa;">start_link</span>() -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">start_link</span>({<span style="color:#7fffd4;">local</span>, ?<span style="color:#b0c4de;">MODULE</span>}, ?<span style="color:#b0c4de;">MODULE</span>, [], []).

<span style="color:#b0c4de;">-spec</span>(<span style="color:#b0c4de;">register</span>(#<span style="color:#b0c4de;">wn_job</span>{}) -&gt; <span style="color:#7fffd4;">ok</span> | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).
<span style="color:#87cefa;">register</span>(<span style="color:#eedd82;">WnJob</span>) -&gt;
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">try_send_files</span>(<span style="color:#eedd82;">WnJob</span>#<span style="color:#b0c4de;">wn_job</span>.<span style="color:#7fffd4;">files</span>) <span style="color:#00ffff;">of</span>
        <span style="color:#7fffd4;">ok</span> -&gt; <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,{<span style="color:#7fffd4;">add_job</span>,<span style="color:#eedd82;">WnJob</span>});
        <span style="color:#eedd82;">E</span> -&gt; <span style="color:#eedd82;">E</span>
    <span style="color:#00ffff;">end</span>.

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">list_all_jobs</span>() -&gt; [#<span style="color:#b0c4de;">wn_job</span>{}]).
<span style="color:#87cefa;">list_all_jobs</span>() -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#7fffd4;">list_all_jobs</span>).

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">stop</span>() -&gt; <span style="color:#7fffd4;">ok</span>).
<span style="color:#87cefa;">stop</span>() -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#7fffd4;">stop</span>).

<span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">==========================================================
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">gen_server callbacks
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">==========================================================
</span><span style="color:#87cefa;">init</span>([]) -&gt;
    {<span style="color:#7fffd4;">ok</span>, #<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">jobs</span> = <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">new</span>(<span style="color:#7fffd4;">jobs_table</span>,[<span style="color:#7fffd4;">set</span>])}}.

<span style="color:#87cefa;">handle_cast</span>(<span style="color:#eedd82;">_Msg</span>,<span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>}.

<span style="color:#87cefa;">handle_call</span>(<span style="color:#7fffd4;">stop</span>,<span style="color:#eedd82;">_From</span>,<span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">stop</span>,<span style="color:#7fffd4;">normal</span>,<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">State</span>};

<span style="color:#87cefa;">handle_call</span>(<span style="color:#7fffd4;">list_all_jobs</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#b0c4de;">spawn_link</span>(<span style="color:#98fb98;">job_collector</span>(<span style="color:#eedd82;">From</span>)),
    {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>};

<span style="color:#87cefa;">handle_call</span>(<span style="color:#7fffd4;">list_jobs</span>,<span style="color:#eedd82;">_From</span>,<span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">reply</span>,[<span style="color:#eedd82;">WnJob</span> <span style="color:#00ffff;">||</span> {<span style="color:#eedd82;">_</span>,<span style="color:#eedd82;">_</span>,<span style="color:#eedd82;">WnJob</span>} <span style="color:#00ffff;">&lt;-</span> <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">tab2list</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">jobs</span>)],<span style="color:#eedd82;">State</span>};

<span style="color:#87cefa;">handle_call</span>({<span style="color:#7fffd4;">add_job</span>,<span style="color:#eedd82;">WnJob</span>}, <span style="color:#eedd82;">_From</span>, <span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#eedd82;">JobId</span> = <span style="color:#eedd82;">WnJob</span>#<span style="color:#b0c4de;">wn_job</span>.<span style="color:#7fffd4;">id</span>,
    {<span style="color:#7fffd4;">reply</span>,
     <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">lookup</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">jobs</span>,<span style="color:#eedd82;">JobId</span>) <span style="color:#00ffff;">of</span>
         [] -&gt; <span style="color:#eedd82;">Pid</span> = <span style="color:#98fb98;">wn_job_keeper</span>:<span style="color:#98fb98;">start_link</span>(<span style="color:#eedd82;">WnJob</span>),
               <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">insert</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">jobs</span>,{<span style="color:#eedd82;">JobId</span>,<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">WnJob</span>}),
               <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foreach</span>(
                 <span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">WnResource</span>)  -&gt;
                         <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">resource_is_sufficient</span>(<span style="color:#eedd82;">WnJob</span>,<span style="color:#eedd82;">WnResource</span>) <span style="color:#00ffff;">of</span>
                             <span style="color:#7fffd4;">true</span> -&gt; <span style="color:#98fb98;">signal_resource</span>(<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">WnResource</span>);
                             <span style="color:#7fffd4;">false</span> -&gt; <span style="color:#7fffd4;">ignore</span>
                         <span style="color:#00ffff;">end</span>
                 <span style="color:#00ffff;">end</span>,<span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">list_resources</span>()),
               <span style="color:#7fffd4;">ok</span>;
         [<span style="color:#eedd82;">_</span>] -&gt;
             <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foreach</span>(
               <span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">File</span>) -&gt;
                       <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">delete_file</span>(<span style="color:#eedd82;">File</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">resides</span>,
                                                 <span style="color:#eedd82;">File</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">id</span>)
               <span style="color:#00ffff;">end</span>,<span style="color:#eedd82;">WnJob</span>#<span style="color:#b0c4de;">wn_job</span>.<span style="color:#7fffd4;">files</span>),
             {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">already_exists</span>}
     <span style="color:#00ffff;">end</span>, <span style="color:#eedd82;">State</span>}.

<span style="color:#87cefa;">handle_info</span>(<span style="color:#eedd82;">_Info</span>, <span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">noreply</span>, <span style="color:#eedd82;">State</span>}.

<span style="color:#87cefa;">terminate</span>(<span style="color:#eedd82;">_Reason</span>, <span style="color:#eedd82;">_State</span>) -&gt;
    <span style="color:#7fffd4;">ok</span>.

<span style="color:#87cefa;">code_change</span>(<span style="color:#eedd82;">_OldVsn</span>, <span style="color:#eedd82;">State</span>, <span style="color:#eedd82;">_Extra</span>) -&gt;
    {<span style="color:#7fffd4;">ok</span>, <span style="color:#eedd82;">State</span>}.

<span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">==========================================================
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">Internal functions
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">==========================================================
</span><span style="color:#87cefa;">try_send_files</span>([<span style="color:#eedd82;">F</span>|<span style="color:#eedd82;">R</span>]) -&gt;
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">add_file</span>(<span style="color:#eedd82;">F</span>) <span style="color:#00ffff;">of</span>
        <span style="color:#7fffd4;">ok</span> -&gt; <span style="color:#98fb98;">try_send_files</span>(<span style="color:#eedd82;">R</span>);
        <span style="color:#eedd82;">E</span> -&gt; <span style="color:#eedd82;">E</span>
    <span style="color:#00ffff;">end</span>;
<span style="color:#87cefa;">try_send_files</span>([]) -&gt; <span style="color:#7fffd4;">ok</span>.

<span style="color:#87cefa;">resource_is_sufficient</span>(<span style="color:#eedd82;">WnJob</span>,<span style="color:#eedd82;">WnResource</span>) -&gt;
    <span style="color:#eedd82;">JobResourceType</span> = <span style="color:#eedd82;">WnJob</span>#<span style="color:#b0c4de;">wn_job</span>.<span style="color:#7fffd4;">resources</span>,
    <span style="color:#eedd82;">ResourceTypes</span> = [ <span style="color:#eedd82;">T</span> <span style="color:#00ffff;">||</span> {<span style="color:#eedd82;">T</span>,<span style="color:#eedd82;">_</span>} <span style="color:#00ffff;">&lt;-</span> <span style="color:#eedd82;">WnResource</span>#<span style="color:#b0c4de;">wn_resource</span>.<span style="color:#7fffd4;">type</span>],
    <span style="color:#98fb98;">at_least_one</span>(<span style="color:#eedd82;">JobResourceType</span>,<span style="color:#eedd82;">ResourceTypes</span>).

<span style="color:#87cefa;">at_least_one</span>([],<span style="color:#eedd82;">_</span>) -&gt; <span style="color:#7fffd4;">false</span>;
<span style="color:#87cefa;">at_least_one</span>([<span style="color:#eedd82;">X</span>|<span style="color:#eedd82;">R</span>],<span style="color:#eedd82;">T</span>) -&gt;
    <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">member</span>(<span style="color:#eedd82;">X</span>,<span style="color:#eedd82;">T</span>) <span style="color:#00ffff;">orelse</span> <span style="color:#98fb98;">at_least_one</span>(<span style="color:#eedd82;">R</span>,<span style="color:#eedd82;">T</span>).

<span style="color:#87cefa;">signal_resource</span>(<span style="color:#eedd82;">JobKeeperPid</span>,<span style="color:#eedd82;">WnResource</span>) -&gt;
    <span style="color:#eedd82;">WnResource</span>#<span style="color:#b0c4de;">wn_resource</span>.<span style="color:#7fffd4;">pid</span> ! <span style="color:#eedd82;">JobKeeperPid</span>.

<span style="color:#87cefa;">job_collector</span>(<span style="color:#eedd82;">From</span>) -&gt;
    <span style="color:#eedd82;">Nodes</span> = [<span style="color:#b0c4de;">node</span>()|<span style="color:#b0c4de;">nodes</span>()],
    <span style="color:#00ffff;">fun</span>() -&gt;
            <span style="color:#eedd82;">Res</span> =
                <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foldr</span>(
                  <span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Acc</span>) -&gt;
                          <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#7fffd4;">erlang</span>,<span style="color:#7fffd4;">whereis</span>,[?<span style="color:#b0c4de;">MODULE</span>]) <span style="color:#00ffff;">of</span>
                              <span style="color:#7fffd4;">undefined</span> -&gt; <span style="color:#eedd82;">Acc</span>;
                              <span style="color:#eedd82;">_Pid</span> -&gt;
                                  <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>({?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#eedd82;">Node</span>},
                                                  <span style="color:#7fffd4;">list_jobs</span>)<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">Acc</span>
                          <span style="color:#00ffff;">end</span>
                  <span style="color:#00ffff;">end</span>,[],<span style="color:#eedd82;">Nodes</span>),
            <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">reply</span>(<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Res</span>)
    <span style="color:#00ffff;">end</span>.</pre>
<p><!--- End Of Snippet --></p>
<p>This implementation also causes us to add a new component module, the <em>wn_job_keeper.erl. </em>Likewise, this is a minimal module which will just trigger a process to start.</p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">-------------------------------------------------------------------
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@author Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@copyright (C) 2011, Gianfranco
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">Created : 13 Jan 2011 by Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">-------------------------------------------------------------------
</span><span style="color:#b0c4de;">-module</span>(<span style="color:#7fffd4;">wn_job_keeper</span>).
<span style="color:#b0c4de;">-export</span>([<span style="color:#87cefa;">start_link/1</span>, <span style="color:#87cefa;">init/1</span>]).
<span style="color:#b0c4de;">-include</span>(<span style="color:#ffa07a;">"include/worker_net.hrl"</span>).

<span style="color:#87cefa;">start_link</span>(<span style="color:#eedd82;">WnJob</span>) -&gt;
    <span style="color:#b0c4de;">spawn_link</span>(<span style="color:#7fffd4;">wn_job_keeper</span>, <span style="color:#7fffd4;">init</span>, [<span style="color:#eedd82;">WnJob</span>]).

<span style="color:#87cefa;">init</span>(<span style="color:#eedd82;">WnJob</span>) -&gt;
    <span style="color:#98fb98;">loop</span>(<span style="color:#eedd82;">WnJob</span>).

<span style="color:#87cefa;">loop</span>(<span style="color:#eedd82;">WnJob</span>) -&gt;
    <span style="color:#00ffff;">receive</span>
        <span style="color:#eedd82;">_</span> -&gt;
            <span style="color:#98fb98;">loop</span>(<span style="color:#eedd82;">WnJob</span>)
    <span style="color:#00ffff;">end</span>.</pre>
<p><!--- End Of Snippet --></p>
<p>Now, with a base implementation that almost fullfils the first story,</p>
<p>“<em>I want to be able to describe a job as</em></p>
<ul>
<li><em>A set of Files [#wn_file{}]</em></li>
<li><em>The possible resource types needed (disjunction)</em></li>
<li><em>A list of commands for running the job</em></li>
<li><em>A timeout the job is given while running (in seconds)</em></li>
<li><em>A job id – primary key for the job</em><em>“</em></li>
</ul>
<p>we can try making a test design for the job execution, and adding the timeout field for the record, but that will be handled in the next post &#8211; otherwise this post will get gigantic and never be posted as I&#8217;ve had a lot of other stuff to do the previous weeks.</p>
<p>Cheers<br />
/G</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/erlcode.wordpress.com/449/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/erlcode.wordpress.com/449/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=erlcode.wordpress.com&#038;blog=15510807&#038;post=449&#038;subd=erlcode&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://erlcode.wordpress.com/2011/01/17/erlang-tdd-hands-on-project-%e2%80%93-workernet-part-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/861b8f824c3cd15c17ac6aa1b902e029?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">gianfrancoalongi</media:title>
		</media:content>

		<media:content url="http://erlcode.files.wordpress.com/2011/01/job_layer_design.png?w=412" medium="image">
			<media:title type="html">job_layer_design</media:title>
		</media:content>
	</item>
		<item>
		<title>Erlang TDD hands on project &#8211; WorkerNet part 2</title>
		<link>http://erlcode.wordpress.com/2010/12/25/erlang-tdd-hands-on-project-workernet-part-2/</link>
		<comments>http://erlcode.wordpress.com/2010/12/25/erlang-tdd-hands-on-project-workernet-part-2/#comments</comments>
		<pubDate>Sat, 25 Dec 2010 23:28:28 +0000</pubDate>
		<dc:creator>gianfrancoalongi</dc:creator>
				<category><![CDATA[WorkerNet]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[workernet]]></category>

		<guid isPermaLink="false">http://erlcode.wordpress.com/?p=417</guid>
		<description><![CDATA[This part will focus on the file layer, the layer responsible for file storage and file retrieval.  I will once again express the desired functionality as so called stories, each story should capture the intent of the functionality without being to technical. &#8220;I want to be able to store a file in the file layer, [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=erlcode.wordpress.com&#038;blog=15510807&#038;post=417&#038;subd=erlcode&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>This part will focus on the file layer, the layer responsible for file storage and file retrieval.  I will once again express the desired functionality as so called stories, each story should capture the intent of the functionality without being to technical.</p>
<p><em>&#8220;I want to be able to store a file in the file layer, through any node&#8221;</em></p>
<p><em>&#8220;I want to be able to retrieve a file from the file layer, through any node&#8221;</em></p>
<p><em>&#8220;I want to be able to delete a file from the file layer, through any node&#8221;</em></p>
<p><em>&#8220;I want to be able to get a list of all files in the file layer, through any node&#8221;</em></p>
<p><em>&#8220;I want the file layer to be persistent, should a node fail and be restarted, it should keep the files previously stored at it&#8217;s location&#8221;</em></p>
<p>The adopted approach will be similar to the one found in the resource layer, which will make the tests a bit similar. However, the file layer will have configuration parameters which will be read from the workernet application variables.</p>
<p>What needs to be defined is mainly how the file storage should operate, inside this lies the questions of <em>how</em> the files should be named and stored at the local node. Arguably, storing stuff under the node-name is a good place to start.</p>
<h2>Design decision: On-disk storage of file layer</h2>
<p>There will be a file_layer_root value which will point to a directory on disk in which the node can create a directory $NODE_root/ where $NODE is the name of the node. Also, subfolders are to be named based on $UPLOAD_ID, the user-chosen upload for their file on upload.</p>
<p>Now time for the first test in for the file layer.</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@author Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@copyright (C) 2010, Gianfranco
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">Created : 19 Dec 2010 by Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#b0c4de;">-module</span>(<span style="color:#7fffd4;">wn_file_layer_tests</span>).
<span style="color:#b0c4de;">-include_lib</span>(<span style="color:#ffa07a;">"eunit/include/eunit.hrl"</span>).
<span style="color:#b0c4de;">-include</span>(<span style="color:#ffa07a;">"include/worker_net.hrl"</span>).

<span style="color:#b0c4de;">-define</span>(<span style="color:#b0c4de;">NODE_ROOT</span>,
        <span style="color:#ffa07a;">"/Users/zenon/ErlangBlog/worker_net-0.1/node_root/"</span>).

<span style="color:#87cefa;">file_layer_local_test_</span>() -&gt;
    {<span style="color:#7fffd4;">foreach</span>,
     <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">setup/0</span>,
     <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">cleanup/1</span>,
     [
      {<span style="color:#ffa07a;">"Can store file locally"</span>, <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">store_locally/0</span>}
      ]}.

<span style="color:#87cefa;">store_locally</span>() -&gt;
    <span style="color:#eedd82;">Path</span> = <span style="color:#98fb98;">create_file_at</span>(?<span style="color:#b0c4de;">NODE_ROOT</span>),
    <span style="color:#eedd82;">Id</span> = <span style="color:#ffa07a;">"AddedFile1"</span>,
    <span style="color:#eedd82;">File</span> = #<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#eedd82;">Id</span>,<span style="color:#7fffd4;">file</span> = <span style="color:#eedd82;">Path</span>,<span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()},
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">add_file</span>(<span style="color:#eedd82;">File</span>),
    [<span style="color:#eedd82;">Res</span>] = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">list_files</span>(),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Path</span>),<span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Res</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">file</span>)),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">Res</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">id</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#eedd82;">Res</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">resides</span>),
    <span style="color:#ff7f24;">% </span><span style="color:#ff7f24;">Check change in file-system
</span>    <span style="color:#eedd82;">ExpectedPath</span> = ?<span style="color:#b0c4de;">NODE_ROOT</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#b0c4de;">atom_to_list</span>(<span style="color:#b0c4de;">node</span>())<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span>
        <span style="color:#eedd82;">Id</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Path</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">true</span>,<span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_file</span>(<span style="color:#eedd82;">Path</span>)),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">true</span>,<span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_file</span>(<span style="color:#eedd82;">ExpectedPath</span>)).
<span style="color:#ff7f24;">%%</span><span style="color:#ff7f24;">------------------------------------------------------------------
</span><span style="color:#87cefa;">create_file_at</span>(<span style="color:#eedd82;">X</span>) -&gt;
    <span style="color:#eedd82;">Path</span> = <span style="color:#eedd82;">X</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"EUnitFile"</span>,
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">ensure_dir</span>(<span style="color:#eedd82;">X</span>),
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">write_file</span>(<span style="color:#eedd82;">Path</span>,&lt;&lt;1,2,3&gt;&gt;),
    <span style="color:#eedd82;">Path</span>.

<span style="color:#87cefa;">clean_up</span>(<span style="color:#eedd82;">X</span>) -&gt;
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_dir</span>(<span style="color:#eedd82;">X</span>) <span style="color:#00ffff;">of</span>
        <span style="color:#7fffd4;">true</span> -&gt;
            {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">Files</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">list_dir</span>(<span style="color:#eedd82;">X</span>),
            <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foreach</span>(
              <span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">File</span>) -&gt;
                      <span style="color:#98fb98;">clean_up</span>(<span style="color:#eedd82;">X</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">File</span>)
              <span style="color:#00ffff;">end</span>,<span style="color:#eedd82;">Files</span>);
        <span style="color:#7fffd4;">false</span> -&gt;
            <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">X</span>)
    <span style="color:#00ffff;">end</span>.

 <span style="color:#98fb98;">setup</span>() -&gt;
     {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>} = <span style="color:#98fb98;">net_kernel</span>:<span style="color:#98fb98;">start</span>([<span style="color:#7fffd4;">eunit_resource</span>,<span style="color:#7fffd4;">shortnames</span>]),
     <span style="color:#98fb98;">erlang</span>:<span style="color:#98fb98;">set_cookie</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#7fffd4;">eunit</span>),
     {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>} = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">start_link</span>(?<span style="color:#b0c4de;">NODE_ROOT</span>).

 <span style="color:#98fb98;">cleanup</span>(<span style="color:#eedd82;">_</span>) -&gt;
    <span style="color:#98fb98;">clean_up</span>(?<span style="color:#b0c4de;">NODE_ROOT</span>),
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">net_kernel</span>:<span style="color:#98fb98;">stop</span>(),
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">stop</span>().</pre>
<p><!--- End Of Snippet --></p>
<p>This test requires &#8220;a lot&#8221; of interaction with the file system (naturally) as we do file operations like write/read etc.  The imposed changes for this to pass now follow in order; first of the <em>added</em> record definition in worker_net.hrl header file<br />
<!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-record</span>(<span style="color:#b0c4de;">wn_file</span>,
        {<span style="color:#7fffd4;">id</span> :: <span style="color:#98fb98;">string</span>(),
         <span style="color:#7fffd4;">file</span> :: <span style="color:#98fb98;">string</span>(),
         <span style="color:#7fffd4;">resides</span> :: <span style="color:#b0c4de;">node</span>()
        }).</pre>
<p><!--- End Of Snippet --></p>
<p>then the actual wn_file_layer.erl module, as for the wn_resource_layer, this can also be a gen_server implementation. A skeleton is used as usual . The added API functions, changed callbacks and added internal functions now follow, all to make this test pass</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">===========================================================
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">API
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">===========================================================
</span><span style="color:#87cefa;">start_link</span>(<span style="color:#eedd82;">NodeRoot</span>) -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">start_link</span>({<span style="color:#7fffd4;">local</span>, ?<span style="color:#b0c4de;">MODULE</span>}, ?<span style="color:#b0c4de;">MODULE</span>, <span style="color:#eedd82;">NodeRoot</span>, []).

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">add_file</span>(#<span style="color:#b0c4de;">wn_file</span>{}) -&gt; <span style="color:#7fffd4;">ok</span> | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).
<span style="color:#87cefa;">add_file</span>(<span style="color:#eedd82;">WnFile</span>) -&gt;
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,{<span style="color:#7fffd4;">add_file</span>,<span style="color:#eedd82;">WnFile</span>}) <span style="color:#00ffff;">of</span>
        {<span style="color:#7fffd4;">ok</span>,{<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">Ref</span>}} -&gt;
            {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">IoDev</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">open</span>(<span style="color:#eedd82;">WnFile</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">file</span>,[<span style="color:#7fffd4;">read</span>,<span style="color:#7fffd4;">binary</span>]),
            <span style="color:#eedd82;">Pid</span> ! {<span style="color:#eedd82;">Ref</span>,<span style="color:#b0c4de;">self</span>(),<span style="color:#eedd82;">IoDev</span>},
            <span style="color:#00ffff;">receive</span>
                {<span style="color:#eedd82;">Ref</span>,<span style="color:#eedd82;">Result</span>} -&gt; <span style="color:#eedd82;">Result</span>
            <span style="color:#00ffff;">end</span>;
        <span style="color:#eedd82;">Error</span> -&gt; <span style="color:#eedd82;">Error</span>
    <span style="color:#00ffff;">end</span>.

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">list_files</span>() -&gt; [#<span style="color:#b0c4de;">wn_file</span>{}]).
<span style="color:#87cefa;">list_files</span>() -&gt;
   <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#7fffd4;">list_all_files</span>).

<span style="color:#87cefa;">stop</span>() -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#7fffd4;">stop</span>).</pre>
<p><!--  End Of Snippet --></p>
<p>and the changed internal callbacks</p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">===========================================================
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">gen_server callbacks
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">===========================================================
</span>
<span style="color:#87cefa;">init</span>(<span style="color:#eedd82;">NodeRoot</span>) -&gt;
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">ensure_dir</span>(<span style="color:#eedd82;">NodeRoot</span>),
    {<span style="color:#7fffd4;">ok</span>, #<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">node_root</span> = <span style="color:#eedd82;">NodeRoot</span>,
              <span style="color:#7fffd4;">files</span> = <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">new</span>(<span style="color:#7fffd4;">files</span>,[<span style="color:#7fffd4;">set</span>])
               }}.

<span style="color:#87cefa;">handle_call</span>(<span style="color:#7fffd4;">stop</span>,<span style="color:#eedd82;">_From</span>,<span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">stop</span>,<span style="color:#7fffd4;">normal</span>,<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">State</span>};

<span style="color:#87cefa;">handle_call</span>(<span style="color:#7fffd4;">list_all_files</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#b0c4de;">spawn_link</span>(<span style="color:#98fb98;">file_collector</span>(<span style="color:#eedd82;">From</span>)),
    {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>};

<span style="color:#87cefa;">handle_call</span>(<span style="color:#7fffd4;">list_files</span>,<span style="color:#eedd82;">_From</span>,<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#98fb98;">check_files</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">node_root</span>,<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">files</span>),
    {<span style="color:#7fffd4;">reply</span>,[<span style="color:#eedd82;">V</span> <span style="color:#00ffff;">||</span> {<span style="color:#eedd82;">_</span>,<span style="color:#eedd82;">V</span>} <span style="color:#00ffff;">&lt;-</span> <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">tab2list</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">files</span>)],<span style="color:#eedd82;">State</span>};

<span style="color:#87cefa;">handle_call</span>({<span style="color:#7fffd4;">add_file</span>,<span style="color:#eedd82;">WnFile</span>}, <span style="color:#eedd82;">From</span>, <span style="color:#eedd82;">State</span>) -&gt;
    #<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">resides</span>=<span style="color:#eedd82;">Node</span>} = <span style="color:#eedd82;">WnFile</span>,
    <span style="color:#00ffff;">case</span> {<span style="color:#eedd82;">Node</span> == <span style="color:#b0c4de;">node</span>(),<span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">member</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#b0c4de;">nodes</span>())} <span style="color:#00ffff;">of</span>
        {<span style="color:#7fffd4;">true</span>,<span style="color:#eedd82;">_</span>} -&gt;
            <span style="color:#eedd82;">Path</span> = <span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">node_root</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span>
                <span style="color:#b0c4de;">atom_to_list</span>(<span style="color:#b0c4de;">node</span>())<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">WnFile</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">id</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span>
                <span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">WnFile</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">file</span>),
            <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_file</span>(<span style="color:#eedd82;">Path</span>) <span style="color:#00ffff;">of</span>
                <span style="color:#7fffd4;">true</span> -&gt;
                    {<span style="color:#7fffd4;">reply</span>,{<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">exists</span>},<span style="color:#eedd82;">State</span>};
                <span style="color:#7fffd4;">false</span> -&gt;
                    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">ensure_dir</span>(<span style="color:#eedd82;">Path</span>),
                    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">WriteDev</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">open</span>(<span style="color:#eedd82;">Path</span>,[<span style="color:#7fffd4;">write</span>,<span style="color:#7fffd4;">binary</span>]),
                    <span style="color:#eedd82;">Ref</span> = <span style="color:#b0c4de;">make_ref</span>(),
                    <span style="color:#eedd82;">Pid</span> = <span style="color:#b0c4de;">spawn_link</span>(<span style="color:#98fb98;">receive_file</span>(<span style="color:#eedd82;">Ref</span>,<span style="color:#eedd82;">WriteDev</span>)),
                    {<span style="color:#7fffd4;">reply</span>,{<span style="color:#7fffd4;">ok</span>,{<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">Ref</span>}},<span style="color:#eedd82;">State</span>}
            <span style="color:#00ffff;">end</span>;
        {<span style="color:#7fffd4;">false</span>,<span style="color:#7fffd4;">true</span>} -&gt;
            <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">cast</span>({?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#eedd82;">Node</span>},{<span style="color:#7fffd4;">add_file</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">WnFile</span>}),
            {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>};
        {<span style="color:#7fffd4;">false</span>,<span style="color:#7fffd4;">false</span>} -&gt;
            {<span style="color:#7fffd4;">reply</span>,{<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">noresides</span>},<span style="color:#eedd82;">State</span>}
    <span style="color:#00ffff;">end</span>.

<span style="color:#87cefa;">handle_cast</span>({<span style="color:#7fffd4;">add_file</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">WnFile</span>},<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#eedd82;">Path</span> = <span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">node_root</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span>
        <span style="color:#b0c4de;">atom_to_list</span>(<span style="color:#b0c4de;">node</span>())<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">WnFile</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">id</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span>
        <span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">WnFile</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">file</span>),
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_file</span>(<span style="color:#eedd82;">Path</span>) <span style="color:#00ffff;">of</span>
        <span style="color:#7fffd4;">true</span> -&gt;
            <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">reply</span>(<span style="color:#eedd82;">From</span>,{<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">exists</span>});
        <span style="color:#7fffd4;">false</span> -&gt;
            <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">ensure_dir</span>(<span style="color:#eedd82;">Path</span>),
            {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">WriteDev</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">open</span>(<span style="color:#eedd82;">Path</span>,[<span style="color:#7fffd4;">write</span>,<span style="color:#7fffd4;">binary</span>]),
            <span style="color:#eedd82;">Ref</span> = <span style="color:#b0c4de;">make_ref</span>(),
            <span style="color:#eedd82;">Pid</span> = <span style="color:#b0c4de;">spawn</span>(<span style="color:#98fb98;">receive_file</span>(<span style="color:#eedd82;">Ref</span>,<span style="color:#eedd82;">WriteDev</span>)),
            <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">reply</span>(<span style="color:#eedd82;">From</span>,{<span style="color:#7fffd4;">ok</span>,{<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">Ref</span>}})
    <span style="color:#00ffff;">end</span>,
    {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>}.</pre>
<p><!--- End Of Snippet --></p>
<p>and internal functions added</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">===========================================================
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">Internal functions
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">===========================================================
</span><span style="color:#87cefa;">check_files</span>(<span style="color:#eedd82;">Root</span>,<span style="color:#eedd82;">ETS</span>) -&gt;
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">ensure_dir</span>(<span style="color:#eedd82;">Root</span>),
    <span style="color:#eedd82;">Path</span> = <span style="color:#eedd82;">Root</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#b0c4de;">atom_to_list</span>(<span style="color:#b0c4de;">node</span>())<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span>,
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">NameDirs</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">list_dir</span>(<span style="color:#eedd82;">Path</span>),
    <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">delete_all_objects</span>(<span style="color:#eedd82;">ETS</span>),
    <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foreach</span>(
      <span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">Dir</span>) -&gt;
              {<span style="color:#7fffd4;">ok</span>,[<span style="color:#eedd82;">File</span>]}  = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">list_dir</span>(<span style="color:#eedd82;">Path</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">Dir</span>),
              <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">insert</span>(<span style="color:#eedd82;">ETS</span>,{<span style="color:#eedd82;">Dir</span>,#<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#eedd82;">Dir</span>,
                                      <span style="color:#7fffd4;">file</span> = <span style="color:#eedd82;">Path</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">Dir</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">File</span>,
                                     <span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()}})
      <span style="color:#00ffff;">end</span>,<span style="color:#eedd82;">NameDirs</span>).

<span style="color:#87cefa;">receive_file</span>(<span style="color:#eedd82;">Ref</span>,<span style="color:#eedd82;">WriteDev</span>) -&gt;
    <span style="color:#00ffff;">fun</span>() -&gt;
      <span style="color:#00ffff;">receive</span>
         {<span style="color:#eedd82;">Ref</span>,<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">ReadDev</span>} -&gt;
             <span style="color:#98fb98;">receive_file</span>(<span style="color:#eedd82;">Ref</span>,<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>,<span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">read</span>(<span style="color:#eedd82;">ReadDev</span>,1024))
      <span style="color:#00ffff;">end</span>
    <span style="color:#00ffff;">end</span>.
<span style="color:#87cefa;">receive_file</span>(<span style="color:#eedd82;">Ref</span>,<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>,{<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">Data</span>}) -&gt;
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">write</span>(<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">Data</span>),
    <span style="color:#98fb98;">receive_file</span>(<span style="color:#eedd82;">Ref</span>,<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>,<span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">read</span>(<span style="color:#eedd82;">ReadDev</span>,1024));
<span style="color:#87cefa;">receive_file</span>(<span style="color:#eedd82;">Ref</span>,<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>,<span style="color:#7fffd4;">eof</span>) -&gt;
    <span style="color:#eedd82;">Pid</span> ! {<span style="color:#eedd82;">Ref</span>,<span style="color:#7fffd4;">ok</span>},
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">close</span>(<span style="color:#eedd82;">WriteDev</span>),
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">close</span>(<span style="color:#eedd82;">ReadDev</span>);
<span style="color:#87cefa;">receive_file</span>(<span style="color:#eedd82;">Ref</span>,<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>,<span style="color:#eedd82;">Error</span>) -&gt;
    <span style="color:#eedd82;">Pid</span> ! {<span style="color:#eedd82;">Ref</span>,<span style="color:#eedd82;">Error</span>},
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">close</span>(<span style="color:#eedd82;">WriteDev</span>),
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">close</span>(<span style="color:#eedd82;">ReadDev</span>).

<span style="color:#87cefa;">file_collector</span>(<span style="color:#eedd82;">From</span>) -&gt;
    <span style="color:#eedd82;">Nodes</span> = [<span style="color:#b0c4de;">node</span>()|<span style="color:#b0c4de;">nodes</span>()],
    <span style="color:#00ffff;">fun</span>() -&gt;
        <span style="color:#eedd82;">Res</span> =
           <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foldr</span>(
              <span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Acc</span>) -&gt;
                     <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#7fffd4;">erlang</span>,<span style="color:#7fffd4;">whereis</span>,[?<span style="color:#b0c4de;">MODULE</span>]) <span style="color:#00ffff;">of</span>
                         <span style="color:#7fffd4;">undefined</span> -&gt; <span style="color:#eedd82;">Acc</span>;
                         <span style="color:#eedd82;">_Pid</span> -&gt;
                          <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>({?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#eedd82;">Node</span>},<span style="color:#7fffd4;">list_files</span>)<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">Acc</span>
                   <span style="color:#00ffff;">end</span>
             <span style="color:#00ffff;">end</span>,[],<span style="color:#eedd82;">Nodes</span>),
       <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">reply</span>(<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Res</span>)
    <span style="color:#00ffff;">end</span>.</pre>
<p><!--- End Of Snippet --></p>
<p>I also made a modification to the Makefile so as to run all the tests</p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">all</span>:
        erlc -pa . -o ebin/  src/*.erl test/*.erl

<span style="color:#87cefa;">test</span>:   all
        erl -pa ebin/ -eval <span style="color:#ffa07a;">'eunit:test(wn_resource_layer,[verbose]), init:stop().'</span>
        erl -pa ebin/ -eval <span style="color:#ffa07a;">'eunit:test(wn_file_layer,[verbose]), init:stop().'</span>

<span style="color:#87cefa;">dialyze</span>:
        dialyzer src/*.erl test/*.erl

<span style="color:#87cefa;">full</span>: all test dialyze</pre>
<p><!--- End Of Snippet --></p>
<p>Using the gen_server skeleton with added modifications, a &#8216;make full&#8217; works perfectly fine.<br />
<!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#7fffd4;">zen</span>:<span style="color:#7fffd4;">worker_net</span>-0.1 <span style="color:#7fffd4;">zenon</span><span style="color:#ffa07a;">$ </span><span style="color:#7fffd4;">make</span> <span style="color:#7fffd4;">full</span>
<span style="color:#7fffd4;">erlc</span> -<span style="color:#7fffd4;">pa</span> . -<span style="color:#7fffd4;">o</span> <span style="color:#7fffd4;">ebin</span>/  <span style="color:#7fffd4;">src</span>/*.<span style="color:#7fffd4;">erl</span> <span style="color:#7fffd4;">test</span>/*.<span style="color:#7fffd4;">erl</span>
<span style="color:#7fffd4;">erl</span> -<span style="color:#7fffd4;">pa</span> <span style="color:#7fffd4;">ebin</span>/ -<span style="color:#7fffd4;">eval</span> 'eunit:<span style="color:#98fb98;">test</span>(<span style="color:#7fffd4;">wn_resource_layer</span>,[<span style="color:#7fffd4;">verbose</span>]), <span style="color:#98fb98;">init</span>:<span style="color:#98fb98;">stop</span>().'
<span style="color:#eedd82;">Erlang</span> <span style="color:#eedd82;">R14B</span> (<span style="color:#7fffd4;">erts</span>-5.8.1) [<span style="color:#7fffd4;">source</span>] [<span style="color:#7fffd4;">smp</span>:4:4] [<span style="color:#7fffd4;">rq</span>:4] [<span style="color:#7fffd4;">async</span>-<span style="color:#7fffd4;">threads</span>:0] [<span style="color:#7fffd4;">hipe</span>]
 [<span style="color:#7fffd4;">kernel</span>-<span style="color:#7fffd4;">poll</span>:<span style="color:#7fffd4;">false</span>]

<span style="color:#eedd82;">Eshell</span> <span style="color:#eedd82;">V5</span>.8.1  (<span style="color:#7fffd4;">abort</span> <span style="color:#7fffd4;">with</span> ^<span style="color:#eedd82;">G</span>)
1&gt; ======================== <span style="color:#eedd82;">EUnit</span> ========================
<span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_resource_layer'</span>
  <span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_resource_layer_tests'</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">local_resource_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">register</span> <span style="color:#7fffd4;">resources</span> <span style="color:#7fffd4;">locally</span>)...<span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">register_distributed</span> (<span style="color:#eedd82;">Can</span> <span style="color:#eedd82;">Register</span> <span style="color:#eedd82;">Distributed</span>)...[0.005 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">register_restart_register</span> (<span style="color:#eedd82;">Can</span> <span style="color:#eedd82;">Register</span>, <span style="color:#eedd82;">Restart</span> <span style="color:#7fffd4;">and</span> <span style="color:#eedd82;">Register</span>)...[0.010 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">register_deregister</span> (<span style="color:#eedd82;">Can</span> <span style="color:#eedd82;">Register</span>, <span style="color:#eedd82;">Deregister</span> <span style="color:#7fffd4;">and</span> <span style="color:#eedd82;">Register</span>)...[0.012 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0.875 <span style="color:#7fffd4;">s</span>]
  [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0.875 <span style="color:#7fffd4;">s</span>]
=======================================================
  <span style="color:#eedd82;">All</span> 4 <span style="color:#7fffd4;">tests</span> <span style="color:#7fffd4;">passed</span>.
<span style="color:#7fffd4;">erl</span> -<span style="color:#7fffd4;">pa</span> <span style="color:#7fffd4;">ebin</span>/ -<span style="color:#7fffd4;">eval</span> 'eunit:<span style="color:#98fb98;">test</span>(<span style="color:#7fffd4;">wn_file_layer</span>,[<span style="color:#7fffd4;">verbose</span>]), <span style="color:#98fb98;">init</span>:<span style="color:#98fb98;">stop</span>().'
<span style="color:#eedd82;">Erlang</span> <span style="color:#eedd82;">R14B</span> (<span style="color:#7fffd4;">erts</span>-5.8.1) [<span style="color:#7fffd4;">source</span>] [<span style="color:#7fffd4;">smp</span>:4:4] [<span style="color:#7fffd4;">rq</span>:4] [<span style="color:#7fffd4;">async</span>-<span style="color:#7fffd4;">threads</span>:0] [<span style="color:#7fffd4;">hipe</span>] [<span style="color:#7fffd4;">kernel</span>-<span style="color:#7fffd4;">poll</span>:<span style="color:#7fffd4;">false</span>]

<span style="color:#eedd82;">Eshell</span> <span style="color:#eedd82;">V5</span>.8.1  (<span style="color:#7fffd4;">abort</span> <span style="color:#7fffd4;">with</span> ^<span style="color:#eedd82;">G</span>)
1&gt; ======================== <span style="color:#eedd82;">EUnit</span> ========================
<span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_file_layer'</span>
  <span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_file_layer_tests'</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">file_layer_local_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">store</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">locally</span>)...[0.001 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0.005 <span style="color:#7fffd4;">s</span>]
  [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0.014 <span style="color:#7fffd4;">s</span>]
=======================================================
  <span style="color:#eedd82;">Test</span> <span style="color:#7fffd4;">passed</span>.
<span style="color:#7fffd4;">dialyzer</span> <span style="color:#7fffd4;">src</span>/*.<span style="color:#7fffd4;">erl</span> <span style="color:#7fffd4;">test</span>/*.<span style="color:#7fffd4;">erl</span>
  <span style="color:#eedd82;">Checking</span> <span style="color:#7fffd4;">whether</span> <span style="color:#7fffd4;">the</span> <span style="color:#eedd82;">PLT</span> /<span style="color:#eedd82;">Users</span>/<span style="color:#7fffd4;">zenon</span>/.<span style="color:#7fffd4;">dialyzer_plt</span> <span style="color:#7fffd4;">is</span> <span style="color:#7fffd4;">up</span>-<span style="color:#7fffd4;">to</span>-<span style="color:#7fffd4;">date</span>... <span style="color:#7fffd4;">yes</span>
  <span style="color:#eedd82;">Proceeding</span> <span style="color:#7fffd4;">with</span> <span style="color:#7fffd4;">analysis</span>...
<span style="color:#eedd82;">Unknown</span> <span style="color:#7fffd4;">functions</span>:
  <span style="color:#7fffd4;">eunit</span>:<span style="color:#87cefa;">test/1</span>
 <span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0m1.62s
<span style="color:#87cefa;">done</span> (<span style="color:#7fffd4;">passed</span> <span style="color:#7fffd4;">successfully</span>)
<span style="color:#7fffd4;">zen</span>:<span style="color:#7fffd4;">worker_net</span>-0.1 <span style="color:#7fffd4;">zenon</span><span style="color:#ffa07a;">$ </span></pre>
<p><!--- End Of Snippet --></p>
<p>Nice! Now we know that locally storing a file works fine, can we retrieve it locally as well? Let&#8217;s write a test for it.</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">store_retrieve_locally</span>() -&gt;
    <span style="color:#eedd82;">Path</span> = <span style="color:#98fb98;">create_file_at</span>(?<span style="color:#b0c4de;">NODE_ROOT</span>),
    <span style="color:#eedd82;">Id</span> = <span style="color:#ffa07a;">"AddedFile1"</span>,
    <span style="color:#eedd82;">File</span> = #<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#eedd82;">Id</span>,<span style="color:#7fffd4;">file</span> = <span style="color:#eedd82;">Path</span>,<span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()},
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">add_file</span>(<span style="color:#eedd82;">File</span>),
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">OriginalData</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">read_file</span>(<span style="color:#eedd82;">Path</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">Path</span>)),
    <span style="color:#ff7f24;">% </span><span style="color:#ff7f24;">Retrieve and see change in file system
</span>    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">FileName</span>} =  <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">retrieve_file</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#eedd82;">Id</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">true</span>,<span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_file</span>(<span style="color:#eedd82;">FileName</span>)),
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">NewData</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">read_file</span>(<span style="color:#eedd82;">FileName</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#eedd82;">OriginalData</span>,<span style="color:#eedd82;">NewData</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Path</span>),<span style="color:#eedd82;">FileName</span>),
    <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">FileName</span>).</pre>
<p><!--- End Of Snippet --></p>
<p>The test must create a file (with some binary innards), store it, remove the original, retrive it, and check that the retrieved file contains the same and has the same name! The implementation for this to work also brought some refactoring with it as there now was an evident recurring pattern which asked for refactoring!</p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">retrieve_file</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#98fb98;">string</span>()) -&gt; {<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">string</span>()} | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).
<span style="color:#87cefa;">retrieve_file</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Id</span>) -&gt;
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,{<span style="color:#7fffd4;">retrieve_file</span>,<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Id</span>}) <span style="color:#00ffff;">of</span>
        {<span style="color:#7fffd4;">ok</span>,{<span style="color:#eedd82;">ReadDev</span>,<span style="color:#eedd82;">Name</span>}} -&gt;
            <span style="color:#98fb98;">retrieve_file</span>(<span style="color:#eedd82;">ReadDev</span>,<span style="color:#eedd82;">Name</span>,<span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">open</span>(<span style="color:#eedd82;">Name</span>,[<span style="color:#7fffd4;">write</span>,<span style="color:#7fffd4;">binary</span>]));
        <span style="color:#eedd82;">X</span> -&gt; <span style="color:#eedd82;">X</span>
    <span style="color:#00ffff;">end</span>.
<span style="color:#87cefa;">retrieve_file</span>(<span style="color:#eedd82;">ReadDev</span>,<span style="color:#eedd82;">Name</span>,{<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">WriteDev</span>}) -&gt;
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">receive_file_client</span>(<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>) <span style="color:#00ffff;">of</span>
        <span style="color:#7fffd4;">ok</span> -&gt; {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">Name</span>};
        <span style="color:#eedd82;">Err</span> -&gt; <span style="color:#eedd82;">Err</span>
    <span style="color:#00ffff;">end</span>;
<span style="color:#87cefa;">retrieve_file</span>(<span style="color:#eedd82;">ReadDev</span>,<span style="color:#eedd82;">_Name</span>,<span style="color:#eedd82;">Err</span>) -&gt;
    <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">close</span>(<span style="color:#eedd82;">ReadDev</span>),
    <span style="color:#eedd82;">Err</span>.</pre>
<p><!--- End Of Snippet --></p>
<p>shown above is the API side, and below comes the seen callback and internal functions</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_call</span>({<span style="color:#7fffd4;">retrieve_file</span>,<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Id</span>},<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#00ffff;">case</span> {<span style="color:#b0c4de;">node</span>() == <span style="color:#eedd82;">Node</span>, <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">member</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#b0c4de;">nodes</span>())} <span style="color:#00ffff;">of</span>
        {<span style="color:#7fffd4;">true</span>,<span style="color:#7fffd4;">false</span>} -&gt;
            <span style="color:#eedd82;">Result</span> = <span style="color:#98fb98;">try_retrieve</span>(<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">State</span>),
            {<span style="color:#7fffd4;">reply</span>,<span style="color:#eedd82;">Result</span>,<span style="color:#eedd82;">State</span>};
        {<span style="color:#7fffd4;">false</span>,<span style="color:#7fffd4;">true</span>} -&gt;
            <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#7fffd4;">erlang</span>,<span style="color:#7fffd4;">whereis</span>,[?<span style="color:#b0c4de;">MODULE</span>]) <span style="color:#00ffff;">of</span>
                <span style="color:#7fffd4;">undefined</span> -&gt; {<span style="color:#7fffd4;">reply</span>,{<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">noresides</span>},<span style="color:#eedd82;">State</span>};
                <span style="color:#eedd82;">_Pid</span> -&gt;
                    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">cast</span>({?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#eedd82;">Node</span>},{<span style="color:#7fffd4;">retrieve_file</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Id</span>}),
                    {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>}
            <span style="color:#00ffff;">end</span>;
        {<span style="color:#7fffd4;">false</span>,<span style="color:#7fffd4;">false</span>} -&gt;
            {<span style="color:#7fffd4;">reply</span>,{<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">noresides</span>},<span style="color:#eedd82;">State</span>}
    <span style="color:#00ffff;">end</span>;
<span style="color:#87cefa;">handle_cast</span>({<span style="color:#7fffd4;">retrieve_file</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Id</span>},<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#eedd82;">Result</span> = <span style="color:#98fb98;">try_retrieve</span>(<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">State</span>),
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">reply</span>(<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Result</span>),
    {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>};</pre>
<p><!--- End Of Snippet --></p>
<p>the callback consists mostly of internal try-this-node-try-other-node-logic, whereas the internal logic of the actual retrieval has been factored away into the internal try_retrieve/2 function, also the internal logic of the actual retrieval was stowed away in the receive_file_client/2 function</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">try_retrieve</span>(<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#eedd82;">PropList</span> = <span style="color:#98fb98;">check_files</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">node_root</span>),
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">proplists</span>:<span style="color:#98fb98;">lookup</span>(<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">PropList</span>) <span style="color:#00ffff;">of</span>
        <span style="color:#7fffd4;">none</span> -&gt; {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">noexists</span>};
        {<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">WnFile</span>} -&gt;
            <span style="color:#eedd82;">Path</span> = <span style="color:#eedd82;">WnFile</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">file</span>,
            {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">ReadDev</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">open</span>(<span style="color:#eedd82;">Path</span>,[<span style="color:#7fffd4;">read</span>,<span style="color:#7fffd4;">binary</span>]),
            {<span style="color:#7fffd4;">ok</span>,{<span style="color:#eedd82;">ReadDev</span>,<span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Path</span>)}}
    <span style="color:#00ffff;">end</span>.</pre>
<p><!--- End Of Snippet --></p>
<p>and here is the client logic part</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">receive_file_client</span>(<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>) -&gt;
    <span style="color:#98fb98;">close_transfer</span>(<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>,
                <span style="color:#98fb98;">transfer</span>(<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>)).

<span style="color:#87cefa;">close_transfer</span>(<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>,<span style="color:#eedd82;">TransferResult</span>) -&gt;
    <span style="color:#00ffff;">case</span>
        <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">dropwhile</span>(<span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">X</span>) -&gt; <span style="color:#eedd82;">X</span> == <span style="color:#7fffd4;">ok</span> <span style="color:#00ffff;">end</span>,
                        [<span style="color:#eedd82;">TransferResult</span>,
                         <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">close</span>(<span style="color:#eedd82;">WriteDev</span>),
                         <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">close</span>(<span style="color:#eedd82;">ReadDev</span>)]) <span style="color:#00ffff;">of</span>
        [] -&gt; <span style="color:#7fffd4;">ok</span>;
        [<span style="color:#eedd82;">X</span>|<span style="color:#eedd82;">_</span>] -&gt; <span style="color:#eedd82;">X</span>
    <span style="color:#00ffff;">end</span>.

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">transfer</span>(<span style="color:#b0c4de;">pid</span>(),<span style="color:#b0c4de;">pid</span>()) -&gt; <span style="color:#7fffd4;">ok</span> | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).
<span style="color:#87cefa;">transfer</span>(<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>) -&gt;
    <span style="color:#98fb98;">transfer</span>(<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>,<span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">read</span>(<span style="color:#eedd82;">ReadDev</span>,1024)).

<span style="color:#87cefa;">transfer</span>(<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>,{<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">Data</span>}) -&gt;
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">write</span>(<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">Data</span>) <span style="color:#00ffff;">of</span>
        <span style="color:#7fffd4;">ok</span> -&gt; <span style="color:#98fb98;">transfer</span>(<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>,<span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">read</span>(<span style="color:#eedd82;">ReadDev</span>,1024));
        <span style="color:#eedd82;">Err</span> -&gt; <span style="color:#eedd82;">Err</span>
    <span style="color:#00ffff;">end</span>;
<span style="color:#87cefa;">transfer</span>(<span style="color:#eedd82;">_WriteDev</span>,<span style="color:#eedd82;">_ReadDev</span>,<span style="color:#7fffd4;">eof</span>) -&gt; <span style="color:#7fffd4;">ok</span>;
<span style="color:#87cefa;">transfer</span>(<span style="color:#eedd82;">_WriteDev</span>,<span style="color:#eedd82;">_ReadDev</span>,<span style="color:#eedd82;">Err</span>) -&gt; <span style="color:#eedd82;">Err</span>.</pre>
<p><!--- End Of Snippet --></p>
<p>this transfer logic has also been applied to the add_file functionality, and most of the old code has now been refactored as to be cleaner and leaner. This is where we are immensely happy to have a voley of tests! Whenever we start punting around old code, we want to see that the original functionality has not been removed!</p>
<p>Next, running this test with the added code succeeds!  The proof can be seen here</p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#7fffd4;">zen</span>:<span style="color:#7fffd4;">worker_net</span>-0.1 <span style="color:#7fffd4;">zenon</span><span style="color:#ffa07a;">$ </span><span style="color:#7fffd4;">make</span> <span style="color:#7fffd4;">full</span>
<span style="color:#7fffd4;">erlc</span> -<span style="color:#7fffd4;">pa</span> . -<span style="color:#7fffd4;">o</span> <span style="color:#7fffd4;">ebin</span>/  <span style="color:#7fffd4;">src</span>/*.<span style="color:#7fffd4;">erl</span> <span style="color:#7fffd4;">test</span>/*.<span style="color:#7fffd4;">erl</span>
<span style="color:#7fffd4;">erl</span> -<span style="color:#7fffd4;">pa</span> <span style="color:#7fffd4;">ebin</span>/ -<span style="color:#7fffd4;">eval</span> 'eunit:<span style="color:#98fb98;">test</span>(<span style="color:#7fffd4;">wn_resource_layer</span>,[<span style="color:#7fffd4;">verbose</span>]), <span style="color:#98fb98;">init</span>:<span style="color:#98fb98;">stop</span>().'
<span style="color:#eedd82;">Erlang</span> <span style="color:#eedd82;">R14B</span> (<span style="color:#7fffd4;">erts</span>-5.8.1) [<span style="color:#7fffd4;">source</span>] [<span style="color:#7fffd4;">smp</span>:4:4] [<span style="color:#7fffd4;">rq</span>:4] [<span style="color:#7fffd4;">async</span>-<span style="color:#7fffd4;">threads</span>:0] [<span style="color:#7fffd4;">hipe</span>]
[<span style="color:#7fffd4;">kernel</span>-<span style="color:#7fffd4;">poll</span>:<span style="color:#7fffd4;">false</span>]

<span style="color:#eedd82;">Eshell</span> <span style="color:#eedd82;">V5</span>.8.1  (<span style="color:#7fffd4;">abort</span> <span style="color:#7fffd4;">with</span> ^<span style="color:#eedd82;">G</span>)
1&gt; ======================== <span style="color:#eedd82;">EUnit</span> ========================
<span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_resource_layer'</span>
  <span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_resource_layer_tests'</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">local_resource_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">register</span> <span style="color:#7fffd4;">resources</span> <span style="color:#7fffd4;">locally</span>)...[0.001 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">register_distributed</span> (<span style="color:#eedd82;">Can</span> <span style="color:#eedd82;">Register</span> <span style="color:#eedd82;">Distributed</span>)...[0.004 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">register_restart_register</span> (<span style="color:#eedd82;">Can</span> <span style="color:#eedd82;">Register</span>, <span style="color:#eedd82;">Restart</span> <span style="color:#7fffd4;">and</span> <span style="color:#eedd82;">Register</span>)...[0.008 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">register_deregister</span> (<span style="color:#eedd82;">Can</span> <span style="color:#eedd82;">Register</span>, <span style="color:#eedd82;">Deregister</span> <span style="color:#7fffd4;">and</span> <span style="color:#eedd82;">Register</span>)...[0.011 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0.865 <span style="color:#7fffd4;">s</span>]
  [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0.865 <span style="color:#7fffd4;">s</span>]
=======================================================
  <span style="color:#eedd82;">All</span> 4 <span style="color:#7fffd4;">tests</span> <span style="color:#7fffd4;">passed</span>.
<span style="color:#7fffd4;">erl</span> -<span style="color:#7fffd4;">pa</span> <span style="color:#7fffd4;">ebin</span>/ -<span style="color:#7fffd4;">eval</span> 'eunit:<span style="color:#98fb98;">test</span>(<span style="color:#7fffd4;">wn_file_layer</span>,[<span style="color:#7fffd4;">verbose</span>]), <span style="color:#98fb98;">init</span>:<span style="color:#98fb98;">stop</span>().'
<span style="color:#eedd82;">Erlang</span> <span style="color:#eedd82;">R14B</span> (<span style="color:#7fffd4;">erts</span>-5.8.1) [<span style="color:#7fffd4;">source</span>] [<span style="color:#7fffd4;">smp</span>:4:4] [<span style="color:#7fffd4;">rq</span>:4] [<span style="color:#7fffd4;">async</span>-<span style="color:#7fffd4;">threads</span>:0] [<span style="color:#7fffd4;">hipe</span>]
[<span style="color:#7fffd4;">kernel</span>-<span style="color:#7fffd4;">poll</span>:<span style="color:#7fffd4;">false</span>]

<span style="color:#eedd82;">Eshell</span> <span style="color:#eedd82;">V5</span>.8.1  (<span style="color:#7fffd4;">abort</span> <span style="color:#7fffd4;">with</span> ^<span style="color:#eedd82;">G</span>)
1&gt; ======================== <span style="color:#eedd82;">EUnit</span> ========================
<span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_file_layer'</span>
  <span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_file_layer_tests'</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">file_layer_local_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">store</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">locally</span>)...[0.001 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">file_layer_local_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">retrieve</span> <span style="color:#7fffd4;">files</span> <span style="color:#7fffd4;">locally</span>)...[0.002 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0.025 <span style="color:#7fffd4;">s</span>]
  [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0.025 <span style="color:#7fffd4;">s</span>]
=======================================================
  <span style="color:#eedd82;">All</span> 3 <span style="color:#7fffd4;">tests</span> <span style="color:#7fffd4;">passed</span>.
<span style="color:#7fffd4;">dialyzer</span> <span style="color:#7fffd4;">src</span>/*.<span style="color:#7fffd4;">erl</span> <span style="color:#7fffd4;">test</span>/*.<span style="color:#7fffd4;">erl</span>
  <span style="color:#eedd82;">Checking</span> <span style="color:#7fffd4;">whether</span> <span style="color:#7fffd4;">the</span> <span style="color:#eedd82;">PLT</span> /<span style="color:#eedd82;">Users</span>/<span style="color:#7fffd4;">zenon</span>/.<span style="color:#7fffd4;">dialyzer_plt</span> <span style="color:#7fffd4;">is</span> <span style="color:#7fffd4;">up</span>-<span style="color:#7fffd4;">to</span>-<span style="color:#7fffd4;">date</span>... <span style="color:#7fffd4;">yes</span>
  <span style="color:#eedd82;">Proceeding</span> <span style="color:#7fffd4;">with</span> <span style="color:#7fffd4;">analysis</span>...
<span style="color:#eedd82;">Unknown</span> <span style="color:#7fffd4;">functions</span>:
  <span style="color:#7fffd4;">eunit</span>:<span style="color:#87cefa;">test/1</span>
 <span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0m1.95s
<span style="color:#87cefa;">done</span> (<span style="color:#7fffd4;">passed</span> <span style="color:#7fffd4;">successfully</span>)
<span style="color:#7fffd4;">zen</span>:<span style="color:#7fffd4;">worker_net</span>-0.1 <span style="color:#7fffd4;">zenon</span><span style="color:#ffa07a;">$ </span></pre>
<p><!--- End Of Snippet --></p>
<p>All dandy. Next up is the test for deletion of a file. This test needs to add a file to the file layer, delete it from the file layer, and request it from the file layer too see that nothing is retrieved</p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">store_delete_locally</span>() -&gt;
    <span style="color:#eedd82;">Path</span> = <span style="color:#98fb98;">create_file_at</span>(?<span style="color:#b0c4de;">NODE_ROOT</span>),
    <span style="color:#eedd82;">Id</span> = <span style="color:#ffa07a;">"AddedFile1"</span>,
    <span style="color:#eedd82;">File</span> = #<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#eedd82;">Id</span>,<span style="color:#7fffd4;">file</span> = <span style="color:#eedd82;">Path</span>,<span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()},
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">add_file</span>(<span style="color:#eedd82;">File</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">delete_file</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#eedd82;">Id</span>)),
    ?<span style="color:#b0c4de;">assertEqual</span>([],<span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">list_files</span>()),
    <span style="color:#ff7f24;">% </span><span style="color:#ff7f24;">Check change in file-system
</span>    <span style="color:#eedd82;">ExpectedPath</span> = ?<span style="color:#b0c4de;">NODE_ROOT</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span>
        <span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#b0c4de;">atom_to_list</span>(<span style="color:#b0c4de;">node</span>())
        <span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">Id</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Path</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">false</span>,<span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_file</span>(<span style="color:#eedd82;">ExpectedPath</span>)),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">false</span>,<span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_dir</span>(?<span style="color:#b0c4de;">NODE_ROOT</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span>
                                      <span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#b0c4de;">atom_to_list</span>(<span style="color:#b0c4de;">node</span>())<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span>
                                      <span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">Id</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span>)).</pre>
<p><!--- End Of Snippet --></p>
<p>This implementation is easier, API</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">delete_file</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#98fb98;">string</span>()) -&gt; <span style="color:#7fffd4;">ok</span> | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).
<span style="color:#87cefa;">delete_file</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Id</span>) -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,{<span style="color:#7fffd4;">delete_file</span>,<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Id</span>}).</pre>
<p><!--- End Of Snippet --></p>
<p>callbacks and internals as usual,</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_call</span>({<span style="color:#7fffd4;">delete_file</span>,<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Id</span>},<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#00ffff;">case</span> {<span style="color:#b0c4de;">node</span>() == <span style="color:#eedd82;">Node</span>, <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">member</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#b0c4de;">nodes</span>())} <span style="color:#00ffff;">of</span>
        {<span style="color:#7fffd4;">true</span>,<span style="color:#7fffd4;">false</span>} -&gt;
            {<span style="color:#7fffd4;">reply</span>,<span style="color:#98fb98;">try_delete_file</span>(<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">State</span>),<span style="color:#eedd82;">State</span>};
        {<span style="color:#7fffd4;">false</span>,<span style="color:#7fffd4;">true</span>} -&gt;
            <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#7fffd4;">erlang</span>,<span style="color:#7fffd4;">whereis</span>,[?<span style="color:#b0c4de;">MODULE</span>]) <span style="color:#00ffff;">of</span>
                <span style="color:#7fffd4;">undefined</span> -&gt; {<span style="color:#7fffd4;">reply</span>,{<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">noresides</span>},<span style="color:#eedd82;">State</span>};
                <span style="color:#eedd82;">_Pid</span> -&gt;
                    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">cast</span>({?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#eedd82;">Node</span>},{<span style="color:#7fffd4;">delete_file</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Id</span>}),
                    {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>}
            <span style="color:#00ffff;">end</span>;
        {<span style="color:#7fffd4;">false</span>,<span style="color:#7fffd4;">false</span>} -&gt;
            {<span style="color:#7fffd4;">reply</span>,{<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">noresides</span>},<span style="color:#eedd82;">State</span>}
    <span style="color:#00ffff;">end</span>;
<span style="color:#87cefa;">handle_cast</span>({<span style="color:#7fffd4;">delete_file</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Id</span>},<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#eedd82;">Result</span> = <span style="color:#98fb98;">try_delete_file</span>(<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">State</span>),
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">reply</span>(<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Result</span>),
    {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>};</pre>
<p><!--- End Of Snippet --></p>
<p>and internals</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">try_delete_file</span>(<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#eedd82;">PropList</span> = <span style="color:#98fb98;">check_files</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">node_root</span>),
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">proplists</span>:<span style="color:#98fb98;">lookup</span>(<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">PropList</span>) <span style="color:#00ffff;">of</span>
        <span style="color:#7fffd4;">none</span> -&gt;
            {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">noexists</span>};
        {<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">WnFile</span>} -&gt;
            <span style="color:#eedd82;">List</span> = [ <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">WnFile</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">file</span>),
                     <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">del_dir</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">node_root</span><span style="color:#ffc0cb;font-weight:bold;">++</span>
                                  <span style="color:#b0c4de;">atom_to_list</span>(<span style="color:#b0c4de;">node</span>())<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span>
                                  <span style="color:#eedd82;">WnFile</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">id</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span>) ],
            <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">dropwhile</span>(<span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">X</span>) -&gt; <span style="color:#eedd82;">X</span> == <span style="color:#7fffd4;">ok</span> <span style="color:#00ffff;">end</span>,<span style="color:#eedd82;">List</span>) <span style="color:#00ffff;">of</span>
                [] -&gt; <span style="color:#7fffd4;">ok</span>;
                [<span style="color:#eedd82;">X</span>|<span style="color:#eedd82;">_</span>] -&gt; <span style="color:#eedd82;">X</span>
            <span style="color:#00ffff;">end</span>
    <span style="color:#00ffff;">end</span>.</pre>
<p><!--- End Of Snippet --></p>
<p>The next set of tests is to test whether all this works in a distributed setting as well, thus, it&#8217;s time to use the slave nodes as used for the resource layer tests. The test is easily written and put into it&#8217;s own test generator</p>
<p><!--- Snippet  --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">file_layer_distributed_test_</span>() -&gt;
   {<span style="color:#7fffd4;">foreach</span>,
     <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">distr_setup/0</span>,
     <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">distr_cleanup/1</span>,
     [
      <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">can_store_distributed/1</span>
      ]}.</pre>
<p><!--- End Of Snippet --></p>
<p>and the setup/cleanup with the test</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">distr_setup</span>() -&gt;
    <span style="color:#98fb98;">setup</span>(),
    <span style="color:#eedd82;">Host</span> = <span style="color:#b0c4de;">list_to_atom</span>(<span style="color:#98fb98;">inet_db</span>:<span style="color:#98fb98;">gethostname</span>()),
    <span style="color:#eedd82;">Args</span> = <span style="color:#ffa07a;">" -pa "</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#b0c4de;">hd</span>(<span style="color:#98fb98;">code</span>:<span style="color:#98fb98;">get_path</span>())<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">" -setcookie eunit"</span>,
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">N1</span>} = <span style="color:#98fb98;">slave</span>:<span style="color:#98fb98;">start</span>(<span style="color:#eedd82;">Host</span>,<span style="color:#7fffd4;">n1</span>,<span style="color:#eedd82;">Args</span>),
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">N2</span>} = <span style="color:#98fb98;">slave</span>:<span style="color:#98fb98;">start</span>(<span style="color:#eedd82;">Host</span>,<span style="color:#7fffd4;">n2</span>,<span style="color:#eedd82;">Args</span>),
    <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">net_kernel</span>,<span style="color:#7fffd4;">connect_node</span>,[<span style="color:#eedd82;">N2</span>]),
    [<span style="color:#eedd82;">N1</span>,<span style="color:#eedd82;">N2</span>].

<span style="color:#87cefa;">distr_cleanup</span>([<span style="color:#eedd82;">N1</span>,<span style="color:#eedd82;">N2</span>]) -&gt;
    <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">stop</span>,[]),
    <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">stop</span>,[]),
    <span style="color:#98fb98;">slave</span>:<span style="color:#98fb98;">stop</span>(<span style="color:#eedd82;">N1</span>),
    <span style="color:#98fb98;">slave</span>:<span style="color:#98fb98;">stop</span>(<span style="color:#eedd82;">N2</span>),    
    <span style="color:#98fb98;">cleanup</span>(<span style="color:#7fffd4;">nothing</span>).
<span style="color:#87cefa;">can_store_distributed</span>([<span style="color:#eedd82;">N1</span>,<span style="color:#eedd82;">N2</span>]) -&gt;
    {<span style="color:#ffa07a;">"Can store file distributed"</span>,
     <span style="color:#00ffff;">fun</span>() -&gt;
     ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>},<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">start_link</span>,[?<span style="color:#b0c4de;">NODE_ROOT</span>])),
     ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>},<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">start_link</span>,[?<span style="color:#b0c4de;">NODE_ROOT</span>])),
     <span style="color:#eedd82;">Path</span> = <span style="color:#98fb98;">create_file_at</span>(?<span style="color:#b0c4de;">NODE_ROOT</span>),
     <span style="color:#eedd82;">Id</span> = <span style="color:#ffa07a;">"AddedFile1"</span>,
     <span style="color:#eedd82;">File</span> = #<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#eedd82;">Id</span>,<span style="color:#7fffd4;">file</span> = <span style="color:#eedd82;">Path</span>,<span style="color:#7fffd4;">resides</span> = <span style="color:#eedd82;">N1</span>},
     <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">add_file</span>(<span style="color:#eedd82;">File</span>),
     [<span style="color:#eedd82;">Res</span>] = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">list_files</span>(),
     [<span style="color:#eedd82;">Res2</span>] = <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">list_files</span>,[]),
     [<span style="color:#eedd82;">Res3</span>] = <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">list_files</span>,[]),
     ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Path</span>),<span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Res</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">file</span>)),
     ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">Res</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">id</span>),
     ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#eedd82;">Res</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">resides</span>),
     ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#eedd82;">Res</span>,<span style="color:#eedd82;">Res2</span>),
     ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#eedd82;">Res2</span>,<span style="color:#eedd82;">Res3</span>),
     <span style="color:#ff7f24;">% </span><span style="color:#ff7f24;">Check change in file-system
</span>     <span style="color:#eedd82;">ExpectedPath</span> = ?<span style="color:#b0c4de;">NODE_ROOT</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#b0c4de;">atom_to_list</span>(<span style="color:#eedd82;">N1</span>)<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span>
                   <span style="color:#eedd82;">Id</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Path</span>),
     ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">true</span>,<span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_file</span>(<span style="color:#eedd82;">Path</span>)),
     ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">true</span>,<span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_file</span>(<span style="color:#eedd82;">ExpectedPath</span>))        
   <span style="color:#00ffff;">end</span>}.</pre>
<p><!--- End Of Snippet --></p>
<p>When I ran the tests with this new addition, it actually failed! The reason being that the current implementation of check_files/1 crashes here</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">check_files</span>(<span style="color:#eedd82;">Root</span>) -&gt;
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">ensure_dir</span>(<span style="color:#eedd82;">Root</span>),
    <span style="color:#eedd82;">Path</span> = <span style="color:#eedd82;">Root</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#b0c4de;">atom_to_list</span>(<span style="color:#b0c4de;">node</span>())<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span>,    
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">NameDirs</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">list_dir</span>(<span style="color:#eedd82;">Path</span>),</pre>
<p><!--- End Of Snippet --></p>
<p>Explanation is that the local node directory is not created inside the node_root until a file is added! Thus, any attempts to file:list_dir/1 such a directory will fail. The fix was easy, whenever the layer is started; assure the directory.</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">init</span>(<span style="color:#eedd82;">NodeRoot</span>) -&gt;
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">ensure_dir</span>(<span style="color:#eedd82;">NodeRoot</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#b0c4de;">atom_to_list</span>(<span style="color:#b0c4de;">node</span>())<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span>),
    {<span style="color:#7fffd4;">ok</span>, #<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">node_root</span> = <span style="color:#eedd82;">NodeRoot</span>}}.</pre>
<p><!--- End Of Snippet --></p>
<p>Now the test passed. As It passed I added the all the other distributed versions of the previous tests. And nicely enough, all of them passed without any other error! So, let me present them in one go!</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">file_layer_distributed_test_</span>() -&gt;
   {<span style="color:#7fffd4;">foreach</span>,
     <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">distr_setup/0</span>,
     <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">distr_cleanup/1</span>,
     [
      <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">can_store_distributed/1</span>,
      <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">can_retrieve_distributed/1</span>,
      <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">can_delete_distributed/1</span>,
      <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">must_retain/1</span>
      ]}.</pre>
<p><!--- End Of Snippet --></p>
<p>A comment is now appropriate: The must_retain/1 instantiator gives a test which tests the last point of the stories. Namely</p>
<p><em>&#8220;I want the file layer to be persistent, should a node fail and be restarted, it should keep the files previously stored at it&#8217;s location&#8221;</em></p>
<p>Now all of them follow (first test excluded for duplication)</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">must_retain</span>([<span style="color:#eedd82;">N1</span>,<span style="color:#eedd82;">N2</span>]) -&gt;
    {<span style="color:#ffa07a;">"Must retain information between node kill and node restart"</span>,
     <span style="color:#00ffff;">fun</span>() -&gt;
             ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>},<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">start_link</span>,[?<span style="color:#b0c4de;">NODE_ROOT</span>])),
             ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>},<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">start_link</span>,[?<span style="color:#b0c4de;">NODE_ROOT</span>])),
             <span style="color:#eedd82;">Path</span> = <span style="color:#98fb98;">create_file_at</span>(?<span style="color:#b0c4de;">NODE_ROOT</span>),
             <span style="color:#eedd82;">FileA</span> = #<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"File1"</span>,<span style="color:#7fffd4;">file</span> = <span style="color:#eedd82;">Path</span>,<span style="color:#7fffd4;">resides</span> = <span style="color:#eedd82;">N1</span>},
             <span style="color:#eedd82;">FileB</span> = #<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"File2"</span>,<span style="color:#7fffd4;">file</span> = <span style="color:#eedd82;">Path</span>,<span style="color:#7fffd4;">resides</span> = <span style="color:#eedd82;">N2</span>},
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">add_file</span>(<span style="color:#eedd82;">FileA</span>),
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">add_file</span>(<span style="color:#eedd82;">FileB</span>),
             [<span style="color:#eedd82;">ResA</span>,<span style="color:#eedd82;">ResB</span>] = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">list_files</span>(),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Path</span>),<span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">ResA</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">file</span>)),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Path</span>),<span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">ResB</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">file</span>)),
             <span style="color:#ff7f24;">% </span><span style="color:#ff7f24;">Kill N1 and N2
</span>             <span style="color:#98fb98;">slave</span>:<span style="color:#98fb98;">stop</span>(<span style="color:#eedd82;">N1</span>),
             <span style="color:#98fb98;">slave</span>:<span style="color:#98fb98;">stop</span>(<span style="color:#eedd82;">N2</span>),
             ?<span style="color:#b0c4de;">assertEqual</span>([],<span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">list_files</span>()),
             <span style="color:#ff7f24;">% </span><span style="color:#ff7f24;">Restart and check
</span>             <span style="color:#eedd82;">Host</span> = <span style="color:#b0c4de;">list_to_atom</span>(<span style="color:#98fb98;">inet_db</span>:<span style="color:#98fb98;">gethostname</span>()),
             <span style="color:#eedd82;">Args</span> = <span style="color:#ffa07a;">" -pa "</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#b0c4de;">hd</span>(<span style="color:#98fb98;">code</span>:<span style="color:#98fb98;">get_path</span>())<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">" -setcookie eunit"</span>,
             {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">N1</span>} = <span style="color:#98fb98;">slave</span>:<span style="color:#98fb98;">start</span>(<span style="color:#eedd82;">Host</span>,<span style="color:#7fffd4;">n1</span>,<span style="color:#eedd82;">Args</span>),
             {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">N2</span>} = <span style="color:#98fb98;">slave</span>:<span style="color:#98fb98;">start</span>(<span style="color:#eedd82;">Host</span>,<span style="color:#7fffd4;">n2</span>,<span style="color:#eedd82;">Args</span>),
             <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">net_kernel</span>,<span style="color:#7fffd4;">connect_node</span>,[<span style="color:#eedd82;">N2</span>]),
             ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>},<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">start_link</span>,[?<span style="color:#b0c4de;">NODE_ROOT</span>])),
             ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>},<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">start_link</span>,[?<span style="color:#b0c4de;">NODE_ROOT</span>])),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResA</span>,<span style="color:#eedd82;">ResB</span>],<span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">list_files</span>())
     <span style="color:#00ffff;">end</span>}.

<span style="color:#87cefa;">can_delete_distributed</span>([<span style="color:#eedd82;">N1</span>,<span style="color:#eedd82;">N2</span>]) -&gt;
    {<span style="color:#ffa07a;">"Can delete file distributed"</span>,
     <span style="color:#00ffff;">fun</span>() -&gt;
             ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>},<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">start_link</span>,[?<span style="color:#b0c4de;">NODE_ROOT</span>])),
             ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>},<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">start_link</span>,[?<span style="color:#b0c4de;">NODE_ROOT</span>])),
             <span style="color:#eedd82;">Path</span> = <span style="color:#98fb98;">create_file_at</span>(?<span style="color:#b0c4de;">NODE_ROOT</span>),
             <span style="color:#eedd82;">Id</span> = <span style="color:#ffa07a;">"AddedFile1"</span>,
             <span style="color:#eedd82;">File</span> = #<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#eedd82;">Id</span>,<span style="color:#7fffd4;">file</span> = <span style="color:#eedd82;">Path</span>,<span style="color:#7fffd4;">resides</span> = <span style="color:#eedd82;">N1</span>},
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">add_file</span>(<span style="color:#eedd82;">File</span>),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">delete_file</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#eedd82;">Id</span>)),
             ?<span style="color:#b0c4de;">assertEqual</span>([],<span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">list_files</span>()),
             <span style="color:#ff7f24;">% </span><span style="color:#ff7f24;">Check change in file-system
</span>             <span style="color:#eedd82;">ExpectedPath</span> = ?<span style="color:#b0c4de;">NODE_ROOT</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span>
                 <span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#b0c4de;">atom_to_list</span>(<span style="color:#b0c4de;">node</span>())
                 <span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">Id</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Path</span>),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">false</span>,<span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_file</span>(<span style="color:#eedd82;">ExpectedPath</span>)),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">false</span>,<span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_dir</span>(?<span style="color:#b0c4de;">NODE_ROOT</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span>
                                               <span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#b0c4de;">atom_to_list</span>(<span style="color:#eedd82;">N1</span>)<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span>
                                               <span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">Id</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span>))
     <span style="color:#00ffff;">end</span>}.

<span style="color:#87cefa;">can_retrieve_distributed</span>([<span style="color:#eedd82;">N1</span>,<span style="color:#eedd82;">N2</span>]) -&gt;
    {<span style="color:#ffa07a;">"Can retrieve file distributed"</span>,
     <span style="color:#00ffff;">fun</span>() -&gt;
             ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>},<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">start_link</span>,[?<span style="color:#b0c4de;">NODE_ROOT</span>])),
             ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>},<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">start_link</span>,[?<span style="color:#b0c4de;">NODE_ROOT</span>])),
             <span style="color:#eedd82;">Path</span> = <span style="color:#98fb98;">create_file_at</span>(?<span style="color:#b0c4de;">NODE_ROOT</span>),
             <span style="color:#eedd82;">Id</span> = <span style="color:#ffa07a;">"AddedFile1"</span>,
             <span style="color:#eedd82;">File</span> = #<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#eedd82;">Id</span>,<span style="color:#7fffd4;">file</span> = <span style="color:#eedd82;">Path</span>,<span style="color:#7fffd4;">resides</span> = <span style="color:#eedd82;">N1</span>},
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">add_file</span>(<span style="color:#eedd82;">File</span>),
             {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">OriginalData</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">read_file</span>(<span style="color:#eedd82;">Path</span>),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">Path</span>)),
             <span style="color:#ff7f24;">% </span><span style="color:#ff7f24;">Retrieve and see change in file system
</span>             {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">FileName</span>} =  <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">retrieve_file</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#eedd82;">Id</span>),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">true</span>,<span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_file</span>(<span style="color:#eedd82;">FileName</span>)),
             {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">NewData</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">read_file</span>(<span style="color:#eedd82;">FileName</span>),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#eedd82;">OriginalData</span>,<span style="color:#eedd82;">NewData</span>),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Path</span>),<span style="color:#eedd82;">FileName</span>),
             <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">FileName</span>)
     <span style="color:#00ffff;">end</span>}.</pre>
<p><!--- End Of Snippet --></p>
<p>Interestingly (and embarrassingly) enough; I noticed that I had a bug in the cleanup code for the test module, the fixed version will be shown in the listing in the end of this post.</p>
<p>As I can now see, all the initial stories have been fulfilled, and the final &#8216;make full&#8217; prooves this.<br />
<!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#7fffd4;">zen</span>:<span style="color:#7fffd4;">worker_net</span>-0.1 <span style="color:#7fffd4;">zenon</span><span style="color:#ffa07a;">$ </span><span style="color:#7fffd4;">make</span> <span style="color:#7fffd4;">full</span>
<span style="color:#7fffd4;">erlc</span> -<span style="color:#7fffd4;">pa</span> . -<span style="color:#7fffd4;">o</span> <span style="color:#7fffd4;">ebin</span>/  <span style="color:#7fffd4;">src</span>/*.<span style="color:#7fffd4;">erl</span> <span style="color:#7fffd4;">test</span>/*.<span style="color:#7fffd4;">erl</span>
<span style="color:#7fffd4;">erl</span> -<span style="color:#7fffd4;">pa</span> <span style="color:#7fffd4;">ebin</span>/ -<span style="color:#7fffd4;">eval</span> 'eunit:<span style="color:#98fb98;">test</span>(<span style="color:#7fffd4;">wn_resource_layer</span>,[<span style="color:#7fffd4;">verbose</span>]), <span style="color:#98fb98;">init</span>:<span style="color:#98fb98;">stop</span>().'
<span style="color:#eedd82;">Erlang</span> <span style="color:#eedd82;">R14B</span> (<span style="color:#7fffd4;">erts</span>-5.8.1) [<span style="color:#7fffd4;">source</span>] [<span style="color:#7fffd4;">smp</span>:4:4] [<span style="color:#7fffd4;">rq</span>:4] [<span style="color:#7fffd4;">async</span>-<span style="color:#7fffd4;">threads</span>:0] [<span style="color:#7fffd4;">hipe</span>] [<span style="color:#7fffd4;">kernel</span>-<span style="color:#7fffd4;">poll</span>:<span style="color:#7fffd4;">false</span>]

<span style="color:#eedd82;">Eshell</span> <span style="color:#eedd82;">V5</span>.8.1  (<span style="color:#7fffd4;">abort</span> <span style="color:#7fffd4;">with</span> ^<span style="color:#eedd82;">G</span>)
1&gt; ======================== <span style="color:#eedd82;">EUnit</span> ========================
<span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_resource_layer'</span>
  <span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_resource_layer_tests'</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">local_resource_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">register</span> <span style="color:#7fffd4;">resources</span> <span style="color:#7fffd4;">locally</span>)...<span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">register_distributed</span> (<span style="color:#eedd82;">Can</span> <span style="color:#eedd82;">Register</span> <span style="color:#eedd82;">Distributed</span>)...[0.004 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">register_restart_register</span> (<span style="color:#eedd82;">Can</span> <span style="color:#eedd82;">Register</span>, <span style="color:#eedd82;">Restart</span> <span style="color:#7fffd4;">and</span> <span style="color:#eedd82;">Register</span>)...[0.008 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">register_deregister</span> (<span style="color:#eedd82;">Can</span> <span style="color:#eedd82;">Register</span>, <span style="color:#eedd82;">Deregister</span> <span style="color:#7fffd4;">and</span> <span style="color:#eedd82;">Register</span>)...[0.011 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0.907 <span style="color:#7fffd4;">s</span>]
  [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0.907 <span style="color:#7fffd4;">s</span>]
=======================================================
  <span style="color:#eedd82;">All</span> 4 <span style="color:#7fffd4;">tests</span> <span style="color:#7fffd4;">passed</span>.
<span style="color:#7fffd4;">erl</span> -<span style="color:#7fffd4;">pa</span> <span style="color:#7fffd4;">ebin</span>/ -<span style="color:#7fffd4;">eval</span> 'eunit:<span style="color:#98fb98;">test</span>(<span style="color:#7fffd4;">wn_file_layer</span>,[<span style="color:#7fffd4;">verbose</span>]), <span style="color:#98fb98;">init</span>:<span style="color:#98fb98;">stop</span>().'
<span style="color:#eedd82;">Erlang</span> <span style="color:#eedd82;">R14B</span> (<span style="color:#7fffd4;">erts</span>-5.8.1) [<span style="color:#7fffd4;">source</span>] [<span style="color:#7fffd4;">smp</span>:4:4] [<span style="color:#7fffd4;">rq</span>:4] [<span style="color:#7fffd4;">async</span>-<span style="color:#7fffd4;">threads</span>:0] [<span style="color:#7fffd4;">hipe</span>] [<span style="color:#7fffd4;">kernel</span>-<span style="color:#7fffd4;">poll</span>:<span style="color:#7fffd4;">false</span>]

<span style="color:#eedd82;">Eshell</span> <span style="color:#eedd82;">V5</span>.8.1  (<span style="color:#7fffd4;">abort</span> <span style="color:#7fffd4;">with</span> ^<span style="color:#eedd82;">G</span>)
1&gt; ======================== <span style="color:#eedd82;">EUnit</span> ========================
<span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_file_layer'</span>
  <span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_file_layer_tests'</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">file_layer_local_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">store</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">locally</span>)...[0.001 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">file_layer_local_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">retrieve</span> <span style="color:#7fffd4;">files</span> <span style="color:#7fffd4;">locally</span>)...[0.002 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">file_layer_local_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">delete</span> <span style="color:#7fffd4;">files</span> <span style="color:#7fffd4;">locally</span>)...[0.001 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">can_store_distributed</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">store</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">distributed</span>)...[0.015 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">can_retrieve_distributed</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">retrieve</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">distributed</span>)...[0.013 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">can_delete_distributed</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">delete</span> <span style="color:#7fffd4;">file</span> <span style="color:#7fffd4;">distributed</span>)...[0.014 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_file_layer_tests</span>: <span style="color:#98fb98;">must_retain</span> (<span style="color:#eedd82;">Must</span> <span style="color:#7fffd4;">retain</span> <span style="color:#7fffd4;">information</span> <span style="color:#7fffd4;">between</span> <span style="color:#7fffd4;">node</span> <span style="color:#7fffd4;">kill</span> <span style="color:#7fffd4;">and</span> <span style="color:#7fffd4;">node</span> <span style="color:#7fffd4;">restart</span>)...[0.294 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 1.478 <span style="color:#7fffd4;">s</span>]
  [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 1.478 <span style="color:#7fffd4;">s</span>]
=======================================================
  <span style="color:#eedd82;">All</span> 7 <span style="color:#7fffd4;">tests</span> <span style="color:#7fffd4;">passed</span>.
<span style="color:#7fffd4;">dialyzer</span> <span style="color:#7fffd4;">src</span>/*.<span style="color:#7fffd4;">erl</span> <span style="color:#7fffd4;">test</span>/*.<span style="color:#7fffd4;">erl</span>
  <span style="color:#eedd82;">Checking</span> <span style="color:#7fffd4;">whether</span> <span style="color:#7fffd4;">the</span> <span style="color:#eedd82;">PLT</span> /<span style="color:#eedd82;">Users</span>/<span style="color:#7fffd4;">zenon</span>/.<span style="color:#7fffd4;">dialyzer_plt</span> <span style="color:#7fffd4;">is</span> <span style="color:#7fffd4;">up</span>-<span style="color:#7fffd4;">to</span>-<span style="color:#7fffd4;">date</span>... <span style="color:#7fffd4;">yes</span>
  <span style="color:#eedd82;">Proceeding</span> <span style="color:#7fffd4;">with</span> <span style="color:#7fffd4;">analysis</span>...
<span style="color:#eedd82;">Unknown</span> <span style="color:#7fffd4;">functions</span>:
  <span style="color:#7fffd4;">eunit</span>:<span style="color:#87cefa;">test/1</span>
 <span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0m2.69s
<span style="color:#87cefa;">done</span> (<span style="color:#7fffd4;">passed</span> <span style="color:#7fffd4;">successfully</span>)
<span style="color:#7fffd4;">zen</span>:<span style="color:#7fffd4;">worker_net</span>-0.1 <span style="color:#7fffd4;">zenon</span><span style="color:#ffa07a;">$ </span></pre>
<p><!--- End Of Snippet --></p>
<p>Next time, the work layer, and the work tests. Now the listings as usual</p>
<h2>Listing: wn_file_layer.erl</h2>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">-------------------------------------------------------------------
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@author Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@copyright (C) 2010, Gianfranco
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">Created : 19 Dec 2010 by Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">-------------------------------------------------------------------
</span><span style="color:#b0c4de;">-module</span>(<span style="color:#7fffd4;">wn_file_layer</span>).
<span style="color:#b0c4de;">-behaviour</span>(<span style="color:#7fffd4;">gen_server</span>).
<span style="color:#b0c4de;">-include</span>(<span style="color:#ffa07a;">"include/worker_net.hrl"</span>).

<span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">API
</span><span style="color:#b0c4de;">-export</span>([<span style="color:#87cefa;">start_link/1</span>,<span style="color:#87cefa;">add_file/1</span>,<span style="color:#87cefa;">list_files/0</span>,<span style="color:#87cefa;">stop/0</span>,
        <span style="color:#87cefa;">retrieve_file/2</span>,<span style="color:#87cefa;">delete_file/2</span>]).

<span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">gen_server callbacks
</span><span style="color:#b0c4de;">-export</span>([<span style="color:#87cefa;">init/1</span>, <span style="color:#87cefa;">handle_call/3</span>, <span style="color:#87cefa;">handle_cast/2</span>, <span style="color:#87cefa;">handle_info/2</span>,
         <span style="color:#87cefa;">terminate/2</span>, <span style="color:#87cefa;">code_change/3</span>]).

<span style="color:#b0c4de;">-record</span>(<span style="color:#b0c4de;">state</span>,
        { <span style="color:#7fffd4;">node_root</span> :: <span style="color:#98fb98;">string</span>()
         }).

<span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">===================================================================
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">API
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">===================================================================
</span><span style="color:#87cefa;">start_link</span>(<span style="color:#eedd82;">NodeRoot</span>) -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">start_link</span>({<span style="color:#7fffd4;">local</span>, ?<span style="color:#b0c4de;">MODULE</span>}, ?<span style="color:#b0c4de;">MODULE</span>, <span style="color:#eedd82;">NodeRoot</span>, []).

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">add_file</span>(#<span style="color:#b0c4de;">wn_file</span>{}) -&gt; <span style="color:#7fffd4;">ok</span> | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).
<span style="color:#87cefa;">add_file</span>(<span style="color:#eedd82;">WnFile</span>) -&gt;
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,{<span style="color:#7fffd4;">add_file</span>,<span style="color:#eedd82;">WnFile</span>}) <span style="color:#00ffff;">of</span>
        {<span style="color:#7fffd4;">ok</span>,{<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">Ref</span>}} -&gt;
            {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">IoDev</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">open</span>(<span style="color:#eedd82;">WnFile</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">file</span>,[<span style="color:#7fffd4;">read</span>,<span style="color:#7fffd4;">binary</span>]),
            <span style="color:#eedd82;">Pid</span> ! {<span style="color:#eedd82;">Ref</span>,<span style="color:#b0c4de;">self</span>(),<span style="color:#eedd82;">IoDev</span>},
            <span style="color:#00ffff;">receive</span>
                {<span style="color:#eedd82;">Ref</span>,<span style="color:#eedd82;">Result</span>} -&gt; <span style="color:#eedd82;">Result</span>
            <span style="color:#00ffff;">end</span>;
        <span style="color:#eedd82;">Error</span> -&gt; <span style="color:#eedd82;">Error</span>
    <span style="color:#00ffff;">end</span>.

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">list_files</span>() -&gt; [#<span style="color:#b0c4de;">wn_file</span>{}]).         
<span style="color:#87cefa;">list_files</span>() -&gt;
   <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#7fffd4;">list_all_files</span>).

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">stop</span>() -&gt; <span style="color:#7fffd4;">ok</span>).         
<span style="color:#87cefa;">stop</span>() -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#7fffd4;">stop</span>).

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">retrieve_file</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#98fb98;">string</span>()) -&gt; {<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">string</span>()} | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).             
<span style="color:#87cefa;">retrieve_file</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Id</span>) -&gt;
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,{<span style="color:#7fffd4;">retrieve_file</span>,<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Id</span>}) <span style="color:#00ffff;">of</span>
        {<span style="color:#7fffd4;">ok</span>,{<span style="color:#eedd82;">ReadDev</span>,<span style="color:#eedd82;">Name</span>}} -&gt;
            <span style="color:#98fb98;">retrieve_file</span>(<span style="color:#eedd82;">ReadDev</span>,<span style="color:#eedd82;">Name</span>,<span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">open</span>(<span style="color:#eedd82;">Name</span>,[<span style="color:#7fffd4;">write</span>,<span style="color:#7fffd4;">binary</span>]));
        <span style="color:#eedd82;">X</span> -&gt; <span style="color:#eedd82;">X</span>
    <span style="color:#00ffff;">end</span>.
<span style="color:#87cefa;">retrieve_file</span>(<span style="color:#eedd82;">ReadDev</span>,<span style="color:#eedd82;">Name</span>,{<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">WriteDev</span>}) -&gt;
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">receive_file_client</span>(<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>) <span style="color:#00ffff;">of</span>
        <span style="color:#7fffd4;">ok</span> -&gt; {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">Name</span>};
        <span style="color:#eedd82;">Err</span> -&gt; <span style="color:#eedd82;">Err</span>
    <span style="color:#00ffff;">end</span>;
<span style="color:#87cefa;">retrieve_file</span>(<span style="color:#eedd82;">ReadDev</span>,<span style="color:#eedd82;">_Name</span>,<span style="color:#eedd82;">Err</span>) -&gt;
    <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">close</span>(<span style="color:#eedd82;">ReadDev</span>),
    <span style="color:#eedd82;">Err</span>.

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">delete_file</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#98fb98;">string</span>()) -&gt; <span style="color:#7fffd4;">ok</span> | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).
<span style="color:#87cefa;">delete_file</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Id</span>) -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,{<span style="color:#7fffd4;">delete_file</span>,<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Id</span>}).

<span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">===================================================================
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">gen_server callbacks
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">===================================================================
</span>
<span style="color:#87cefa;">init</span>(<span style="color:#eedd82;">NodeRoot</span>) -&gt;
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">ensure_dir</span>(<span style="color:#eedd82;">NodeRoot</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#b0c4de;">atom_to_list</span>(<span style="color:#b0c4de;">node</span>())<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span>),
    {<span style="color:#7fffd4;">ok</span>, #<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">node_root</span> = <span style="color:#eedd82;">NodeRoot</span>}}.

<span style="color:#87cefa;">handle_call</span>(<span style="color:#7fffd4;">stop</span>,<span style="color:#eedd82;">_From</span>,<span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">stop</span>,<span style="color:#7fffd4;">normal</span>,<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">State</span>};

<span style="color:#87cefa;">handle_call</span>(<span style="color:#7fffd4;">list_all_files</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#b0c4de;">spawn_link</span>(<span style="color:#98fb98;">file_collector</span>(<span style="color:#eedd82;">From</span>)),
    {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>};

<span style="color:#87cefa;">handle_call</span>(<span style="color:#7fffd4;">list_files</span>,<span style="color:#eedd82;">_From</span>,<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#eedd82;">PropList</span> = <span style="color:#98fb98;">check_files</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">node_root</span>),
    {<span style="color:#7fffd4;">reply</span>,[<span style="color:#eedd82;">V</span> <span style="color:#00ffff;">||</span> {<span style="color:#eedd82;">_</span>,<span style="color:#eedd82;">V</span>} <span style="color:#00ffff;">&lt;-</span> <span style="color:#eedd82;">PropList</span>],<span style="color:#eedd82;">State</span>};

<span style="color:#87cefa;">handle_call</span>({<span style="color:#7fffd4;">delete_file</span>,<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Id</span>},<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#00ffff;">case</span> {<span style="color:#b0c4de;">node</span>() == <span style="color:#eedd82;">Node</span>, <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">member</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#b0c4de;">nodes</span>())} <span style="color:#00ffff;">of</span>
        {<span style="color:#7fffd4;">true</span>,<span style="color:#7fffd4;">false</span>} -&gt;     
            {<span style="color:#7fffd4;">reply</span>,<span style="color:#98fb98;">try_delete_file</span>(<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">State</span>),<span style="color:#eedd82;">State</span>};
        {<span style="color:#7fffd4;">false</span>,<span style="color:#7fffd4;">true</span>} -&gt;
            <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#7fffd4;">erlang</span>,<span style="color:#7fffd4;">whereis</span>,[?<span style="color:#b0c4de;">MODULE</span>]) <span style="color:#00ffff;">of</span>
                <span style="color:#7fffd4;">undefined</span> -&gt; {<span style="color:#7fffd4;">reply</span>,{<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">noresides</span>},<span style="color:#eedd82;">State</span>};               
                <span style="color:#eedd82;">_Pid</span> -&gt;
                    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">cast</span>({?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#eedd82;">Node</span>},{<span style="color:#7fffd4;">delete_file</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Id</span>}),
                    {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>}
            <span style="color:#00ffff;">end</span>;
        {<span style="color:#7fffd4;">false</span>,<span style="color:#7fffd4;">false</span>} -&gt;
            {<span style="color:#7fffd4;">reply</span>,{<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">noresides</span>},<span style="color:#eedd82;">State</span>}
    <span style="color:#00ffff;">end</span>;

<span style="color:#87cefa;">handle_call</span>({<span style="color:#7fffd4;">retrieve_file</span>,<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Id</span>},<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#00ffff;">case</span> {<span style="color:#b0c4de;">node</span>() == <span style="color:#eedd82;">Node</span>, <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">member</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#b0c4de;">nodes</span>())} <span style="color:#00ffff;">of</span>
        {<span style="color:#7fffd4;">true</span>,<span style="color:#7fffd4;">false</span>} -&gt;
            <span style="color:#eedd82;">Result</span> = <span style="color:#98fb98;">try_retrieve</span>(<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">State</span>),
            {<span style="color:#7fffd4;">reply</span>,<span style="color:#eedd82;">Result</span>,<span style="color:#eedd82;">State</span>};
        {<span style="color:#7fffd4;">false</span>,<span style="color:#7fffd4;">true</span>} -&gt;
            <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#7fffd4;">erlang</span>,<span style="color:#7fffd4;">whereis</span>,[?<span style="color:#b0c4de;">MODULE</span>]) <span style="color:#00ffff;">of</span>
                <span style="color:#7fffd4;">undefined</span> -&gt; {<span style="color:#7fffd4;">reply</span>,{<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">noresides</span>},<span style="color:#eedd82;">State</span>};               
                <span style="color:#eedd82;">_Pid</span> -&gt;
                    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">cast</span>({?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#eedd82;">Node</span>},{<span style="color:#7fffd4;">retrieve_file</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Id</span>}),
                    {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>}
            <span style="color:#00ffff;">end</span>;
        {<span style="color:#7fffd4;">false</span>,<span style="color:#7fffd4;">false</span>} -&gt;
            {<span style="color:#7fffd4;">reply</span>,{<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">noresides</span>},<span style="color:#eedd82;">State</span>}
    <span style="color:#00ffff;">end</span>;

<span style="color:#87cefa;">handle_call</span>({<span style="color:#7fffd4;">add_file</span>,<span style="color:#eedd82;">WnFile</span>}, <span style="color:#eedd82;">From</span>, <span style="color:#eedd82;">State</span>) -&gt;
    #<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">resides</span>=<span style="color:#eedd82;">Node</span>} = <span style="color:#eedd82;">WnFile</span>,
    <span style="color:#00ffff;">case</span> {<span style="color:#eedd82;">Node</span> == <span style="color:#b0c4de;">node</span>(),<span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">member</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#b0c4de;">nodes</span>())} <span style="color:#00ffff;">of</span>
        {<span style="color:#7fffd4;">true</span>,<span style="color:#7fffd4;">false</span>} -&gt;
            <span style="color:#eedd82;">Result</span> = <span style="color:#98fb98;">try_add</span>(<span style="color:#eedd82;">WnFile</span>,<span style="color:#eedd82;">State</span>),
            {<span style="color:#7fffd4;">reply</span>,<span style="color:#eedd82;">Result</span>,<span style="color:#eedd82;">State</span>};
        {<span style="color:#7fffd4;">false</span>,<span style="color:#7fffd4;">true</span>} -&gt;
            <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#7fffd4;">erlang</span>,<span style="color:#7fffd4;">whereis</span>,[?<span style="color:#b0c4de;">MODULE</span>]) <span style="color:#00ffff;">of</span>
                <span style="color:#7fffd4;">undefined</span> -&gt; {<span style="color:#7fffd4;">reply</span>,{<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">noresides</span>},<span style="color:#eedd82;">State</span>};               
                <span style="color:#eedd82;">_Pid</span> -&gt;
                    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">cast</span>({?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#eedd82;">Node</span>},{<span style="color:#7fffd4;">add_file</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">WnFile</span>}),
                    {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>}
            <span style="color:#00ffff;">end</span>;
        {<span style="color:#7fffd4;">false</span>,<span style="color:#7fffd4;">false</span>} -&gt;
            {<span style="color:#7fffd4;">reply</span>,{<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">noresides</span>},<span style="color:#eedd82;">State</span>}
    <span style="color:#00ffff;">end</span>.

<span style="color:#87cefa;">handle_cast</span>({<span style="color:#7fffd4;">delete_file</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Id</span>},<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#eedd82;">Result</span> = <span style="color:#98fb98;">try_delete_file</span>(<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">State</span>),
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">reply</span>(<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Result</span>),
    {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>};

<span style="color:#87cefa;">handle_cast</span>({<span style="color:#7fffd4;">retrieve_file</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Id</span>},<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#eedd82;">Result</span> = <span style="color:#98fb98;">try_retrieve</span>(<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">State</span>),
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">reply</span>(<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Result</span>),
    {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>};

<span style="color:#87cefa;">handle_cast</span>({<span style="color:#7fffd4;">add_file</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">WnFile</span>},<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#eedd82;">Result</span> = <span style="color:#98fb98;">try_add</span>(<span style="color:#eedd82;">WnFile</span>,<span style="color:#eedd82;">State</span>),
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">reply</span>(<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Result</span>),
    {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>}.

<span style="color:#87cefa;">handle_info</span>(<span style="color:#eedd82;">_Info</span>, <span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">noreply</span>, <span style="color:#eedd82;">State</span>}.

<span style="color:#87cefa;">terminate</span>(<span style="color:#eedd82;">_Reason</span>, <span style="color:#eedd82;">_State</span>) -&gt;
    <span style="color:#7fffd4;">ok</span>.

<span style="color:#87cefa;">code_change</span>(<span style="color:#eedd82;">_OldVsn</span>, <span style="color:#eedd82;">State</span>, <span style="color:#eedd82;">_Extra</span>) -&gt;
    {<span style="color:#7fffd4;">ok</span>, <span style="color:#eedd82;">State</span>}.

<span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">===================================================================
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">Internal functions
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">===================================================================
</span><span style="color:#87cefa;">check_files</span>(<span style="color:#eedd82;">Root</span>) -&gt;
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">ensure_dir</span>(<span style="color:#eedd82;">Root</span>),
    <span style="color:#eedd82;">Path</span> = <span style="color:#eedd82;">Root</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#b0c4de;">atom_to_list</span>(<span style="color:#b0c4de;">node</span>())<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span>,    
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">NameDirs</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">list_dir</span>(<span style="color:#eedd82;">Path</span>),
    <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foldl</span>(
      <span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">Dir</span>,<span style="color:#eedd82;">Acc</span>) -&gt;
              {<span style="color:#7fffd4;">ok</span>,[<span style="color:#eedd82;">File</span>]}  = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">list_dir</span>(<span style="color:#eedd82;">Path</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">Dir</span>),
              [{<span style="color:#eedd82;">Dir</span>,#<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#eedd82;">Dir</span>,
                             <span style="color:#7fffd4;">file</span> = <span style="color:#eedd82;">Path</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">Dir</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">File</span>,
                             <span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()}} | <span style="color:#eedd82;">Acc</span>]
      <span style="color:#00ffff;">end</span>,[],<span style="color:#eedd82;">NameDirs</span>).

<span style="color:#87cefa;">receive_file</span>(<span style="color:#eedd82;">Ref</span>,<span style="color:#eedd82;">WriteDev</span>) -&gt;
    <span style="color:#00ffff;">fun</span>() -&gt;
            <span style="color:#00ffff;">receive</span>
                {<span style="color:#eedd82;">Ref</span>,<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">ReadDev</span>} -&gt;
                    <span style="color:#98fb98;">receive_file</span>(<span style="color:#eedd82;">Ref</span>,<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>)
            <span style="color:#00ffff;">end</span>
    <span style="color:#00ffff;">end</span>.

<span style="color:#87cefa;">receive_file</span>(<span style="color:#eedd82;">Ref</span>,<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>) -&gt;
    <span style="color:#eedd82;">Res</span> = <span style="color:#98fb98;">close_transfer</span>(<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>,
                         <span style="color:#98fb98;">transfer</span>(<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>)),
    <span style="color:#eedd82;">Pid</span> ! {<span style="color:#eedd82;">Ref</span>,<span style="color:#eedd82;">Res</span>}.

<span style="color:#87cefa;">receive_file_client</span>(<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>) -&gt;
    <span style="color:#98fb98;">close_transfer</span>(<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>,
                   <span style="color:#98fb98;">transfer</span>(<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>)).

<span style="color:#87cefa;">close_transfer</span>(<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>,<span style="color:#eedd82;">TransferResult</span>) -&gt;
    <span style="color:#00ffff;">case</span>
        <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">dropwhile</span>(<span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">X</span>) -&gt; <span style="color:#eedd82;">X</span> == <span style="color:#7fffd4;">ok</span> <span style="color:#00ffff;">end</span>,
                        [<span style="color:#eedd82;">TransferResult</span>,
                         <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">close</span>(<span style="color:#eedd82;">WriteDev</span>),
                         <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">close</span>(<span style="color:#eedd82;">ReadDev</span>)]) <span style="color:#00ffff;">of</span>
        [] -&gt; <span style="color:#7fffd4;">ok</span>;
        [<span style="color:#eedd82;">X</span>|<span style="color:#eedd82;">_</span>] -&gt; <span style="color:#eedd82;">X</span>
    <span style="color:#00ffff;">end</span>.

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">transfer</span>(<span style="color:#b0c4de;">pid</span>(),<span style="color:#b0c4de;">pid</span>()) -&gt; <span style="color:#7fffd4;">ok</span> | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).
<span style="color:#87cefa;">transfer</span>(<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>) -&gt;
    <span style="color:#98fb98;">transfer</span>(<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>,<span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">read</span>(<span style="color:#eedd82;">ReadDev</span>,1024)).

<span style="color:#87cefa;">transfer</span>(<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>,{<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">Data</span>}) -&gt;
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">write</span>(<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">Data</span>) <span style="color:#00ffff;">of</span>
        <span style="color:#7fffd4;">ok</span> -&gt; <span style="color:#98fb98;">transfer</span>(<span style="color:#eedd82;">WriteDev</span>,<span style="color:#eedd82;">ReadDev</span>,<span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">read</span>(<span style="color:#eedd82;">ReadDev</span>,1024));           
        <span style="color:#eedd82;">Err</span> -&gt; <span style="color:#eedd82;">Err</span>
    <span style="color:#00ffff;">end</span>;
<span style="color:#87cefa;">transfer</span>(<span style="color:#eedd82;">_WriteDev</span>,<span style="color:#eedd82;">_ReadDev</span>,<span style="color:#7fffd4;">eof</span>) -&gt; <span style="color:#7fffd4;">ok</span>;
<span style="color:#87cefa;">transfer</span>(<span style="color:#eedd82;">_WriteDev</span>,<span style="color:#eedd82;">_ReadDev</span>,<span style="color:#eedd82;">Err</span>) -&gt; <span style="color:#eedd82;">Err</span>.

<span style="color:#87cefa;">file_collector</span>(<span style="color:#eedd82;">From</span>) -&gt;
    <span style="color:#eedd82;">Nodes</span> = [<span style="color:#b0c4de;">node</span>()|<span style="color:#b0c4de;">nodes</span>()],
    <span style="color:#00ffff;">fun</span>() -&gt;
            <span style="color:#eedd82;">Res</span> =
                <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foldl</span>(
                  <span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Acc</span>) -&gt;
                          <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#7fffd4;">erlang</span>,<span style="color:#7fffd4;">whereis</span>,[?<span style="color:#b0c4de;">MODULE</span>]) <span style="color:#00ffff;">of</span>
                              <span style="color:#7fffd4;">undefined</span> -&gt; <span style="color:#eedd82;">Acc</span>;
                              <span style="color:#eedd82;">_Pid</span> -&gt;
                                  <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>({?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#eedd82;">Node</span>},
                                                  <span style="color:#7fffd4;">list_files</span>)<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">Acc</span>
                        <span style="color:#00ffff;">end</span>
                  <span style="color:#00ffff;">end</span>,[],<span style="color:#eedd82;">Nodes</span>),
            <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">reply</span>(<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Res</span>)
    <span style="color:#00ffff;">end</span>.

<span style="color:#87cefa;">try_delete_file</span>(<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#eedd82;">PropList</span> = <span style="color:#98fb98;">check_files</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">node_root</span>),
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">proplists</span>:<span style="color:#98fb98;">lookup</span>(<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">PropList</span>) <span style="color:#00ffff;">of</span>
        <span style="color:#7fffd4;">none</span> -&gt;
            {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">noexists</span>};
        {<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">WnFile</span>} -&gt;
            <span style="color:#eedd82;">List</span> = [ <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">WnFile</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">file</span>),
                     <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">del_dir</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">node_root</span><span style="color:#ffc0cb;font-weight:bold;">++</span>
                                  <span style="color:#b0c4de;">atom_to_list</span>(<span style="color:#b0c4de;">node</span>())<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span>
                                  <span style="color:#eedd82;">WnFile</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">id</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span>) ],
            <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">dropwhile</span>(<span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">X</span>) -&gt; <span style="color:#eedd82;">X</span> == <span style="color:#7fffd4;">ok</span> <span style="color:#00ffff;">end</span>,<span style="color:#eedd82;">List</span>) <span style="color:#00ffff;">of</span>
                [] -&gt; <span style="color:#7fffd4;">ok</span>;                    
                [<span style="color:#eedd82;">X</span>|<span style="color:#eedd82;">_</span>] -&gt; <span style="color:#eedd82;">X</span>
            <span style="color:#00ffff;">end</span>
    <span style="color:#00ffff;">end</span>.

<span style="color:#87cefa;">try_retrieve</span>(<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#eedd82;">PropList</span> = <span style="color:#98fb98;">check_files</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">node_root</span>),
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">proplists</span>:<span style="color:#98fb98;">lookup</span>(<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">PropList</span>) <span style="color:#00ffff;">of</span>
        <span style="color:#7fffd4;">none</span> -&gt; {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">noexists</span>};
        {<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">WnFile</span>} -&gt;
            <span style="color:#eedd82;">Path</span> = <span style="color:#eedd82;">WnFile</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">file</span>,
            {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">ReadDev</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">open</span>(<span style="color:#eedd82;">Path</span>,[<span style="color:#7fffd4;">read</span>,<span style="color:#7fffd4;">binary</span>]),
            {<span style="color:#7fffd4;">ok</span>,{<span style="color:#eedd82;">ReadDev</span>,<span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Path</span>)}}
    <span style="color:#00ffff;">end</span>.

<span style="color:#87cefa;">try_add</span>(<span style="color:#eedd82;">WnFile</span>,<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#eedd82;">Path</span> = <span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">node_root</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span>
        <span style="color:#b0c4de;">atom_to_list</span>(<span style="color:#b0c4de;">node</span>())<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">WnFile</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">id</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span>
        <span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">WnFile</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">file</span>),
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_file</span>(<span style="color:#eedd82;">Path</span>) <span style="color:#00ffff;">of</span>
        <span style="color:#7fffd4;">true</span> -&gt; {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">exists</span>};
        <span style="color:#7fffd4;">false</span> -&gt;
            <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">ensure_dir</span>(<span style="color:#eedd82;">Path</span>),
            {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">WriteDev</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">open</span>(<span style="color:#eedd82;">Path</span>,[<span style="color:#7fffd4;">write</span>,<span style="color:#7fffd4;">binary</span>]),
            <span style="color:#eedd82;">Ref</span> = <span style="color:#b0c4de;">make_ref</span>(),
            <span style="color:#eedd82;">Pid</span> = <span style="color:#b0c4de;">spawn</span>(<span style="color:#98fb98;">receive_file</span>(<span style="color:#eedd82;">Ref</span>,<span style="color:#eedd82;">WriteDev</span>)),
            {<span style="color:#7fffd4;">ok</span>,{<span style="color:#eedd82;">Pid</span>,<span style="color:#eedd82;">Ref</span>}}
    <span style="color:#00ffff;">end</span>.</pre>
<p><!--- End Of Snippet --></p>
<h2>Listing: wn_file_layer_tests.erl</h2>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@author Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@copyright (C) 2010, Gianfranco
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">Created : 19 Dec 2010 by Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#b0c4de;">-module</span>(<span style="color:#7fffd4;">wn_file_layer_tests</span>).
<span style="color:#b0c4de;">-include_lib</span>(<span style="color:#ffa07a;">"eunit/include/eunit.hrl"</span>).
<span style="color:#b0c4de;">-include</span>(<span style="color:#ffa07a;">"include/worker_net.hrl"</span>).

<span style="color:#b0c4de;">-define</span>(<span style="color:#b0c4de;">NODE_ROOT</span>,
        <span style="color:#ffa07a;">"/Users/zenon/ErlangBlog/worker_net-0.1/node_root/"</span>).

<span style="color:#87cefa;">file_layer_local_test_</span>() -&gt;
    {<span style="color:#7fffd4;">foreach</span>,
     <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">setup/0</span>,
     <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">cleanup/1</span>,
     [
      {<span style="color:#ffa07a;">"Can store file locally"</span>, <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">store_locally/0</span>},
      {<span style="color:#ffa07a;">"Can retrieve files locally"</span>,<span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">store_retrieve_locally/0</span>},
      {<span style="color:#ffa07a;">"Can delete files locally"</span>,<span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">store_delete_locally/0</span>}
      ]}.

<span style="color:#87cefa;">file_layer_distributed_test_</span>() -&gt;
   {<span style="color:#7fffd4;">foreach</span>,
     <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">distr_setup/0</span>,
     <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">distr_cleanup/1</span>,
     [
      <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">can_store_distributed/1</span>,
      <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">can_retrieve_distributed/1</span>,
      <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">can_delete_distributed/1</span>,
      <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">must_retain/1</span>
      ]}.

<span style="color:#87cefa;">must_retain</span>([<span style="color:#eedd82;">N1</span>,<span style="color:#eedd82;">N2</span>]) -&gt;
    {<span style="color:#ffa07a;">"Must retain information between node kill and node restart"</span>,
     <span style="color:#00ffff;">fun</span>() -&gt;
             ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>},<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">start_link</span>,[?<span style="color:#b0c4de;">NODE_ROOT</span>])),
             ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>},<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">start_link</span>,[?<span style="color:#b0c4de;">NODE_ROOT</span>])),
             <span style="color:#eedd82;">Path</span> = <span style="color:#98fb98;">create_file_at</span>(?<span style="color:#b0c4de;">NODE_ROOT</span>),
             <span style="color:#eedd82;">FileA</span> = #<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"File1"</span>,<span style="color:#7fffd4;">file</span> = <span style="color:#eedd82;">Path</span>,<span style="color:#7fffd4;">resides</span> = <span style="color:#eedd82;">N1</span>},
             <span style="color:#eedd82;">FileB</span> = #<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#ffa07a;">"File2"</span>,<span style="color:#7fffd4;">file</span> = <span style="color:#eedd82;">Path</span>,<span style="color:#7fffd4;">resides</span> = <span style="color:#eedd82;">N2</span>},
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">add_file</span>(<span style="color:#eedd82;">FileA</span>),
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">add_file</span>(<span style="color:#eedd82;">FileB</span>),
             [<span style="color:#eedd82;">ResA</span>,<span style="color:#eedd82;">ResB</span>] = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">list_files</span>(),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Path</span>),<span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">ResA</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">file</span>)),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Path</span>),<span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">ResB</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">file</span>)),
             <span style="color:#ff7f24;">% </span><span style="color:#ff7f24;">Kill N1 and N2
</span>             <span style="color:#98fb98;">slave</span>:<span style="color:#98fb98;">stop</span>(<span style="color:#eedd82;">N1</span>),
             <span style="color:#98fb98;">slave</span>:<span style="color:#98fb98;">stop</span>(<span style="color:#eedd82;">N2</span>),
             ?<span style="color:#b0c4de;">assertEqual</span>([],<span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">list_files</span>()),
             <span style="color:#ff7f24;">% </span><span style="color:#ff7f24;">Restart and check
</span>             <span style="color:#eedd82;">Host</span> = <span style="color:#b0c4de;">list_to_atom</span>(<span style="color:#98fb98;">inet_db</span>:<span style="color:#98fb98;">gethostname</span>()),
             <span style="color:#eedd82;">Args</span> = <span style="color:#ffa07a;">" -pa "</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#b0c4de;">hd</span>(<span style="color:#98fb98;">code</span>:<span style="color:#98fb98;">get_path</span>())<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">" -setcookie eunit"</span>,
             {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">N1</span>} = <span style="color:#98fb98;">slave</span>:<span style="color:#98fb98;">start</span>(<span style="color:#eedd82;">Host</span>,<span style="color:#7fffd4;">n1</span>,<span style="color:#eedd82;">Args</span>),
             {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">N2</span>} = <span style="color:#98fb98;">slave</span>:<span style="color:#98fb98;">start</span>(<span style="color:#eedd82;">Host</span>,<span style="color:#7fffd4;">n2</span>,<span style="color:#eedd82;">Args</span>),
             <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">net_kernel</span>,<span style="color:#7fffd4;">connect_node</span>,[<span style="color:#eedd82;">N2</span>]),
             ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>},<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">start_link</span>,[?<span style="color:#b0c4de;">NODE_ROOT</span>])),
             ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>},<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">start_link</span>,[?<span style="color:#b0c4de;">NODE_ROOT</span>])),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResA</span>,<span style="color:#eedd82;">ResB</span>],<span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">list_files</span>())
     <span style="color:#00ffff;">end</span>}.

<span style="color:#87cefa;">can_delete_distributed</span>([<span style="color:#eedd82;">N1</span>,<span style="color:#eedd82;">N2</span>]) -&gt;
    {<span style="color:#ffa07a;">"Can delete file distributed"</span>,
     <span style="color:#00ffff;">fun</span>() -&gt;
             ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>},<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">start_link</span>,[?<span style="color:#b0c4de;">NODE_ROOT</span>])),
             ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>},<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">start_link</span>,[?<span style="color:#b0c4de;">NODE_ROOT</span>])),
             <span style="color:#eedd82;">Path</span> = <span style="color:#98fb98;">create_file_at</span>(?<span style="color:#b0c4de;">NODE_ROOT</span>),
             <span style="color:#eedd82;">Id</span> = <span style="color:#ffa07a;">"AddedFile1"</span>,
             <span style="color:#eedd82;">File</span> = #<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#eedd82;">Id</span>,<span style="color:#7fffd4;">file</span> = <span style="color:#eedd82;">Path</span>,<span style="color:#7fffd4;">resides</span> = <span style="color:#eedd82;">N1</span>},
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">add_file</span>(<span style="color:#eedd82;">File</span>),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">delete_file</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#eedd82;">Id</span>)),
             ?<span style="color:#b0c4de;">assertEqual</span>([],<span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">list_files</span>()),
             <span style="color:#ff7f24;">% </span><span style="color:#ff7f24;">Check change in file-system
</span>             <span style="color:#eedd82;">ExpectedPath</span> = ?<span style="color:#b0c4de;">NODE_ROOT</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span>
                 <span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#b0c4de;">atom_to_list</span>(<span style="color:#b0c4de;">node</span>())
                 <span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">Id</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Path</span>),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">false</span>,<span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_file</span>(<span style="color:#eedd82;">ExpectedPath</span>)),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">false</span>,<span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_dir</span>(?<span style="color:#b0c4de;">NODE_ROOT</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span>
                                               <span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#b0c4de;">atom_to_list</span>(<span style="color:#eedd82;">N1</span>)<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span>
                                               <span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">Id</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span>))
     <span style="color:#00ffff;">end</span>}.

<span style="color:#87cefa;">can_retrieve_distributed</span>([<span style="color:#eedd82;">N1</span>,<span style="color:#eedd82;">N2</span>]) -&gt;
    {<span style="color:#ffa07a;">"Can retrieve file distributed"</span>,
     <span style="color:#00ffff;">fun</span>() -&gt;
             ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>},<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">start_link</span>,[?<span style="color:#b0c4de;">NODE_ROOT</span>])),
             ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>},<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">start_link</span>,[?<span style="color:#b0c4de;">NODE_ROOT</span>])),
             <span style="color:#eedd82;">Path</span> = <span style="color:#98fb98;">create_file_at</span>(?<span style="color:#b0c4de;">NODE_ROOT</span>),
             <span style="color:#eedd82;">Id</span> = <span style="color:#ffa07a;">"AddedFile1"</span>,
             <span style="color:#eedd82;">File</span> = #<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#eedd82;">Id</span>,<span style="color:#7fffd4;">file</span> = <span style="color:#eedd82;">Path</span>,<span style="color:#7fffd4;">resides</span> = <span style="color:#eedd82;">N1</span>},
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">add_file</span>(<span style="color:#eedd82;">File</span>),
             {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">OriginalData</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">read_file</span>(<span style="color:#eedd82;">Path</span>),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">Path</span>)),
             <span style="color:#ff7f24;">% </span><span style="color:#ff7f24;">Retrieve and see change in file system
</span>             {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">FileName</span>} =  <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">retrieve_file</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#eedd82;">Id</span>),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">true</span>,<span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_file</span>(<span style="color:#eedd82;">FileName</span>)),
             {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">NewData</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">read_file</span>(<span style="color:#eedd82;">FileName</span>),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#eedd82;">OriginalData</span>,<span style="color:#eedd82;">NewData</span>),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Path</span>),<span style="color:#eedd82;">FileName</span>),
             <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">FileName</span>)
     <span style="color:#00ffff;">end</span>}.

<span style="color:#87cefa;">can_store_distributed</span>([<span style="color:#eedd82;">N1</span>,<span style="color:#eedd82;">N2</span>]) -&gt;
    {<span style="color:#ffa07a;">"Can store file distributed"</span>,
     <span style="color:#00ffff;">fun</span>() -&gt;
             ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>},<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">start_link</span>,[?<span style="color:#b0c4de;">NODE_ROOT</span>])),
             ?<span style="color:#b0c4de;">assertMatch</span>({<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>},<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">start_link</span>,[?<span style="color:#b0c4de;">NODE_ROOT</span>])),
             <span style="color:#eedd82;">Path</span> = <span style="color:#98fb98;">create_file_at</span>(?<span style="color:#b0c4de;">NODE_ROOT</span>),
             <span style="color:#eedd82;">Id</span> = <span style="color:#ffa07a;">"AddedFile1"</span>,
             <span style="color:#eedd82;">File</span> = #<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#eedd82;">Id</span>,<span style="color:#7fffd4;">file</span> = <span style="color:#eedd82;">Path</span>,<span style="color:#7fffd4;">resides</span> = <span style="color:#eedd82;">N1</span>},
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">add_file</span>(<span style="color:#eedd82;">File</span>),
             [<span style="color:#eedd82;">Res</span>] = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">list_files</span>(),
             [<span style="color:#eedd82;">Res2</span>] = <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">list_files</span>,[]),
             [<span style="color:#eedd82;">Res3</span>] = <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">list_files</span>,[]),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Path</span>),<span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Res</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">file</span>)),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">Res</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">id</span>),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#eedd82;">Res</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">resides</span>),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#eedd82;">Res</span>,<span style="color:#eedd82;">Res2</span>),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#eedd82;">Res2</span>,<span style="color:#eedd82;">Res3</span>),
             <span style="color:#ff7f24;">% </span><span style="color:#ff7f24;">Check change in file-system
</span>             <span style="color:#eedd82;">ExpectedPath</span> = ?<span style="color:#b0c4de;">NODE_ROOT</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#b0c4de;">atom_to_list</span>(<span style="color:#eedd82;">N1</span>)<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span>
                 <span style="color:#eedd82;">Id</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Path</span>),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">true</span>,<span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_file</span>(<span style="color:#eedd82;">Path</span>)),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">true</span>,<span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_file</span>(<span style="color:#eedd82;">ExpectedPath</span>))        
     <span style="color:#00ffff;">end</span>}.

<span style="color:#87cefa;">store_locally</span>() -&gt;
    <span style="color:#eedd82;">Path</span> = <span style="color:#98fb98;">create_file_at</span>(?<span style="color:#b0c4de;">NODE_ROOT</span>),
    <span style="color:#eedd82;">Id</span> = <span style="color:#ffa07a;">"AddedFile1"</span>,
    <span style="color:#eedd82;">File</span> = #<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#eedd82;">Id</span>,<span style="color:#7fffd4;">file</span> = <span style="color:#eedd82;">Path</span>,<span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()},
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">add_file</span>(<span style="color:#eedd82;">File</span>),
    [<span style="color:#eedd82;">Res</span>] = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">list_files</span>(),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Path</span>),<span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Res</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">file</span>)),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#eedd82;">Id</span>,<span style="color:#eedd82;">Res</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">id</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#eedd82;">Res</span>#<span style="color:#b0c4de;">wn_file</span>.<span style="color:#7fffd4;">resides</span>),   
    <span style="color:#ff7f24;">% </span><span style="color:#ff7f24;">Check change in file-system
</span>    <span style="color:#eedd82;">ExpectedPath</span> = ?<span style="color:#b0c4de;">NODE_ROOT</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#b0c4de;">atom_to_list</span>(<span style="color:#b0c4de;">node</span>())<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span>
        <span style="color:#eedd82;">Id</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Path</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">true</span>,<span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_file</span>(<span style="color:#eedd82;">Path</span>)),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">true</span>,<span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_file</span>(<span style="color:#eedd82;">ExpectedPath</span>)).

<span style="color:#87cefa;">store_retrieve_locally</span>() -&gt;
    <span style="color:#eedd82;">Path</span> = <span style="color:#98fb98;">create_file_at</span>(?<span style="color:#b0c4de;">NODE_ROOT</span>),
    <span style="color:#eedd82;">Id</span> = <span style="color:#ffa07a;">"AddedFile1"</span>,
    <span style="color:#eedd82;">File</span> = #<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#eedd82;">Id</span>,<span style="color:#7fffd4;">file</span> = <span style="color:#eedd82;">Path</span>,<span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()},
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">add_file</span>(<span style="color:#eedd82;">File</span>),
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">OriginalData</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">read_file</span>(<span style="color:#eedd82;">Path</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">Path</span>)),
    <span style="color:#ff7f24;">% </span><span style="color:#ff7f24;">Retrieve and see change in file system
</span>    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">FileName</span>} =  <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">retrieve_file</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#eedd82;">Id</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">true</span>,<span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_file</span>(<span style="color:#eedd82;">FileName</span>)),
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">NewData</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">read_file</span>(<span style="color:#eedd82;">FileName</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#eedd82;">OriginalData</span>,<span style="color:#eedd82;">NewData</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Path</span>),<span style="color:#eedd82;">FileName</span>),
    <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">FileName</span>).

<span style="color:#87cefa;">store_delete_locally</span>() -&gt;
    <span style="color:#eedd82;">Path</span> = <span style="color:#98fb98;">create_file_at</span>(?<span style="color:#b0c4de;">NODE_ROOT</span>),
    <span style="color:#eedd82;">Id</span> = <span style="color:#ffa07a;">"AddedFile1"</span>,
    <span style="color:#eedd82;">File</span> = #<span style="color:#b0c4de;">wn_file</span>{<span style="color:#7fffd4;">id</span> = <span style="color:#eedd82;">Id</span>,<span style="color:#7fffd4;">file</span> = <span style="color:#eedd82;">Path</span>,<span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()},
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">add_file</span>(<span style="color:#eedd82;">File</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">delete_file</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#eedd82;">Id</span>)),
    ?<span style="color:#b0c4de;">assertEqual</span>([],<span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">list_files</span>()),
    <span style="color:#ff7f24;">% </span><span style="color:#ff7f24;">Check change in file-system
</span>    <span style="color:#eedd82;">ExpectedPath</span> = ?<span style="color:#b0c4de;">NODE_ROOT</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span>
        <span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#b0c4de;">atom_to_list</span>(<span style="color:#b0c4de;">node</span>())
        <span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">Id</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#98fb98;">filename</span>:<span style="color:#98fb98;">basename</span>(<span style="color:#eedd82;">Path</span>),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">false</span>,<span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_file</span>(<span style="color:#eedd82;">ExpectedPath</span>)),
    ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">false</span>,<span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_dir</span>(?<span style="color:#b0c4de;">NODE_ROOT</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span>
                                      <span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#b0c4de;">atom_to_list</span>(<span style="color:#b0c4de;">node</span>())<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span>
                                      <span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">Id</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span>)).

<span style="color:#ff7f24;">%%</span><span style="color:#ff7f24;">------------------------------------------------------------------
</span><span style="color:#87cefa;">create_file_at</span>(<span style="color:#eedd82;">X</span>) -&gt;
    <span style="color:#eedd82;">Path</span> = <span style="color:#eedd82;">X</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"EUnitFile"</span>,
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">ensure_dir</span>(<span style="color:#eedd82;">X</span>),
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">write_file</span>(<span style="color:#eedd82;">Path</span>,&lt;&lt;1,2,3&gt;&gt;),
    <span style="color:#eedd82;">Path</span>.

<span style="color:#87cefa;">clean_up</span>(<span style="color:#eedd82;">X</span>) -&gt;
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">filelib</span>:<span style="color:#98fb98;">is_dir</span>(<span style="color:#eedd82;">X</span>) <span style="color:#00ffff;">of</span>
        <span style="color:#7fffd4;">true</span> -&gt;
            {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">Files</span>} = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">list_dir</span>(<span style="color:#eedd82;">X</span>),
            <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foreach</span>(
              <span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">File</span>) -&gt;
                      <span style="color:#98fb98;">clean_up</span>(<span style="color:#eedd82;">X</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">"/"</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">File</span>)
              <span style="color:#00ffff;">end</span>,<span style="color:#eedd82;">Files</span>),
            <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">del_dir</span>(<span style="color:#eedd82;">X</span>);
        <span style="color:#7fffd4;">false</span> -&gt;
            <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">file</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">X</span>)
    <span style="color:#00ffff;">end</span>.

<span style="color:#87cefa;">setup</span>() -&gt;
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>} = <span style="color:#98fb98;">net_kernel</span>:<span style="color:#98fb98;">start</span>([<span style="color:#7fffd4;">eunit_resource</span>,<span style="color:#7fffd4;">shortnames</span>]),
    <span style="color:#98fb98;">erlang</span>:<span style="color:#98fb98;">set_cookie</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#7fffd4;">eunit</span>),
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>} = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">start_link</span>(?<span style="color:#b0c4de;">NODE_ROOT</span>).

<span style="color:#87cefa;">cleanup</span>(<span style="color:#eedd82;">_</span>) -&gt;
    <span style="color:#98fb98;">clean_up</span>(?<span style="color:#b0c4de;">NODE_ROOT</span>),    
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">net_kernel</span>:<span style="color:#98fb98;">stop</span>(),
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_file_layer</span>:<span style="color:#98fb98;">stop</span>().

<span style="color:#87cefa;">distr_setup</span>() -&gt;
    <span style="color:#98fb98;">setup</span>(),
    <span style="color:#eedd82;">Host</span> = <span style="color:#b0c4de;">list_to_atom</span>(<span style="color:#98fb98;">inet_db</span>:<span style="color:#98fb98;">gethostname</span>()),
    <span style="color:#eedd82;">Args</span> = <span style="color:#ffa07a;">" -pa "</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#b0c4de;">hd</span>(<span style="color:#98fb98;">code</span>:<span style="color:#98fb98;">get_path</span>())<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">" -setcookie eunit"</span>,
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">N1</span>} = <span style="color:#98fb98;">slave</span>:<span style="color:#98fb98;">start</span>(<span style="color:#eedd82;">Host</span>,<span style="color:#7fffd4;">n1</span>,<span style="color:#eedd82;">Args</span>),
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">N2</span>} = <span style="color:#98fb98;">slave</span>:<span style="color:#98fb98;">start</span>(<span style="color:#eedd82;">Host</span>,<span style="color:#7fffd4;">n2</span>,<span style="color:#eedd82;">Args</span>),
    <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">net_kernel</span>,<span style="color:#7fffd4;">connect_node</span>,[<span style="color:#eedd82;">N2</span>]),
    [<span style="color:#eedd82;">N1</span>,<span style="color:#eedd82;">N2</span>].

<span style="color:#87cefa;">distr_cleanup</span>([<span style="color:#eedd82;">N1</span>,<span style="color:#eedd82;">N2</span>]) -&gt;
    <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">stop</span>,[]),
    <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_file_layer</span>,<span style="color:#7fffd4;">stop</span>,[]),
    <span style="color:#98fb98;">slave</span>:<span style="color:#98fb98;">stop</span>(<span style="color:#eedd82;">N1</span>),
    <span style="color:#98fb98;">slave</span>:<span style="color:#98fb98;">stop</span>(<span style="color:#eedd82;">N2</span>),    
    <span style="color:#98fb98;">cleanup</span>(<span style="color:#7fffd4;">nothing</span>).</pre>
<p><!--- End Of Snippet --></p>
<p>Cheers<br />
/G</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/erlcode.wordpress.com/417/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/erlcode.wordpress.com/417/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=erlcode.wordpress.com&#038;blog=15510807&#038;post=417&#038;subd=erlcode&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://erlcode.wordpress.com/2010/12/25/erlang-tdd-hands-on-project-workernet-part-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/861b8f824c3cd15c17ac6aa1b902e029?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">gianfrancoalongi</media:title>
		</media:content>
	</item>
		<item>
		<title>Erlang TDD hands on project &#8211; WorkerNet part 1</title>
		<link>http://erlcode.wordpress.com/2010/12/17/erlang-tdd-hands-on-project-workernet-part-1/</link>
		<comments>http://erlcode.wordpress.com/2010/12/17/erlang-tdd-hands-on-project-workernet-part-1/#comments</comments>
		<pubDate>Fri, 17 Dec 2010 22:55:44 +0000</pubDate>
		<dc:creator>gianfrancoalongi</dc:creator>
				<category><![CDATA[WorkerNet]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[eunit]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[workernet]]></category>

		<guid isPermaLink="false">http://erlcode.wordpress.com/?p=375</guid>
		<description><![CDATA[History &#8211; Perl, Ericsson and late evenings This series of posts will go through the design, testing and implementation of a distributed Worker-Net (something that I saw/implemented @Ericsson AB in 2009 &#8211; at the time written in a combination of Perl [~6000 lines of Perl!], bash scripts and other exotic animals). Needles to say, this [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=erlcode.wordpress.com&#038;blog=15510807&#038;post=375&#038;subd=erlcode&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<h2>History &#8211; Perl, Ericsson and late evenings</h2>
<p>This series of posts will go through the design, testing and implementation of a distributed Worker-Net (something that I saw/implemented @Ericsson AB in 2009 &#8211; at the time written in a combination of Perl [~6000 lines of Perl!], bash scripts and other exotic animals). Needles to say, this could have been written in a more suitable language (as Erlang), and so I tried &#8211; on evenings, it was a great way of learning Erlang and a great fun. My wife&#8217;s computer served a lot as testing ground. However, nothing is so good it can&#8217;t be re-done in a better way, and it suits perfectly well for this series.</p>
<h2>WorkerNet &#8211; What?</h2>
<p>A WorkerNet (WN) is a distributed application across erlang nodes that allows people to send jobs and related files across the network to a resource that can perform the job. A job can be anything defined by the sender but must be bound to an available resource type.</p>
<p><a href="http://erlcode.files.wordpress.com/2010/12/explanation12.png"><img class="alignnone size-full wp-image-403" title="Explanation1" src="http://erlcode.files.wordpress.com/2010/12/explanation12.png?w=600" alt=""   /></a></p>
<p>Resources are defined by each node and published publicly in the network. Each node in the WN must serve as an entry point to the network. Each node must know about the available pool of resources and the types of resources. Each resource-type in the network has a queue, and the incoming jobs must be scheduled fairly across the resources, some jobs may have higher priority than others.  Anything capable of running the erts with network interfaces can serve as a node in the WN, the WN is thus scalable and can easily be resized in any direction.</p>
<p>A layered (modular) architecture is often cleaner and easier to test, so such a one will be chosen here. Each process will then utilize the functionality of a layer through one facade module.</p>
<p><a href="http://erlcode.files.wordpress.com/2010/12/node1.png"><img class="size-full wp-image-385 aligncenter" title="Node" src="http://erlcode.files.wordpress.com/2010/12/node1.png?w=600" alt=""   /></a></p>
<h2>Iteration 1  - The design and testing of the Resource Layer</h2>
<p>The first iteration will start of with the test based design and implementation of the resource layer. To share my ideas with you in the blog, I will present the main use cases I want to be able to satisfy</p>
<p>&#8220;<em>I want to be able to specify the types of my resources. Resources should be able to be of multiple types</em>.&#8221;</p>
<p>&#8220;<em>I want to be able to specify the amount of available resources for each resource type, for the resources that I register</em>.&#8221;</p>
<p>&#8220;<em>I want to be able to dynamically register and de-register my resources from any node</em>.&#8221;</p>
<p><em>&#8220;I want to be able to list the available resources in the resource layer, through any node&#8221;</em></p>
<p>Keeping this in mind, and also remembering that the resource layer should be a distributed layer; the first test is written</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@author Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@copyright (C) 2010, Gianfranco
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">Created : 10 Dec 2010 by Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#b0c4de;">-module</span>(<span style="color:#7fffd4;">wn_resource_layer_tests</span>).
<span style="color:#b0c4de;">-include_lib</span>(<span style="color:#ffa07a;">"eunit/include/eunit.hrl"</span>).
<span style="color:#b0c4de;">-include</span>(<span style="color:#ffa07a;">"include/worker_net.hrl"</span>).

<span style="color:#87cefa;">register_resource_test_</span>() -&gt;
    {<span style="color:#7fffd4;">foreach</span>,
     <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">setup/0</span>,
     <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">cleanup/1</span>,
     [{<span style="color:#ffa07a;">"Can register resources locally"</span>,<span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">register_locally/0</span>}
     ]}.

<span style="color:#87cefa;">register_locally</span>() -&gt;
    <span style="color:#eedd82;">ResourceA</span> = #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"macbook pro laptop"</span>,
                          <span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">'os-x'</span>,1},{<span style="color:#7fffd4;">bsd</span>,1}],
                          <span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()},
    <span style="color:#eedd82;">ResourceB</span> = #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"erlang runtime system"</span>,
                          <span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">erlang</span>,4}],
                          <span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()},
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceA</span>),
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceB</span>),
    <span style="color:#eedd82;">List</span> = <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">sort</span>(<span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">list_resources</span>()),
    ?<span style="color:#b0c4de;">assertMatch</span>([<span style="color:#eedd82;">ResourceB</span>,<span style="color:#eedd82;">ResourceA</span>],<span style="color:#eedd82;">List</span>).

<span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">-----------------------------------------------------------------
</span><span style="color:#87cefa;">setup</span>() -&gt;
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>} = <span style="color:#98fb98;">net_kernel</span>:<span style="color:#98fb98;">start</span>([<span style="color:#7fffd4;">eunit_resource</span>,<span style="color:#7fffd4;">shortnames</span>]),
    <span style="color:#98fb98;">erlang</span>:<span style="color:#98fb98;">set_cookie</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#7fffd4;">eunit</span>),
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>} = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">start_link</span>().

<span style="color:#87cefa;">cleanup</span>(<span style="color:#eedd82;">_</span>) -&gt;
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">net_kernel</span>:<span style="color:#98fb98;">stop</span>(),
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">stop</span>().</pre>
<p><!--- End Of Snippet --></p>
<p>Keep in mind that no code exists what so ever, this is the first lines of code in the whole project. First off, I will write the worker_net.hrl header file.</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@author Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@copyright (C) 2010, Gianfranco
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">Created : 10 Dec 2010 by Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span>
<span style="color:#b0c4de;">-record</span>(<span style="color:#b0c4de;">wn_resource</span>,
      {<span style="color:#7fffd4;">name</span> :: <span style="color:#98fb98;">string</span>(),
       <span style="color:#7fffd4;">type</span> :: [{<span style="color:#7fffd4;">atom</span>(), <span style="color:#98fb98;">non_neg_integer</span>() | <span style="color:#7fffd4;">infinity</span>}],
       <span style="color:#7fffd4;">resides</span> :: <span style="color:#b0c4de;">node</span>()
      }).</pre>
<p><!--- End Of Snippet --></p>
<p>It is very important to add type specs wherever possible as early as possible, as it fosters the good culture of using dialyzer. Next I write the implementation, taking a bit of time on it. I start of by plugging in a gen_server skeleton, and go from there, only showing the modified /added parts</p>
<p>First the API</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">===========================================================
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">API
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">===========================================================
</span>
<span style="color:#87cefa;">start_link</span>() -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">start_link</span>({<span style="color:#7fffd4;">local</span>, ?<span style="color:#b0c4de;">MODULE</span>}, ?<span style="color:#b0c4de;">MODULE</span>, <span style="color:#7fffd4;">not_used</span>, []).

<span style="color:#b0c4de;">-spec</span>(<span style="color:#b0c4de;">register</span>(#<span style="color:#b0c4de;">wn_resource</span>{}) -&gt; <span style="color:#7fffd4;">ok</span> | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).
<span style="color:#87cefa;">register</span>(<span style="color:#eedd82;">Resource</span>) -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,{<span style="color:#7fffd4;">register</span>,<span style="color:#eedd82;">Resource</span>}).

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">list_resources</span>() -&gt; [#<span style="color:#b0c4de;">wn_resource</span>{}]).
<span style="color:#87cefa;">list_resources</span>() -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#7fffd4;">list_all_resources</span>).

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">stop</span>() -&gt; <span style="color:#7fffd4;">ok</span>).
<span style="color:#87cefa;">stop</span>() -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#7fffd4;">stop</span>).</pre>
<p><!--- End Of Snippet --></p>
<p>and the modified callbacks</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">init</span>(<span style="color:#7fffd4;">not_used</span>) -&gt;
    {<span style="color:#7fffd4;">ok</span>, #<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">resources</span> = <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">new</span>(<span style="color:#7fffd4;">resources</span>,[<span style="color:#7fffd4;">set</span>])}}.

<span style="color:#87cefa;">handle_call</span>(<span style="color:#7fffd4;">stop</span>,<span style="color:#eedd82;">_From</span>,<span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">stop</span>,<span style="color:#7fffd4;">normal</span>,<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">State</span>};

<span style="color:#87cefa;">handle_call</span>(<span style="color:#7fffd4;">list_all_resources</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#b0c4de;">spawn_link</span>(<span style="color:#98fb98;">resource_collector</span>(<span style="color:#eedd82;">From</span>)),
    {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>};

<span style="color:#87cefa;">handle_call</span>(<span style="color:#7fffd4;">list_resources</span>,<span style="color:#eedd82;">_From</span>,<span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">reply</span>,[<span style="color:#eedd82;">V</span> <span style="color:#00ffff;">||</span> {<span style="color:#eedd82;">_</span>,<span style="color:#eedd82;">V</span>} <span style="color:#00ffff;">&lt;-</span> <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">tab2list</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">resources</span>)],<span style="color:#eedd82;">State</span>};

<span style="color:#87cefa;">handle_call</span>({<span style="color:#7fffd4;">register</span>,<span style="color:#eedd82;">Resource</span>},<span style="color:#eedd82;">From</span>, <span style="color:#eedd82;">State</span>) -&gt;
    #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">resides</span>=<span style="color:#eedd82;">Node</span>} = <span style="color:#eedd82;">Resource</span>,
    <span style="color:#00ffff;">case</span> {<span style="color:#eedd82;">Node</span> == <span style="color:#b0c4de;">node</span>(),<span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">member</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#b0c4de;">nodes</span>())} <span style="color:#00ffff;">of</span>
        {<span style="color:#7fffd4;">true</span>,<span style="color:#eedd82;">_</span>} -&gt;
            <span style="color:#eedd82;">Reply</span> = <span style="color:#98fb98;">try_register</span>(<span style="color:#eedd82;">State</span>,<span style="color:#eedd82;">Resource</span>),
            {<span style="color:#7fffd4;">reply</span>,<span style="color:#eedd82;">Reply</span>,<span style="color:#eedd82;">State</span>};
        {<span style="color:#7fffd4;">false</span>,<span style="color:#7fffd4;">true</span>} -&gt;
            <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">cast</span>({?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#eedd82;">Node</span>},{<span style="color:#7fffd4;">register</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Resource</span>}),
            {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>};
        {<span style="color:#7fffd4;">false</span>,<span style="color:#7fffd4;">false</span>} -&gt;
            {<span style="color:#7fffd4;">reply</span>,{<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">noresides</span>},<span style="color:#eedd82;">State</span>}
    <span style="color:#00ffff;">end</span>.

<span style="color:#87cefa;">handle_cast</span>({<span style="color:#7fffd4;">register</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Resource</span>},<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">reply</span>(<span style="color:#eedd82;">From</span>,<span style="color:#98fb98;">try_register</span>(<span style="color:#eedd82;">State</span>,<span style="color:#eedd82;">Resource</span>)),
    {<span style="color:#7fffd4;">noreply</span>, <span style="color:#eedd82;">State</span>}.</pre>
<p><!--- End Of Snippet --></p>
<p>and added internal functions to <em>wn_resource_layer.erl</em></p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">===========================================================
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">Internal functions
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">===========================================================
</span><span style="color:#87cefa;">try_register</span>(<span style="color:#eedd82;">State</span>,<span style="color:#eedd82;">Resource</span>) -&gt;
    #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span>=<span style="color:#eedd82;">Name</span>} = <span style="color:#eedd82;">Resource</span>,
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">lookup</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">resources</span>,<span style="color:#eedd82;">Name</span>) <span style="color:#00ffff;">of</span>
        [] -&gt; <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">insert</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">resources</span>,{<span style="color:#eedd82;">Name</span>,<span style="color:#eedd82;">Resource</span>}),
              <span style="color:#7fffd4;">ok</span>;
        <span style="color:#eedd82;">_</span> -&gt;
            {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">already_exists</span>}
    <span style="color:#00ffff;">end</span>.

<span style="color:#87cefa;">resource_collector</span>(<span style="color:#eedd82;">From</span>) -&gt;
    <span style="color:#eedd82;">Nodes</span> = [<span style="color:#b0c4de;">node</span>()|<span style="color:#b0c4de;">nodes</span>()],
    <span style="color:#00ffff;">fun</span>() -&gt;
      <span style="color:#eedd82;">Res</span> =
       <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foldr</span>(
        <span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Acc</span>) -&gt;
          <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>({?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#eedd82;">Node</span>},<span style="color:#7fffd4;">list_resources</span>)<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">Acc</span>
        <span style="color:#00ffff;">end</span>,[],<span style="color:#eedd82;">Nodes</span>),
      <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">reply</span>(<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Res</span>)
    <span style="color:#00ffff;">end</span>.</pre>
<p><!--- End Of Snippet --></p>
<p>at this time I have created a Makefile to facilitate working with this, just the bare minimals</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">all</span>:
     erlc -pa . -o ebin/  src/*.erl test/*.erl

<span style="color:#87cefa;">test</span>:  all
     erl -pa ebin/ -eval <span style="color:#ffa07a;">'eunit:test(wn_resource_layer), init:stop().'</span>

<span style="color:#87cefa;">dialyze</span>:
     dialyzer src/*.erl test/*.erl

<span style="color:#87cefa;">full</span>: all test dialyze</pre>
<p><!--- End Of Snippet --></p>
<p>Running <em>make full</em> gives the following result</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#7fffd4;">zen</span>:<span style="color:#7fffd4;">worker_net</span>-0.1 <span style="color:#7fffd4;">zenon</span><span style="color:#ffa07a;">$ </span><span style="color:#7fffd4;">make</span> <span style="color:#7fffd4;">full</span>
<span style="color:#7fffd4;">erlc</span> -<span style="color:#7fffd4;">pa</span> . -<span style="color:#7fffd4;">o</span> <span style="color:#7fffd4;">ebin</span>/  <span style="color:#7fffd4;">src</span>/*.<span style="color:#7fffd4;">erl</span> <span style="color:#7fffd4;">test</span>/*.<span style="color:#7fffd4;">erl</span>
<span style="color:#7fffd4;">erl</span> -<span style="color:#7fffd4;">pa</span> <span style="color:#7fffd4;">ebin</span>/ -<span style="color:#7fffd4;">eval</span> 'eunit:<span style="color:#98fb98;">test</span>(<span style="color:#7fffd4;">wn_resource_layer</span>), <span style="color:#98fb98;">init</span>:<span style="color:#98fb98;">stop</span>().'
<span style="color:#eedd82;">Erlang</span> <span style="color:#eedd82;">R14B</span> (<span style="color:#7fffd4;">erts</span>-5.8.1) [<span style="color:#7fffd4;">source</span>] [<span style="color:#7fffd4;">smp</span>:4:4] [<span style="color:#7fffd4;">rq</span>:4] [<span style="color:#7fffd4;">async</span>-<span style="color:#7fffd4;">threads</span>:0]
[<span style="color:#7fffd4;">hipe</span>] [<span style="color:#7fffd4;">kernel</span>-<span style="color:#7fffd4;">poll</span>:<span style="color:#7fffd4;">false</span>]

<span style="color:#eedd82;">Eshell</span> <span style="color:#eedd82;">V5</span>.8.1  (<span style="color:#7fffd4;">abort</span> <span style="color:#7fffd4;">with</span> ^<span style="color:#eedd82;">G</span>)
1&gt;   <span style="color:#eedd82;">Test</span> <span style="color:#7fffd4;">passed</span>.
<span style="color:#7fffd4;">dialyzer</span> <span style="color:#7fffd4;">src</span>/*.<span style="color:#7fffd4;">erl</span> <span style="color:#7fffd4;">test</span>/*.<span style="color:#7fffd4;">erl</span>
  <span style="color:#eedd82;">Checking</span> <span style="color:#7fffd4;">whether</span> <span style="color:#7fffd4;">the</span> <span style="color:#eedd82;">PLT</span> /<span style="color:#eedd82;">Users</span>/<span style="color:#7fffd4;">zenon</span>/.<span style="color:#7fffd4;">dialyzer_plt</span> <span style="color:#7fffd4;">is</span> <span style="color:#7fffd4;">up</span>-<span style="color:#7fffd4;">to</span>-<span style="color:#7fffd4;">date</span>... <span style="color:#7fffd4;">yes</span>
  <span style="color:#eedd82;">Proceeding</span> <span style="color:#7fffd4;">with</span> <span style="color:#7fffd4;">analysis</span>...
<span style="color:#eedd82;">Unknown</span> <span style="color:#7fffd4;">functions</span>:
  <span style="color:#7fffd4;">eunit</span>:<span style="color:#87cefa;">test/1</span>
 <span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0m0.43s
<span style="color:#87cefa;">done</span> (<span style="color:#7fffd4;">passed</span> <span style="color:#7fffd4;">successfully</span>)
<span style="color:#7fffd4;">zen</span>:<span style="color:#7fffd4;">worker_net</span>-0.1 <span style="color:#7fffd4;">zenon</span><span style="color:#ffa07a;">$ </span></pre>
<p><!--- End Of Snippet --></p>
<p>Of course this was not the first compilation (I had some errors and mistakes to fix). Adding a second test will check whether I can add and access resources on remote nodes, writing the second test and refactoring the tests a bit, the added test generator is</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">distr_resource_test_</span>() -&gt;
    {<span style="color:#7fffd4;">foreach</span>,
     <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">distr_setup/0</span>,
     <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">distr_cleanup/1</span>,
     [<span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">register_distributed/1</span>
     ]
    }.</pre>
<p><!--- End Of Snippet --></p>
<p>with an added test istantiator</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">register_distributed</span>([<span style="color:#eedd82;">N1</span>,<span style="color:#eedd82;">N2</span>]) -&gt;
    {<span style="color:#ffa07a;">"Can Register Distributed"</span>,
     <span style="color:#00ffff;">fun</span>() -&gt;
         <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">start_link</span>,[]),
         <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">start_link</span>,[]),
         <span style="color:#eedd82;">ResourceA</span> = #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"erlang R14"</span>,
                                <span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">erlang</span>,<span style="color:#7fffd4;">infinity</span>}],
                                <span style="color:#7fffd4;">resides</span> = <span style="color:#eedd82;">N1</span>},
         <span style="color:#eedd82;">ResourceB</span> = #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"os-x macbook pro"</span>,
                                <span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">'os-x'</span>,1}],
                                <span style="color:#7fffd4;">resides</span> = <span style="color:#eedd82;">N2</span>},
         <span style="color:#eedd82;">ResourceC</span> = #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"g++"</span>,
                               <span style="color:#7fffd4;">type</span> = [{'g<span style="color:#ffc0cb;font-weight:bold;">++</span>',1}],
                               <span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()},
         <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceA</span>),
         <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceB</span>),
         <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceC</span>),
         <span style="color:#eedd82;">ListA</span> = <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">sort</span>(<span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">list_resources</span>()),
         <span style="color:#eedd82;">ListB</span> = <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">sort</span>(<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">list_resources</span>,[])),
         <span style="color:#eedd82;">ListC</span> = <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">sort</span>(<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">list_resources</span>,[])),
         ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceC</span>,<span style="color:#eedd82;">ResourceB</span>],<span style="color:#eedd82;">ListA</span>),
         ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceC</span>,<span style="color:#eedd82;">ResourceB</span>],<span style="color:#eedd82;">ListB</span>),
         ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceC</span>,<span style="color:#eedd82;">ResourceB</span>],<span style="color:#eedd82;">ListC</span>)
     <span style="color:#00ffff;">end</span>}.</pre>
<p><!--- End Of Snippet --></p>
<p>This test passed without problem. Next test will test that the resource layer can be started and restarted with re-registration. This test starts a layer on slave nodes, registers, resources, accesses them, stops layers, starts layers, registers and finds resources. All in a controlled manner.</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">register_restart_register</span>([<span style="color:#eedd82;">N1</span>,<span style="color:#eedd82;">N2</span>]) -&gt;
    {<span style="color:#ffa07a;">"Can Register, Restart and Register"</span>,
     <span style="color:#00ffff;">fun</span>() -&gt;
        <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">start_link</span>,[]),
        <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">start_link</span>,[]),
        <span style="color:#eedd82;">ResourceA</span> = #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"erlang R14"</span>,
                              <span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">erlang</span>,<span style="color:#7fffd4;">infinity</span>}],
                              <span style="color:#7fffd4;">resides</span> = <span style="color:#eedd82;">N1</span>},
        <span style="color:#eedd82;">ResourceB</span> = #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"os-x macbook pro"</span>,
                              <span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">'os-x'</span>,1}],
                              <span style="color:#7fffd4;">resides</span> = <span style="color:#eedd82;">N2</span>},
        <span style="color:#eedd82;">ResourceC</span> = #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"g++"</span>,
                              <span style="color:#7fffd4;">type</span> = [{'g<span style="color:#ffc0cb;font-weight:bold;">++</span>',1}],
                              <span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()},
        <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceA</span>),
        <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceB</span>),
        <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceC</span>),
        <span style="color:#eedd82;">M</span> = <span style="color:#00ffff;">fun</span>() -&gt; <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">sort</span>(<span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">list_resources</span>()) <span style="color:#00ffff;">end</span>,
        <span style="color:#eedd82;">S1</span> = <span style="color:#00ffff;">fun</span>() -&gt; <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">sort</span>(<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">list_resources</span>,[]))
             <span style="color:#00ffff;">end</span>,
        <span style="color:#eedd82;">S2</span> = <span style="color:#00ffff;">fun</span>() -&gt; <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">sort</span>(<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">list_resources</span>,[]))
             <span style="color:#00ffff;">end</span>,
        ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceC</span>,<span style="color:#eedd82;">ResourceB</span>],<span style="color:#eedd82;">M</span>()),
        ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceC</span>,<span style="color:#eedd82;">ResourceB</span>],<span style="color:#eedd82;">S1</span>()),
        ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceC</span>,<span style="color:#eedd82;">ResourceB</span>],<span style="color:#eedd82;">S2</span>()),
        <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">stop</span>,[]),
        ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceC</span>,<span style="color:#eedd82;">ResourceB</span>],<span style="color:#eedd82;">M</span>()),
        ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceC</span>,<span style="color:#eedd82;">ResourceB</span>],<span style="color:#eedd82;">S2</span>()),
        <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">stop</span>,[]),
        ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">M</span>()),
        {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>} = <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">start_link</span>,[]),
        {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>} = <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">start_link</span>,[]),
        <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceA</span>),
        ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">M</span>()),
        <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceB</span>),
        ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceC</span>,<span style="color:#eedd82;">ResourceB</span>],<span style="color:#eedd82;">M</span>()),
        ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceC</span>,<span style="color:#eedd82;">ResourceB</span>],<span style="color:#eedd82;">S1</span>()),
        ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceC</span>,<span style="color:#eedd82;">ResourceB</span>],<span style="color:#eedd82;">S2</span>())
     <span style="color:#00ffff;">end</span>}.</pre>
<p><!--- End Of Snippet --></p>
<p>After having written the test and tried it with <em>&#8216;make full&#8217;</em>,  It became evident that one <strong>flaw</strong> of the current implementation was that (should be for whoever is trying this out themselves) is that the resource layer treats ALL seen nodes as having a resource layer running, this is not a healthy assumption not be the case and we need a fix to prevent the gen_server:call/2 in case there is no running wn_resource_layer gen_server running.</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">resource_collector</span>(<span style="color:#eedd82;">From</span>) -&gt;
    <span style="color:#eedd82;">Nodes</span> = [<span style="color:#b0c4de;">node</span>()|<span style="color:#b0c4de;">nodes</span>()],
    <span style="color:#00ffff;">fun</span>() -&gt;
       <span style="color:#eedd82;">Res</span> =
          <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foldr</span>(
             <span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Acc</span>) -&gt;
                <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#7fffd4;">erlang</span>,<span style="color:#7fffd4;">whereis</span>,[?<span style="color:#b0c4de;">MODULE</span>]) <span style="color:#00ffff;">of</span>
                   <span style="color:#7fffd4;">undefined</span> -&gt; <span style="color:#eedd82;">Acc</span>;
                   <span style="color:#eedd82;">_Pid</span> -&gt;
                      <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>({?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#eedd82;">Node</span>},<span style="color:#7fffd4;">list_resources</span>)<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">Acc</span>
              <span style="color:#00ffff;">end</span>
            <span style="color:#00ffff;">end</span>,[],<span style="color:#eedd82;">Nodes</span>),
      <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">reply</span>(<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Res</span>)
    <span style="color:#00ffff;">end</span>.</pre>
<p><!--- End Of Snippet --></p>
<p>The fix seen above in <em>wn_resource_layer.erl</em> was to add the case-of with rpc:call/4 erlang:whereis(?MODULE). Fixed and running, the &#8216;make full&#8217; reports. What is now left to fulfill the initial &#8220;requirements&#8221; is a test that proves the ability to deregister resources dynamically through any node. Test first as always.</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">register_deregister</span>([<span style="color:#eedd82;">N1</span>,<span style="color:#eedd82;">N2</span>]) -&gt;
    {<span style="color:#ffa07a;">"Can Register, Deregister and Register"</span>,
     <span style="color:#00ffff;">fun</span>() -&gt;
             <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">start_link</span>,[]),
             <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">start_link</span>,[]),
             <span style="color:#eedd82;">M</span> = <span style="color:#00ffff;">fun</span>() -&gt; <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">sort</span>(<span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">list_resources</span>()) <span style="color:#00ffff;">end</span>,
             <span style="color:#eedd82;">S1</span> = <span style="color:#00ffff;">fun</span>() -&gt; <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">sort</span>(<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">list_resources</span>,[])) <span style="color:#00ffff;">end</span>,
             <span style="color:#eedd82;">S2</span> = <span style="color:#00ffff;">fun</span>() -&gt; <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">sort</span>(<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">list_resources</span>,[])) <span style="color:#00ffff;">end</span>,
             <span style="color:#eedd82;">ResourceA</span> = #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"A"</span>,<span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">a</span>,1}],<span style="color:#7fffd4;">resides</span> = <span style="color:#eedd82;">N1</span>},
             <span style="color:#eedd82;">ResourceB</span> = #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"B"</span>,<span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">b</span>,2}],<span style="color:#7fffd4;">resides</span> = <span style="color:#eedd82;">N2</span>},
             <span style="color:#eedd82;">ResourceC</span> = #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"C"</span>,<span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">c</span>,3}],<span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()},
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceA</span>),
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceB</span>),
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceC</span>),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceB</span>,<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">M</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceB</span>,<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">S1</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceB</span>,<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">S2</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">deregister</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#ffa07a;">"A"</span>)),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceB</span>,<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">M</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceB</span>,<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">S1</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceB</span>,<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">S2</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">deregister</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#ffa07a;">"B"</span>)),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">M</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">S1</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">S2</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">deregister</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#ffa07a;">"C"</span>)),
             ?<span style="color:#b0c4de;">assertEqual</span>([],<span style="color:#eedd82;">M</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>([],<span style="color:#eedd82;">S1</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>([],<span style="color:#eedd82;">S2</span>()),
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceA</span>),
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceB</span>),
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceC</span>),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceB</span>,<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">M</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceB</span>,<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">S1</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceB</span>,<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">S2</span>())
     <span style="color:#00ffff;">end</span>}.</pre>
<p><!--- End Of Snippet --></p>
<p>Then the necessary changes to make the tests pass, changes to API in wn_resource_layer</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">deregister</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#98fb98;">string</span>()) -&gt; <span style="color:#7fffd4;">ok</span> | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).
<span style="color:#87cefa;">deregister</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Name</span>) -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,{<span style="color:#7fffd4;">deregister</span>,<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Name</span>}).</pre>
<p><!--- End Of Snippet --></p>
<p>the added handling inside the callbacks</p>
<p><!--- Snippet --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#87cefa;">handle_call</span>({<span style="color:#7fffd4;">deregister</span>,<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Name</span>},<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#00ffff;">case</span> {<span style="color:#eedd82;">Node</span> == <span style="color:#b0c4de;">node</span>(),<span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">member</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#b0c4de;">nodes</span>())} <span style="color:#00ffff;">of</span>
        {<span style="color:#7fffd4;">true</span>,<span style="color:#eedd82;">_</span>} -&gt;
            <span style="color:#eedd82;">Reply</span> = <span style="color:#98fb98;">try_deregister</span>(<span style="color:#eedd82;">State</span>,<span style="color:#eedd82;">Name</span>),
            {<span style="color:#7fffd4;">reply</span>,<span style="color:#eedd82;">Reply</span>,<span style="color:#eedd82;">State</span>};
        {<span style="color:#7fffd4;">false</span>,<span style="color:#7fffd4;">true</span>} -&gt;
            <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">cast</span>({?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#eedd82;">Node</span>},{<span style="color:#7fffd4;">deregister</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Name</span>}),
            {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>};
        {<span style="color:#7fffd4;">false</span>,<span style="color:#7fffd4;">false</span>} -&gt;
            {<span style="color:#7fffd4;">reply</span>,{<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">noresides</span>},<span style="color:#eedd82;">State</span>}
    <span style="color:#00ffff;">end</span>.

<span style="color:#87cefa;">handle_cast</span>({<span style="color:#7fffd4;">deregister</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">_Node</span>,<span style="color:#eedd82;">Name</span>},<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">reply</span>(<span style="color:#eedd82;">From</span>,<span style="color:#98fb98;">try_deregister</span>(<span style="color:#eedd82;">State</span>,<span style="color:#eedd82;">Name</span>)),
    {<span style="color:#7fffd4;">noreply</span>, <span style="color:#eedd82;">State</span>};</pre>
<p><!--- End Of Snippet --></p>
<p>With &#8216;make full&#8217;</p>
<p><!--- Snippet  --></p>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#7fffd4;">zen</span>:<span style="color:#7fffd4;">worker_net</span>-0.1 <span style="color:#7fffd4;">zenon</span><span style="color:#ffa07a;">$ </span><span style="color:#7fffd4;">make</span> <span style="color:#7fffd4;">full</span>
<span style="color:#7fffd4;">erlc</span> -<span style="color:#7fffd4;">pa</span> . -<span style="color:#7fffd4;">o</span> <span style="color:#7fffd4;">ebin</span>/  <span style="color:#7fffd4;">src</span>/*.<span style="color:#7fffd4;">erl</span> <span style="color:#7fffd4;">test</span>/*.<span style="color:#7fffd4;">erl</span>
<span style="color:#7fffd4;">erl</span> -<span style="color:#7fffd4;">pa</span> <span style="color:#7fffd4;">ebin</span>/ -<span style="color:#7fffd4;">eval</span> 'eunit:<span style="color:#98fb98;">test</span>(<span style="color:#7fffd4;">wn_resource_layer</span>,[<span style="color:#7fffd4;">verbose</span>]), <span style="color:#98fb98;">init</span>:<span style="color:#98fb98;">stop</span>().'
<span style="color:#eedd82;">Erlang</span> <span style="color:#eedd82;">R14B</span> (<span style="color:#7fffd4;">erts</span>-5.8.1) [<span style="color:#7fffd4;">source</span>] [<span style="color:#7fffd4;">smp</span>:4:4] [<span style="color:#7fffd4;">rq</span>:4] [<span style="color:#7fffd4;">async</span>-<span style="color:#7fffd4;">threads</span>:0] [<span style="color:#7fffd4;">hipe</span>]
[<span style="color:#7fffd4;">kernel</span>-<span style="color:#7fffd4;">poll</span>:<span style="color:#7fffd4;">false</span>]

<span style="color:#eedd82;">Eshell</span> <span style="color:#eedd82;">V5</span>.8.1  (<span style="color:#7fffd4;">abort</span> <span style="color:#7fffd4;">with</span> ^<span style="color:#eedd82;">G</span>)
1&gt; ======================== <span style="color:#eedd82;">EUnit</span> ========================
<span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_resource_layer'</span>
  <span style="color:#7fffd4;">module</span> <span style="color:#7fffd4;">'wn_resource_layer_tests'</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">local_resource_test_</span> (<span style="color:#eedd82;">Can</span> <span style="color:#7fffd4;">register</span> <span style="color:#7fffd4;">resources</span> <span style="color:#7fffd4;">locally</span>)...<span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">register_distributed</span> (<span style="color:#eedd82;">Can</span> <span style="color:#eedd82;">Register</span> <span style="color:#eedd82;">Distributed</span>)...[0.004 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">register_restart_register</span> (<span style="color:#eedd82;">Can</span> <span style="color:#eedd82;">Register</span>, <span style="color:#eedd82;">Restart</span> <span style="color:#7fffd4;">and</span> <span style="color:#eedd82;">Register</span>)...[0.008 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    <span style="color:#98fb98;">wn_resource_layer_tests</span>: <span style="color:#98fb98;">register_deregister</span> (<span style="color:#eedd82;">Can</span> <span style="color:#eedd82;">Register</span>, <span style="color:#eedd82;">Deregister</span> <span style="color:#7fffd4;">and</span> <span style="color:#eedd82;">Register</span>)...[0.012 <span style="color:#7fffd4;">s</span>] <span style="color:#7fffd4;">ok</span>
    [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0.885 <span style="color:#7fffd4;">s</span>]
  [<span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0.885 <span style="color:#7fffd4;">s</span>]
=======================================================
  <span style="color:#eedd82;">All</span> 4 <span style="color:#7fffd4;">tests</span> <span style="color:#7fffd4;">passed</span>.
<span style="color:#7fffd4;">dialyzer</span> <span style="color:#7fffd4;">src</span>/*.<span style="color:#7fffd4;">erl</span> <span style="color:#7fffd4;">test</span>/*.<span style="color:#7fffd4;">erl</span>
  <span style="color:#eedd82;">Checking</span> <span style="color:#7fffd4;">whether</span> <span style="color:#7fffd4;">the</span> <span style="color:#eedd82;">PLT</span> /<span style="color:#eedd82;">Users</span>/<span style="color:#7fffd4;">zenon</span>/.<span style="color:#7fffd4;">dialyzer_plt</span> <span style="color:#7fffd4;">is</span> <span style="color:#7fffd4;">up</span>-<span style="color:#7fffd4;">to</span>-<span style="color:#7fffd4;">date</span>... <span style="color:#7fffd4;">yes</span>
  <span style="color:#eedd82;">Proceeding</span> <span style="color:#7fffd4;">with</span> <span style="color:#7fffd4;">analysis</span>...
<span style="color:#eedd82;">Unknown</span> <span style="color:#7fffd4;">functions</span>:
  <span style="color:#7fffd4;">eunit</span>:<span style="color:#87cefa;">test/1</span>
 <span style="color:#7fffd4;">done</span> <span style="color:#7fffd4;">in</span> 0m1.13s
<span style="color:#87cefa;">done</span> (<span style="color:#7fffd4;">passed</span> <span style="color:#7fffd4;">successfully</span>)
<span style="color:#7fffd4;">zen</span>:<span style="color:#7fffd4;">worker_net</span>-0.1 <span style="color:#7fffd4;">zenon</span><span style="color:#ffa07a;">$ </span></pre>
<p><!--- End Of Snippet --></p>
<p>Now, this should be enough to fulfill the initial requirements described in the beginning</p>
<p>&#8220;<em>I want to be able to specify the types of my resources. Resources should be able to be of multiple types</em>.&#8221;</p>
<p>&#8220;<em>I want to be able to specify the amount of available resources for each resource type, for the resources that I register</em>.&#8221;</p>
<p>&#8220;<em>I want to be able to dynamically register and de-register my resources from any node</em>.&#8221;</p>
<p><em>&#8220;I want to be able to list the available resources in the resource layer, through any node&#8221;</em></p>
<p><em> </em>The current design is a &#8220;local-first, distributed second&#8221; design as follows</p>
<p><a href="http://erlcode.files.wordpress.com/2010/12/localfirst.png"><img class="alignnone size-full wp-image-409" title="LocalFirst" src="http://erlcode.files.wordpress.com/2010/12/localfirst.png?w=600" alt=""   /></a></p>
<p>Next iteration we will start work on the file layer.<br />
Cheers<br />
/G</p>
<p>Below follows listing of the <em>wn_resource_layer.erl</em> and <em>wn_resource_layer_tests.erl</em></p>
<h1>Listing: wn_resource_layer.erl</h1>
<h6>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">-------------------------------------------------------------------
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@author Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@copyright (C) 2010, Gianfranco
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">Created : 11 Dec 2010 by Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">-------------------------------------------------------------------
</span><span style="color:#b0c4de;">-module</span>(<span style="color:#7fffd4;">wn_resource_layer</span>).
<span style="color:#b0c4de;">-behaviour</span>(<span style="color:#7fffd4;">gen_server</span>).
<span style="color:#b0c4de;">-include</span>(<span style="color:#ffa07a;">"include/worker_net.hrl"</span>).

<span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">API
</span><span style="color:#b0c4de;">-export</span>([<span style="color:#87cefa;">start_link/0</span>,<span style="color:#87cefa;">register/1</span>,<span style="color:#87cefa;">list_resources/0</span>,<span style="color:#87cefa;">stop/0</span>,
        <span style="color:#87cefa;">deregister/2</span>]).

<span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">gen_server callbacks
</span><span style="color:#b0c4de;">-export</span>([<span style="color:#87cefa;">init/1</span>, <span style="color:#87cefa;">handle_call/3</span>, <span style="color:#87cefa;">handle_cast/2</span>, <span style="color:#87cefa;">handle_info/2</span>,
         <span style="color:#87cefa;">terminate/2</span>, <span style="color:#87cefa;">code_change/3</span>]).

<span style="color:#b0c4de;">-record</span>(<span style="color:#b0c4de;">state</span>,
        {<span style="color:#7fffd4;">resources</span> <span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">ETS table
</span>         }).

<span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">===================================================================
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">API
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">===================================================================
</span>
<span style="color:#87cefa;">start_link</span>() -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">start_link</span>({<span style="color:#7fffd4;">local</span>, ?<span style="color:#b0c4de;">MODULE</span>}, ?<span style="color:#b0c4de;">MODULE</span>, <span style="color:#7fffd4;">not_used</span>, []).

<span style="color:#b0c4de;">-spec</span>(<span style="color:#b0c4de;">register</span>(#<span style="color:#b0c4de;">wn_resource</span>{}) -&gt; <span style="color:#7fffd4;">ok</span> | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).
<span style="color:#87cefa;">register</span>(<span style="color:#eedd82;">Resource</span>) -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,{<span style="color:#7fffd4;">register</span>,<span style="color:#eedd82;">Resource</span>}).

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">deregister</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#98fb98;">string</span>()) -&gt; <span style="color:#7fffd4;">ok</span> | {<span style="color:#7fffd4;">error</span>,<span style="color:#98fb98;">term</span>()}).
<span style="color:#87cefa;">deregister</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Name</span>) -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,{<span style="color:#7fffd4;">deregister</span>,<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Name</span>}).    

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">list_resources</span>() -&gt; [#<span style="color:#b0c4de;">wn_resource</span>{}]).
<span style="color:#87cefa;">list_resources</span>() -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#7fffd4;">list_all_resources</span>).

<span style="color:#b0c4de;">-spec</span>(<span style="color:#98fb98;">stop</span>() -&gt; <span style="color:#7fffd4;">ok</span>).
<span style="color:#87cefa;">stop</span>() -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>(?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#7fffd4;">stop</span>).

<span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">===================================================================
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">gen_server callbacks
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">===================================================================
</span>
<span style="color:#87cefa;">init</span>(<span style="color:#7fffd4;">not_used</span>) -&gt;
    {<span style="color:#7fffd4;">ok</span>, #<span style="color:#b0c4de;">state</span>{<span style="color:#7fffd4;">resources</span> = <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">new</span>(<span style="color:#7fffd4;">resources</span>,[<span style="color:#7fffd4;">set</span>])}}.

<span style="color:#87cefa;">handle_call</span>(<span style="color:#7fffd4;">stop</span>,<span style="color:#eedd82;">_From</span>,<span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">stop</span>,<span style="color:#7fffd4;">normal</span>,<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">State</span>};

<span style="color:#87cefa;">handle_call</span>(<span style="color:#7fffd4;">list_all_resources</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#b0c4de;">spawn_link</span>(<span style="color:#98fb98;">resource_collector</span>(<span style="color:#eedd82;">From</span>)),
    {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>};

<span style="color:#87cefa;">handle_call</span>(<span style="color:#7fffd4;">list_resources</span>,<span style="color:#eedd82;">_From</span>,<span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">reply</span>,[<span style="color:#eedd82;">V</span> <span style="color:#00ffff;">||</span> {<span style="color:#eedd82;">_</span>,<span style="color:#eedd82;">V</span>} <span style="color:#00ffff;">&lt;-</span> <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">tab2list</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">resources</span>)],<span style="color:#eedd82;">State</span>};

<span style="color:#87cefa;">handle_call</span>({<span style="color:#7fffd4;">register</span>,<span style="color:#eedd82;">Resource</span>},<span style="color:#eedd82;">From</span>, <span style="color:#eedd82;">State</span>) -&gt;
    #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">resides</span>=<span style="color:#eedd82;">Node</span>} = <span style="color:#eedd82;">Resource</span>,
    <span style="color:#00ffff;">case</span> {<span style="color:#eedd82;">Node</span> == <span style="color:#b0c4de;">node</span>(),<span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">member</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#b0c4de;">nodes</span>())} <span style="color:#00ffff;">of</span>
        {<span style="color:#7fffd4;">true</span>,<span style="color:#eedd82;">_</span>} -&gt;
            <span style="color:#eedd82;">Reply</span> = <span style="color:#98fb98;">try_register</span>(<span style="color:#eedd82;">State</span>,<span style="color:#eedd82;">Resource</span>),
            {<span style="color:#7fffd4;">reply</span>,<span style="color:#eedd82;">Reply</span>,<span style="color:#eedd82;">State</span>};
        {<span style="color:#7fffd4;">false</span>,<span style="color:#7fffd4;">true</span>} -&gt;
            <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">cast</span>({?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#eedd82;">Node</span>},{<span style="color:#7fffd4;">register</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Resource</span>}),
            {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>};
        {<span style="color:#7fffd4;">false</span>,<span style="color:#7fffd4;">false</span>} -&gt;
            {<span style="color:#7fffd4;">reply</span>,{<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">noresides</span>},<span style="color:#eedd82;">State</span>}
    <span style="color:#00ffff;">end</span>;

<span style="color:#87cefa;">handle_call</span>({<span style="color:#7fffd4;">deregister</span>,<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Name</span>},<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#00ffff;">case</span> {<span style="color:#eedd82;">Node</span> == <span style="color:#b0c4de;">node</span>(),<span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">member</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#b0c4de;">nodes</span>())} <span style="color:#00ffff;">of</span>
        {<span style="color:#7fffd4;">true</span>,<span style="color:#eedd82;">_</span>} -&gt;
            <span style="color:#eedd82;">Reply</span> = <span style="color:#98fb98;">try_deregister</span>(<span style="color:#eedd82;">State</span>,<span style="color:#eedd82;">Name</span>),
            {<span style="color:#7fffd4;">reply</span>,<span style="color:#eedd82;">Reply</span>,<span style="color:#eedd82;">State</span>};
        {<span style="color:#7fffd4;">false</span>,<span style="color:#7fffd4;">true</span>} -&gt;
            <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">cast</span>({?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#eedd82;">Node</span>},{<span style="color:#7fffd4;">deregister</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Name</span>}),
            {<span style="color:#7fffd4;">noreply</span>,<span style="color:#eedd82;">State</span>};
        {<span style="color:#7fffd4;">false</span>,<span style="color:#7fffd4;">false</span>} -&gt;
            {<span style="color:#7fffd4;">reply</span>,{<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">noresides</span>},<span style="color:#eedd82;">State</span>}
    <span style="color:#00ffff;">end</span>.

<span style="color:#87cefa;">handle_cast</span>({<span style="color:#7fffd4;">deregister</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">_Node</span>,<span style="color:#eedd82;">Name</span>},<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">reply</span>(<span style="color:#eedd82;">From</span>,<span style="color:#98fb98;">try_deregister</span>(<span style="color:#eedd82;">State</span>,<span style="color:#eedd82;">Name</span>)),
    {<span style="color:#7fffd4;">noreply</span>, <span style="color:#eedd82;">State</span>};

<span style="color:#87cefa;">handle_cast</span>({<span style="color:#7fffd4;">register</span>,<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Resource</span>},<span style="color:#eedd82;">State</span>) -&gt;
    <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">reply</span>(<span style="color:#eedd82;">From</span>,<span style="color:#98fb98;">try_register</span>(<span style="color:#eedd82;">State</span>,<span style="color:#eedd82;">Resource</span>)),
    {<span style="color:#7fffd4;">noreply</span>, <span style="color:#eedd82;">State</span>}.

<span style="color:#87cefa;">handle_info</span>(<span style="color:#eedd82;">_Info</span>, <span style="color:#eedd82;">State</span>) -&gt;
    {<span style="color:#7fffd4;">noreply</span>, <span style="color:#eedd82;">State</span>}.

<span style="color:#87cefa;">terminate</span>(<span style="color:#eedd82;">_Reason</span>, <span style="color:#eedd82;">_State</span>) -&gt;
    <span style="color:#7fffd4;">ok</span>.

<span style="color:#87cefa;">code_change</span>(<span style="color:#eedd82;">_OldVsn</span>, <span style="color:#eedd82;">State</span>, <span style="color:#eedd82;">_Extra</span>) -&gt;
    {<span style="color:#7fffd4;">ok</span>, <span style="color:#eedd82;">State</span>}.

<span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">===================================================================
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">Internal functions
</span><span style="color:#ff7f24;">%%%</span><span style="color:#ff7f24;">===================================================================
</span><span style="color:#87cefa;">try_deregister</span>(<span style="color:#eedd82;">State</span>,<span style="color:#eedd82;">Name</span>) -&gt;
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">lookup</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">resources</span>,<span style="color:#eedd82;">Name</span>) <span style="color:#00ffff;">of</span>
        [] -&gt; {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">noexists</span>};
        <span style="color:#eedd82;">_</span> -&gt; <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">delete</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">resources</span>,<span style="color:#eedd82;">Name</span>),
             <span style="color:#7fffd4;">ok</span>
    <span style="color:#00ffff;">end</span>.

<span style="color:#87cefa;">try_register</span>(<span style="color:#eedd82;">State</span>,<span style="color:#eedd82;">Resource</span>) -&gt;
    #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span>=<span style="color:#eedd82;">Name</span>} = <span style="color:#eedd82;">Resource</span>,
    <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">lookup</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">resources</span>,<span style="color:#eedd82;">Name</span>) <span style="color:#00ffff;">of</span>
        [] -&gt; <span style="color:#98fb98;">ets</span>:<span style="color:#98fb98;">insert</span>(<span style="color:#eedd82;">State</span>#<span style="color:#b0c4de;">state</span>.<span style="color:#7fffd4;">resources</span>,{<span style="color:#eedd82;">Name</span>,<span style="color:#eedd82;">Resource</span>}),
              <span style="color:#7fffd4;">ok</span>;
        <span style="color:#eedd82;">_</span> -&gt;
            {<span style="color:#7fffd4;">error</span>,<span style="color:#7fffd4;">already_exists</span>}
    <span style="color:#00ffff;">end</span>.

<span style="color:#87cefa;">resource_collector</span>(<span style="color:#eedd82;">From</span>) -&gt;
    <span style="color:#eedd82;">Nodes</span> = [<span style="color:#b0c4de;">node</span>()|<span style="color:#b0c4de;">nodes</span>()],
    <span style="color:#00ffff;">fun</span>() -&gt;
            <span style="color:#eedd82;">Res</span> =
                <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">foldr</span>(
                  <span style="color:#00ffff;">fun</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#eedd82;">Acc</span>) -&gt;
                          <span style="color:#00ffff;">case</span> <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">Node</span>,<span style="color:#7fffd4;">erlang</span>,<span style="color:#7fffd4;">whereis</span>,[?<span style="color:#b0c4de;">MODULE</span>]) <span style="color:#00ffff;">of</span>
                              <span style="color:#7fffd4;">undefined</span> -&gt; <span style="color:#eedd82;">Acc</span>;
                              <span style="color:#eedd82;">_Pid</span> -&gt;
                                  <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">call</span>({?<span style="color:#b0c4de;">MODULE</span>,<span style="color:#eedd82;">Node</span>},
                                                  <span style="color:#7fffd4;">list_resources</span>)<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#eedd82;">Acc</span>
                        <span style="color:#00ffff;">end</span>
                  <span style="color:#00ffff;">end</span>,[],<span style="color:#eedd82;">Nodes</span>),
            <span style="color:#98fb98;">gen_server</span>:<span style="color:#98fb98;">reply</span>(<span style="color:#eedd82;">From</span>,<span style="color:#eedd82;">Res</span>)
    <span style="color:#00ffff;">end</span>.</pre>
</h6>
<h1>Listing: wn_resource_layer_tests.erl</h1>
<h6>
<pre style="color:#ffffff;background-color:#000000;overflow:auto;padding:5px;"><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@author Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">@copyright (C) 2010, Gianfranco
</span><span style="color:#ff7f24;">%%% </span><span style="color:#ff7f24;">Created : 10 Dec 2010 by Gianfranco &lt;<a href="mailto:zenon@zen.local">zenon@zen.local</a>&gt;
</span><span style="color:#b0c4de;">-module</span>(<span style="color:#7fffd4;">wn_resource_layer_tests</span>).
<span style="color:#b0c4de;">-include_lib</span>(<span style="color:#ffa07a;">"eunit/include/eunit.hrl"</span>).
<span style="color:#b0c4de;">-include</span>(<span style="color:#ffa07a;">"include/worker_net.hrl"</span>).

<span style="color:#87cefa;">local_resource_test_</span>() -&gt;
    {<span style="color:#7fffd4;">foreach</span>,
     <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">setup/0</span>,
     <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">cleanup/1</span>,
     [{<span style="color:#ffa07a;">"Can register resources locally"</span>,<span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">register_locally/0</span>}
     ]}.

<span style="color:#87cefa;">distr_resource_test_</span>() -&gt;
    {<span style="color:#7fffd4;">foreach</span>,
     <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">distr_setup/0</span>,
     <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">distr_cleanup/1</span>,
     [<span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">register_distributed/1</span>,
      <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">register_restart_register/1</span>,
      <span style="color:#00ffff;">fun</span> <span style="color:#87cefa;">register_deregister/1</span>
     ]
    }.

<span style="color:#87cefa;">register_locally</span>() -&gt;
    <span style="color:#eedd82;">ResourceA</span> = #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"macbook pro laptop"</span>,
                             <span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">'os-x'</span>,1},{<span style="color:#7fffd4;">bsd</span>,1}],
                             <span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()},
    <span style="color:#eedd82;">ResourceB</span> = #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"erlang runtime system"</span>,
                             <span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">erlang</span>,4}],
                             <span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()},
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceA</span>),
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceB</span>),
    <span style="color:#eedd82;">List</span> = <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">sort</span>(<span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">list_resources</span>()),
    ?<span style="color:#b0c4de;">assertMatch</span>([<span style="color:#eedd82;">ResourceB</span>,<span style="color:#eedd82;">ResourceA</span>],<span style="color:#eedd82;">List</span>).

<span style="color:#87cefa;">register_distributed</span>([<span style="color:#eedd82;">N1</span>,<span style="color:#eedd82;">N2</span>]) -&gt;
    {<span style="color:#ffa07a;">"Can Register Distributed"</span>,
     <span style="color:#00ffff;">fun</span>() -&gt;
             <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">start_link</span>,[]),
             <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">start_link</span>,[]),
             <span style="color:#eedd82;">ResourceA</span> = #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"erlang R14"</span>,
                                      <span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">erlang</span>,<span style="color:#7fffd4;">infinity</span>}],
                                      <span style="color:#7fffd4;">resides</span> = <span style="color:#eedd82;">N1</span>},
             <span style="color:#eedd82;">ResourceB</span> = #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"os-x macbook pro"</span>,
                                      <span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">'os-x'</span>,1}],
                                      <span style="color:#7fffd4;">resides</span> = <span style="color:#eedd82;">N2</span>},
             <span style="color:#eedd82;">ResourceC</span> = #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"g++"</span>,
                                      <span style="color:#7fffd4;">type</span> = [{'g<span style="color:#ffc0cb;font-weight:bold;">++</span>',1}],
                                      <span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()},
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceA</span>),
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceB</span>),
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceC</span>),
             <span style="color:#eedd82;">ListA</span> = <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">sort</span>(<span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">list_resources</span>()),
             <span style="color:#eedd82;">ListB</span> = <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">sort</span>(<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">list_resources</span>,[])),
             <span style="color:#eedd82;">ListC</span> = <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">sort</span>(<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">list_resources</span>,[])),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceC</span>,<span style="color:#eedd82;">ResourceB</span>],<span style="color:#eedd82;">ListA</span>),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceC</span>,<span style="color:#eedd82;">ResourceB</span>],<span style="color:#eedd82;">ListB</span>),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceC</span>,<span style="color:#eedd82;">ResourceB</span>],<span style="color:#eedd82;">ListC</span>)
     <span style="color:#00ffff;">end</span>}.

<span style="color:#87cefa;">register_restart_register</span>([<span style="color:#eedd82;">N1</span>,<span style="color:#eedd82;">N2</span>]) -&gt;
    {<span style="color:#ffa07a;">"Can Register, Restart and Register"</span>,
     <span style="color:#00ffff;">fun</span>() -&gt;
             <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">start_link</span>,[]),
             <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">start_link</span>,[]),
             <span style="color:#eedd82;">ResourceA</span> = #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"erlang R14"</span>,
                                      <span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">erlang</span>,<span style="color:#7fffd4;">infinity</span>}],
                                      <span style="color:#7fffd4;">resides</span> = <span style="color:#eedd82;">N1</span>},
             <span style="color:#eedd82;">ResourceB</span> = #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"os-x macbook pro"</span>,
                                      <span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">'os-x'</span>,1}],
                                      <span style="color:#7fffd4;">resides</span> = <span style="color:#eedd82;">N2</span>},
             <span style="color:#eedd82;">ResourceC</span> = #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"g++"</span>,
                                      <span style="color:#7fffd4;">type</span> = [{'g<span style="color:#ffc0cb;font-weight:bold;">++</span>',1}],
                                      <span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()},
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceA</span>),
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceB</span>),
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceC</span>),
             <span style="color:#eedd82;">M</span> = <span style="color:#00ffff;">fun</span>() -&gt; <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">sort</span>(<span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">list_resources</span>()) <span style="color:#00ffff;">end</span>,
             <span style="color:#eedd82;">S1</span> = <span style="color:#00ffff;">fun</span>() -&gt; <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">sort</span>(<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">list_resources</span>,[])) <span style="color:#00ffff;">end</span>,
             <span style="color:#eedd82;">S2</span> = <span style="color:#00ffff;">fun</span>() -&gt; <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">sort</span>(<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">list_resources</span>,[])) <span style="color:#00ffff;">end</span>,
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceC</span>,<span style="color:#eedd82;">ResourceB</span>],<span style="color:#eedd82;">M</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceC</span>,<span style="color:#eedd82;">ResourceB</span>],<span style="color:#eedd82;">S1</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceC</span>,<span style="color:#eedd82;">ResourceB</span>],<span style="color:#eedd82;">S2</span>()),
             <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">stop</span>,[]),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceC</span>,<span style="color:#eedd82;">ResourceB</span>],<span style="color:#eedd82;">M</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceC</span>,<span style="color:#eedd82;">ResourceB</span>],<span style="color:#eedd82;">S2</span>()),
             <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">stop</span>,[]),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">M</span>()),
             {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>} = <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">start_link</span>,[]),
             {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>} = <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">start_link</span>,[]),
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceA</span>),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">M</span>()),
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceB</span>),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceC</span>,<span style="color:#eedd82;">ResourceB</span>],<span style="color:#eedd82;">M</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceC</span>,<span style="color:#eedd82;">ResourceB</span>],<span style="color:#eedd82;">S1</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceC</span>,<span style="color:#eedd82;">ResourceB</span>],<span style="color:#eedd82;">S2</span>())
     <span style="color:#00ffff;">end</span>}.

<span style="color:#87cefa;">register_deregister</span>([<span style="color:#eedd82;">N1</span>,<span style="color:#eedd82;">N2</span>]) -&gt;
    {<span style="color:#ffa07a;">"Can Register, Deregister and Register"</span>,
     <span style="color:#00ffff;">fun</span>() -&gt;
             <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">start_link</span>,[]),
             <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">start_link</span>,[]),
             <span style="color:#eedd82;">M</span> = <span style="color:#00ffff;">fun</span>() -&gt; <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">sort</span>(<span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">list_resources</span>()) <span style="color:#00ffff;">end</span>,
             <span style="color:#eedd82;">S1</span> = <span style="color:#00ffff;">fun</span>() -&gt; <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">sort</span>(<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">list_resources</span>,[])) <span style="color:#00ffff;">end</span>,
             <span style="color:#eedd82;">S2</span> = <span style="color:#00ffff;">fun</span>() -&gt; <span style="color:#98fb98;">lists</span>:<span style="color:#98fb98;">sort</span>(<span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">list_resources</span>,[])) <span style="color:#00ffff;">end</span>,
             <span style="color:#eedd82;">ResourceA</span> = #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"A"</span>,<span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">a</span>,1}],<span style="color:#7fffd4;">resides</span> = <span style="color:#eedd82;">N1</span>},
             <span style="color:#eedd82;">ResourceB</span> = #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"B"</span>,<span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">b</span>,2}],<span style="color:#7fffd4;">resides</span> = <span style="color:#eedd82;">N2</span>},
             <span style="color:#eedd82;">ResourceC</span> = #<span style="color:#b0c4de;">wn_resource</span>{<span style="color:#7fffd4;">name</span> = <span style="color:#ffa07a;">"C"</span>,<span style="color:#7fffd4;">type</span> = [{<span style="color:#7fffd4;">c</span>,3}],<span style="color:#7fffd4;">resides</span> = <span style="color:#b0c4de;">node</span>()},
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceA</span>),
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceB</span>),
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceC</span>),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceB</span>,<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">M</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceB</span>,<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">S1</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceB</span>,<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">S2</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">deregister</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#ffa07a;">"A"</span>)),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceB</span>,<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">M</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceB</span>,<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">S1</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceB</span>,<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">S2</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">deregister</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#ffa07a;">"B"</span>)),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">M</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">S1</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">S2</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>(<span style="color:#7fffd4;">ok</span>,<span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">deregister</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#ffa07a;">"C"</span>)),
             ?<span style="color:#b0c4de;">assertEqual</span>([],<span style="color:#eedd82;">M</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>([],<span style="color:#eedd82;">S1</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>([],<span style="color:#eedd82;">S2</span>()),
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceA</span>),
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceB</span>),
             <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">register</span>(<span style="color:#eedd82;">ResourceC</span>),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceB</span>,<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">M</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceB</span>,<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">S1</span>()),
             ?<span style="color:#b0c4de;">assertEqual</span>([<span style="color:#eedd82;">ResourceA</span>,<span style="color:#eedd82;">ResourceB</span>,<span style="color:#eedd82;">ResourceC</span>],<span style="color:#eedd82;">S2</span>())
     <span style="color:#00ffff;">end</span>}.

<span style="color:#ff7f24;">%% </span><span style="color:#ff7f24;">-----------------------------------------------------------------
</span><span style="color:#87cefa;">setup</span>() -&gt;
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>} = <span style="color:#98fb98;">net_kernel</span>:<span style="color:#98fb98;">start</span>([<span style="color:#7fffd4;">eunit_resource</span>,<span style="color:#7fffd4;">shortnames</span>]),
    <span style="color:#98fb98;">erlang</span>:<span style="color:#98fb98;">set_cookie</span>(<span style="color:#b0c4de;">node</span>(),<span style="color:#7fffd4;">eunit</span>),
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">_</span>} = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">start_link</span>().

<span style="color:#87cefa;">cleanup</span>(<span style="color:#eedd82;">_</span>) -&gt;
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">net_kernel</span>:<span style="color:#98fb98;">stop</span>(),
    <span style="color:#7fffd4;">ok</span> = <span style="color:#98fb98;">wn_resource_layer</span>:<span style="color:#98fb98;">stop</span>().

<span style="color:#87cefa;">distr_setup</span>() -&gt;
    <span style="color:#98fb98;">setup</span>(),
    <span style="color:#eedd82;">Host</span> = <span style="color:#b0c4de;">list_to_atom</span>(<span style="color:#98fb98;">inet_db</span>:<span style="color:#98fb98;">gethostname</span>()),
    <span style="color:#eedd82;">Args</span> = <span style="color:#ffa07a;">" -pa "</span><span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#b0c4de;">hd</span>(<span style="color:#98fb98;">code</span>:<span style="color:#98fb98;">get_path</span>())<span style="color:#ffc0cb;font-weight:bold;">++</span><span style="color:#ffa07a;">" -setcookie eunit"</span>,
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">N1</span>} = <span style="color:#98fb98;">slave</span>:<span style="color:#98fb98;">start</span>(<span style="color:#eedd82;">Host</span>,<span style="color:#7fffd4;">n1</span>,<span style="color:#eedd82;">Args</span>),
    {<span style="color:#7fffd4;">ok</span>,<span style="color:#eedd82;">N2</span>} = <span style="color:#98fb98;">slave</span>:<span style="color:#98fb98;">start</span>(<span style="color:#eedd82;">Host</span>,<span style="color:#7fffd4;">n2</span>,<span style="color:#eedd82;">Args</span>),
    <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">net_kernel</span>,<span style="color:#7fffd4;">connect_node</span>,[<span style="color:#eedd82;">N2</span>]),
    [<span style="color:#eedd82;">N1</span>,<span style="color:#eedd82;">N2</span>].

<span style="color:#87cefa;">distr_cleanup</span>([<span style="color:#eedd82;">N1</span>,<span style="color:#eedd82;">N2</span>]) -&gt;
    <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N1</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">stop</span>,[]),
    <span style="color:#98fb98;">rpc</span>:<span style="color:#98fb98;">call</span>(<span style="color:#eedd82;">N2</span>,<span style="color:#7fffd4;">wn_resource_layer</span>,<span style="color:#7fffd4;">stop</span>,[]),
    <span style="color:#98fb98;">slave</span>:<span style="color:#98fb98;">stop</span>(<span style="color:#eedd82;">N1</span>),
    <span style="color:#98fb98;">slave</span>:<span style="color:#98fb98;">stop</span>(<span style="color:#eedd82;">N2</span>),
    <span style="color:#98fb98;">cleanup</span>(<span style="color:#7fffd4;">nothing</span>).</pre>
</h6>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/erlcode.wordpress.com/375/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/erlcode.wordpress.com/375/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=erlcode.wordpress.com&#038;blog=15510807&#038;post=375&#038;subd=erlcode&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://erlcode.wordpress.com/2010/12/17/erlang-tdd-hands-on-project-workernet-part-1/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/861b8f824c3cd15c17ac6aa1b902e029?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">gianfrancoalongi</media:title>
		</media:content>

		<media:content url="http://erlcode.files.wordpress.com/2010/12/explanation12.png" medium="image">
			<media:title type="html">Explanation1</media:title>
		</media:content>

		<media:content url="http://erlcode.files.wordpress.com/2010/12/node1.png" medium="image">
			<media:title type="html">Node</media:title>
		</media:content>

		<media:content url="http://erlcode.files.wordpress.com/2010/12/localfirst.png" medium="image">
			<media:title type="html">LocalFirst</media:title>
		</media:content>
	</item>
	</channel>
</rss>
