You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by fh...@apache.org on 2006/05/27 04:32:22 UTC

svn commit: r409799 - in /tomcat/container/tc5.5.x/modules/groupcom: doc/introduction.xml src/share/org/apache/catalina/tribes/group/GroupChannel.java to-do.txt

Author: fhanik
Date: Fri May 26 19:32:21 2006
New Revision: 409799

URL: http://svn.apache.org/viewvc?rev=409799&view=rev
Log:
Absence reply should be sent if the message was not by an RPC channel

Modified:
    tomcat/container/tc5.5.x/modules/groupcom/doc/introduction.xml
    tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/tribes/group/GroupChannel.java
    tomcat/container/tc5.5.x/modules/groupcom/to-do.txt

Modified: tomcat/container/tc5.5.x/modules/groupcom/doc/introduction.xml
URL: http://svn.apache.org/viewvc/tomcat/container/tc5.5.x/modules/groupcom/doc/introduction.xml?rev=409799&r1=409798&r2=409799&view=diff
==============================================================================
--- tomcat/container/tc5.5.x/modules/groupcom/doc/introduction.xml (original)
+++ tomcat/container/tc5.5.x/modules/groupcom/doc/introduction.xml Fri May 26 19:32:21 2006
@@ -31,33 +31,33 @@
       <source>
         //create a channel
         Channel myChannel = new GroupChannel();
-        
+
         //create my listeners
-        MyMessageListener msgListener = new MyMessageListener();
-        MyMemberListener mbrListener = new MyMemberListener();
-        
+        ChannelListener msgListener = new MyMessageListener();
+        MembershipListener mbrListener = new MyMemberListener();
+
         //attach the listeners to the channel
         myChannel.addMembershipListener(mbrListener);
         myChannel.addChannelListener(msgListener);
-        
+
         //start the channel
         myChannel.start(Channel.DEFAULT);
-        
+
         //create a message to be sent, message must implement java.io.Serializable
         //for performance reasons you probably want them to implement java.io.Externalizable
         Serializable myMsg = new MyMessage();
 
         //retrieve my current members
         Member[] group = myChannel.getMembers();
-        
+
         //send the message
         channel.send(group,myMsg,Channel.SEND_OPTIONS_DEFAULT);
       </source>
     </li>
   </ul>
   <p>
-      Simple yeah? There is a lot more to Tribes than we have shown, hopefully the docs will be able 
-      to explain more to you. Remember, that we are always interested in suggestions, improvements, bug fixes 
+      Simple yeah? There is a lot more to Tribes than we have shown, hopefully the docs will be able
+      to explain more to you. Remember, that we are always interested in suggestions, improvements, bug fixes
       and anything that you think would help this project.
   </p>
   <p>
@@ -70,20 +70,20 @@
   <p>
     Tribes is a messaging framework with group communication abilities. Tribes allows you to send and receive
     messages over a network, it also allows for dynamic discovery of other nodes in the network.<br/>
-    And that is the short story, it really is as simple as that. What makes Tribes useful and unique will be 
+    And that is the short story, it really is as simple as that. What makes Tribes useful and unique will be
     described in the section below.<br/>
   </p>
   <p>
-    The Tribes module was started early 2006 and a small part of the code base comes from the clustering module 
-    that has been existing since 2003 or 2004. 
-    The current cluster implementation has several short comings and many work arounds were created due 
+    The Tribes module was started early 2006 and a small part of the code base comes from the clustering module
+    that has been existing since 2003 or 2004.
+    The current cluster implementation has several short comings and many work arounds were created due
     to the complexity in group communication. Long story short, what should have been two modules a long time
-    ago, will be now. Tribes takes out the complexity of messaging from the replication module and becomes 
+    ago, will be now. Tribes takes out the complexity of messaging from the replication module and becomes
     a fully independent and highly flexible group communication module.<br/>
   </p>
   <p>
     In Tomcat the old <code>modules/cluster</code> has now become <code>modules/groupcom</code>(Tribes) and
-    <code>modules/ha</code> (replication). This will allow development to proceed and let the developers 
+    <code>modules/ha</code> (replication). This will allow development to proceed and let the developers
     focus on the issues they are actually working on rather than getting boggled down in details of a module
     they are not interested in. The understanding is that both communication and replication are complex enough,
     and when trying to develop them in the same module, well you know, it becomes a cluster :)<br/>
