summaryrefslogtreecommitdiff
path: root/code/spyglass/docs/lookout.html
diff options
context:
space:
mode:
Diffstat (limited to 'code/spyglass/docs/lookout.html')
-rw-r--r--code/spyglass/docs/lookout.html325
1 files changed, 325 insertions, 0 deletions
diff --git a/code/spyglass/docs/lookout.html b/code/spyglass/docs/lookout.html
new file mode 100644
index 0000000..a017f33
--- /dev/null
+++ b/code/spyglass/docs/lookout.html
@@ -0,0 +1,325 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+ <title>lookout.rb</title>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
+ <link rel="stylesheet" media="all" href="docco.css" />
+</head>
+<body>
+ <div id="container">
+ <div id="background"></div>
+
+ <ul id="jump_to">
+ <li>
+ <a class="large" href="javascript:void(0);">Jump To &hellip;</a>
+ <a class="small" href="javascript:void(0);">+</a>
+ <div id="jump_wrapper">
+ <div id="jump_page">
+
+
+ <a class="source" href="configurator.html">
+ configurator.rb
+ </a>
+
+
+ <a class="source" href="logging.html">
+ logging.rb
+ </a>
+
+
+ <a class="source" href="lookout.html">
+ lookout.rb
+ </a>
+
+
+ <a class="source" href="master.html">
+ master.rb
+ </a>
+
+
+ <a class="source" href="server.html">
+ server.rb
+ </a>
+
+
+ <a class="source" href="worker.html">
+ worker.rb
+ </a>
+
+ </div>
+ </li>
+ </ul>
+
+ <ul class="sections">
+
+ <li id="title">
+ <div class="annotation">
+ <h1>lookout.rb</h1>
+ </div>
+ </li>
+
+
+
+ <li id="section-1">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-1">&#182;</a>
+ </div>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre><span class="class"><span class="keyword">module</span> <span class="title">Spyglass</span></span>
+ <span class="class"><span class="keyword">class</span> <span class="title">Lookout</span></span>
+ <span class="keyword">include</span> <span class="constant">Singleton</span>, <span class="constant">Logging</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-2">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-2">&#182;</a>
+ </div>
+ <p>This method is the main entry point for the Lookout class. It takes
+a socket object.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="function"><span class="keyword">def</span> <span class="title">start</span><span class="params">(socket)</span></span>
+ trap_signals</pre></div></div>
+
+ </li>
+
+
+ <li id="section-3">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-3">&#182;</a>
+ </div>
+ <p>The Lookout doesn&#39;t know anything about the app itself, so there&#39;s
+no app related setup to do here.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> loop <span class="keyword">do</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-4">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-4">&#182;</a>
+ </div>
+ <p>Accepts a new connection on our socket. This class won&#39;t actually
+do anything interesting with this connection, it will pass it down
+to the <code>Master</code> class created below to do the actual request handling.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> conn = socket.accept
+ out <span class="string">"Received incoming connection"</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-5">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-5">&#182;</a>
+ </div>
+ <p>In this block the Lookout forks a new process and invokes a Master,
+passing along the socket it received and the connection it accepted
+above.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="variable">@master_pid</span> = fork <span class="keyword">do</span>
+ master = <span class="constant">Master</span>.new(conn, socket)
+ master.start
+ <span class="keyword">end</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-6">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-6">&#182;</a>
+ </div>
+ <p>The Lookout can now close its handle on the client socket. This doesn&#39;t
+translate to the socket being closed on the clients end because the
+forked Master process also has a handle on the same socket. Since this
+handle is now cleaned up it&#39;s up to the Master process to ensure that
+its handle gets cleaned up.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> conn.close</pre></div></div>
+
+ </li>
+
+
+ <li id="section-7">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-7">&#182;</a>
+ </div>
+ <p>Now this process blocks until the Master process exits. The Master process
+will only exit once traffic is slow enough that it has reached its timeout
+without receiving any new connections.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="constant">Process</span>.waitpid(<span class="variable">@master_pid</span>)</pre></div></div>
+
+ </li>
+
+
+ <li id="section-8">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-8">&#182;</a>
+ </div>
+ <p>The interaction of fork(2)/waitpid(2) above deserve some explanation.</p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-9">
+ <div class="annotation">
+
+ <div class="pilwrap for-h3">
+ <a class="pilcrow" href="#section-9">&#182;</a>
+ </div>
+ <h3>Why fork(2)? Why not just spin up the Master?</h3>
+<p>The whole point of the Lookout process is to be very lean. The only resource
+that it initializes is the listening socket for the server. It doesn&#39;t load
+any of your application into memory, so its resource footprint is very small.</p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-10">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-10">&#182;</a>
+ </div>
+ <p>The reason that it does a fork(2) before invoking the Master is because once
+the Master times out we want the Lookout process to remain lean when accepting
+the next connection. </p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-11">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-11">&#182;</a>
+ </div>
+ <p>If it were to load the application code without forking
+then there would be no (simple) way for it to later unload the application code.</p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-12">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-12">&#182;</a>
+ </div>
+ <p>By doing a fork(2), then waiting for the Master process to exit, that guarantees
+that all resources (notably memory usage) that were in use by the Master process
+will be reclaimed by the kernel. </p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-13">
+ <div class="annotation">
+
+ <div class="pilwrap for-h3">
+ <a class="pilcrow" href="#section-13">&#182;</a>
+ </div>
+ <h3>Who knows what your app will demand!</h3>
+<p>While handling requests your app may require lots of memory. Containing this in a
+child process, and exiting that process, is the easiest way to ensure that memory
+bloat isn&#39;t shared with our simple parent process.</p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-14">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-14">&#182;</a>
+ </div>
+ <p>This allows our Lookout process will to go back around
+the loop with nothing more than it started with, just a listening socket.</p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-15">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-15">&#182;</a>
+ </div>
+ <p>The fork(2)/waitpid(2) approach requires little code to implement, and pushes
+responsibility down to the kernel to track resource usage and nicely clean up
+the Master process when it&#39;s finished.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">end</span>
+ <span class="keyword">end</span>
+
+ <span class="function"><span class="keyword">def</span> <span class="title">trap_signals</span></span>
+ [<span class="symbol">:INT</span>, <span class="symbol">:QUIT</span>].each <span class="keyword">do</span> |sig|
+ trap(sig) {
+ <span class="keyword">begin</span>
+ <span class="constant">Process</span>.kill(sig, <span class="variable">@master_pid</span>) <span class="keyword">if</span> <span class="variable">@master_pid</span>
+ <span class="keyword">rescue</span> <span class="constant">Errno::ESRCH</span>
+ <span class="keyword">end</span>
+ exit
+ }
+ <span class="keyword">end</span>
+ <span class="keyword">end</span>
+ <span class="keyword">end</span>
+<span class="keyword">end</span></pre></div></div>
+
+ </li>
+
+ </ul>
+ </div>
+</body>
+</html>