pclients.html   [plain text]


<?xml version="1.0"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><title>Twisted Documentation: Managing Clients of Perspectives</title><link href="../howto/stylesheet.css" type="text/css" rel="stylesheet" /><link href="http://twistedmatrix.com/users/acapnotic/" rel="author" title="Kevin Turner" /></head><body bgcolor="white"><h1 class="title">Managing Clients of Perspectives</h1><div class="toc"><ol><li><a href="#auto0">Overview</a></li><li><a href="#auto1">Managing Avatars</a></li><li><a href="#auto2">Managing Clients</a></li></ol></div><div class="content"><span></span><h2>Overview<a name="auto0"></a></h2><p>In all the <code class="API"><a href="http://twistedmatrix.com/documents/TwistedDocs/TwistedDocs-1.3.0/api/twisted.spread.pb.IPerspective.html" title="twisted.spread.pb.IPerspective">IPerspective</a></code>
we have shown so far, we ignored the <code>mind</code> argument and created
a new <code>Avatar</code> for every connection. This is usually an easy
design choice, and it works well for simple cases.</p><p>In more complicated cases, for example an <code>Avatar</code> that
represents a player object which is persistent in the game universe,
we will want connections from the same player to use the same
<code>Avatar</code>.</p><p>Another thing which is necessary in more complicated scenarios
is notifying a player asynchronously. While it is possible, of
course, to allow a player to call
<code>perspective_remoteListener(referencable)</code> that would
mean both duplication of code and a higher latency in logging in,
both bad.</p><p>In previous sections all realms looked to be identical.
In this one we will show the usefulness of realms in accomplishing
those two objectives.</p><h2>Managing Avatars<a name="auto1"></a></h2><p>The simplest way to manage persistent avatars is to use a straight-forward
caching mechanism:</p><pre class="python">
<span class="py-src-keyword">class</span> <span class="py-src-identifier">SimpleAvatar</span><span class="py-src-op">(</span><span class="py-src-parameter">pb</span><span class="py-src-op">.</span><span class="py-src-parameter">Avatar</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">    </span><span class="py-src-variable">greetings</span> <span class="py-src-op">=</span> <span class="py-src-number">0</span><span class="py-src-newline">
</span>    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">name</span><span class="py-src-op">)</span><span class="py-src-op">:</span> <span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">name</span> <span class="py-src-op">=</span> <span class="py-src-variable">name</span><span class="py-src-newline">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">perspective_greet</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">greetings</span> <span class="py-src-op">+=</span> <span class="py-src-number">1</span><span class="py-src-newline">
</span>        <span class="py-src-keyword">return</span> <span class="py-src-string">&quot;&lt;%d&gt;hello %s&quot;</span> <span class="py-src-op">%</span> <span class="py-src-op">(</span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">greetings</span><span class="py-src-op">,</span> <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">name</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span><span class="py-src-dedent"></span><span class="py-src-dedent"></span><span class="py-src-keyword">class</span> <span class="py-src-identifier">CachingRealm</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">    </span><span class="py-src-variable">__implements__</span> <span class="py-src-op">=</span> <span class="py-src-variable">portal</span><span class="py-src-op">.</span><span class="py-src-variable">IRealm</span><span class="py-src-op">,</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">avatars</span> <span class="py-src-op">=</span> <span class="py-src-op">{</span><span class="py-src-op">}</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">requestAvatar</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">avatarId</span><span class="py-src-op">,</span> <span class="py-src-parameter">mind</span><span class="py-src-op">,</span> <span class="py-src-op">*</span><span class="py-src-parameter">interfaces</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-keyword">if</span> <span class="py-src-variable">pb</span><span class="py-src-op">.</span><span class="py-src-variable">IPerspective</span> <span class="py-src-keyword">not</span> <span class="py-src-keyword">in</span> <span class="py-src-variable">interfaces</span><span class="py-src-op">:</span> <span class="py-src-keyword">raise</span> <span class="py-src-variable">NotImplementedError</span><span class="py-src-newline">
</span>        <span class="py-src-keyword">if</span> <span class="py-src-variable">avatarId</span> <span class="py-src-keyword">in</span> <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">avatars</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">            </span><span class="py-src-variable">p</span> <span class="py-src-op">=</span> <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">avatars</span><span class="py-src-op">[</span><span class="py-src-variable">avatarId</span><span class="py-src-op">]</span><span class="py-src-newline">
</span>        <span class="py-src-dedent"></span><span class="py-src-keyword">else</span><span class="py-src-op">:</span> <span class="py-src-newline">
</span><span class="py-src-indent">            </span><span class="py-src-variable">p</span> <span class="py-src-op">=</span> <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">avatars</span><span class="py-src-op">[</span><span class="py-src-variable">avatarId</span><span class="py-src-op">]</span> <span class="py-src-op">=</span> <span class="py-src-variable">SimpleAvatar</span><span class="py-src-op">(</span><span class="py-src-variable">avatarId</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>        <span class="py-src-dedent"></span><span class="py-src-keyword">return</span> <span class="py-src-variable">pb</span><span class="py-src-op">.</span><span class="py-src-variable">IPerspective</span><span class="py-src-op">,</span> <span class="py-src-variable">p</span><span class="py-src-op">,</span> <span class="py-src-keyword">lambda</span><span class="py-src-op">:</span><span class="py-src-variable">None</span><span class="py-src-newline">
</span><span class="py-src-dedent"></span><span class="py-src-dedent"></span><span class="py-src-endmarker"></span></pre><p>This gives us a perspective which counts the number of greetings it
sent its client. Implementing a caching strategy, as opposed to generating
a realm with the correct avatars already in it, is usually easier. This
makes adding new checkers to the portal, or adding new users to a checker
database, transparent. Otherwise, careful synchronization is needed between
the checker and avatar is needed (much like the synchronization between
UNIX's <code>/etc/shadow</code> and <code>/etc/passwd</code>).</p><p>Sometimes, however, an avatar will need enough per-connection state
that it would be easier to generate a new avatar and cache something
else. Here is an example of that:</p><pre class="python">
<span class="py-src-keyword">class</span> <span class="py-src-identifier">Greeter</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">    </span><span class="py-src-variable">greetings</span> <span class="py-src-op">=</span> <span class="py-src-number">0</span><span class="py-src-newline">
</span>    <span class="py-src-keyword">def</span> <span class="py-src-identifier">hello</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">greetings</span> <span class="py-src-op">+=</span> <span class="py-src-number">1</span><span class="py-src-newline">
</span>        <span class="py-src-keyword">return</span> <span class="py-src-string">&quot;&lt;%d&gt;hello&quot;</span> <span class="py-src-op">%</span> <span class="py-src-op">(</span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">greetings</span><span class="py-src-op">,</span> <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">name</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span><span class="py-src-dedent"></span><span class="py-src-dedent"></span><span class="py-src-keyword">class</span> <span class="py-src-identifier">SimpleAvatar</span><span class="py-src-op">(</span><span class="py-src-parameter">pb</span><span class="py-src-op">.</span><span class="py-src-parameter">Avatar</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">    </span><span class="py-src-variable">greetings</span> <span class="py-src-op">=</span> <span class="py-src-number">0</span><span class="py-src-newline">
</span>    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">name</span><span class="py-src-op">,</span> <span class="py-src-parameter">greeter</span><span class="py-src-op">)</span><span class="py-src-op">:</span> <span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">name</span> <span class="py-src-op">=</span> <span class="py-src-variable">name</span><span class="py-src-newline">
</span>        <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">greeter</span> <span class="py-src-op">=</span> <span class="py-src-variable">greeter</span><span class="py-src-newline">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">perspective_greet</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-keyword">return</span> <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">greeter</span><span class="py-src-op">.</span><span class="py-src-variable">hello</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-op">+</span><span class="py-src-string">' '</span><span class="py-src-op">+</span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">name</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span><span class="py-src-dedent"></span><span class="py-src-dedent"></span><span class="py-src-keyword">class</span> <span class="py-src-identifier">CachingRealm</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">    </span><span class="py-src-variable">__implements__</span> <span class="py-src-op">=</span> <span class="py-src-variable">portal</span><span class="py-src-op">.</span><span class="py-src-variable">IRealm</span><span class="py-src-op">,</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">greeters</span> <span class="py-src-op">=</span> <span class="py-src-op">{</span><span class="py-src-op">}</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">requestAvatar</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">avatarId</span><span class="py-src-op">,</span> <span class="py-src-parameter">mind</span><span class="py-src-op">,</span> <span class="py-src-op">*</span><span class="py-src-parameter">interfaces</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-keyword">if</span> <span class="py-src-variable">pb</span><span class="py-src-op">.</span><span class="py-src-variable">IPerspective</span> <span class="py-src-keyword">not</span> <span class="py-src-keyword">in</span> <span class="py-src-variable">interfaces</span><span class="py-src-op">:</span> <span class="py-src-keyword">raise</span> <span class="py-src-variable">NotImplementedError</span><span class="py-src-newline">
</span>        <span class="py-src-keyword">if</span> <span class="py-src-variable">avatarId</span> <span class="py-src-keyword">in</span> <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">greeters</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">            </span><span class="py-src-variable">p</span> <span class="py-src-op">=</span> <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">greeters</span><span class="py-src-op">[</span><span class="py-src-variable">avatarId</span><span class="py-src-op">]</span><span class="py-src-newline">
</span>        <span class="py-src-dedent"></span><span class="py-src-keyword">else</span><span class="py-src-op">:</span> <span class="py-src-newline">
</span><span class="py-src-indent">            </span><span class="py-src-variable">p</span> <span class="py-src-op">=</span> <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">greeters</span><span class="py-src-op">[</span><span class="py-src-variable">avatarId</span><span class="py-src-op">]</span> <span class="py-src-op">=</span> <span class="py-src-variable">Greeter</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>        <span class="py-src-dedent"></span><span class="py-src-keyword">return</span> <span class="py-src-variable">pb</span><span class="py-src-op">.</span><span class="py-src-variable">IPerspective</span><span class="py-src-op">,</span> <span class="py-src-variable">SimpleAvatar</span><span class="py-src-op">(</span><span class="py-src-variable">avatarId</span><span class="py-src-op">,</span> <span class="py-src-variable">p</span><span class="py-src-op">)</span><span class="py-src-op">,</span> <span class="py-src-keyword">lambda</span><span class="py-src-op">:</span><span class="py-src-variable">None</span><span class="py-src-newline">
</span><span class="py-src-dedent"></span><span class="py-src-dedent"></span><span class="py-src-endmarker"></span></pre><p>It might seem tempting to use this pattern to have an avatar which
is notified of new connections. However, the problems here are twofold:
it would lead to a thin class which needs to forward all of its methods,
and it would be impossible to know when disconnections occur. Luckily,
there is a better pattern:</p><pre class="python">
<span class="py-src-keyword">class</span> <span class="py-src-identifier">SimpleAvatar</span><span class="py-src-op">(</span><span class="py-src-parameter">pb</span><span class="py-src-op">.</span><span class="py-src-parameter">Avatar</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">    </span><span class="py-src-variable">greetings</span> <span class="py-src-op">=</span> <span class="py-src-number">0</span><span class="py-src-newline">
</span>    <span class="py-src-variable">connections</span> <span class="py-src-op">=</span> <span class="py-src-number">0</span><span class="py-src-newline">
</span>    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">name</span><span class="py-src-op">)</span><span class="py-src-op">:</span> <span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">name</span> <span class="py-src-op">=</span> <span class="py-src-variable">name</span><span class="py-src-newline">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">connect</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">connections</span> <span class="py-src-op">+=</span> <span class="py-src-number">1</span><span class="py-src-newline">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">disconnect</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">connections</span> <span class="py-src-op">-=</span> <span class="py-src-number">1</span><span class="py-src-newline">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">perspective_greet</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">greetings</span> <span class="py-src-op">+=</span> <span class="py-src-number">1</span><span class="py-src-newline">
</span>        <span class="py-src-keyword">return</span> <span class="py-src-string">&quot;&lt;%d&gt;hello %s&quot;</span> <span class="py-src-op">%</span> <span class="py-src-op">(</span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">greetings</span><span class="py-src-op">,</span> <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">name</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span><span class="py-src-dedent"></span><span class="py-src-dedent"></span><span class="py-src-keyword">class</span> <span class="py-src-identifier">CachingRealm</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">    </span><span class="py-src-variable">__implements__</span> <span class="py-src-op">=</span> <span class="py-src-variable">portal</span><span class="py-src-op">.</span><span class="py-src-variable">IRealm</span><span class="py-src-op">,</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">avatars</span> <span class="py-src-op">=</span> <span class="py-src-op">{</span><span class="py-src-op">}</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">requestAvatar</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">avatarId</span><span class="py-src-op">,</span> <span class="py-src-parameter">mind</span><span class="py-src-op">,</span> <span class="py-src-op">*</span><span class="py-src-parameter">interfaces</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-keyword">if</span> <span class="py-src-variable">pb</span><span class="py-src-op">.</span><span class="py-src-variable">IPerspective</span> <span class="py-src-keyword">not</span> <span class="py-src-keyword">in</span> <span class="py-src-variable">interfaces</span><span class="py-src-op">:</span> <span class="py-src-keyword">raise</span> <span class="py-src-variable">NotImplementedError</span><span class="py-src-newline">
</span>        <span class="py-src-keyword">if</span> <span class="py-src-variable">avatarId</span> <span class="py-src-keyword">in</span> <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">avatars</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">            </span><span class="py-src-variable">p</span> <span class="py-src-op">=</span> <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">avatars</span><span class="py-src-op">[</span><span class="py-src-variable">avatarId</span><span class="py-src-op">]</span><span class="py-src-newline">
</span>        <span class="py-src-dedent"></span><span class="py-src-keyword">else</span><span class="py-src-op">:</span> <span class="py-src-newline">
</span><span class="py-src-indent">            </span><span class="py-src-variable">p</span> <span class="py-src-op">=</span> <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">avatars</span><span class="py-src-op">[</span><span class="py-src-variable">avatarId</span><span class="py-src-op">]</span> <span class="py-src-op">=</span> <span class="py-src-variable">SimpleAvatar</span><span class="py-src-op">(</span><span class="py-src-variable">avatarId</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>        <span class="py-src-dedent"></span><span class="py-src-variable">p</span><span class="py-src-op">.</span><span class="py-src-variable">connect</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>        <span class="py-src-keyword">return</span> <span class="py-src-variable">pb</span><span class="py-src-op">.</span><span class="py-src-variable">IPerspective</span><span class="py-src-op">,</span> <span class="py-src-variable">p</span><span class="py-src-op">,</span> <span class="py-src-variable">p</span><span class="py-src-op">.</span><span class="py-src-variable">disconnect</span><span class="py-src-newline">
</span><span class="py-src-dedent"></span><span class="py-src-dedent"></span><span class="py-src-endmarker"></span></pre><p>It is possible to use such a pattern to define an arbitrary limit for
the number of concurrent connections:</p><pre class="python">
<span class="py-src-keyword">class</span> <span class="py-src-identifier">SimpleAvatar</span><span class="py-src-op">(</span><span class="py-src-parameter">pb</span><span class="py-src-op">.</span><span class="py-src-parameter">Avatar</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">    </span><span class="py-src-variable">greetings</span> <span class="py-src-op">=</span> <span class="py-src-number">0</span><span class="py-src-newline">
</span>    <span class="py-src-variable">connections</span> <span class="py-src-op">=</span> <span class="py-src-number">0</span><span class="py-src-newline">
</span>    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">name</span><span class="py-src-op">)</span><span class="py-src-op">:</span> <span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">name</span> <span class="py-src-op">=</span> <span class="py-src-variable">name</span><span class="py-src-newline">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">connect</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">connections</span> <span class="py-src-op">+=</span> <span class="py-src-number">1</span><span class="py-src-newline">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">disconnect</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">connections</span> <span class="py-src-op">-=</span> <span class="py-src-number">1</span><span class="py-src-newline">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">perspective_greet</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">greetings</span> <span class="py-src-op">+=</span> <span class="py-src-number">1</span><span class="py-src-newline">
</span>        <span class="py-src-keyword">return</span> <span class="py-src-string">&quot;&lt;%d&gt;hello %s&quot;</span> <span class="py-src-op">%</span> <span class="py-src-op">(</span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">greetings</span><span class="py-src-op">,</span> <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">name</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span><span class="py-src-dedent"></span><span class="py-src-dedent"></span><span class="py-src-keyword">class</span> <span class="py-src-identifier">CachingRealm</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">    </span><span class="py-src-variable">__implements__</span> <span class="py-src-op">=</span> <span class="py-src-variable">portal</span><span class="py-src-op">.</span><span class="py-src-variable">IRealm</span><span class="py-src-op">,</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">max</span><span class="py-src-op">=</span><span class="py-src-number">1</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">avatars</span> <span class="py-src-op">=</span> <span class="py-src-op">{</span><span class="py-src-op">}</span><span class="py-src-newline">
</span>        <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">max</span> <span class="py-src-op">=</span> <span class="py-src-variable">max</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">requestAvatar</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">avatarId</span><span class="py-src-op">,</span> <span class="py-src-parameter">mind</span><span class="py-src-op">,</span> <span class="py-src-op">*</span><span class="py-src-parameter">interfaces</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-keyword">if</span> <span class="py-src-variable">pb</span><span class="py-src-op">.</span><span class="py-src-variable">IPerspective</span> <span class="py-src-keyword">not</span> <span class="py-src-keyword">in</span> <span class="py-src-variable">interfaces</span><span class="py-src-op">:</span> <span class="py-src-keyword">raise</span> <span class="py-src-variable">NotImplementedError</span><span class="py-src-newline">
</span>        <span class="py-src-keyword">if</span> <span class="py-src-variable">avatarId</span> <span class="py-src-keyword">in</span> <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">avatars</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">            </span><span class="py-src-variable">p</span> <span class="py-src-op">=</span> <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">avatars</span><span class="py-src-op">[</span><span class="py-src-variable">avatarId</span><span class="py-src-op">]</span><span class="py-src-newline">
</span>        <span class="py-src-dedent"></span><span class="py-src-keyword">else</span><span class="py-src-op">:</span> <span class="py-src-newline">
</span><span class="py-src-indent">            </span><span class="py-src-variable">p</span> <span class="py-src-op">=</span> <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">avatars</span><span class="py-src-op">[</span><span class="py-src-variable">avatarId</span><span class="py-src-op">]</span> <span class="py-src-op">=</span> <span class="py-src-variable">SimpleAvatar</span><span class="py-src-op">(</span><span class="py-src-variable">avatarId</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>        <span class="py-src-dedent"></span><span class="py-src-keyword">if</span> <span class="py-src-variable">p</span><span class="py-src-op">.</span><span class="py-src-variable">connections</span> <span class="py-src-op">&gt;=</span> <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">max</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">            </span><span class="py-src-keyword">raise</span> <span class="py-src-variable">ValueError</span><span class="py-src-op">(</span><span class="py-src-string">&quot;too many connections&quot;</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>        <span class="py-src-dedent"></span><span class="py-src-variable">p</span><span class="py-src-op">.</span><span class="py-src-variable">connect</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>        <span class="py-src-keyword">return</span> <span class="py-src-variable">pb</span><span class="py-src-op">.</span><span class="py-src-variable">IPerspective</span><span class="py-src-op">,</span> <span class="py-src-variable">p</span><span class="py-src-op">,</span> <span class="py-src-variable">p</span><span class="py-src-op">.</span><span class="py-src-variable">disconnect</span><span class="py-src-newline">
</span><span class="py-src-dedent"></span><span class="py-src-dedent"></span><span class="py-src-endmarker"></span></pre><h2>Managing Clients<a name="auto2"></a></h2><p>So far, all our realms have ignored the <code>mind</code> argument.
In the case of PB, the <code>mind</code> is an object supplied by
the remote login method -- usually, when it passes over the wire,
it becomes a <code>pb.RemoteReference</code>. This object allows
sending messages to the client as soon as the connection is established
and authenticated.</p><p>Here is a simple remote-clock application which shows the usefulness
of the <code>mind</code> argument:</p><pre class="python">
<span class="py-src-keyword">class</span> <span class="py-src-identifier">SimpleAvatar</span><span class="py-src-op">(</span><span class="py-src-parameter">pb</span><span class="py-src-op">.</span><span class="py-src-parameter">Avatar</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">    </span><span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">client</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">s</span> <span class="py-src-op">=</span> <span class="py-src-variable">internet</span><span class="py-src-op">.</span><span class="py-src-variable">TimerService</span><span class="py-src-op">(</span><span class="py-src-number">1</span><span class="py-src-op">,</span> <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">telltime</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>        <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">s</span><span class="py-src-op">.</span><span class="py-src-variable">startService</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>        <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">client</span> <span class="py-src-op">=</span> <span class="py-src-variable">client</span><span class="py-src-newline">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">telltime</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">client</span><span class="py-src-op">.</span><span class="py-src-variable">callRemote</span><span class="py-src-op">(</span><span class="py-src-string">&quot;notifyTime&quot;</span><span class="py-src-op">,</span> <span class="py-src-variable">time</span><span class="py-src-op">.</span><span class="py-src-variable">time</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">perspective_setperiod</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">period</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">s</span><span class="py-src-op">.</span><span class="py-src-variable">stopService</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>        <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">s</span> <span class="py-src-op">=</span> <span class="py-src-variable">internet</span><span class="py-src-op">.</span><span class="py-src-variable">TimerService</span><span class="py-src-op">(</span><span class="py-src-variable">period</span><span class="py-src-op">,</span> <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">telltime</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>        <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">s</span><span class="py-src-op">.</span><span class="py-src-variable">startService</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">logout</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">s</span><span class="py-src-op">.</span><span class="py-src-variable">stopService</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>         <span class="py-src-nl">
</span><span class="py-src-dedent"></span><span class="py-src-dedent"></span><span class="py-src-keyword">class</span> <span class="py-src-identifier">Realm</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">    </span><span class="py-src-variable">__implements__</span> <span class="py-src-op">=</span> <span class="py-src-variable">portal</span><span class="py-src-op">.</span><span class="py-src-variable">IRealm</span><span class="py-src-op">,</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-keyword">def</span> <span class="py-src-identifier">requestAvatar</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">avatarId</span><span class="py-src-op">,</span> <span class="py-src-parameter">mind</span><span class="py-src-op">,</span> <span class="py-src-op">*</span><span class="py-src-parameter">interfaces</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-keyword">if</span> <span class="py-src-variable">pb</span><span class="py-src-op">.</span><span class="py-src-variable">IPerspective</span> <span class="py-src-keyword">not</span> <span class="py-src-keyword">in</span> <span class="py-src-variable">interfaces</span><span class="py-src-op">:</span> <span class="py-src-keyword">raise</span> <span class="py-src-variable">NotImplementedError</span><span class="py-src-newline">
</span>        <span class="py-src-variable">p</span> <span class="py-src-op">=</span> <span class="py-src-variable">SimpleAvatar</span><span class="py-src-op">(</span><span class="py-src-variable">mind</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>        <span class="py-src-keyword">return</span> <span class="py-src-variable">pb</span><span class="py-src-op">.</span><span class="py-src-variable">IPerspective</span><span class="py-src-op">,</span> <span class="py-src-variable">p</span><span class="py-src-op">,</span> <span class="py-src-variable">p</span><span class="py-src-op">.</span><span class="py-src-variable">logout</span><span class="py-src-newline">
</span><span class="py-src-dedent"></span><span class="py-src-dedent"></span><span class="py-src-endmarker"></span></pre><p>In more complicated situations, you might want to cache the avatars
and give each one a set of <q>current clients</q> or something similar.</p></div><p><a href="../howto/index.html">Index</a></p><span class="version">Version: 1.3.0</span></body></html>