Author: fhanik Date: Mon Mar 26 23:45:41 2007 New Revision: 522773 URL: http://svn.apache.org/viewvc?view=rev&rev=522773 Log: (empty)
Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/ha/context/ReplicatedContext.java tomcat/tc6.0.x/trunk/java/org/apache/catalina/tribes/tipis/AbstractReplicatedMap.java tomcat/tc6.0.x/trunk/java/org/apache/catalina/tribes/tipis/LazyReplicatedMap.java tomcat/tc6.0.x/trunk/java/org/apache/catalina/tribes/tipis/ReplicatedMap.java tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/ha/context/ReplicatedContext.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/ha/context/ReplicatedContext.java?view=diff&rev=522773&r1=522772&r2=522773 ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/catalina/ha/context/ReplicatedContext.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/ha/context/ReplicatedContext.java Mon Mar 26 23:45:41 2007 @@ -31,21 +31,30 @@ import java.util.Iterator; import javax.servlet.ServletContextAttributeListener; import javax.servlet.ServletContextAttributeEvent; +import org.apache.catalina.LifecycleEvent; +import org.apache.catalina.LifecycleListener; +import java.util.Enumeration; +import java.util.concurrent.ConcurrentHashMap; +import org.apache.catalina.util.Enumerator; /** * @author Filip Hanik * @version 1.0 */ -public class ReplicatedContext extends StandardContext { +public class ReplicatedContext extends StandardContext implements LifecycleListener { private int mapSendOptions = Channel.SEND_OPTIONS_DEFAULT; public static org.apache.juli.logging.Log log = org.apache.juli.logging.LogFactory.getLog( ReplicatedContext.class ); - + protected boolean startComplete = false; protected static long DEFAULT_REPL_TIMEOUT = 15000;//15 seconds - + public void lifecycleEvent(LifecycleEvent event) { + if ( event.getType() == AFTER_START_EVENT ) + startComplete = true; + } public synchronized void start() throws LifecycleException { if ( this.started ) return; + super.addLifecycleListener(this); try { CatalinaCluster catclust = (CatalinaCluster)this.getCluster(); if (this.context == null) this.context = new ReplApplContext(this.getBasePath(), this); @@ -71,12 +80,15 @@ } if ( !this.started ) return; try { + super.lifecycle.removeLifecycleListener(this); } catch ( Exception x ){ log.error("Unable to stop ReplicatedContext",x); throw new LifecycleException("Failed to stop ReplicatedContext",x); } finally { + this.startComplete = false; super.stop(); } + } @@ -115,11 +127,17 @@ protected static class ReplApplContext extends ApplicationContext { - public ReplApplContext(String basePath, StandardContext context) { + protected ConcurrentHashMap tomcatAttributes = new ConcurrentHashMap(); + + public ReplApplContext(String basePath, ReplicatedContext context) { super(basePath,context); } - protected ServletContext getFacade() { + protected ReplicatedContext getParent() { + return (ReplicatedContext)getContext(); + } + + protected ServletContext getFacade() { return super.getFacade(); } @@ -131,17 +149,49 @@ } public void removeAttribute(String name) { + tomcatAttributes.remove(name); //do nothing super.removeAttribute(name); } public void setAttribute(String name, Object value) { - //do nothing - super.setAttribute(name,value); + if ( (!getParent().startComplete) || "org.apache.jasper.runtime.JspApplicationContextImpl".equals(name) ){ + tomcatAttributes.put(name,value); + } else + super.setAttribute(name,value); + } + + public Object getAttribute(String name) { + if (tomcatAttributes.containsKey(name) ) + return tomcatAttributes.get(name); + else + return super.getAttribute(name); + } + + public Enumeration getAttributeNames() { + return new MultiEnumeration(new Enumeration[] {super.getAttributeNames(),new Enumerator(tomcatAttributes.keySet(), true)}); } } + protected static class MultiEnumeration implements Enumeration { + Enumeration[] e=null; + public MultiEnumeration(Enumeration[] lists) { + e = lists; + } + public boolean hasMoreElements() { + for ( int i=0; i<e.length; i++ ) { + if ( e[i].hasMoreElements() ) return true; + } + return false; + } + public Object nextElement() { + for ( int i=0; i<e.length; i++ ) { + if ( e[i].hasMoreElements() ) return e[i].nextElement(); + } + return null; + } + } } Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/tribes/tipis/AbstractReplicatedMap.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/tribes/tipis/AbstractReplicatedMap.java?view=diff&rev=522773&r1=522772&r2=522773 ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/catalina/tribes/tipis/AbstractReplicatedMap.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/tribes/tipis/AbstractReplicatedMap.java Mon Mar 26 23:45:41 2007 @@ -73,6 +73,8 @@ //------------------------------------------------------------------------------ // INSTANCE VARIABLES //------------------------------------------------------------------------------ + protected abstract int getStateMessageType(); + /** * Timeout for RPC messages, how long we will wait for a reply @@ -433,7 +435,7 @@ Member[] members = getMapMembers(); Member backup = members.length > 0 ? (Member) members[0] : null; if (backup != null) { - MapMessage msg = new MapMessage(mapContextName, MapMessage.MSG_STATE, false, + MapMessage msg = new MapMessage(mapContextName, getStateMessageType(), false, null, null, null, null); Response[] resp = rpcChannel.send(new Member[] {backup}, msg, rpcChannel.FIRST_REPLY, channelSendOptions, rpcTimeout); if (resp.length > 0) { @@ -490,16 +492,18 @@ } //state transfer request - if (mapmsg.getMsgType() == mapmsg.MSG_STATE) { + if (mapmsg.getMsgType() == mapmsg.MSG_STATE || mapmsg.getMsgType() == mapmsg.MSG_STATE_COPY) { synchronized (stateMutex) { //make sure we dont do two things at the same time ArrayList list = new ArrayList(); Iterator i = super.entrySet().iterator(); while (i.hasNext()) { Map.Entry e = (Map.Entry) i.next(); - MapEntry entry = (MapEntry) e.getValue(); + MapEntry entry = (MapEntry) super.get(e.getKey()); if ( entry.isSerializable() ) { - MapMessage me = new MapMessage(mapContextName, MapMessage.MSG_PROXY, - false, (Serializable) entry.getKey(), null, null, entry.getBackupNodes()); + boolean copy = (mapmsg.getMsgType() == mapmsg.MSG_STATE_COPY); + MapMessage me = new MapMessage(mapContextName, + copy?MapMessage.MSG_COPY:MapMessage.MSG_PROXY, + false, (Serializable) entry.getKey(), copy?(Serializable) entry.getValue():null, null, entry.getBackupNodes()); list.add(me); } } @@ -584,18 +588,18 @@ super.remove(mapmsg.getKey()); } - if (mapmsg.getMsgType() == MapMessage.MSG_BACKUP) { + if (mapmsg.getMsgType() == MapMessage.MSG_BACKUP || mapmsg.getMsgType() == MapMessage.MSG_COPY) { MapEntry entry = (MapEntry)super.get(mapmsg.getKey()); if (entry == null) { entry = new MapEntry(mapmsg.getKey(), mapmsg.getValue()); - entry.setBackup(true); + entry.setBackup(mapmsg.getMsgType() == MapMessage.MSG_BACKUP); entry.setProxy(false); entry.setBackupNodes(mapmsg.getBackupNodes()); if (mapmsg.getValue()!=null && mapmsg.getValue() instanceof ReplicatedMapEntry ) { ((ReplicatedMapEntry)mapmsg.getValue()).setOwner(getMapOwner()); } } else { - entry.setBackup(true); + entry.setBackup(mapmsg.getMsgType() == MapMessage.MSG_BACKUP); entry.setProxy(false); entry.setBackupNodes(mapmsg.getBackupNodes()); if (entry.getValue() instanceof ReplicatedMapEntry) { @@ -650,7 +654,7 @@ Iterator i = super.entrySet().iterator(); while (i.hasNext()) { Map.Entry e = (Map.Entry) i.next(); - MapEntry entry = (MapEntry) e.getValue(); + MapEntry entry = (MapEntry) super.get(e.getKey()); if ( entry == null ) continue; if (entry.isPrimary() && (entry.getBackupNodes() == null || entry.getBackupNodes().length == 0)) { try { @@ -696,7 +700,7 @@ Iterator i = super.entrySet().iterator(); while (i.hasNext()) { Map.Entry e = (Map.Entry) i.next(); - MapEntry entry = (MapEntry) e.getValue(); + MapEntry entry = (MapEntry) super.get(e.getKey()); if (entry.isPrimary() && inSet(member,entry.getBackupNodes())) { try { Member[] backup = publishEntryInfo(entry.getKey(), entry.getValue()); @@ -837,7 +841,7 @@ while (i.hasNext()) { Map.Entry e = (Map.Entry) i.next(); - System.out.println( (++cnt) + ". " + e.getValue()); + System.out.println( (++cnt) + ". " + super.get(e.getKey())); } System.out.println("EndMap]\n\n"); }catch ( Exception ignore) { @@ -856,8 +860,11 @@ return super.containsKey(key); } - public Object put(Object key, Object value) { + return put(key,value,true); + } + + public Object put(Object key, Object value, boolean notify) { MapEntry entry = new MapEntry(key,value); entry.setBackup(false); entry.setProxy(false); @@ -867,8 +874,10 @@ //make sure that any old values get removed if ( containsKey(key) ) old = remove(key); try { - Member[] backup = publishEntryInfo(key, value); - entry.setBackupNodes(backup); + if ( notify ) { + Member[] backup = publishEntryInfo(key, value); + entry.setBackupNodes(backup); + } } catch (ChannelException x) { log.error("Unable to replicate out data for a LazyReplicatedMap.put operation", x); } @@ -911,7 +920,7 @@ Iterator i = super.entrySet().iterator(); while (i.hasNext()) { Map.Entry e = (Map.Entry) i.next(); - MapEntry entry = (MapEntry) e.getValue(); + MapEntry entry = (MapEntry) super.get(e.getKey()); if (entry.isPrimary() && value.equals(entry.getValue())) return true; }//while return false; @@ -976,7 +985,7 @@ while (it.hasNext() ) { Map.Entry e = (Map.Entry) it.next(); if ( e != null ) { - MapEntry entry = (MapEntry) e.getValue(); + MapEntry entry = (MapEntry) super.get(e.getKey()); if (entry.isPrimary() && entry.getValue() != null) counter++; } } @@ -996,7 +1005,7 @@ Iterator i = super.entrySet().iterator(); while ( i.hasNext() ) { Map.Entry e = (Map.Entry)i.next(); - MapEntry entry = (MapEntry)e.getValue(); + MapEntry entry = (MapEntry)super.get(e.getKey()); if ( entry.isPrimary() && entry.getValue()!=null) values.add(entry.getValue()); } return Collections.unmodifiableCollection(values); @@ -1144,6 +1153,8 @@ public static final int MSG_START = 6; public static final int MSG_STOP = 7; public static final int MSG_INIT = 8; + public static final int MSG_COPY = 9; + public static final int MSG_STATE_COPY = 10; private byte[] mapId; private int msgtype; @@ -1177,6 +1188,8 @@ case MSG_START: return "MSG_START"; case MSG_STOP: return "MSG_STOP"; case MSG_INIT: return "MSG_INIT"; + case MSG_STATE_COPY: return "MSG_STATE_COPY"; + case MSG_COPY: return "MSG_COPY"; default : return "UNKNOWN"; } } Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/tribes/tipis/LazyReplicatedMap.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/tribes/tipis/LazyReplicatedMap.java?view=diff&rev=522773&r1=522772&r2=522773 ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/catalina/tribes/tipis/LazyReplicatedMap.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/tribes/tipis/LazyReplicatedMap.java Mon Mar 26 23:45:41 2007 @@ -113,6 +113,10 @@ //------------------------------------------------------------------------------ // METHODS TO OVERRIDE //------------------------------------------------------------------------------ + protected int getStateMessageType() { + return AbstractReplicatedMap.MapMessage.MSG_STATE; + } + /** * publish info about a map pair (key/value) to other nodes in the cluster * @param key Object Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/tribes/tipis/ReplicatedMap.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/tribes/tipis/ReplicatedMap.java?view=diff&rev=522773&r1=522772&r2=522773 ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/catalina/tribes/tipis/ReplicatedMap.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/tribes/tipis/ReplicatedMap.java Mon Mar 26 23:45:41 2007 @@ -92,6 +92,10 @@ //------------------------------------------------------------------------------ // METHODS TO OVERRIDE //------------------------------------------------------------------------------ + protected int getStateMessageType() { + return AbstractReplicatedMap.MapMessage.MSG_STATE_COPY; + } + /** * publish info about a map pair (key/value) to other nodes in the cluster * @param key Object @@ -107,8 +111,8 @@ if (backup == null || backup.length == 0) return null; //publish the data out to all nodes - MapMessage msg = new MapMessage(getMapContextName(), MapMessage.MSG_BACKUP, false, - (Serializable) key, null, null, backup); + MapMessage msg = new MapMessage(getMapContextName(), MapMessage.MSG_COPY, false, + (Serializable) key, (Serializable) value, null, backup); getChannel().send(getMapMembers(), msg, getChannelSendOptions()); Modified: tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml?view=diff&rev=522773&r1=522772&r2=522773 ============================================================================== --- tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml (original) +++ tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml Mon Mar 26 23:45:41 2007 @@ -17,6 +17,9 @@ <section name="Tomcat 6.0.11 (remm)"> <subsection name="Catalina"> <changelog> + <fix> + <bug>41166</bug> Invalid handling when using replicated context (fhanik) + </fix> <add> Added SENDFILE support for the NIO connector. (fhanik) <br/> </add> --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]