Author: pero
Date: Tue Dec 13 08:53:40 2005
New Revision: 356540

URL: http://svn.apache.org/viewcvs?rev=356540&view=rev
Log:
Optimized getMembers access from McastMembership

Modified:
    
tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/MembershipService.java
    
tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/mcast/McastMembership.java
    
tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/mcast/McastService.java
    
tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/mcast/McastServiceImpl.java
    
tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/tcp/ReplicationValve.java
    
tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/tcp/SimpleTcpCluster.java
    tomcat/container/tc5.5.x/modules/cluster/to-do.txt
    tomcat/container/tc5.5.x/webapps/docs/changelog.xml

Modified: 
tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/MembershipService.java
URL: 
http://svn.apache.org/viewcvs/tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/MembershipService.java?rev=356540&r1=356539&r2=356540&view=diff
==============================================================================
--- 
tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/MembershipService.java
 (original)
+++ 
tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/MembershipService.java
 Tue Dec 13 08:53:40 2005
@@ -62,10 +62,18 @@
      * Stops the membership service
      */
     public void stop();
+    
+    /**
+     * Returns that cluster has members.
+     */
+    public boolean hasMembers();
+    
     /**
      * Returns a list of all the members in the cluster.
      */
+    
     public Member[] getMembers();
+    
     /**
      * Returns the member object that defines this member
      */
@@ -85,12 +93,14 @@
      * Sets the local member properties for broadcasting
      */
     public void setLocalMemberProperties(String listenHost, int listenPort);
+    
     /**
      * Sets the membership listener, only one listener can be added.
      * If you call this method twice, the last listener will be used.
      * @param listener The listener
      */
     public void addMembershipListener(MembershipListener listener);
+    
     /**
      * removes the membership listener.
      */

Modified: 
tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/mcast/McastMembership.java
URL: 
http://svn.apache.org/viewcvs/tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/mcast/McastMembership.java?rev=356540&r1=356539&r2=356540&view=diff
==============================================================================
--- 
tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/mcast/McastMembership.java
 (original)
+++ 
tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/mcast/McastMembership.java
 Tue Dec 13 08:53:40 2005
@@ -18,6 +18,11 @@
 
 
 import java.util.HashMap;
+import java.util.Map;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+
 /**
  * A <b>membership</b> implementation using simple multicast.
  * This is the representation of a multicast membership.
@@ -25,28 +30,40 @@
  * If a node fails to send out a heartbeat, the node will be dismissed.
  *
  * @author Filip Hanik
+ * @author Peter Rossbach
  * @version $Revision$, $Date$
  */
