SOLR-4595: CachingDirectoryFactory#close can throw a concurrent modification exception.

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1457292 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Mark Robert Miller 2013-03-16 19:01:11 +00:00
parent 681f24ca8a
commit c216ff7d82
3 changed files with 30 additions and 3 deletions

View File

@ -137,6 +137,9 @@ Bug Fixes
* SOLR-4573: Accessing Admin UI files in SolrCloud mode logs warnings.
(Mark Miller, Phil John)
* SOLR-4595: CachingDirectoryFactory#close can throw a concurrent
modification exception. (Mark Miller)
Optimizations
----------------------

View File

@ -20,6 +20,7 @@ package org.apache.solr.core;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
@ -123,7 +124,9 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory {
public void close() throws IOException {
synchronized (this) {
this.closed = true;
for (CacheValue val : byDirectoryCache.values()) {
Collection<CacheValue> values = new ArrayList<CacheValue>();
values.addAll(byDirectoryCache.values());
for (CacheValue val : values) {
try {
// if there are still refs out, we have to wait for them
int cnt = 0;
@ -135,7 +138,15 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory {
break;
}
}
assert val.refCnt == 0 : val.refCnt;
} catch (Throwable t) {
SolrException.log(log, "Error closing directory", t);
}
}
values = byDirectoryCache.values();
for (CacheValue val : values) {
try {
assert val.refCnt == 0 : val.refCnt;
log.info("Closing directory when closing factory: " + val.path);
closeDirectory(val);
@ -143,6 +154,7 @@ public abstract class CachingDirectoryFactory extends DirectoryFactory {
SolrException.log(log, "Error closing directory", t);
}
}
byDirectoryCache.clear();
byPathCache.clear();
}

View File

@ -73,6 +73,17 @@ public class CachingDirectoryFactoryTest extends SolrTestCaseJ4 {
thread.join();
}
Thread thread = new Thread() {
public void run() {
try {
df.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
};
thread.start();
// do any remaining releases
synchronized (dirs) {
int sz = dirs.size();
@ -98,7 +109,8 @@ public class CachingDirectoryFactoryTest extends SolrTestCaseJ4 {
}
df.close();
thread.join();
}
private class ReleaseDirThread extends Thread {