@@ -92,14 +92,14 @@
     Tribes allows for guaranteed messaging, and can be customized in many ways. Why is this important?<br/>
     Well, you as a developer want to know that the messages you are sending are reaching their destination.
     More than that, if a message doesn't reach its destination, the application on top of Tribes will be notified
-    that the message was never sent, and what node it failed. 
+    that the message was never sent, and what node it failed.
   </p>
-  
+
 </section>
 
 <section name="Why another messaging framework">
   <p>
-    I am a big fan of reusing code and would never dream of developing something if someone else has already 
+    I am a big fan of reusing code and would never dream of developing something if someone else has already
     done it and it was available to me and the community I try to serve.<br/>
     When I did my research to improve the clustering module I was constantly faced with a few obstacles:<br/>
     1. The framework wasn't flexible enough<br/>
@@ -110,8 +110,8 @@
     And the list continues...
   </p>
   <p>
-    So I came up with Tribes, to address these issues and other issues that came along. 
-    When designing Tribes I wanted to make sure I didn't lose any of the flexibility and 
+    So I came up with Tribes, to address these issues and other issues that came along.
+    When designing Tribes I wanted to make sure I didn't lose any of the flexibility and
     delivery semantics that the existing frameworks already delivered. The goal was to create a framework
     that could do everything that the others already did, but to provide more flexibility for the application
     developer. In the next section will give you the high level overview of what features tribes offers or will offer.
@@ -142,7 +142,7 @@
     There are three different levels of delivery guarantee when a message is sent.<br/>
     <ol>
       <li>IO Based send guarantee. - fastest, least reliable<br/>
-          This means that Tribes considers the message transfer to be successful 
+          This means that Tribes considers the message transfer to be successful
           if the message was sent to the socket send buffer and accepted.<br/>
           On blocking IO, this would be <code>socket.getOutputStream().write(msg)</code><br/>
           On non blocking IO, this would be <code>socketChannel.write()</code>, and the buffer byte buffer gets emptied
@@ -166,8 +166,8 @@
           and associate that exception with the member that didn't process the message.
       </li>
     </ol>
-    You can of course write even more sophisticated guarantee levels, and some of them will be mentioned later on 
-    in the documentation. One mentionable level would be a 2-Phase-Commit, where the remote applications don't receive 
+    You can of course write even more sophisticated guarantee levels, and some of them will be mentioned later on
+    in the documentation. One mentionable level would be a 2-Phase-Commit, where the remote applications don't receive
     the message until all nodes have received the message. Sort of like a all-or-nothing protocol.
   </p>
   <p>
@@ -191,14 +191,14 @@
       Message_9 - RPC message, asynchronous, don't wait for a reply, collect them via a callback
       Message_10- sent to a member that is not part of this group
     </source>
-    As you can imagine by now, these are just examples. The number of different semantics you can apply on a 
+    As you can imagine by now, these are just examples. The number of different semantics you can apply on a
     per-message-basis is almost limitless. Tribes allows you to set up to 28 different on a message
     and then configure Tribes to what flag results in what action on the message.<br/>
     Imagine a shared transactional cache, probably &gt;90% are reads, and the dirty reads should be completely
-    unordered and delivered as fast as possible. But transactional writes on the other hand, have to 
+    unordered and delivered as fast as possible. But transactional writes on the other hand, have to
     be ordered so that no cache gets corrupted. With tribes you would send the write messages totally ordered,
     while the read messages you simple fire to achieve highest throughput.<br/>
-    There are probably better examples on how this powerful feature can be used, so use your imagination and 
+    There are probably better examples on how this powerful feature can be used, so use your imagination and
     your experience to think of how this could benefit you in your application.
   </p>
   <p>
@@ -211,7 +211,7 @@
     by the applications running on top of Tribes.<br/>
     This is how Tribes is able to send some messages totally ordered and others fire and forget style
     like the example above.<br/>
-    The number of interceptors that are available will keep growing, and we would appreciate any contributions 
+    The number of interceptors that are available will keep growing, and we would appreciate any contributions
     that you might have.
   </p>
   <p>
