You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by bu...@apache.org on 2018/01/19 22:44:53 UTC

svn commit: r1024039 - in /websites/staging/directory/trunk/content: ./ api/internal-design-guide/ api/internal-design-guide/images/

Author: buildbot
Date: Fri Jan 19 22:44:53 2018
New Revision: 1024039

Log:
Staging update by buildbot for directory

Added:
    websites/staging/directory/trunk/content/api/internal-design-guide/images/ldapconnection.graphml   (with props)
    websites/staging/directory/trunk/content/api/internal-design-guide/images/ldapconnection.png   (with props)
Modified:
    websites/staging/directory/trunk/content/   (props changed)
    websites/staging/directory/trunk/content/api/internal-design-guide/2-general-structure.html
    websites/staging/directory/trunk/content/api/internal-design-guide/5-network.html

Propchange: websites/staging/directory/trunk/content/
------------------------------------------------------------------------------
--- cms:source-revision (original)
+++ cms:source-revision Fri Jan 19 22:44:53 2018
@@ -1 +1 @@
-1821474
+1821721

Modified: websites/staging/directory/trunk/content/api/internal-design-guide/2-general-structure.html
==============================================================================
--- websites/staging/directory/trunk/content/api/internal-design-guide/2-general-structure.html (original)
+++ websites/staging/directory/trunk/content/api/internal-design-guide/2-general-structure.html Fri Jan 19 22:44:53 2018
@@ -186,74 +186,7 @@
 h2:hover > .headerlink, h3:hover > .headerlink, h1:hover > .headerlink, h6:hover > .headerlink, h4:hover > .headerlink, h5:hover > .headerlink, dt:hover > .elementid-permalink { visibility: visible }</style>
 <h1 id="2-general-structure">2 - General Structure<a class="headerlink" href="#2-general-structure" title="Permanent link">&para;</a></h1>
 <p>The <strong>Apache LDAP API</strong> is split into many modules. Here is their hierarchy :</p>
-<p><img alt="Modules" src="images/ldap-api-modules.png" />
-<pre>
-LDAP API root
-  |
-  +-- all
-  |
-  +-- asn1
-  |    |
-  |    +-- api
-  |    |
-  |    +-- ber
-  |
-  +-- distribution
-  |
-  +-- dsml
-  |    |
-  |    +-- engine
-  |    |
-  |    +-- parser
-  |
-  +-- i18n
-  |
-  +-- integ
-  |
-  +-- integ-osgi
-  |
-  +-- ldap
-  |    |
-  |    +-- client
-  |    |    |
-  |    |    +-- all
-  |    |    |
-  |    |    +-- api
-  |    |
-  |    +-- codec
-  |    |    |
-  |    |    +-- core
-  |    |    |
-  |    |    +-- standalone
-  |    |
-  |    +-- extras
-  |    |    |
-  |    |    +-- aci
-  |    |    |
-  |    |    +-- codec
-  |    |    |
-  |    |    +-- codec-api
-  |    |    |
-  |    |    +--sp
-  |    |    |
-  |    |    +-- trigger
-  |    |    |
-  |    |    +-- util
-  |    |
-  |    +-- model
-  |    |
-  |    +-- net
-  |    |    |
-  |    |    +-- mina
-  |    |
-  |    +-- schema
-  |         |
-  |         +-- converter
-  |         |
-  |         +-- data
-  |
-  +-- util
-</pre></p>
+<p><img alt="Modules" src="images/ldap-api-modules.png" /></p>
 <ul>
 <li>
 <p>The <strong>all</strong> module is just a packaging module, gathering all the other modules in one single jar to simplify the work for those who want to use the API. One can import each module speparately, or the <strong>all</strong> module only. Note that it does not include the tests and integration modules (<strong>integ</strong>, <strong>integ-osgi</strong> and <strong>distribution</strong>)</p>

Modified: websites/staging/directory/trunk/content/api/internal-design-guide/5-network.html
==============================================================================
--- websites/staging/directory/trunk/content/api/internal-design-guide/5-network.html (original)
+++ websites/staging/directory/trunk/content/api/internal-design-guide/5-network.html Fri Jan 19 22:44:53 2018
@@ -185,7 +185,146 @@
 }
 h2:hover > .headerlink, h3:hover > .headerlink, h1:hover > .headerlink, h6:hover > .headerlink, h4:hover > .headerlink, h5:hover > .headerlink, dt:hover > .elementid-permalink { visibility: visible }</style>
 <h1 id="5-network">5 - Network<a class="headerlink" href="#5-network" title="Permanent link">&para;</a></h1>
