You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by aw...@apache.org on 2007/07/20 00:47:01 UTC

svn commit: r557803 - in /myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal: application/StateManagerImpl.java config/xmlHttp/XmlHttpConfigurator.java webapp/TrinidadFilterImpl.java

Author: awiner
Date: Thu Jul 19 15:47:00 2007
New Revision: 557803

URL: http://svn.apache.org/viewvc?view=rev&rev=557803
Log:
TRINIDAD-116: PPR + State Management: reuse state tokens while PPRing to avoid flushing the cache
- When we're performing PPR, try to reuse the existing state token.
  This keeps us from losing the view state of the prior page (and other windows) just
  because we've had a lot of PPR requests on one page, and makes sure that we're using
  memory only for view states that can be returned to, instead of intermediate page states
  that are not in the browser history.
- The implementation is basically just in StateManagerImpl, which exposes one static method,
  reuseRequestTokenForResponse(), called to indicate this is a request where state tokens
  can be reused.
- When in effect, restoreView() caches the token that was used to retrieve the view,
  and saveView() will use that token instead of fetching a new one.
  

Modified:
    myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/application/StateManagerImpl.java
    myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/xmlHttp/XmlHttpConfigurator.java
    myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/webapp/TrinidadFilterImpl.java

Modified: myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/application/StateManagerImpl.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/application/StateManagerImpl.java?view=diff&rev=557803&r1=557802&r2=557803
==============================================================================
--- myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/application/StateManagerImpl.java (original)
+++ myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/application/StateManagerImpl.java Thu Jul 19 15:47:00 2007
@@ -125,6 +125,9 @@
     _delegate = delegate;
   }
 
+  /**
+   * Save a component tree as an Object.
+   */
   static public Object saveComponentTree(
     FacesContext context,
     UIComponent  component)
@@ -134,7 +137,11 @@
     Object state = component.processSaveState(context);
     return new PageState(context, structure, state, null);
   }
-
+  
+  /**
+   * Take an object created by saveComponentTree()
+   * and instantiate it as a UIComponent.
+   */
   static public UIComponent restoreComponentTree(
     FacesContext context,
     Object       savedState) throws ClassNotFoundException,
@@ -280,13 +287,33 @@
             // if this feature has not been disabled
             _useViewRootCache(context) ? root : null);
 
-        // See if we should pin this new state to any old state
-        String pinnedToken = (String)
-          context.getExternalContext().getRequestMap().get(_PINNED_STATE_TOKEN_KEY);
-
-        token = cache.addNewEntry(pageState,
-                                  stateMap,
-                                  pinnedToken);
+        String requestToken = _getRequestTokenForResponse(context);
+        // If we have a cached token that we want to reuse,
+        // and that token hasn't disappeared from the cache already
+        // (unlikely, but not impossible), use the stateMap directly
+        // without asking the cache for a new token
+        if ((requestToken != null) && cache.isAvailable(requestToken))
+        {
+          // NOTE: under *really* high pressure, the cache might
+          // have been emptied between the isAvailable() call and
+          // this put().  This seems sufficiently implausible to
+          // be worth punting on
+          stateMap.put(requestToken, pageState);
+          token = requestToken;
+          // NOTE 2: we have not pinned this reused state to any old state
+          // This is OK for current uses of pinning and state reuse,
+          // as pinning stays constant within a window, and we're not
+          // erasing pinning at all.
+        }
+        else
+        {
+          // See if we should pin this new state to any old state
+          String pinnedToken = (String)
+            context.getExternalContext().getRequestMap().get(_PINNED_STATE_TOKEN_KEY);
+          token = cache.addNewEntry(pageState,
+                                    stateMap,
+                                    pinnedToken);
+        }
       }
       // If we got the "applicationViewCache", we're using it.
       else
@@ -335,6 +362,7 @@
    * to the token will not be released before the state for this request
    * is released.
    */