@@ -221,20 +221,20 @@
     The exception is the <code>MessageDispatchInterceptor</code> that will queue up the message
     and send it on a separate thread for asynchronous message delivery.
     Messages received are controlled by a thread pool in the <code>receiver</code> component.<br/>
-    The channel object can send a <code>heartbeat()</code> through the interceptor stack to allow 
+    The channel object can send a <code>heartbeat()</code> through the interceptor stack to allow
     for timeouts, cleanup and other events.<br/>
     The <code>MessageDispatchInterceptor</code> is the only interceptor that is configured by default.
   </p>
   <p>
     <b>Parallel Delivery</b><br/>
-    Tribes support parallel delivery of messages. Meaning that node_A could send three messages to node_B in 
+    Tribes support parallel delivery of messages. Meaning that node_A could send three messages to node_B in
     parallel. This feature becomes useful when sending messages with different delivery semantics.
     Otherwise if Message_1 was sent totally ordered, Message_2 would have to wait for that message to complete.<br/>
     Through NIO, Tribes is also able to send a message to several receivers at the same time on the same thread.
   </p>
   <p>
     <b>Silent Member Messaging</b><br/>
-    With Tribes you are able to send messages to members that are not in your group. 
+    With Tribes you are able to send messages to members that are not in your group.
     So by default, you can already send messages over a wide area network, even though the dynamic discover
     module today is limited to local area networks by using multicast for dynamic node discovery.
     Of course, the membership component will be expanded to support WAN memberships in the future.
@@ -247,8 +247,8 @@
     I hope you have enjoyed this short introduction to Tribes. You can download <a href="../apache-tribes.jar">Tribes here</a>
     or you can download Tribes <a href="../tribes-all.zip">including javadoc and this doc</a>
   </p>
-      
-    
+
+
 </section>
 
 <!--
@@ -289,7 +289,7 @@
     <td>acknowledge timeout and only usefull it waitForAck is true</td>
     <td><code>15000</code></td>
   </tr>
-  
+
   <tr>
     <td>waitForAck</td>
     <td>Wait for ack after data send</td>
@@ -321,9 +321,9 @@
       waitForAck="true"
       autoConnect="false"/&gt;
 </source>
-</p>  
+</p>
 </section>
-     
+
 -->
 </body>
 

Modified: tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/tribes/group/GroupChannel.java
URL: http://svn.apache.org/viewvc/tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/tribes/group/GroupChannel.java?rev=409799&r1=409798&r2=409799&view=diff
==============================================================================
--- tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/tribes/group/GroupChannel.java (original)
+++ tomcat/container/tc5.5.x/modules/groupcom/src/share/org/apache/catalina/tribes/group/GroupChannel.java Fri May 26 19:32:21 2006
@@ -1,12 +1,12 @@
 /*
  * Copyright 1999,2004-2006 The Apache Software Foundation.
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -56,16 +56,16 @@
      */
     protected boolean heartbeat = true;
     /**
-     * If <code>heartbeat == true</code> then how often do we want this 
+     * If <code>heartbeat == true</code> then how often do we want this
      * heartbeat to run. default is one minute
      */
     protected long heartbeatSleeptime = 60*1000;//only run once a minute
-    
+
     /**
      * Internal heartbeat thread
      */
     protected HeartbeatThread hbthread = null;
-    
+
     /**
      * The  <code>ChannelCoordinator</code> coordinates the bottom layer components:<br>
      * - MembershipService<br>
@@ -73,39 +73,39 @@
      * - ChannelReceiver<br>
      */
     protected ChannelCoordinator coordinator = new ChannelCoordinator();
-    
+
     /**
      * The first interceptor in the inteceptor stack.
-     * The interceptors are chained in a linked list, so we only need a reference to the 
+     * The interceptors are chained in a linked list, so we only need a reference to the
      * first one
      */
     protected ChannelInterceptor interceptors = null;
-    
+
     /**
      * A list of membership listeners that subscribe to membership announcements
      */
     protected ArrayList membershipListeners = new ArrayList();
-    
+
     /**
      * A list of channel listeners that subscribe to incoming messages
      */
     protected ArrayList channelListeners = new ArrayList();
-    
+
     /**
-     * If set to true, the GroupChannel will check to make sure that 
+     * If set to true, the GroupChannel will check to make sure that
      */
     protected boolean optionCheck = false;
 
     /**
-     * Creates a GroupChannel. This constructor will also 
+     * Creates a GroupChannel. This constructor will also
      * add the first interceptor in the GroupChannel.<br>
      * The first interceptor is always the channel itself.
      */
     public GroupChannel() {
         addInterceptor(this);
     }