-
-
 public class McastMembership
 {
+    protected static final McastMember[] EMPTY_MEMBERS = new McastMember[0];
+    
     /**
      * The name of this membership, has to be the same as the name for the 
local
      * member
      */
     protected String name;
+    
     /**
      * A map of all the members in the cluster.
      */
-    protected HashMap map = new java.util.HashMap();
+    protected Map map = new HashMap();
+    
+    /**
+     * A list of all the members in the cluster.
+     */
+    protected McastMember[] members = EMPTY_MEMBERS;
+    
+    /**
+      * sort members by alive time
+      */
+    protected MemberComparator memberComparator = new MemberComparator();
 
     /**
      * Constructs a new membership
-     * @param myName - has to be the name of the local member. Used to filter 
the local member from the cluster membership
+     * @param name - has to be the name of the local member. Used to filter 
the local member from the cluster membership
      */
-    public McastMembership(String myName) {
-        name = myName;
+    public McastMembership(String name) {
+        this.name = name;
     }
 
     /**
@@ -55,35 +72,85 @@
      */
     public synchronized void reset() {
         map.clear();
+        members = EMPTY_MEMBERS ;
     }
 
     /**
      * Notify the membership that this member has announced itself.
      *
-     * @param m - the member that just pinged us
+     * @param member - the member that just pinged us
      * @return - true if this member is new to the cluster, false otherwise.
-     * @return - false if this member is the local member.
+     * @return - false if this member is the local member or updated.
      */
-    public synchronized boolean memberAlive(McastMember m) {
+    public synchronized boolean memberAlive(McastMember member) {
         boolean result = false;
         //ignore ourselves
-        if ( m.getName().equals(name) ) return result;
+        if ( member.getName().equals(name) ) return result;
 
         //return true if the membership has changed
-        MbrEntry entry = (MbrEntry)map.get(m.getName());
+        MbrEntry entry = (MbrEntry)map.get(member.getName());
         if ( entry == null ) {
-            entry = new MbrEntry(m);
-            map.put(m.getName(),entry);
+            entry = new MbrEntry(member);
+            map.put(member.getName(),entry);
+            addMcastMember(member);
             result = true;
-        } else {
+       } else {
             //update the member alive time
-            entry.getMember().setMemberAliveTime(m.getMemberAliveTime());
-        }//end if
+            McastMember updateMember = entry.getMember() ;
+            if(updateMember.getMemberAliveTime() != 
member.getMemberAliveTime()) {
+                updateMember.setMemberAliveTime(member.getMemberAliveTime());
+                Arrays.sort(members, memberComparator);
+            }
+        }
         entry.accessed();
+ 
         return result;
     }
 
     /**
+     * Add a member to this component and sort array with memberComparator
+     * @param member The member to add
+     */
+    protected void addMcastMember(McastMember member) {
+      synchronized (members) {
+          McastMember results[] =
+            new McastMember[members.length + 1];
+          for (int i = 0; i < members.length; i++)
+              results[i] = members[i];
+          results[members.length] = member;
+          members = results;
+          Arrays.sort(members, memberComparator);
+      }
+    }
+    
+    /**
+     * Remove a member from this component.
+     * 
+     * @param member The member to remove
+     */
+    protected void removeMcastMember(McastMember member) {
+        synchronized (members) {
+            int n = -1;
+            for (int i = 0; i < members.length; i++) {
+                if (members[i] == member) {
+                    n = i;
+                    break;
+                }
+            }
+            if (n < 0)
+                return;
+            McastMember results[] =
+              new McastMember[members.length - 1];
+            int j = 0;
+            for (int i = 0; i < members.length; i++) {
+                if (i != n)
+                    results[j++] = members[i];
+            }
+            members = results;
+        }
+    }
+
+    /**
      * Runs a refresh cycle and returns a list of members that has expired.
      * This also removes the members from the membership, in such a way that
      * getMembers() = getMembers() - expire()
@@ -91,33 +158,55 @@
      * @return the list of expired members
      */
     public synchronized McastMember[] expire(long maxtime) {
-        MbrEntry[] members = getMemberEntries();
-        java.util.ArrayList list = new java.util.ArrayList();
-        for (int i=0; i<members.length; i++) {
-            MbrEntry entry = members[i];
-            if ( entry.hasExpired(maxtime) ) {
+        if(!hasMembers() )
+           return EMPTY_MEMBERS;
+       
+        ArrayList list = null;
+        Iterator i = map.values().iterator();
+        while(i.hasNext()) {
+            MbrEntry entry = (MbrEntry)i.next();
+            if( entry.hasExpired(maxtime) ) {
+                if(list == null) // only need a list when members are expired 
(smaller gc)
+                    list = new java.util.ArrayList();
                 list.add(entry.getMember());
-            }//end if
-        }//while
-        McastMember[] result = new McastMember[list.size()];
-        list.toArray(result);
-        for ( int j=0; j<result.length; j++) map.remove(result[j].getName());
-        return result;
-
-    }//expire
+            }
+        }
+        
+        if(list != null) {
+            McastMember[] result = new McastMember[list.size()];
+            list.toArray(result);
+            for( int j=0; j<result.length; j++) {
+                map.remove(result[j].getName());
+                removeMcastMember(result[j]);
+            }
+            return result;
+        } else {
+            return EMPTY_MEMBERS ;
+        }
+    }
 
     /**
+     * Returning that service has members or not
+     */
+    public synchronized boolean hasMembers() {
+        return members.length > 0 ;
+    }
+ 
+    /**
      * Returning a list of all the members in the membership
+     * We not need a copy: add and remove generate new arrays.
      */
     public synchronized McastMember[] getMembers() {
-        McastMember[] result = new McastMember[map.size()];
-        java.util.Iterator i = map.entrySet().iterator();
-        int pos = 0;
-        while ( i.hasNext() )
-            result[pos++] = 
((MbrEntry)((java.util.Map.Entry)i.next()).getValue()).getMember();
-        return result;
+        if(hasMembers()) {
+            return members;
+        } else {
+            return EMPTY_MEMBERS;
+        }
     }
 
+    /**
+     * get a copy from all member entries
+     */
     protected synchronized MbrEntry[] getMemberEntries()
     {
         MbrEntry[] result = new MbrEntry[map.size()];
@@ -127,8 +216,31 @@
             result[pos++] = 
((MbrEntry)((java.util.Map.Entry)i.next()).getValue());
         return result;
     }
+    
+    // --------------------------------------------- Inner Class
 
+    private class MemberComparator implements java.util.Comparator {
 
+        public int compare(Object o1, Object o2) {
+            try {
+                return compare((McastMember) o1, (McastMember) o2);
+            } catch (ClassCastException x) {
+                return 0;
+            }
+        }
+
+        public int compare(McastMember m1, McastMember m2) {
+            //longer alive time, means sort first
+            long result = m2.getMemberAliveTime() - m1.getMemberAliveTime();
+            if (result < 0)
+                return -1;
+            else if (result == 0)
+                return 0;
+            else
+                return 1;
+        }
+    }
+    
     /**
      * Inner class that represents a member entry
      */
@@ -137,15 +249,18 @@
 
         protected McastMember mbr;
         protected long lastHeardFrom;
+
         public MbrEntry(McastMember mbr) {
-            this.mbr = mbr;
+           this.mbr = mbr;
         }
+
         /**
          * Indicate that this member has been accessed.
          */
         public void accessed(){
-            lastHeardFrom = System.currentTimeMillis();
+           lastHeardFrom = System.currentTimeMillis();
         }
+
         /**
          * Return the actual McastMember object
          */
@@ -161,5 +276,5 @@
             long delta = System.currentTimeMillis() - lastHeardFrom;
             return delta > maxtime;
         }
