You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by rj...@apache.org on 2010/10/30 00:44:53 UTC

svn commit: r1028935 - in /tomcat/trunk/java/org/apache/jasper: compiler/JspRuntimeContext.java servlet/JspServletWrapper.java util/FastRemovalDequeue.java

Author: rjung
Date: Fri Oct 29 22:44:52 2010
New Revision: 1028935

URL: http://svn.apache.org/viewvc?rev=1028935&view=rev
Log:
Changes to FastRemovalDequeue:
- Make queue thread safe and remove external synchronisation
- Provide maximal size to queue
- Include size checking when adding entries
- Return handle to displaced entries when queue overflows
  while adding a new entry
- Explicitely invalidate queue entries on removal by using
  new field "valid"

Changes to JspRuntimeContext:
- Initialize FastRemovalDequeue with correct size
- No more external synchronisation for FastRemovalDequeue
- Private utility method to unload a wrapper
- Check for displaced wrapper when adding a new wrapper
  to the queue and unload it

Changes to JspServletWrapper:
- No more explicit overflow check for the queue. It's now
  done implicitely when adding to the queue.

Modified:
    tomcat/trunk/java/org/apache/jasper/compiler/JspRuntimeContext.java
    tomcat/trunk/java/org/apache/jasper/servlet/JspServletWrapper.java
    tomcat/trunk/java/org/apache/jasper/util/FastRemovalDequeue.java

Modified: tomcat/trunk/java/org/apache/jasper/compiler/JspRuntimeContext.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/compiler/JspRuntimeContext.java?rev=1028935&r1=1028934&r2=1028935&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/jasper/compiler/JspRuntimeContext.java (original)
+++ tomcat/trunk/java/org/apache/jasper/compiler/JspRuntimeContext.java Fri Oct 29 22:44:52 2010
@@ -155,6 +155,11 @@ public final class JspRuntimeContext {
                 && options.getCheckInterval() > 0) {
             lastCheck = System.currentTimeMillis();
         }                                            
+
+        if (options.getMaxLoadedJsps() > 0) {
+            jspQueue = new FastRemovalDequeue<JspServletWrapper>(options.getMaxLoadedJsps());
+        }
+
     }
 
     // ----------------------------------------------------- Instance Variables