-    
-    
+
+
     /**
      * Adds an interceptor to the stack for message processing<br>
      * Interceptors are ordered in the way they are added.<br>
@@ -118,7 +118,7 @@
      * <code>Channel -> A -> C -> B -> ChannelCoordinator</code><br>
      * @param interceptor ChannelInterceptorBase
      */
-    public void addInterceptor(ChannelInterceptor interceptor) { 
+    public void addInterceptor(ChannelInterceptor interceptor) {
         if ( interceptors == null ) {
             interceptors = interceptor;
             interceptors.setNext(coordinator);
@@ -135,7 +135,7 @@
             coordinator.setPrevious(interceptor);
         }
     }
-    
+
     /**
      * Sends a heartbeat through the interceptor stack.<br>
      * Invoke this method from the application on a periodic basis if
@@ -155,8 +155,8 @@
         }
 
     }
-    
-    
+
+
     /**
      * Send a message to the destinations specified
      * @param destination Member[] - destination.length > 1
@@ -170,14 +170,14 @@
     public UniqueId send(Member[] destination, Serializable msg, int options) throws ChannelException {
         return send(destination,msg,options,null);
     }
-    
+
     /**
-     * 
+     *
      * @param destination Member[] - destination.length > 1
      * @param msg Serializable - the message to send
      * @param options int - sender options, options can trigger guarantee levels and different interceptors to
      * react to the message see class documentation for the <code>Channel</code> object.<br>
-     * @param handler - callback object for error handling and completion notification, used when a message is 
+     * @param handler - callback object for error handling and completion notification, used when a message is
      * sent asynchronously using the <code>Channel.SEND_OPTIONS_ASYNCHRONOUS</code> flag enabled.
      * @return UniqueId - the unique Id that was assigned to this message
      * @throws ChannelException - if an error occurs processing the message
@@ -218,7 +218,7 @@
             if ( buffer != null ) BufferPool.getBufferPool().returnBuffer(buffer);
         }
     }
-    
+
 
     /**
      * Callback from the interceptor stack. <br>
@@ -231,7 +231,7 @@
     public void messageReceived(ChannelMessage msg) {
         if ( msg == null ) return;
         try {
-            
+
             Serializable fwd = null;
             if ( (msg.getOptions() & SEND_OPTIONS_BYTE_MESSAGE) == SEND_OPTIONS_BYTE_MESSAGE ) {
                 fwd = new ByteMessage(msg.getMessage().getBytes());
@@ -245,7 +245,9 @@
                 ChannelListener channelListener = (ChannelListener)channelListeners.get(i);
                 if (channelListener != null && channelListener.accept(fwd, source)) {
                     channelListener.messageReceived(fwd, source);
-                    rx = true;
+                    //if the message was accepted by an RPC channel, that channel
+                    //is responsible for returning the reply, otherwise we send an absence reply
+                    if ( channelListener instanceof RpcChannel ) rx = true;
                 }
             }//for
             if ((!rx) && (fwd instanceof RpcMessage)) {
@@ -257,7 +259,7 @@
             log.error("Unable to deserialize channel message.",x);
         }
     }
-    
+
     /**
      * Sends a <code>NoRpcChannelReply</code> message to a member<br>
      * This method gets invoked by the channel if a RPC message comes in
@@ -275,7 +277,7 @@
             log.error("Unable to find rpc channel, failed to send NoRpcChannelReply.",x);
         }
     }
-    
+
     /**
      * memberAdded gets invoked by the interceptor below the channel
      * and the channel will broadcast it to the membership listeners
@@ -288,7 +290,7 @@
             if (membershipListener != null) membershipListener.memberAdded(member);
         }
     }
-    
+
     /**
      * memberDisappeared gets invoked by the interceptor below the channel
      * and the channel will broadcast it to the membership listeners
@@ -301,15 +303,15 @@
             if (membershipListener != null) membershipListener.memberDisappeared(member);
         }
     }
-    
+
     /**
      * Sets up the default implementation interceptor stack
      * if no interceptors have been added
      * @throws ChannelException
      */
     protected synchronized void setupDefaultStack() throws ChannelException {
-        
-        if ( getFirstInterceptor() != null && 
+
+        if ( getFirstInterceptor() != null &&
              ((getFirstInterceptor().getNext() instanceof ChannelCoordinator))) {
             ChannelInterceptor interceptor = null;
             Class clazz = null;
@@ -327,7 +329,7 @@
             this.addInterceptor(interceptor);
         }
     }
-    
+
     /**
      * Validates the option flags that each interceptor is using and reports
      * an error if two interceptor share the same flag.
@@ -359,9 +361,9 @@
             first = first.getNext();
         }//while
         if ( conflicts.length() > 0 ) throw new ChannelException("Interceptor option flag conflict: "+conflicts.toString());
-    
+
     }
-    
+
     /**
      * Starts the channel
      * @param svc int - what service to start
@@ -377,7 +379,7 @@
             hbthread.start();
         }
     }
-    
+
     /**
      * Stops the channel
      * @param svc int
@@ -391,7 +393,7 @@
         }
         super.stop(svc);
     }
-    
+
     /**
      * Returns the first interceptor of the stack. Useful for traversal.
      * @return ChannelInterceptor
@@ -400,7 +402,7 @@
         if (interceptors != null) return interceptors;
         else return coordinator;
     }
-    
+
     /**
      * Returns the channel receiver component
      * @return ChannelReceiver
@@ -408,7 +410,7 @@
     public ChannelReceiver getChannelReceiver() {
         return coordinator.getClusterReceiver();
     }
-    
+
     /**
      * Returns the channel sender component
      * @return ChannelSender
@@ -424,7 +426,7 @@
     public MembershipService getMembershipService() {
         return coordinator.getMembershipService();
     }
-    
+
     /**
      * Sets the channel receiver component
      * @param clusterReceiver ChannelReceiver
@@ -440,7 +442,7 @@
     public void setChannelSender(ChannelSender clusterSender) {
         coordinator.setClusterSender(clusterSender);
     }
-    
+
     /**
      * Sets the membership component
      * @param membershipService MembershipService
@@ -448,7 +450,7 @@
     public void setMembershipService(MembershipService membershipService) {
         coordinator.setMembershipService(membershipService);
     }
-    
+
     /**
      * Adds a membership listener to the channel.<br>
      * Membership listeners are uniquely identified using the equals(Object) method
@@ -464,7 +466,7 @@
      * Membership listeners are uniquely identified using the equals(Object) method
      * @param membershipListener MembershipListener
      */
-    
+
     public void removeMembershipListener(MembershipListener membershipListener) {
         membershipListeners.remove(membershipListener);
     }
@@ -478,9 +480,9 @@
         if (!this.channelListeners.contains(channelListener) )
             this.channelListeners.add(channelListener);
     }
-    
+
     /**
-     * 
+     *
      * Removes a channel listener from the channel.<br>
      * Channel listeners are uniquely identified using the equals(Object) method
      * @param channelListener ChannelListener
@@ -488,12 +490,12 @@
     public void removeChannelListener(ChannelListener channelListener) {
         channelListeners.remove(channelListener);
     }
-    
+
     /**
      * Returns an iterator of all the interceptors in this stack
      * @return Iterator
      */
-    public Iterator getInterceptors() { 
+    public Iterator getInterceptors() {
         return new InterceptorIterator(this.getNext(),this.coordinator);
     }
 
@@ -519,7 +521,7 @@
 
     /**
      * Enables or disables local heartbeat.
-     * if <code>setHeartbeat(true)</code> is invoked then the channel will start an internal 
+     * if <code>setHeartbeat(true)</code> is invoked then the channel will start an internal
      * thread to invoke <code>Channel.heartbeat()</code> every <code>getHeartbeatSleeptime</code> milliseconds
      * @param heartbeat boolean
      */
@@ -542,7 +544,7 @@
     public boolean getHeartbeat() {
         return heartbeat;
     }
-    
+
     /**
      * Returns the sleep time in milliseconds that the internal heartbeat will
      * sleep in between invokations of <code>Channel.heartbeat()</code>
@@ -553,11 +555,11 @@
     }
 
     /**
-     * 
-     * <p>Title: Interceptor Iterator</p> 
-     * 
-     * <p>Description: An iterator to loop through the interceptors in a channel</p> 
-     * 
+     *
+     * <p>Title: Interceptor Iterator</p>
+     *
+     * <p>Description: An iterator to loop through the interceptors in a channel</p>
+     *
      * @version 1.0
      */
     public static class InterceptorIterator implements Iterator {
@@ -567,11 +569,11 @@
             this.end = end;
             this.start = start;
         }
-        
+
         public boolean hasNext() {
             return start!=null && start != end;
         }
-        
+
         public Object next() {
             Object result = null;
             if ( hasNext() ) {
@@ -580,19 +582,19 @@
             }
             return result;
         }
-        
+
         public void remove() {
             //empty operation
         }
     }
 
     /**
-     * 
-     * <p>Title: Internal heartbeat thread</p> 
-     * 
+     *
+     * <p>Title: Internal heartbeat thread</p>
+     *
      * <p>Description: if <code>Channel.getHeartbeat()==true</code> then a thread of this class
-     * is created</p> 
-     * 
+     * is created</p>
+     *
      * @version 1.0
      */
     public static class HeartbeatThread extends Thread {
@@ -601,7 +603,7 @@
         protected static synchronized int inc() {
             return counter++;
         }
-        
+
         protected boolean doRun = true;
         protected GroupChannel channel;
         protected long sleepTime;
@@ -617,7 +619,7 @@
             doRun = false;
             interrupt();
         }
-        
+
         public void run() {
             while (doRun) {
                 try {
@@ -631,7 +633,7 @@
             }//while
         }//run
     }//HeartbeatThread
-    
-    
+
+
 
 }

