Return-Path: Delivered-To: apmail-db-derby-commits-archive@www.apache.org Received: (qmail 14935 invoked from network); 1 Jul 2009 22:28:40 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 1 Jul 2009 22:28:40 -0000 Received: (qmail 11292 invoked by uid 500); 1 Jul 2009 22:28:50 -0000 Delivered-To: apmail-db-derby-commits-archive@db.apache.org Received: (qmail 11241 invoked by uid 500); 1 Jul 2009 22:28:50 -0000 Mailing-List: contact derby-commits-help@db.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: "Derby Development" List-Id: Delivered-To: mailing list derby-commits@db.apache.org Received: (qmail 11200 invoked by uid 99); 1 Jul 2009 22:28:44 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 01 Jul 2009 22:28:44 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 01 Jul 2009 22:28:40 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 3A87B238889D; Wed, 1 Jul 2009 22:28:19 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r790412 - in /db/derby/code/branches/10.5: ./ java/engine/org/apache/derby/impl/services/monitor/TopService.java Date: Wed, 01 Jul 2009 22:28:19 -0000 To: derby-commits@db.apache.org From: kahatlen@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090701222819.3A87B238889D@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: kahatlen Date: Wed Jul 1 22:28:18 2009 New Revision: 790412 URL: http://svn.apache.org/viewvc?rev=790412&view=rev Log: DERBY-4018: ArrayIndexOutOfBoundsException in TopService.inService under heavy multithreaded use of EmbeddedDriver Merged fix from trunk (revisions 789264 and 790218). Modified: db/derby/code/branches/10.5/ (props changed) db/derby/code/branches/10.5/java/engine/org/apache/derby/impl/services/monitor/TopService.java Propchange: db/derby/code/branches/10.5/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Wed Jul 1 22:28:18 2009 @@ -1 +1 @@ -/db/derby/code/trunk:772090,772449,772534,774281,779681,782991,785163,785570,785662,788369,788670,788674,788968 +/db/derby/code/trunk:772090,772449,772534,774281,779681,782991,785163,785570,785662,788369,788670,788674,788968,789264,790218 Modified: db/derby/code/branches/10.5/java/engine/org/apache/derby/impl/services/monitor/TopService.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.5/java/engine/org/apache/derby/impl/services/monitor/TopService.java?rev=790412&r1=790411&r2=790412&view=diff ============================================================================== --- db/derby/code/branches/10.5/java/engine/org/apache/derby/impl/services/monitor/TopService.java (original) +++ db/derby/code/branches/10.5/java/engine/org/apache/derby/impl/services/monitor/TopService.java Wed Jul 1 22:28:18 2009 @@ -102,14 +102,11 @@ void setTopModule(Object instance) { synchronized (this) { - for (int i = 0; i < moduleInstances.size(); i++) { - ModuleInstance module = (ModuleInstance) moduleInstances.elementAt(i); - if (module.getInstance() == instance) { - topModule = module; - notifyAll(); - break; - } - } + ModuleInstance module = findModuleInstance(instance); + if (module != null) { + topModule = module; + notifyAll(); + } // now add an additional entry into the hashtable // that maps the server name as seen by the user @@ -223,6 +220,29 @@ return null; } + /** + * Find a {@code ModuleInstance} object whose {@code getInstance()} method + * returns the object specified by the {@code instance} parameter. + * + * @param instance the instance to look for + * @return a {@code ModuleInstance} object, or {@code null} if no match + * was found + */ + private ModuleInstance findModuleInstance(Object instance) { + // DERBY-4018: Need to hold the synchronization over the entire loop + // to prevent concurrent modifications from causing an + // ArrayIndexOutOfBoundsException. + synchronized (moduleInstances) { + for (int i = 0; i < moduleInstances.size(); i++) { + ModuleInstance module = (ModuleInstance) moduleInstances.get(i); + if (module.getInstance() == instance) { + return module; + } + } + } + return null; + } + /** Boot a module, performs three steps. @@ -252,8 +272,20 @@ // see if a running implementation will handle this protocol synchronized (this) { - for (int i = 0; i < moduleInstances.size(); i++) { - ModuleInstance module = (ModuleInstance) moduleInstances.elementAt(i); + for (int i = 0;; i++) { + final ModuleInstance module; + + // DERBY-4018: Synchronized block in order to close the window + // between size() and elementAt() where the size may change + // and result in an ArrayIndexOutOfBoundsException. + synchronized (moduleInstances) { + if (i < moduleInstances.size()) { + module = (ModuleInstance) moduleInstances.elementAt(i); + } else { + // No more instances to look at, break out of the loop. + break; + } + } // DERBY-2074: The module has not been properly booted, so we // cannot yet determine whether or not this is a module we can @@ -394,14 +426,7 @@ } boolean inService(Object instance) { - - for (int i = 0; i < moduleInstances.size(); i++) { - - ModuleInstance mi = (ModuleInstance) moduleInstances.elementAt(i); - if (mi.getInstance() == instance) - return true; - } - return false; + return findModuleInstance(instance) != null; } public ProtocolKey getKey() {