Author: aadamchik Date: Fri Jun 16 07:37:38 2006 New Revision: 414839 URL: http://svn.apache.org/viewvc?rev=414839&view=rev Log: IncrementalFaultList deadlock fix.
When connection pool size is less than the number of concurrent requests, doing commit and filling in IncrementalFaultList in parallel eventually causes a deadlock. IncrementalFaultList is holding an open connection and trying to get a lock on DataRowStore, while a committing thread that locked DataRowStore can's get a connection, cause the pool is empty. (I can't log in to Jira due to Apache network problems; I will enter the bug once this is resolved) Modified: incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/IncrementalFaultList.java Modified: incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/IncrementalFaultList.java URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/IncrementalFaultList.java?rev=414839&r1=414838&r2=414839&view=diff ============================================================================== --- incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/IncrementalFaultList.java (original) +++ incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/IncrementalFaultList.java Fri Jun 16 07:37:38 2006 @@ -221,6 +221,7 @@ rowWidth = 0; try { + int lastResolved = 0; long t1 = System.currentTimeMillis(); ResultIterator it = dataContext.performIteratedQuery(query); try { @@ -230,20 +231,12 @@ // resolve first page if we can if (resolvesFirstPage()) { // read first page completely, the rest as ObjectIds - List firstPage = (fetchesDataRows) ? elements : new ArrayList( - pageSize); for (int i = 0; i < pageSize && it.hasNextRow(); i++) { - firstPage.add(it.nextDataRow()); + elements.add(it.nextDataRow()); + lastResolved++; } - // convert rows to objects - if (!fetchesDataRows) { - elements.addAll(dataContext.objectsFromDataRows( - rootEntity, - firstPage, - info.isRefreshingObjects(), - info.isResolvingInherited())); - } + // defer DataRows -> Objects conversion till we are completely done. } // continue reading ids @@ -255,10 +248,23 @@ QueryLogger.logSelectCount(elements.size(), System .currentTimeMillis() - t1); - } finally { it.close(); + } + + // fill in the first page AFTER the iterator was closed, otherwise we may + // cause an (unobvious) deadlock due to connection pool exhaustion + if (!fetchesDataRows && lastResolved > 0) { + List objects = dataContext.objectsFromDataRows( + rootEntity, + elements.subList(0, lastResolved), + info.isRefreshingObjects(), + info.isResolvingInherited()); + + for(int i = 0; i < lastResolved; i++) { + elements.set(i, objects.get(i)); + } } } catch (CayenneException e) {