Modified: tomcat/container/tc5.5.x/modules/groupcom/to-do.txt
URL: http://svn.apache.org/viewvc/tomcat/container/tc5.5.x/modules/groupcom/to-do.txt?rev=409799&r1=409798&r2=409799&view=diff
==============================================================================
--- tomcat/container/tc5.5.x/modules/groupcom/to-do.txt (original)
+++ tomcat/container/tc5.5.x/modules/groupcom/to-do.txt Fri May 26 19:32:21 2006
@@ -6,29 +6,29 @@
  Why is tribes unique compared to JGroups/Appia and other group comm protocols
 
  1. Uses NIO and TCP for guaranteed delivery and the ability to join large groups
- 
+
  2. Guarantees messages the following way
     a) TCP messaging, with a following READ for NIO to ensure non broken channel
     b) ACK messages from the receiver
     c) ACK after processing
-    
+
  3. Same (single) channel can handle all types of guarantees (a,b,c) at the same time
     and both process synchronous and asynchronous messaging.
-    This is key to support different requirements for messaging through 
+    This is key to support different requirements for messaging through
     the same channel to save system resources.
 
  4. For async messaging, errors are reported through an error handler, callback
- 
+
  5. Ability to send on multiple streams at the same time, in parallel, to improve performance
- 
+
  6. Designed with replication in mind, that some pieces of data don't need to be totally ordered.
