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 2009/09/14 20:53:28 UTC

svn commit: r814775 - in /tomcat/trunk: java/org/apache/juli/AsyncFileHandler.java webapps/docs/config/systemprops.xml

Author: fhanik
Date: Mon Sep 14 18:53:27 2009
New Revision: 814775

URL: http://svn.apache.org/viewvc?rev=814775&view=rev
Log:
Add in behavior and properties around async logging.
Thinking about it, I think the exact same functionality can be achieved in a much simpler manner by just using a blocking queue.
Will attempt that refactor next


Modified:
    tomcat/trunk/java/org/apache/juli/AsyncFileHandler.java
    tomcat/trunk/webapps/docs/config/systemprops.xml

Modified: tomcat/trunk/java/org/apache/juli/AsyncFileHandler.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/juli/AsyncFileHandler.java?rev=814775&r1=814774&r2=814775&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/juli/AsyncFileHandler.java (original)
+++ tomcat/trunk/java/org/apache/juli/AsyncFileHandler.java Mon Sep 14 18:53:27 2009
@@ -30,7 +30,10 @@
 
     public static final int OVERFLOW_DROP_LAST = 1;
     public static final int OVERFLOW_DROP_FIRST = 2;
-    public static final int DEFAULT_MAX_RECORDS = 1000;
+    public static final int OVERFLOW_DROP_FLUSH = 3;
+    
+    public static final int OVERFLOW_DROP_TYPE = Integer.parseInt(System.getProperty("org.apache.juli.AsyncOverflowDropType","1"));
+    public static final int DEFAULT_MAX_RECORDS = Integer.parseInt(System.getProperty("org.apache.juli.AsyncMaxRecordCount","1000"));
     public static final int RECORD_BATCH_COUNT = Integer.parseInt(System.getProperty("org.apache.juli.AsyncRecordBatchCount","100"));
     
     protected static ConcurrentLinkedQueue<FileHandler> handlers = new ConcurrentLinkedQueue<FileHandler>();
@@ -42,7 +45,7 @@
     }
     
     protected LogQueue<LogRecord> queue = new LogQueue<LogRecord>();
-    protected boolean closed = false;
+    protected volatile boolean closed = false;
     
     public AsyncFileHandler() {
         this(null,null,null);
@@ -55,14 +58,18 @@
 
     @Override
     public void close() {
+        if (closed) return;
         closed = true;
         // TODO Auto-generated method stub
         super.close();
         handlers.remove(this);
+        //empty the queue of log entries for this log
+        while (queue.poll()!=null) recordCounter.addAndGet(-1);
     }
     
     @Override
     protected void open() {
+        if(!closed) return;
         closed = false;
         // TODO Auto-generated method stub
         super.open();
@@ -108,14 +115,22 @@
     protected static class SignalAtomicLong {
         AtomicLong delegate = new AtomicLong(0);
         ReentrantLock lock = new ReentrantLock();
-        Condition cond = lock.newCondition();
+        Condition sleepUntilPositiveCond = lock.newCondition();
+        Condition sleepUntilEmpty = lock.newCondition();
         
         public long addAndGet(long i) {
             long prevValue = delegate.getAndAdd(i);
             if (prevValue<=0 && i>0) {
                 lock.lock();
                 try {
-                    cond.signalAll();
+                    sleepUntilPositiveCond.signalAll();
+                } finally {
+                    lock.unlock();
+                }
+            } else if (prevValue>0 && delegate.get()<=0) {
+                lock.lock();
+                try {
+                    sleepUntilEmpty.signalAll();
                 } finally {
                     lock.unlock();
                 }
@@ -128,12 +143,24 @@
             lock.lock();
             try {
                 if (delegate.get()>0) return;
-                cond.await();
+                sleepUntilPositiveCond.await();
             } finally {
                 lock.unlock();
             }
         }
         
+        public void sleepUntilEmpty() throws InterruptedException {
+            if (delegate.get()<=0) return;
+            lock.lock();
+            try {
+                if (delegate.get()<=0) return;
+                sleepUntilPositiveCond.await();
+            } finally {
+                lock.unlock();
+            }
+            
+        }
+        
         public long get() {
             return delegate.get();
         }
@@ -171,7 +198,7 @@
     
     protected static class LogQueue<E> {
         protected int max = DEFAULT_MAX_RECORDS;
-        protected int type = OVERFLOW_DROP_LAST;
+        protected int type = OVERFLOW_DROP_TYPE;
         protected ConcurrentLinkedQueue<E> delegate = new ConcurrentLinkedQueue<E>(); 
         
         public boolean offer(E e) {
@@ -188,6 +215,19 @@
                             return false;
                         }
                     }
+                    case OVERFLOW_DROP_FLUSH: {
+                        try {
+                            recordCounter.sleepUntilEmpty();
+                        }catch (InterruptedException x) {
+                            //no op - simply continue the operation
+                        }
+                        if (delegate.offer(e)) {
+                            recordCounter.addAndGet(1);
+                            return true;
+                        } else {
+                            return false;
+                        }
+                    }
                     default:
                         return false;
                 }

Modified: tomcat/trunk/webapps/docs/config/systemprops.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/systemprops.xml?rev=814775&r1=814774&r2=814775&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/systemprops.xml (original)
+++ tomcat/trunk/webapps/docs/config/systemprops.xml Mon Sep 14 18:53:27 2009
@@ -325,6 +325,37 @@
 
 </section>
 
+<section name="Logging">
+
+  <properties>
+
+    <property name="org.apache.juli.AsyncOverflowDropType">
+      <p>When the memory limit of records has been reached the system needs to determine what action to take.
+         Currently there are three actions that can be taken:
+         <ul>
+           <li><code>int OVERFLOW_DROP_LAST = 1</code> - the record that caused the overflow will be dropped and not logged</li>
+           <li><code>int OVERFLOW_DROP_FIRST = 2</code> - the record that is next in line to be logged will be dropped to make room for the latest record on the queue</li>
+           <li><code>int OVERFLOW_DROP_FLUSH = 3</code> - suspend the thread while the queue empties out and flushes the entries to the write buffer</li>
+         </ul>
+         Default value is <code>1</code> (OVERFLOW_DROP_LAST).
+      </p>
+    </property>
+
+    <property name="org.apache.juli.AsyncMaxRecordCount">
+      <p>The max number of log records that the async logger will keep in memory. When this limit is reached and a new record is being logged by the 
+         JULI framework the system will take an action based on the <code>org.apache.juli.AsyncOverflowDropType</code> setting.
+         The default value is <code>1000</code> records
+      </p>
+    </property>
+
+    <property name="org.apache.juli.AsyncRecordBatchCount">
+      <p>
+      </p>
+    </property>
+
+  </properties>
+
+</section>
 
 <section name="Other">
 



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