Author: peter_firmstone Date: Sat Dec 7 23:26:45 2013 New Revision: 1548978
URL: http://svn.apache.org/r1548978 Log: The existing implementation of ReadersWriter ensures exclusivity for writing threads,but makes no visibility guarantees for writes, as evidenced by test failures on Windows Server 2008 Jdk1.7.0_25: Running com/sun/jini/test/spec/lookupservice/test_set00/MultipleEvntLeaseRenewals.td =============================== CALLING RUN() =============================== net.jini.core.lease.UnknownLeaseException: No event recorded for ID: 0 at com.sun.jini.reggie.RegistrarImpl.checkEvent(RegistrarImpl.java:5471) at com.sun.jini.reggie.RegistrarImpl.renewEventLeaseInt(RegistrarImpl.java:5566) at com.sun.jini.reggie.RegistrarImpl.renewEventLeaseDo(RegistrarImpl.java:5549) at com.sun.jini.reggie.RegistrarImpl.renewEventLease(RegistrarImpl.java:3268) at com.sun.jini.reggie.TransientRegistrarImpl.renewEventLease(TransientRegistrarImpl.java:29) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:601) at net.jini.jeri.BasicInvocationDispatcher.invoke(BasicInvocationDispatcher.java:1134) at net.jini.jeri.BasicInvocationDispatcher.dispatch(BasicInvocationDispatcher.java:610) at com.sun.jini.jeri.internal.runtime.Target$2.run(Target.java:493) at net.jini.export.ServerContext.doWithServerContext(ServerContext.java:108) at com.sun.jini.jeri.internal.runtime.Target.dispatch(Target.java:490) at com.sun.jini.jeri.internal.runtime.Target.access$000(Target.java:57) at com.sun.jini.jeri.internal.runtime.Target$1.run(Target.java:466) at com.sun.jini.start.AggregatePolicyProvider$AggregateSecurityContext$2.run(AggregatePolicyProvider.java:593) at java.security.AccessController.doPrivileged(Native Method) at com.sun.jini.jeri.internal.runtime.Target.dispatch(Target.java:463) at com.sun.jini.jeri.internal.runtime.Target.dispatch(Target.java:428) at com.sun.jini.jeri.internal.runtime.DgcRequestDispatcher.dispatch(DgcRequestDispatcher.java:210) at net.jini.jeri.connection.ServerConnectionManager$Dispatcher.dispatch(ServerConnectionManager.java:147) at com.sun.jini.jeri.internal.mux.MuxServer$1$1.run(MuxServer.java:244) at com.sun.jini.start.AggregatePolicyProvider$AggregateSecurityContext$1.run(AggregatePolicyProvider.java:579) at java.security.AccessController.doPrivileged(Native Method) at com.sun.jini.jeri.internal.mux.MuxServer$1.run(MuxServer.java:241) at com.sun.jini.thread.ThreadPool$Task.run(ThreadPool.java:187) at com.sun.jini.thread.ThreadPool$Worker.run(ThreadPool.java:226) at java.lang.Thread.run(Thread.java:722) at com.sun.jini.jeri.internal.runtime.Util.__________EXCEPTION_RECEIVED_FROM_SERVER__________(Util.java:108) at com.sun.jini.jeri.internal.runtime.Util.exceptionReceivedFromServer(Util.java:101) at net.jini.jeri.BasicInvocationHandler.unmarshalThrow(BasicInvocationHandler.java:1303) at net.jini.jeri.BasicInvocationHandler.invokeRemoteMethodOnce(BasicInvocationHandler.java:832) at net.jini.jeri.BasicInvocationHandler.invokeRemoteMethod(BasicInvocationHandler.java:659) at net.jini.jeri.BasicInvocationHandler.invoke(BasicInvocationHandler.java:528) at com.sun.jini.reggie.$Proxy0.renewEventLease(Unknown Source) at com.sun.jini.reggie.EventLease.doRenew(EventLease.java:98) at com.sun.jini.lease.AbstractLease.renew(AbstractLease.java:83) at com.sun.jini.test.spec.lookupservice.QATestUtils.doRenewLease(QATestUtils.java:681) at com.sun.jini.test.spec.lookupservice.test_set00.MultipleEvntLeaseRenewals.run(MultipleEvntLeaseRenewals.java:193) at com.sun.jini.qa.harness.MasterTest.doTest(MasterTest.java:256) at com.sun.jini.qa.harness.MasterTest.main(MasterTest.java:144) TIME: 11:05:11 AM MasterTest.doTest INFO: ============================ CALLING TEARDOWN() ============================= Removed: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/ReadersPriorityWriter.java Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerImpl.java river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/mercury/MailboxImpl.java river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/PersistentStore.java river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/RegistrarImpl.java river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/start/AggregatePolicyProvider.java river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/ReadersWriter.java river/jtsk/skunk/qa_refactor/trunk/src/net/jini/loader/pref/PreferredClassProvider.java river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/net/RFC3986URLClassLoader.java Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerImpl.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerImpl.java?rev=1548978&r1=1548977&r2=1548978&view=diff ============================================================================== --- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerImpl.java (original) +++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerImpl.java Sat Dec 7 23:26:45 2013 @@ -37,7 +37,6 @@ import com.sun.jini.start.LifeCycle; import org.apache.river.api.util.Commission; import com.sun.jini.thread.InterruptedStatusThread; -import com.sun.jini.thread.ReadersPriorityWriter; import com.sun.jini.thread.ReadersWriter; import com.sun.jini.thread.ReadersWriter.ConcurrentLockException; import com.sun.jini.thread.ReadyState; @@ -280,7 +279,7 @@ class FiddlerImpl implements ServerProxy private final SnapshotThread snapshotThread; /** Concurrent object to control read and write access */ - private final ReadersWriter concurrentObj = new ReadersPriorityWriter(); + private final ReadersWriter concurrentObj = new ReadersWriter(); /** Object for synchronizing with the registration expire thread */ private final Object leaseExpireThreadSyncObj = new Object(); /** Object on which the snapshot-taking thread will synchronize */ Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/mercury/MailboxImpl.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/mercury/MailboxImpl.java?rev=1548978&r1=1548977&r2=1548978&view=diff ============================================================================== --- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/mercury/MailboxImpl.java (original) +++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/mercury/MailboxImpl.java Sat Dec 7 23:26:45 2013 @@ -39,7 +39,6 @@ import com.sun.jini.reliableLog.LogHandl import com.sun.jini.start.LifeCycle; import org.apache.river.api.util.Commission; import com.sun.jini.thread.InterruptedStatusThread; -import com.sun.jini.thread.ReadersPriorityWriter; import com.sun.jini.thread.ReadersWriter; import com.sun.jini.thread.ReadersWriter.ConcurrentLockException; import com.sun.jini.thread.ReadyState; @@ -274,7 +273,7 @@ class MailboxImpl implements MailboxBack /** The admin proxy of this server */ private /*final*/ volatile MailboxAdminProxy mailboxAdminProxy; /** Concurrent object (lock) to control read and write access */ - private final ReadersWriter concurrentObj = new ReadersPriorityWriter(); + private final ReadersWriter concurrentObj = new ReadersWriter(); /** Map from <code>Uuid</code> to <code>ServiceRegistration</code> */ // HashMap is unsynchronized, but we are performing external // synchronization via the <code>concurrentObj</code> field. Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/PersistentStore.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/PersistentStore.java?rev=1548978&r1=1548977&r2=1548978&view=diff ============================================================================== --- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/PersistentStore.java (original) +++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/PersistentStore.java Sat Dec 7 23:26:45 2013 @@ -31,7 +31,6 @@ import com.sun.jini.norm.lookup.SubStore import com.sun.jini.reliableLog.LogHandler; import com.sun.jini.reliableLog.ReliableLog; import com.sun.jini.system.FileSystem; -import com.sun.jini.thread.ReadersPriorityWriter; import com.sun.jini.thread.ReadersWriter; /** @@ -58,7 +57,7 @@ class PersistentStore { * snapshot thread the writer since for us mutation is the * non-exclusive operation. */ - final private ReadersWriter mutatorLock = new ReadersPriorityWriter(); + final private ReadersWriter mutatorLock = new ReadersWriter(); /** * Thread local that tracks if (and how many times) the current thread Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/RegistrarImpl.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/RegistrarImpl.java?rev=1548978&r1=1548977&r2=1548978&view=diff ============================================================================== --- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/RegistrarImpl.java (original) +++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/RegistrarImpl.java Sat Dec 7 23:26:45 2013 @@ -35,7 +35,6 @@ import com.sun.jini.reliableLog.LogHandl import com.sun.jini.reliableLog.ReliableLog; import com.sun.jini.start.LifeCycle; import com.sun.jini.thread.InterruptedStatusThread; -import com.sun.jini.thread.ReadersPriorityWriter; import com.sun.jini.thread.ReadersWriter; import com.sun.jini.thread.ReadersWriter.ConcurrentLockException; import com.sun.jini.thread.ReadyState; @@ -312,7 +311,7 @@ class RegistrarImpl implements Registrar private final Thread snapshotter; /** Concurrent object to control read and write access */ - private final ReadersWriter concurrentObj = new ReadersPriorityWriter(); + private final ReadersWriter concurrentObj = new ReadersWriter(); /** Object for synchronizing with the service expire thread */ private final Object serviceNotifier = new Object(); /** Object for synchronizing with the event expire thread */ Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/start/AggregatePolicyProvider.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/start/AggregatePolicyProvider.java?rev=1548978&r1=1548977&r2=1548978&view=diff ============================================================================== --- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/start/AggregatePolicyProvider.java (original) +++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/start/AggregatePolicyProvider.java Sat Dec 7 23:26:45 2013 @@ -110,7 +110,7 @@ public class AggregatePolicyProvider private final ConcurrentMap<ClassLoader,Policy> subPolicyChildClassLoaderCache = RC.concurrentMap( new ConcurrentHashMap<Referrer<ClassLoader>,Referrer<Policy>>(), - Ref.WEAK_IDENTITY, Ref.STRONG, 1000L, 0L); + Ref.WEAK_IDENTITY, Ref.STRONG, 10000L, 0L); private final ReadWriteLock rwl = new ReentrantReadWriteLock(); private final Lock lock = rwl.writeLock(); private final Lock readLock = rwl.readLock(); // stop access to subPolicyChildClassLoaderCache while write in progress. Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/ReadersWriter.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/ReadersWriter.java?rev=1548978&r1=1548977&r2=1548978&view=diff ============================================================================== --- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/ReadersWriter.java (original) +++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/ReadersWriter.java Sat Dec 7 23:26:45 2013 @@ -17,92 +17,102 @@ */ package com.sun.jini.thread; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + /** * An Object to control the concurrent state. Allows multiple readers or - * a single writer. Waiting writers have priority over new readers. - * Waiting priority writers have priority over waiting regular writers. + * a single writer. + * Waiting priority writers have priority over waiting regular writers and + * waiting readers. * A single thread cannot hold a lock more than once. * * @author Sun Microsystems, Inc. * */ public class ReadersWriter { - /** The number of active readers */ - private int activeReaders = 0; - /** The number of waiting writers (both regular and priority) */ - private int waitingWriters = 0; - /** The number of waiting priority writers */ - private int waitingPriorityWriters = 0; - /** True if there is an active writer */ - private boolean activeWriter = false; - - public ReadersWriter() {} + private int waitingWriters; + private final AtomicInteger waitingPriorityWriters; + private final ReadWriteLock lock; + private final Lock readLock; + private final Lock writeLock; + private final Condition waitingPriorityWriter; + private final Condition waitingWriter; + + public ReadersWriter() { + super(); + lock = new ReentrantReadWriteLock(); + readLock = lock.readLock(); + writeLock = lock.writeLock(); + waitingPriorityWriter = writeLock.newCondition(); + waitingWriter = writeLock.newCondition(); + waitingWriters = 0; + waitingPriorityWriters = new AtomicInteger(); + } /** Obtain a read lock. Multiple concurrent readers allowed. */ - public synchronized void readLock() { - while (activeWriter || waitingWriters != 0) { - try { - wait(); - } catch (InterruptedException e) { - throw new ConcurrentLockException( - "read lock interrupted in thread"); - } - } - activeReaders++; + public void readLock() { + // Stop new readers from obtaining read lock if priority writer + // is waiting for current readers to finish. Prevents writer lock + // starvation. + while (waitingPriorityWriters.get() > 0){ + try { + Thread.sleep(50L); + } catch (InterruptedException ex) { + // reestablish interrupted status. + Thread.currentThread().interrupt(); + } + } + readLock.lock(); } /** Release a read lock. */ - public synchronized void readUnlock() { - activeReaders--; - if (activeReaders == 0) - notifyAll(); + public void readUnlock() { + readLock.unlock(); } /** Obtain a regular write lock. Only a single writer allowed at once. */ - public synchronized void writeLock() { - while (activeWriter || - activeReaders != 0 || - waitingPriorityWriters != 0) - { - try { - waitingWriters++; - try { - wait(); - } finally { - waitingWriters--; - } - } catch (InterruptedException e) { - throw new ConcurrentLockException( - "write lock interrupted in thread"); - } - } - activeWriter = true; + public void writeLock() { + writeLock.lock(); + while (waitingPriorityWriters.get() > 0) + { + try { + waitingWriters++; + try { + waitingPriorityWriter.signal(); + waitingWriter.await(); + } finally { + waitingWriters--; + } + } catch (InterruptedException e) { + throw new ConcurrentLockException( + "write lock interrupted in thread"); + } + } } /** Obtain a priority write lock. Only a single writer allowed at once. */ - public synchronized void priorityWriteLock() { - while (activeWriter || activeReaders != 0) { - try { - waitingWriters++; - waitingPriorityWriters++; - try { - wait(); - } finally { - waitingWriters--; - waitingPriorityWriters--; - } - } catch (InterruptedException e) { - throw new ConcurrentLockException( - "write lock interrupted in thread"); - } - } - activeWriter = true; + public void priorityWriteLock() { + waitingPriorityWriters.getAndIncrement(); + try { + writeLock.lock(); + } finally { + waitingPriorityWriters.getAndDecrement(); + } } /** Release a (regular or priority) write lock. */ - public synchronized void writeUnlock() { - activeWriter = false; - notifyAll(); + public void writeUnlock() { + // should be in a locked state or an exception will be thrown. + try { + if (waitingPriorityWriters.get() > 0) waitingPriorityWriter.signal(); + else if (waitingWriters > 0) waitingWriter.signal(); + } finally { + writeLock.unlock(); + } } /** Modified: river/jtsk/skunk/qa_refactor/trunk/src/net/jini/loader/pref/PreferredClassProvider.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/net/jini/loader/pref/PreferredClassProvider.java?rev=1548978&r1=1548977&r2=1548978&view=diff ============================================================================== --- river/jtsk/skunk/qa_refactor/trunk/src/net/jini/loader/pref/PreferredClassProvider.java (original) +++ river/jtsk/skunk/qa_refactor/trunk/src/net/jini/loader/pref/PreferredClassProvider.java Sat Dec 7 23:26:45 2013 @@ -299,7 +299,7 @@ public class PreferredClassProvider exte private static final Set<ClassLoader> localLoaders; static { Set<Referrer<ClassLoader>> internal = Collections.newSetFromMap(new ConcurrentHashMap<Referrer<ClassLoader>,Boolean>()); - localLoaders = RC.set(internal, Ref.WEAK_IDENTITY, 100L); + localLoaders = RC.set(internal, Ref.WEAK_IDENTITY, 10000L); AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() { public ClassLoader run() { for (ClassLoader loader = ClassLoader.getSystemClassLoader(); @@ -393,7 +393,7 @@ public class PreferredClassProvider exte this.requireDlPerm = requireDlPerm; ConcurrentMap<Referrer<ClassLoader>,Referrer<PermissionCollection>> inter = new ConcurrentHashMap<Referrer<ClassLoader>,Referrer<PermissionCollection>>(); - classLoaderPerms = RC.concurrentMap(inter, Ref.WEAK_IDENTITY, Ref.STRONG, 200L, 200L); + classLoaderPerms = RC.concurrentMap(inter, Ref.WEAK_IDENTITY, Ref.STRONG, 5000L, 5000L); initialized = true; } Modified: river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/net/RFC3986URLClassLoader.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/net/RFC3986URLClassLoader.java?rev=1548978&r1=1548977&r2=1548978&view=diff ============================================================================== --- river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/net/RFC3986URLClassLoader.java (original) +++ river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/net/RFC3986URLClassLoader.java Sat Dec 7 23:26:45 2013 @@ -1085,6 +1085,11 @@ public class RFC3986URLClassLoader exten * Returns an URL that will be checked if it contains the class or resource. * If the file component of the URL is not a directory, a Jar URL will be * created. + * + * We need to modify this implementation to allow URLStreamHandlerFactory's + * to use custom caching, such as the per ClassLoader caching used by + * Apache Geronimo. This would be very useful as it allows services + * to upgrade themselves by reloading and replacing their proxy's. * * @return java.net.URL a test URL */