- 
+
  7. Its not built with the uniform group model in mind, but it can be accomplished using interceptors.
- 
+
  8. Future version will have WAN membership and replication
- 
+
  9. Silent members, the ability to send messages to a node not in the membership
- 
+
 10. Sender burst, concurrent messaging between two or more nodes
 
 11. Multicasting can still be done on a per message basis using a MulticastInterceptor
@@ -36,18 +36,23 @@
 Bugs:
 ===========================================
  a) Somehow the first NIO connection made, always closes down, why
- 
+
  b) pull the network cord and watch the membership layer freak out
- 
+
 Code Tasks:
 ===========================================
+50. On top of versioning, implement version syncs from primary to backup
+    Or when a backup receives an update that is out of sync
+
+49. Implement versioning on the AbstractReplicatedMap
+
 
 9. CoordinatorInterceptor - manages the selection of a cluster coordinator
    just had a brilliant idea, if GroupChannel keeps its own view of members,
    the coordinator interceptor can hold on to the member added/disappared event
    It can also intercept down going messages if the coordinator disappeared
    while a new coordinator is chosen
-   It can also intercept down going messages for members disappeared that the 
+   It can also intercept down going messages for members disappeared that the
    calling app not yet knows about, to avoid a ChannelException
    The coordinator is needed because of the mixup when two channels startup instantly
 