-    }//MbrEntry
+    }
 }

Modified: 
tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/mcast/McastService.java
URL: 
http://svn.apache.org/viewcvs/tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/mcast/McastService.java?rev=356540&r1=356539&r2=356540&view=diff
==============================================================================
--- 
tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/mcast/McastService.java
 (original)
+++ 
tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/mcast/McastService.java
 Tue Dec 13 08:53:40 2005
@@ -58,7 +58,7 @@
     /**
      * The descriptive information about this implementation.
      */
-    private static final String info = "McastService/2.0";
+    private static final String info = "McastService/2.1";
 
     /**
      * The implementation specific properties
@@ -419,7 +419,15 @@
         }
         return null;
     }
- 
+
+    /**
+     * has members?
+     */
+    public boolean hasMembers() {
+       if ( impl == null || impl.membership == null ) return false;
+       return impl.membership.hasMembers();
+    }
+
     /**
      * Return all the members
      */

Modified: 
tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/mcast/McastServiceImpl.java
URL: 
http://svn.apache.org/viewcvs/tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/mcast/McastServiceImpl.java?rev=356540&r1=356539&r2=356540&view=diff
==============================================================================
--- 
tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/mcast/McastServiceImpl.java
 (original)
+++ 
tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/mcast/McastServiceImpl.java
 Tue Dec 13 08:53:40 2005
