001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.resource.connectionmanager;
023:
024: import java.security.AccessController;
025: import java.security.PrivilegedAction;
026: import java.util.ArrayList;
027: import java.util.Collection;
028: import java.util.Iterator;
029:
030: import org.jboss.logging.Logger;
031:
032: /**
033: * A ConnectionValidator that performs background validation of managed connections for an
034: * InternalManagedConnectionPool.
035: *
036: * @author <a href="weston.price@jboss.com">Weston Price</a>
037: * @version $Revision: 57189 $
038: */
039: public class ConnectionValidator {
040:
041: /** The log */
042: private static final Logger log = Logger
043: .getLogger(ConnectionValidator.class);
044:
045: /** The pools */
046: private Collection pools = new ArrayList();
047:
048: /** The interval */
049: private long interval = Long.MAX_VALUE;
050:
051: /** The next */
052: private long next = Long.MAX_VALUE;//important initialization!
053:
054: /** The validator */
055: private static final ConnectionValidator validator = new ConnectionValidator();
056:
057: private ConnectionValidator() {
058:
059: AccessController.doPrivileged(new PrivilegedAction() {
060: public Object run() {
061: Runnable runnable = new ConnectionValidatorRunnable();
062: Thread removerThread = new Thread(runnable,
063: "ConnectionValidator");
064: removerThread.setDaemon(true);
065: removerThread.start();
066: return null;
067: }
068: });
069:
070: }
071:
072: public static void registerPool(InternalManagedConnectionPool mcp,
073: long interval) {
074: validator.internalRegisterPool(mcp, interval);
075:
076: }
077:
078: public static void unRegisterPool(InternalManagedConnectionPool mcp) {
079: validator.internalUnregisterPool(mcp);
080:
081: }
082:
083: private void internalRegisterPool(
084: InternalManagedConnectionPool mcp, long interval) {
085:
086: synchronized (pools) {
087: pools.add(mcp);
088:
089: if (interval > 1 && interval / 2 < this .interval) {
090: this .interval = interval / 2;
091: long maybeNext = System.currentTimeMillis()
092: + this .interval;
093: if (next > maybeNext && maybeNext > 0) {
094: next = maybeNext;
095: log
096: .debug("internalRegisterPool: about to notify thread: old next: "
097: + next + ", new next: " + maybeNext);
098: pools.notify();
099: }
100: }
101: }
102:
103: }
104:
105: private void internalUnregisterPool(
106: InternalManagedConnectionPool mcp) {
107:
108: synchronized (pools) {
109: pools.remove(mcp);
110: if (pools.size() == 0) {
111: log
112: .debug("internalUnregisterPool: setting interval to Long.MAX_VALUE");
113: interval = Long.MAX_VALUE;
114: }
115:
116: }
117:
118: }
119:
120: private void setupContextClassLoader() {
121: // Could be null if loaded from system classloader
122: final ClassLoader cl = IdleRemover.class.getClassLoader();
123: if (cl == null)
124: return;
125:
126: SecurityManager sm = System.getSecurityManager();
127: if (sm == null)
128: Thread.currentThread().setContextClassLoader(cl);
129:
130: AccessController.doPrivileged(new PrivilegedAction() {
131: public Object run() {
132: Thread.currentThread().setContextClassLoader(cl);
133: return null;
134: }
135: });
136: }
137:
138: public static void waitForBackgroundThread() {
139: synchronized (validator.pools) {
140: return;
141: }
142: }
143:
144: private class ConnectionValidatorRunnable implements Runnable {
145:
146: public void run() {
147: setupContextClassLoader();
148:
149: synchronized (pools) {
150:
151: while (true) {
152:
153: try {
154:
155: pools.wait(interval);
156:
157: log
158: .debug("run: ConnectionValidator notifying pools, interval: "
159: + interval);
160:
161: for (Iterator iter = pools.iterator(); iter
162: .hasNext();) {
163:
164: InternalManagedConnectionPool mcp = (InternalManagedConnectionPool) iter
165: .next();
166: mcp.validateConnections();
167: }
168:
169: next = System.currentTimeMillis() + interval;
170:
171: if (next < 0) {
172: next = Long.MAX_VALUE;
173:
174: }
175:
176: } catch (InterruptedException e) {
177: log
178: .info("run: ConnectionValidator has been interrupted, returning");
179: return;
180: } catch (RuntimeException e) {
181: log
182: .warn(
183: "run: ConnectionValidator ignored unexpected runtime exception",
184: e);
185: } catch (Exception e) {
186: log
187: .warn(
188: "run: ConnectionValidator ignored unexpected error",
189: e);
190:
191: }
192:
193: }
194:
195: }
196:
197: }
198:
199: }
200: }
|