@@ -61,7 +66,7 @@
 
 36. UDP Sender and Receiver, initially without flow control and guaranteed delivery.
     This can be easily done as an interceptor, and operate in parallel with the TCP sender.
-    It can implement an auto detect, so that if the message is going to a destination in the same network 
+    It can implement an auto detect, so that if the message is going to a destination in the same network
     patch, then send it over UDP.
 
 35. The ability to share one channel amongst multiple processes
@@ -75,8 +80,8 @@
 
 30. CookieBasedReplicationMap - a very simple extension to the LazyReplicatedMap
     but instead of randomly selecting a backup node and then publishing the PROXY to all
-    the other nodes in the group, this will simply 
-    read/write a cookie, for a backup location, so the nodes will 
+    the other nodes in the group, this will simply
+    read/write a cookie, for a backup location, so the nodes will
     never know until the request comes in.
     This is useful in extremely large clusters, and essentially reduces
     very much of the network chatter, this task is dependent on task25
@@ -94,14 +99,14 @@
 
 27. XmlConfigurator - read an XML file to configure the channel.
 
-26. JNDIChannel - a way to bind the group channel in a JNDI tree, 
+26. JNDIChannel - a way to bind the group channel in a JNDI tree,
     so that shared resources can access it.
 
 23. TotalOrderInterceptor - fairly straight forward implementation
-    This interceptor would depend on the fact that there is some sort of 
+    This interceptor would depend on the fact that there is some sort of
     membership coordinator, see task 9.
-    Once there is a coordinator in the group, the total order protocol is the same 
-    as the OrderInterceptor, except that it gets its message number from 
+    Once there is a coordinator in the group, the total order protocol is the same
+    as the OrderInterceptor, except that it gets its message number from
     the coordinator, prior to sending it out.
     The TotalOrderInterceptor, will keep a order number per member,
     this way, ordering is kept intact when different messages are sent
@@ -128,7 +133,7 @@
       NOTES! THIS CANT BE DONE USING A SEQUENCER THAT SENDS THE MESSAGE SINCE WE
       LOSE THE ABILITY TO REPORT FEEDBACK
 
-21. Implement a WAN membership layer, using a WANMbrInterceptor and a 
+21. Implement a WAN membership layer, using a WANMbrInterceptor and a
     WAN Router/Forwarder (Tipi on top of a ManagedChannel)
 
 20. Implement a TCP membership interceptor, for guaranteed functionality, not just discovery
@@ -143,15 +148,15 @@
 11. Code a ReplicatedFileSystem example, package org.apache.catalina.tipis
 
 13. StateTransfer interceptor
-    the ideas just come up in my head. the state transfer interceptor 
+    the ideas just come up in my head. the state transfer interceptor
     will hold all incoming messages until it has received a message
     with a STATE_TRANSFER header as the first of the bytes.
     Once it has received state, it will pretty much take itself out of the loop
     The benefit of the new ParallelNioSender is that it doesn't require to know about
     a member to transfer state, all it has to do is to reply to a message that came in.
-    State is a one time deal for the entire channel, so a 
+    State is a one time deal for the entire channel, so a
     session replication cluster, would transfer state as one block, not one per context
-    
+
 14. Keepalive count and idle kill off for Nio senders
 
 17. Implement transactions - the ability to start a transaction, send several messages,
@@ -160,12 +165,12 @@
 Tasks Completed
 ===========================================
 1. True synchronized/asynchronized replication enabled using flags
-Sender.sendAck/Receiver.waitForAck/Receiver.synchronized 
+Sender.sendAck/Receiver.waitForAck/Receiver.synchronized
 Task Desc: waitForAck - should only mean, we received the message, not for the
 message to get processesed. This should improve throughput, and an interceptor
 can do waitForCompletion
 Status: Complete
-Notes: 
+Notes:
 
 2. Unique id, send it in byte array instead of string
 
@@ -176,7 +181,7 @@
 4. ChannelMessage.getMessage should return streamable, that way we can wrap,
 pass it around and all those good things without having to copy byte arrays
 left and right
-Notes: Instead of using a streamable, this is implemented using the XByteBuffer, 
+Notes: Instead of using a streamable, this is implemented using the XByteBuffer,
        which is very easy to use. It also becomes a single spot for optimizations.
        Ideally, there would be a pool of XByteBuffers, that all use direct ByteBuffers
        for its data handling.