@@ -16,6 +16,13 @@
 
 package org.apache.catalina.cluster.mcast;
 
+
+import java.net.MulticastSocket;
+import java.io.IOException;
+import java.net.InetAddress ;
+import java.net.DatagramPacket;
+import org.apache.catalina.cluster.MembershipListener;
+
 /**
  * A <b>membership</b> implementation using simple multicast.
  * This is the representation of a multicast membership service.
@@ -27,12 +34,6 @@
  * @author Filip Hanik
  * @version $Revision$, $Date$
  */
-
-import java.net.MulticastSocket;
-import java.io.IOException;
-import java.net.InetAddress ;
-import java.net.DatagramPacket;
-import org.apache.catalina.cluster.MembershipListener;
 public class McastServiceImpl
 {
     private static org.apache.commons.logging.Log log =

Modified: 
tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/tcp/ReplicationValve.java
URL: 
http://svn.apache.org/viewcvs/tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/tcp/ReplicationValve.java?rev=356540&r1=356539&r2=356540&view=diff
==============================================================================
--- 
tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/tcp/ReplicationValve.java
 (original)
+++ 
tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/tcp/ReplicationValve.java
 Tue Dec 13 08:53:40 2005
@@ -243,32 +243,32 @@
         long totalstart = System.currentTimeMillis();
         //this happens before the request
         if (primaryIndicator)
-            createPrimaryIndicator( request) ;
+            createPrimaryIndicator(request) ;
         getNext().invoke(request, response);
         //this happens after the request
         long start = System.currentTimeMillis();
         Manager manager = request.getContext().getManager();
         if (manager != null && manager instanceof ClusterManager) {
             ClusterManager clusterManager = (ClusterManager) manager;
-            CatalinaCluster cluster = (CatalinaCluster) getContainer()
+            CatalinaCluster containerCluster = (CatalinaCluster) getContainer()
                     .getCluster();
-            if (cluster == null) {
+            if (containerCluster == null) {
                 if (log.isWarnEnabled())
                     log.warn(sm.getString("ReplicationValve.nocluster"));
                 return;
             }
-            // valve cluster can access manager - other clusterhandle 
replication 
+            // valve cluster can access manager - other cluster handle 
replication 
             // at host level - hopefully!
-            if(cluster.getManager(clusterManager.getName()) == null)
+            if(containerCluster.getManager(clusterManager.getName()) == null)
                 return ;
-            if(cluster.getMembers().length > 0  ) {
+            if(containerCluster.getMembers().length > 0  ) {
                 try {
                     // send invalid sessions
                     // DeltaManager returns String[0]
                     if (!(clusterManager instanceof DeltaManager))
-                        sendInvalidSessions(clusterManager, cluster);
+                        sendInvalidSessions(clusterManager, containerCluster);
                     // send replication
-                    sendSessionReplicationMessage(request, clusterManager, 
cluster);
+                    sendSessionReplicationMessage(request, clusterManager, 
containerCluster);
                 } catch (Exception x) {
                     log.error(sm.getString("ReplicationValve.send.failure"), 
x);
                 } finally {

Modified: 
tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/tcp/SimpleTcpCluster.java
URL: 
http://svn.apache.org/viewcvs/tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/tcp/SimpleTcpCluster.java?rev=356540&r1=356539&r2=356540&view=diff
==============================================================================
--- 
tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/tcp/SimpleTcpCluster.java
 (original)
+++ 
tomcat/container/tc5.5.x/modules/cluster/src/share/org/apache/catalina/cluster/tcp/SimpleTcpCluster.java
 Tue Dec 13 08:53:40 2005
@@ -165,9 +165,6 @@
      */
     protected Map managers = new HashMap();
 
-    //sort members by alive time
-    protected MemberComparator memberComparator = new MemberComparator();
-
     private String managerClassName = 
"org.apache.catalina.cluster.session.DeltaManager";
 
     /**
@@ -395,27 +392,34 @@
         }
     }
 
+    /**
+     * get current Deployer
+     */
     public org.apache.catalina.cluster.ClusterDeployer getClusterDeployer() {
         return clusterDeployer;
     }
 
+    /**
+     * set a new Deployer, must be set before cluster started!
+     */
     public void setClusterDeployer(
             org.apache.catalina.cluster.ClusterDeployer clusterDeployer) {
         this.clusterDeployer = clusterDeployer;
     }
 
     /**
+     * has members
+     */
+    public boolean hasMembers() {
+        return membershipService.hasMembers();
+    }
+    
+    /**
      * Get all current cluster members
      * @return all members or empty array 
      */
     public Member[] getMembers() {
-        Member[] members = membershipService.getMembers();
-        if(members != null) {
-            //sort by alive time
-            java.util.Arrays.sort(members, memberComparator);
-        } else 
-            members = new Member[0];
-        return members;
+        return membershipService.getMembers();
     }
 
     /**
@@ -1345,31 +1349,6 @@
     public ObjectName getObjectName() {
         return objectName;
     }
-
-    // --------------------------------------------- Inner Class
-
-    private class MemberComparator implements java.util.Comparator {
-
-        public int compare(Object o1, Object o2) {
-            try {
-                return compare((Member) o1, (Member) o2);
-            } catch (ClassCastException x) {
-                return 0;
-            }
-        }
-
-        public int compare(Member m1, Member m2) {
-            //longer alive time, means sort first
-            long result = m2.getMemberAliveTime() - m1.getMemberAliveTime();
-            if (result < 0)
-                return -1;
-            else if (result == 0)
-                return 0;
-            else
-                return 1;
-        }
-    }
- 
 
     // ------------------------------------------------------------- deprecated
 

Modified: tomcat/container/tc5.5.x/modules/cluster/to-do.txt
URL: 
http://svn.apache.org/viewcvs/tomcat/container/tc5.5.x/modules/cluster/to-do.txt?rev=356540&r1=356539&r2=356540&view=diff
==============================================================================
--- tomcat/container/tc5.5.x/modules/cluster/to-do.txt (original)
+++ tomcat/container/tc5.5.x/modules/cluster/to-do.txt Tue Dec 13 08:53:40 2005
@@ -1,7 +1,11 @@
 ==============================
 Next actions
 ==============================
-
+- support CrossContext session replication
+    Idea: use endAccess to signal replicationValve that session from other app 
has changed.
+    refactor ReplicationValve 
+    When session is serialzed from other app, set right app classloader
+    endaccess is also send at CoyoteAdpater for context session as recycle the 
request
 - Add MbeanFactory to generate dynamic cluster at runtime.
     Problem: How we can start those central services?
     - StandardEngine support load Mbean from external file.     
@@ -199,6 +203,11 @@
 ==============================   
 COMPLETED
 ==============================
+5.5.15 (pero)
+- Optimized getMembers access from McastMembership
+    Member list was copied at every access. (Used inside 
ReplicationValve.invoke)
+    SimpleTcpCluster need a alive time sorted array
+
 5.5.11 (pero)
 - MemoryUser principal from UserDatabaseRealm not handled to replicated 
        - look inside DeltaRequest.setPrincipal(Principal,boolean)

Modified: tomcat/container/tc5.5.x/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewcvs/tomcat/container/tc5.5.x/webapps/docs/changelog.xml?rev=356540&r1=356539&r2=356540&view=diff
==============================================================================
--- tomcat/container/tc5.5.x/webapps/docs/changelog.xml (original)
+++ tomcat/container/tc5.5.x/webapps/docs/changelog.xml Tue Dec 13 08:53:40 2005
@@ -37,6 +37,9 @@
       <add>
         DataSender starts new Socket after IOException. (pero)
       </add>
+      <update>
+        Reduce memory usage at membership service. (pero)
+      </update>
     </changelog>
   </subsection>
 </section>



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to