-<p>TODO...</p>
+<p>The <strong>Apache LDAP AP</strong> is built on top of <a href="http://mina.apache.org">**Apache MINA</a> which is a <strong>NIO</strong> framework. </p>
+<p>As <strong>MINA</strong> is fully asynchronous, it has some impact on the design of the <strong>LDAP API</strong>. Basically, we send requests, and we don't wait for responses, we get informed when the response is there. Most of the time, the <strong>API</strong> users will want to wait for a response, instead of leveraging the asyncrhonous aspect of the <strong>API</strong>: this is the reason we have a blocking <strong>API</strong>, based on the non-blocking implementation. We will explain the whole thing here.</p>
+<p>NOTE : <strong>LDAP</strong> protocol is based on <strong>TCP</strong>, we are not dealing with <strong>UDP</strong> at all.</p>
+<h2 id="class-hierarchy">Class hierarchy<a class="headerlink" href="#class-hierarchy" title="Permanent link">&para;</a></h2>
+<p><img alt="LdapConnection hierarchy" src="images/ldapconnection.png" /></p>
+<h2 id="mina-usage">MINA usage<a class="headerlink" href="#mina-usage" title="Permanent link">&para;</a></h2>
+<p>There are two aspects we need to consider when it comes to use <strong>MINA</strong> :</p>
+<ul>
+<li>events processing</li>
+<li>sending a message</li>
+<li>receiving a message</li>
+<li>encoding/decoding</li>
+</ul>
+<h3 id="events-processing">Events processing<a class="headerlink" href="#events-processing" title="Permanent link">&para;</a></h3>
+<p><strong>MINA</strong> is an asynchronous framework, which means it's event based : you will receive events when something 'happens' (like, a message is received, etc). The events have to be processed by the <strong>LDAP API</strong>, and the <strong>IoHandler</strong> interface is listing all the events we have to process. Here they are :</p>
+<ul>
+<li><em>messageReceived</em> : When a message has been fully received from the remote peer</li>
+<li><em>messageSent</em> : When a message has been fully sent to the remote peer</li>
+<li><em>exceptionCaught</em> : If we git an exception from the network layer</li>
+<li><em>inputClosed</em> : When the <em>Input</em> part of a TCP connection has been closed</li>
+<li><em>sessionClosed</em> : When a Session is closed</li>
+<li><em>sessionCreated</em> : When a Session is created</li>
+<li><em>sessionIdle</em> : When a Session is idle</li>
+<li><em>sessionOpened</em> : When a Session is opened</li>
+</ul>
+<p>The <em>session</em> is created when you connect for the first time, it's atcive until it's closed. We are talking about a <strong>TCP</strong> session, not a <strong>LDAP</strong> session.</p>
+<p>So the <em>LdapNetworkConnection</em> class must implement those methods.</p>
+<p>Regarding the <em>messageReceived/messageSent</em> methods, it's important to know that we are talking about <strong>FULL</strong> <strong>LDAP</strong> messages, even if <strong>TCP</strong> does not guarantee that messages can't be fragmented : <strong>MINA</strong> deal with fragmentation.</p>
+<p>Actually, we only implement the <em>messageReceived</em>, <em>exceptionCaught</em>, <em>inputClose</em>, <em>sessionCreated</em> and <em>sessionClosed</em> methods, the other are handled by the <em>IoHandlerAdpater</em> methods (which does nothing with it).</p>
+<h3 id="sending-a-message">Sending a message<a class="headerlink" href="#sending-a-message" title="Permanent link">&para;</a></h3>
+<p>There are two modes : <strong>Synchronous</strong> and <strong>Asyncrhonous</strong>. The methods are respectively described in the <em>LdapConnection</em> interface and <em>LdapAsyncConnection</em> interface. Actually, <em>synchronous</em> methods are calling <em>asynchronous</em> methods, which returns a <em>Future</em> :</p>
+<div class="codehilite"><pre><span class="cm">/**</span>
+<span class="cm"> * {@inheritDoc}</span>
+<span class="cm"> */</span>
+<span class="nd">@Override</span>
+<span class="kd">public</span> <span class="n">AddResponse</span> <span class="nf">add</span><span class="o">(</span> <span class="n">AddRequest</span> <span class="n">addRequest</span> <span class="o">)</span> <span class="kd">throws</span> <span class="n">LdapException</span>
+<span class="o">{</span>
+    <span class="o">...</span>
+
+    <span class="n">AddFuture</span> <span class="n">addFuture</span> <span class="o">=</span> <span class="n">addAsync</span><span class="o">(</span> <span class="n">addRequest</span> <span class="o">);</span>
+
+    <span class="c1">// Get the result from the future</span>
+    <span class="k">try</span>
+    <span class="o">{</span>
+        <span class="c1">// Read the response, waiting for it if not available immediately</span>
+        <span class="c1">// Get the response, blocking</span>
+        <span class="n">AddResponse</span> <span class="n">addResponse</span> <span class="o">=</span> <span class="n">addFuture</span><span class="o">.</span><span class="na">get</span><span class="o">(</span> <span class="n">timeout</span><span class="o">,</span> <span class="n">TimeUnit</span><span class="o">.</span><span class="na">MILLISECONDS</span> <span class="o">);</span>
+
+        <span class="k">if</span> <span class="o">(</span> <span class="n">addResponse</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">)</span>
+        <span class="o">{</span>
+            <span class="c1">// We didn&#39;t received anything : this is an error</span>
+            <span class="n">LOG</span><span class="o">.</span><span class="na">error</span><span class="o">(</span> <span class="s">&quot;Add failed : timeout occurred&quot;</span> <span class="o">);</span>
+            <span class="k">throw</span> <span class="k">new</span> <span class="nf">LdapException</span><span class="o">(</span> <span class="n">TIME_OUT_ERROR</span> <span class="o">);</span>
+        <span class="o">}</span>
+
+        <span class="k">if</span> <span class="o">(</span> <span class="n">addResponse</span><span class="o">.</span><span class="na">getLdapResult</span><span class="o">().</span><span class="na">getResultCode</span><span class="o">()</span> <span class="o">==</span> <span class="n">ResultCodeEnum</span><span class="o">.</span><span class="na">SUCCESS</span> <span class="o">)</span>
+        <span class="o">{</span>
+            <span class="c1">// Everything is fine, return the response</span>
+            <span class="n">LOG</span><span class="o">.</span><span class="na">debug</span><span class="o">(</span> <span class="s">&quot;Add successful : {}&quot;</span><span class="o">,</span> <span class="n">addResponse</span> <span class="o">);</span>
+        <span class="o">}</span>
+        <span class="k">else</span>
+        <span class="o">{</span>
+            <span class="c1">// We have had an error</span>
+            <span class="n">LOG</span><span class="o">.</span><span class="na">debug</span><span class="o">(</span> <span class="s">&quot;Add failed : {}&quot;</span><span class="o">,</span> <span class="n">addResponse</span> <span class="o">);</span>
+        <span class="o">}</span>
+
+        <span class="k">return</span> <span class="n">addResponse</span><span class="o">;</span>
+    <span class="o">}</span>
+    <span class="k">catch</span> <span class="o">(</span> <span class="n">Exception</span> <span class="n">ie</span> <span class="o">)</span>
+    <span class="o">{</span>
+        <span class="c1">// Catch all other exceptions</span>
+        <span class="c1">// Send an abandon request</span>
+        <span class="k">if</span> <span class="o">(</span> <span class="o">!</span><span class="n">addFuture</span><span class="o">.</span><span class="na">isCancelled</span><span class="o">()</span> <span class="o">)</span>
+        <span class="o">{</span>
+            <span class="n">abandon</span><span class="o">(</span> <span class="n">addRequest</span><span class="o">.</span><span class="na">getMessageId</span><span class="o">()</span> <span class="o">);</span>
+        <span class="o">}</span>
+
+        <span class="k">throw</span> <span class="k">new</span> <span class="nf">LdapException</span><span class="o">(</span> <span class="n">NO_RESPONSE_ERROR</span><span class="o">,</span> <span class="n">ie</span> <span class="o">);</span>
+    <span class="o">}</span>
+<span class="o">}</span>
+</pre></div>
+
+
+<p>You can see we wait until the timeout expired, or until we got the response, calling the <em>addAsync</em> method, getting back a <em>Future</em> and waiting on it.</p>
+<p>This method take a <em>AddRequest</em> but we have other simpler flavors (see the <strong>LDAP API</strong> documentation).</p>
+<div class="codehilite"><pre>AddResponse ldapConnection.add( AddResquest )
+    |
+    +-- AddFuture addAsync( AddRequest )
+    |       |
+    |       +-- connect()
+    |       |       |
+    |       |       +-- createConnector()
+    |       |       |       |
+    |       |       |       +-- new NioSocketConnector()
+    |       |       |       |
+    |       |       |       +-- NioSocketConnector.getFilterChain().addLast( &quot;ldapCodec&quot;, ldapProtocolFilter );
+    |       |       |       |
+    |       |       |      [+-- addSslFilter()]
+    |       |       |       |
+    |       |       |       +-- NioSocketConnector.setHandler( this )
+    |       |       |
+    |       |       +-- IoConnector.connect( address )
+    |       |
+    |       +-- checkSession()
+    |       |
+    |       +-- new AddFuture( LdapConnection, ID )
+    |       |
+    |       +-- addToFutureMap( ID, AddFuture )
+    |       |
+    |       +-- writeRequest( AddRequest )
+    |               |
+    |               +-- WriteFuture IoSession.write( request )
+    |               |
+    |               +-- WriteFuture.awaitUninterruptibly( 100 )
+    |
+    +-- AddFuture.get()
+</pre></div>
+
+
+<p>Here, we first create a connection if we don't have one yet, and then we try to write the message to the remote server, and wait for the message to be sent. That means sending message is synchronous, while receiving is aysnchronous by default. (NOTE : This may change in the next version.)</p>
+<p>Once the request has been written, we do a <em>get</em> on the returned <em>Future</em>. Either we get an <em>AddResponse</em>, or an error/timeout.</p>
+<h3 id="receiving-a-message">Receiving a message<a class="headerlink" href="#receiving-a-message" title="Permanent link">&para;</a></h3>
+<p>Once the <em>IoSession.write()</em> method is called, we can assume the message has been sent to the remote server (sort of). The response will come as an event : <em>messageReceived()</em>, which is implemented in <em>LdapNetworkConnection</em>.</p>
+<p>Each <strong>LDAP</strong> message has a unique <strong>ID</strong>, and every sent message is associated with a <em>Future</em>. When the message is sent, we store a tuple &lt;<strong>ID</strong>, <strong>Future</strong>&gt; in a map, so when the response arrives, we just have to pull the <em>Future</em> from the map using teh message <strong>ID</strong>. This is what we do in the <em>messageReceived()</em> implementation. The response is enqueued in the <em>Future</em> (we may have more than one, typically for <strong>Search</strong> operations).</p>
+<h3 id="encodingdecoding">Encoding/decoding<a class="headerlink" href="#encodingdecoding" title="Permanent link">&para;</a></h3>
+<p>Messages are encoded and decoded when we send or receive them. This is done by <strong>MINA</strong>, using a callback in the <strong>LDAP API</strong>. That means we configured <strong>MINA</strong> to process <strong>LDAP</strong> messages. </p>
+<p>The codec is inserted in <strong>MINA</strong> chain while connecting :</p>
+<div class="codehilite"><pre><span class="cm">/** The Ldap codec protocol filter */</span>
+<span class="kd">private</span> <span class="n">IoFilter</span> <span class="n">ldapProtocolFilter</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ProtocolCodecFilter</span><span class="o">(</span> <span class="n">codec</span><span class="o">.</span><span class="na">getProtocolCodecFactory</span><span class="o">()</span> <span class="o">);</span>
+
+<span class="kd">private</span> <span class="kt">void</span> <span class="nf">createConnector</span><span class="o">()</span> <span class="kd">throws</span> <span class="n">LdapException</span>
+<span class="o">{</span>
+    <span class="o">...</span>
+
+    <span class="c1">// Add the codec to the chain</span>
+    <span class="n">connector</span><span class="o">.</span><span class="na">getFilterChain</span><span class="o">().</span><span class="na">addLast</span><span class="o">(</span> <span class="s">&quot;ldapCodec&quot;</span><span class="o">,</span> <span class="n">ldapProtocolFilter</span> <span class="o">);</span>
+</pre></div>
+
+
+<p>So the <em>ProtocolCodecFilter</em> class is responsible for initializing the codec (it's a <strong>MINA</strong> class), and here, we use a factory to inject the encoder and decoder instances. This factory is <em>LdapProtocolCodecFactory</em>.</p>
 
 
     <div class="nav">

Added: websites/staging/directory/trunk/content/api/internal-design-guide/images/ldapconnection.graphml
==============================================================================
Binary file - no diff available.

Propchange: websites/staging/directory/trunk/content/api/internal-design-guide/images/ldapconnection.graphml
------------------------------------------------------------------------------
    svn:mime-type = application/xml

Added: websites/staging/directory/trunk/content/api/internal-design-guide/images/ldapconnection.png
==============================================================================
Binary file - no diff available.

Propchange: websites/staging/directory/trunk/content/api/internal-design-guide/images/ldapconnection.png
------------------------------------------------------------------------------
    svn:mime-type = image/png