@@ -200,9 +205,9 @@
     The lazy hash map will only replicate its attribute names to all members in the group
     with that name, it will also replicate the source (where to get the object)
     and the backup member where it can find a backup if the source is gone.
-    If the source disappears, the backup node will replicate attributes that 
+    If the source disappears, the backup node will replicate attributes that
     are stored to a new primary backups can be chosen on round robin.
-    When a new member arrives and requests state, that member will get all the attribute 
+    When a new member arrives and requests state, that member will get all the attribute
     names and the locations.
     It can replicate every X seconds, or on dirty flags by the objects stored,
     or a request to scan for dirty flags, or a request with the objects.
@@ -216,7 +221,7 @@
 
 24. MessageDispatchInterceptor - for asynchronous sending
     - looks at the options flag SEND_OPTIONS_ASYNCHRONOUS
-    - has two modes 
+    - has two modes
       a) async parallel send - each message to all destinations before next message
       b) async per/member - one thread per member using the FastAsyncQueue (good for groups with slow receivers)
     - Callback error handler - for when messages fail, and the application wishes to become notified
@@ -226,16 +231,16 @@
        Deep cloning is configurable as optimization.
 
 37. Interceptor.getOptionFlag() - lets the system configure a flag to be used
-    for the interceptor. that way, all constants don't have to be configured 
+    for the interceptor. that way, all constants don't have to be configured
     in Channel.SEND_FLAG_XXXX.
-    Also, the GroupChannel will make a conflict check upon startup, 
+    Also, the GroupChannel will make a conflict check upon startup,
     so that there is no conflict. I will change options to a long,
     so that we can have 63 flags, hence up to 60 interceptors.
 Notes: Completed, remained an int, so 31 flags
 
  b) State synchronization for the map - will need to add in MSG_INIT
  Fixed map bug
- 
+
  c) RpcChannel - collect "no reply" replies, so that we don't have to time out
 The RpcChannel now works together with the group channel, so that when it receives an RPC message
 and no one accepts it, then it can reply immediately. this way the rpc sender doesn't have to time out.
@@ -244,14 +249,14 @@
 Notes: Completed. The membership now carries a variable length host address to support IPv6
 
 40. channel.stop() - should broadcast a stop message, to avoid timeout
-Notes: Completed. 
+Notes: Completed.
 
 42. When the option SEND_OPTIONS_SYNCHRONIZED_ACK, and an error happens during
-    processing on the remote node, a FAIL_ACK command should be sent 
+    processing on the remote node, a FAIL_ACK command should be sent
     so that the sending node doesn't have to time out
-Notes: Completed. The error will be wrapped in a ChannelException and marked as a 
+Notes: Completed. The error will be wrapped in a ChannelException and marked as a
        RemoteProcessException for that node.
-       To receive this exception, one must turn on 
+       To receive this exception, one must turn on
 
 43. Silent member, node discovery.
     Add in the ability to start up tribes, but don't start the membership broadcast
@@ -269,9 +274,9 @@
     2. everytime a message is received, update the last check time for that
        member so that we don't need the thread to actively check
     3. when the thread wakes up, it will check maps that are outside
-       the valid range for check time, 
+       the valid range for check time,
     4. send a RPC message, if no reply, remove the map from itself
-    Other solution, use the TcpFailureDetector, catch send errors 
+    Other solution, use the TcpFailureDetector, catch send errors
 Notes: Implemented using a periodic ping in the AbstractReplicatedMap
 
 45. McastServiceImpl.receive should have a SO_TIMEOUT so that we can check
@@ -292,7 +297,7 @@
     Meaning, that all receivers get it, then wait for a process command.
     ala Gossip protocol - this is fairly redundant with a Xa2PhaseCommitInterceptor
     except it doesn't keep a transaction log.
-Notes: Completed in another task    
+Notes: Completed in another task
 
 10. Xa2PhaseCommitInterceptor - make sure the message doesn't reach the receiver unless all members got it
 Notes: Completed
@@ -302,4 +307,4 @@
 Notes: Completed
 
 19. Implement a hardcoded tcp membership
-Notes: Completed
\ No newline at end of file
+Notes: Completed



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org