@@ -178,7 +183,7 @@ public final class JspRuntimeContext {
     /**
      * Keeps JSP pages ordered by last access. 
      */
-    private FastRemovalDequeue<JspServletWrapper> jspQueue = new FastRemovalDequeue<JspServletWrapper>();
+    private FastRemovalDequeue<JspServletWrapper> jspQueue = null;
 
     // ------------------------------------------------------ Public Methods
 
@@ -213,15 +218,18 @@ public final class JspRuntimeContext {
 
     /**
      * Push a newly compiled JspServletWrapper into the queue at first
-     * execution of jsp.
+     * execution of jsp. Destroy any JSP the has been replaced in the queue.
      *
      * @param jsw Servlet wrapper for jsp.
      * @return a ticket that can be pushed to front of queue at later execution times.
      * */
     public FastRemovalDequeue<JspServletWrapper>.Entry push(JspServletWrapper jsw) {
-        synchronized (jspQueue) {
-            return jspQueue.push(jsw);
+        FastRemovalDequeue<JspServletWrapper>.Entry entry = jspQueue.push(jsw);
+        JspServletWrapper replaced = entry.getReplaced();
+        if (replaced != null) {
+            unloadJspServletWrapper(replaced);
         }
+        return entry;
     }
     
     /**
@@ -230,9 +238,7 @@ public final class JspRuntimeContext {
      * @param ticket the ticket for the jsp.
      * */
     public void makeYoungest(FastRemovalDequeue<JspServletWrapper>.Entry ticket) {
-        synchronized(jspQueue) {
-            jspQueue.moveFirst(ticket);
-        }
+        jspQueue.moveFirst(ticket);
     }
     
     /**
@@ -500,6 +506,13 @@ public final class JspRuntimeContext {
         return new SecurityHolder(source, permissions);
     }
 
+    private void unloadJspServletWrapper(JspServletWrapper jsw) {
+        removeWrapper(jsw.getJspUri());
+        synchronized(jsw) {
+            jsw.destroy();
+        }
+    }
+
     /**
      * Method used by background thread to check if any JSP's should be destroyed.
      * If JSP's to be unloaded are found, they will be destroyed.
@@ -522,11 +535,8 @@ public final class JspRuntimeContext {
             }
         }
         if (jsw != null) {
-            removeWrapper(jsw.getJspUri());
-            synchronized(jsw) {
-                jsw.destroy();
-                return true;
-            }
+            unloadJspServletWrapper(jsw);
+            return true;
         }
         return false;
     }

Modified: tomcat/trunk/java/org/apache/jasper/servlet/JspServletWrapper.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/servlet/JspServletWrapper.java?rev=1028935&r1=1028934&r2=1028935&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/jasper/servlet/JspServletWrapper.java (original)
+++ tomcat/trunk/java/org/apache/jasper/servlet/JspServletWrapper.java Fri Oct 29 22:44:52 2010
@@ -377,7 +377,6 @@ public class JspServletWrapper {
                 synchronized(this) {
                     if (ticket == null) {
                         ticket = ctxt.getRuntimeContext().push(this);
-                        ctxt.getRuntimeContext().unloadJsp();
                     } else {
                         ctxt.getRuntimeContext().makeYoungest(ticket);
                     }

Modified: tomcat/trunk/java/org/apache/jasper/util/FastRemovalDequeue.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/util/FastRemovalDequeue.java?rev=1028935&r1=1028934&r2=1028935&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/jasper/util/FastRemovalDequeue.java (original)
+++ tomcat/trunk/java/org/apache/jasper/util/FastRemovalDequeue.java Fri Oct 29 22:44:52 2010
@@ -23,15 +23,18 @@ package org.apache.jasper.util;
  * added to the collection with an Entry type, that is returned to the consumer.
  * When removing an object from the list, the consumer provides this Entry object.
  *
- * The Entry type is completely opaque to the consumer itself.
+ * The Entry type is nearly opaque to the consumer of the queue. The only public
+ * member is the getter for any object displaced when adding a new object to the
+ * queue. This can be used to destroy that object.
  *
  * The Entry object contains the links pointing to the neighbours in the doubly
  * linked list, so that removal of an Entry does not need to search for it but
  * instead can be done in constant time.
  *
- * The implementation is not thread-safe. Full synchronisation has to be provided
- * externally. Invalidation of Entry objects during removal from the list is done
- * by setting their valid field to false. All public methods which take Entry
+ * The implementation is fully thread-safe.
+ *
+ * Invalidation of Entry objects during removal from the list is done
+ * by setting their "valid" field to false. All public methods which take Entry
  * objects as arguments are NOP if the entry is no longer valid.
  *
  * A typical use of the FastRemovalDequeue is a list of entries in sorted order,
@@ -44,6 +47,8 @@ package org.apache.jasper.util;
  */
 public class FastRemovalDequeue<T> {
 
+    /** Maximum size of the queue */
+    private final int maxSize;
     /** First element of the queue. */
     private Entry first;
     /** Last element of the queue. */
@@ -52,7 +57,11 @@ public class FastRemovalDequeue<T> {
     private int size;
 
     /** Initialize empty queue. */
-    public FastRemovalDequeue() {
+    public FastRemovalDequeue(int maxSize) {
+        if (maxSize <=1 ) {
+            maxSize = 2;
+        }
+        this.maxSize = maxSize;
         first = null;
         last = null;
         size = 0;
@@ -65,7 +74,7 @@ public class FastRemovalDequeue<T> {
      * 
      * @return the size of the list.
      * */
-    public int getSize() {
+    public synchronized int getSize() {
         return size;
     }
 
@@ -76,8 +85,11 @@ public class FastRemovalDequeue<T> {
      * @param object the object to prepend to the start of the list.
      * @return an entry for use when the object should be moved.
      * */
-    public Entry push(final T object) {
+    public synchronized Entry push(final T object) {
         Entry entry = new Entry(object);
+        if (size >= maxSize) {
+            entry.setReplaced(pop());
+        }
         if (first == null) {
             first = last = entry;
         } else {
@@ -97,8 +109,11 @@ public class FastRemovalDequeue<T> {
      * @param object the object to append to the end of the list.
      * @return an entry for use when the object should be moved.
      * */
-    public Entry unpop(final T object) {
+    public synchronized Entry unpop(final T object) {
         Entry entry = new Entry(object);
+        if (size >= maxSize) {
+            entry.setReplaced(unpush());
+        }
         if (first == null) {
             first = last = entry;
         } else {
@@ -116,16 +131,17 @@ public class FastRemovalDequeue<T> {
      * 
      * @return the content of the first element of the list.
      **/
-    public T unpush() {
+    public synchronized T unpush() {
         T content = null;
         if (first != null) {
-            content = first.getContent();
-            first.setValid(false);
+            Entry element = first;
             first = first.getNext();
+            content = element.getContent();
             if (first != null) {
                 first.setPrevious(null);
             }
             size--;
+            element.setValid(false);
         }
         return content;
     }
@@ -135,16 +151,17 @@ public class FastRemovalDequeue<T> {
      * 
      * @return the content of the last element of the list.
      **/
-    public T pop() {
+    public synchronized T pop() {
         T content = null;
         if (last != null) {
-            content = last.getContent();
-            last.setValid(false);
+            Entry element = last;
             last = last.getPrevious();
+            content = element.getContent();
             if (last != null) {
                 last.setNext(null);
             }
             size--;
+            element.setValid(false);
         }
         return content;
     }
@@ -152,7 +169,7 @@ public class FastRemovalDequeue<T> {
     /**
      * Removes any element of the list and returns its content.
      **/
-    public void remove(final Entry element) {
+    public synchronized void remove(final Entry element) {
         if (!element.getValid()) {
             return;
         }
@@ -169,6 +186,7 @@ public class FastRemovalDequeue<T> {
             first = next;
         }
         size--;
+        element.setValid(false);
     }
 
     /**
@@ -179,7 +197,7 @@ public class FastRemovalDequeue<T> {
      * 
      * @param element the entry to move in front.
      * */
-    public void moveFirst(final Entry element) {
+    public synchronized void moveFirst(final Entry element) {
         if (element.getValid() &&
             element.getPrevious() != null) {
             Entry prev = element.getPrevious();
@@ -205,7 +223,7 @@ public class FastRemovalDequeue<T> {
      * 
      * @param element the entry to move to the back.
      * */
-    public void moveLast(final Entry element) {
+    public synchronized void moveLast(final Entry element) {
         if (element.getValid() &&
             element.getNext() != null) {
             Entry next = element.getNext();
@@ -235,6 +253,8 @@ public class FastRemovalDequeue<T> {
         private boolean valid = true;
         /** The content this entry is valid for. */
         private final T content;
+        /** Optional content that was displaced by this entry */
+        private T replaced = null;
         /** Pointer to next element in queue. */
         private Entry next = null;
         /** Pointer to previous element in queue. */
@@ -256,6 +276,14 @@ public class FastRemovalDequeue<T> {
             return content;
         }
 
+        public final T getReplaced() {
+            return replaced;
+        }
+
+        private final void setReplaced(final T replaced) {
+            this.replaced = replaced;
+        }
+
         private final Entry getNext() {
             return next;
         }



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