[jboss-svn-commits] JBoss Common SVN: r3303 - in jboss-logmanager/trunk/src/main/java/org/jboss/logmanager: handlers and 1 other directory.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Wed Jun 24 17:22:54 EDT 2009
Author: david.lloyd at jboss.com
Date: 2009-06-24 17:22:53 -0400 (Wed, 24 Jun 2009)
New Revision: 3303
Added:
jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/handlers/ArrayQueue.java
jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/handlers/AsyncHandler.java
Modified:
jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/ExtLogRecord.java
jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/handlers/ExtHandler.java
Log:
Add async handler, because apparently people want it
Modified: jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/ExtLogRecord.java
===================================================================
--- jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/ExtLogRecord.java 2009-06-22 23:35:46 UTC (rev 3302)
+++ jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/ExtLogRecord.java 2009-06-24 21:22:53 UTC (rev 3303)
@@ -115,6 +115,16 @@
}
/**
+ * Disable caller calculation for this record. If the caller has already been calculated, leave it; otherwise
+ * set the caller to {@code "unknown"}.
+ */
+ public void disableCallerCalculation() {
+ if (calculateCaller) {
+ setUnknownCaller();
+ }
+ }
+
+ /**
* Copy all fields and prepare this object to be passed to another thread or to be serialized. Calling this method
* more than once has no additional effect and will not incur extra copies.
*/
Added: jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/handlers/ArrayQueue.java
===================================================================
--- jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/handlers/ArrayQueue.java (rev 0)
+++ jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/handlers/ArrayQueue.java 2009-06-24 21:22:53 UTC (rev 3303)
@@ -0,0 +1,76 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.logmanager.handlers;
+
+import java.util.Queue;
+import java.util.Iterator;
+import java.util.AbstractQueue;
+
+final class ArrayQueue<T> extends AbstractQueue<T> implements Queue<T> {
+ private final T[] elements;
+ private int head, cnt;
+
+ @SuppressWarnings({ "unchecked" })
+ public ArrayQueue(int size) {
+ elements = (T[]) new Object[size];
+ }
+
+ public Iterator<T> iterator() {
+ throw new UnsupportedOperationException();
+ }
+
+ public int size() {
+ return cnt;
+ }
+
+ public boolean offer(final T o) {
+ final T[] elements = this.elements;
+ final int length = elements.length;
+ final int cnt = this.cnt;
+ if (cnt == length) {
+ return false;
+ }
+ elements[(head + cnt) % length] = o;
+ this.cnt = cnt + 1;
+ return true;
+ }
+
+ public T poll() {
+ final T[] elements = this.elements;
+ final int length = elements.length;
+ final int head = this.head;
+ final int cnt = this.cnt;
+ if (cnt == 0) {
+ return null;
+ } else try {
+ return elements[head];
+ } finally {
+ this.head = head + 1 % length;
+ this.cnt = cnt - 1;
+ }
+ }
+
+ public T peek() {
+ return cnt == 0 ? null : elements[head];
+ }
+}
Added: jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/handlers/AsyncHandler.java
===================================================================
--- jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/handlers/AsyncHandler.java (rev 0)
+++ jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/handlers/AsyncHandler.java 2009-06-24 21:22:53 UTC (rev 3303)
@@ -0,0 +1,185 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.logmanager.handlers;
+
+import org.jboss.logmanager.ExtLogRecord;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.Executors;
+import java.util.Queue;
+
+import java.util.logging.Handler;
+import java.util.logging.ErrorManager;
+
+public final class AsyncHandler extends ExtHandler {
+
+ private final CopyOnWriteArrayList<Handler> handlers = new CopyOnWriteArrayList<Handler>();
+ private final ThreadFactory threadFactory;
+ private final Queue<ExtLogRecord> recordQueue;
+ private final AsyncThread asyncThread = new AsyncThread();
+
+ private boolean closed;
+ private boolean taskRunning;
+
+ private static final int DEFAULT_QUEUE_LENGTH = 512;
+
+ public AsyncHandler(final int queueLength, final ThreadFactory threadFactory) {
+ recordQueue = new ArrayQueue<ExtLogRecord>(queueLength);
+ this.threadFactory = threadFactory;
+ }
+
+ public AsyncHandler(final ThreadFactory threadFactory) {
+ this(DEFAULT_QUEUE_LENGTH, threadFactory);
+ }
+
+ public AsyncHandler(final int queueLength) {
+ this(queueLength, Executors.defaultThreadFactory());
+ }
+
+ public AsyncHandler() {
+ this(DEFAULT_QUEUE_LENGTH);
+ }
+
+ public void addHandler(final Handler handler) {
+ checkAccess();
+ synchronized (recordQueue) {
+ if (closed) {
+ throw new IllegalStateException("Handler is closed");
+ }
+ handlers.add(handler);
+ }
+ }
+
+ public void removeHandler(final Handler handler) {
+ checkAccess();
+ synchronized (recordQueue) {
+ if (! closed) {
+ handlers.remove(handler);
+ }
+ }
+ }
+
+ public void publish(final ExtLogRecord record) {
+ final Queue<ExtLogRecord> recordQueue = this.recordQueue;
+ boolean intr = Thread.interrupted();
+ // prepare record to move to another thread
+ record.copyAll();
+ try {
+ synchronized (recordQueue) {
+ if (closed) {
+ return;
+ }
+ startTaskIfNotRunning();
+ while (! recordQueue.offer(record)) {
+ try {
+ recordQueue.wait();
+ } catch (InterruptedException e) {
+ intr = true;
+ }
+ if (closed) {
+ return;
+ }
+ startTaskIfNotRunning();
+ }
+ recordQueue.notify();
+ }
+ } finally {
+ if (intr) Thread.currentThread().interrupt();
+ }
+ }
+
+ private void startTaskIfNotRunning() {
+ if (! taskRunning) {
+ taskRunning = true;
+ threadFactory.newThread(asyncThread).start();
+ }
+ }
+
+ public void flush() {
+ for (Handler handler : handlers) {
+ handler.flush();
+ }
+ }
+
+ public void close() throws SecurityException {
+ checkAccess();
+ closed = true;
+ asyncThread.interrupt();
+ handlers.clear();
+ }
+
+ private final class AsyncThread implements Runnable {
+ private volatile Thread thread;
+
+ void interrupt() {
+ final Thread thread = this.thread;
+ if (thread != null) {
+ thread.interrupt();
+ }
+ }
+
+ public void run() {
+ thread = Thread.currentThread();
+ final Queue<ExtLogRecord> recordQueue = AsyncHandler.this.recordQueue;
+ final CopyOnWriteArrayList<Handler> handlers = AsyncHandler.this.handlers;
+
+ boolean intr = false;
+ try {
+ for (;;) {
+ ExtLogRecord rec;
+ synchronized (recordQueue) {
+ while ((rec = recordQueue.poll()) == null) {
+ if (closed) {
+ return;
+ }
+ try {
+ recordQueue.wait();
+ } catch (InterruptedException e) {
+ intr = true;
+ }
+ }
+ recordQueue.notify();
+ }
+ for (Handler handler : handlers) try {
+ handler.publish(rec);
+ } catch (Exception e) {
+ getErrorManager().error("Publication error", e, ErrorManager.WRITE_FAILURE);
+ } catch (VirtualMachineError e) {
+ throw e;
+ } catch (Throwable t) {
+ // ignore :-/
+ }
+ }
+ } finally {
+ synchronized (recordQueue) {
+ taskRunning = false;
+ recordQueue.notify();
+ }
+ thread = null;
+ if (intr) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+ }
+}
Modified: jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/handlers/ExtHandler.java
===================================================================
--- jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/handlers/ExtHandler.java 2009-06-22 23:35:46 UTC (rev 3302)
+++ jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/handlers/ExtHandler.java 2009-06-24 21:22:53 UTC (rev 3303)
@@ -26,8 +26,10 @@
import java.util.logging.Handler;
import java.util.logging.LogRecord;
+import java.util.logging.LoggingPermission;
import java.io.Flushable;
+import java.security.Permission;
/**
* An extended logger handler. Use this class as a base class for log handlers which require {@code ExtLogRecord}
@@ -36,6 +38,7 @@
public abstract class ExtHandler extends Handler implements Flushable {
private static final String LOGGER_CLASS_NAME = org.jboss.logmanager.Logger.class.getName();
+ private static final Permission CONTROL_PERMISSION = new LoggingPermission("control", null);
/** {@inheritDoc} */
public final void publish(final LogRecord record) {
@@ -53,4 +56,16 @@
* @param record the log record to publish
*/
public abstract void publish(final ExtLogRecord record);
+
+ /**
+ * Check access.
+ *
+ * @throws SecurityException if a security manager is installed and the caller does not have the {@code "control" LoggingPermission}
+ */
+ protected void checkAccess() throws SecurityException {
+ final SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(CONTROL_PERMISSION);
+ }
+ }
}
More information about the jboss-svn-commits
mailing list