+  @SuppressWarnings("unchecked")
   static public void pinStateToRequest(FacesContext context, String stateToken)
   {
     context.getExternalContext().getRequestMap().put(
@@ -352,6 +380,50 @@
   }
   
   
+  /**
+   * Mark the the incoming request token should be used for the response
+   */
+  @SuppressWarnings("unchecked")
+  static public void reuseRequestTokenForResponse(ExternalContext ec)
+  {
+    ec.getRequestMap().put(_REUSE_REQUEST_TOKEN_FOR_RESPONSE_KEY, Boolean.TRUE);    
+  }
+
+  /**
+   * If we've been asked to reuse the request token for the response,
+   * store it off.
+   */
+  @SuppressWarnings("unchecked")
+  static private void _updateRequestTokenForResponse(
+    FacesContext context, String token)
+  {
+    Map<String, Object> requestMap = context.getExternalContext().getRequestMap();
+    // Go from TRUE -> the saved token
+    if (Boolean.TRUE.equals(
+          requestMap.get(_REUSE_REQUEST_TOKEN_FOR_RESPONSE_KEY)))
+    {
+      requestMap.put(_REUSE_REQUEST_TOKEN_FOR_RESPONSE_KEY, token);
+    }
+  }
+
+
+  /**
+   * Get any cached token for the response.
+   */
+  @SuppressWarnings("unchecked")
+  static private String _getRequestTokenForResponse(
+    FacesContext context)
+  {
+    Map<String, Object> requestMap = context.getExternalContext().getRequestMap();
+    Object token = requestMap.get(_REUSE_REQUEST_TOKEN_FOR_RESPONSE_KEY);
+    // We wanted to, but didn't have anything saved
+    if (Boolean.TRUE.equals(token))
+      return null;
+
+    return (String) token;
+  }
+    
+  
   @Override
   public void writeState(FacesContext context,
                          SerializedView state) throws IOException
@@ -418,6 +490,9 @@
                          _VIEW_CACHE_KEY + ".");
         viewState = (PageState) stateMap.get(token);
 
+        if (viewState != null)
+          _updateRequestTokenForResponse(context, (String) token);
+
         // Make sure that if the view state is present, the cache still
         // has the token, and vice versa
 
@@ -955,6 +1030,9 @@
 
   private static final String _PINNED_STATE_TOKEN_KEY =
     "org.apache.myfaces.trinidadinternal.application.PINNED_STATE_TOKEN";
+
+  private static final String _REUSE_REQUEST_TOKEN_FOR_RESPONSE_KEY =
+    "org.apache.myfaces.trinidadinternal.application.REUSE_REQUEST_TOKEN_FOR_RESPONSE";
 
 
   private static final String _APPLICATION_CACHE_TOKEN = "_a_";

Modified: myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/xmlHttp/XmlHttpConfigurator.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/xmlHttp/XmlHttpConfigurator.java?view=diff&rev=557803&r1=557802&r2=557803
==============================================================================
--- myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/xmlHttp/XmlHttpConfigurator.java (original)
+++ myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/xmlHttp/XmlHttpConfigurator.java Thu Jul 19 15:47:00 2007
@@ -35,6 +35,7 @@
 import org.apache.myfaces.trinidad.config.Configurator;
 import org.apache.myfaces.trinidad.context.RequestContext;
 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
+import org.apache.myfaces.trinidadinternal.application.StateManagerImpl;
 import org.apache.myfaces.trinidadinternal.renderkit.core.CoreRenderKit;
 import org.apache.myfaces.trinidadinternal.renderkit.core.ppr.XmlResponseWriter;
 import org.apache.myfaces.trinidadinternal.util.ExternalContextUtils;
@@ -55,6 +56,11 @@
   public static ServletResponse getWrappedServletResponse(ServletResponse response)
   {
     return new XmlHttpServletResponse(response);
+  }
+
+  public static void beginRequest(ExternalContext externalContext)
+  {
+    StateManagerImpl.reuseRequestTokenForResponse(externalContext);
   }
 
   /**

Modified: myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/webapp/TrinidadFilterImpl.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/webapp/TrinidadFilterImpl.java?view=diff&rev=557803&r1=557802&r2=557803
==============================================================================
--- myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/webapp/TrinidadFilterImpl.java (original)
+++ myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/webapp/TrinidadFilterImpl.java Thu Jul 19 15:47:00 2007
@@ -141,7 +141,10 @@
     }
 
     if (isPartialRequest)
+    {
+      XmlHttpConfigurator.beginRequest(externalContext);
       response = XmlHttpConfigurator.getWrappedServletResponse(response);
+    }
 
     try
     {