mirror of https://github.com/apache/lucene.git
SOLR-2654: Directorys used by a SolrCore are now closed when they are no longer used.
SOLR-2654: The same Directory instance is now always used across a SolrCore so that it's easier to add other DirectoryFactory's without static caching hacks. git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1159378 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
277c674be0
commit
7354f8d9e8
|
@ -1180,8 +1180,6 @@ public class IndexWriter implements Closeable, TwoPhaseCommit {
|
||||||
|
|
||||||
/** Returns the Directory used by this index. */
|
/** Returns the Directory used by this index. */
|
||||||
public Directory getDirectory() {
|
public Directory getDirectory() {
|
||||||
// Pass false because the flush during closing calls getDirectory
|
|
||||||
ensureOpen(false);
|
|
||||||
return directory;
|
return directory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -229,6 +229,9 @@ Bug Fixes
|
||||||
|
|
||||||
* SOLR-2682: Remove addException() in SimpleFacet. FacetComponent no longer catches and embeds
|
* SOLR-2682: Remove addException() in SimpleFacet. FacetComponent no longer catches and embeds
|
||||||
exceptions occurred during facet processing, it throws HTTP 400 or 500 exceptions instead. (koji)
|
exceptions occurred during facet processing, it throws HTTP 400 or 500 exceptions instead. (koji)
|
||||||
|
|
||||||
|
* SOLR-2654: Directorys used by a SolrCore are now closed when they are no longer used.
|
||||||
|
(Mark Miller)
|
||||||
|
|
||||||
Other Changes
|
Other Changes
|
||||||
----------------------
|
----------------------
|
||||||
|
@ -293,7 +296,11 @@ Other Changes
|
||||||
|
|
||||||
* SOLR-2698: Enhance CoreAdmin STATUS command to return index size.
|
* SOLR-2698: Enhance CoreAdmin STATUS command to return index size.
|
||||||
(Yury Kats, hossman, Mark Miller)
|
(Yury Kats, hossman, Mark Miller)
|
||||||
|
|
||||||
|
* SOLR-2654: The same Directory instance is now always used across a SolrCore so that
|
||||||
|
it's easier to add other DirectoryFactory's without static caching hacks.
|
||||||
|
(Mark Miller)
|
||||||
|
|
||||||
Documentation
|
Documentation
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,221 @@
|
||||||
|
package org.apache.solr.core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.lucene.store.Directory;
|
||||||
|
import org.apache.lucene.store.NativeFSLockFactory;
|
||||||
|
import org.apache.lucene.store.NoLockFactory;
|
||||||
|
import org.apache.lucene.store.SimpleFSLockFactory;
|
||||||
|
import org.apache.lucene.store.SingleInstanceLockFactory;
|
||||||
|
import org.apache.solr.common.SolrException;
|
||||||
|
import org.apache.solr.common.util.NamedList;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link DirectoryFactory} impl base class for caching Directory instances
|
||||||
|
* per path. Most DirectoryFactory implementations will want to extend this
|
||||||
|
* class and simply implement {@link DirectoryFactory#create(String)}.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public abstract class CachingDirectoryFactory extends DirectoryFactory {
|
||||||
|
class CacheValue {
|
||||||
|
Directory directory;
|
||||||
|
int refCnt = 1;
|
||||||
|
public String path;
|
||||||
|
public boolean doneWithDir = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Logger log = LoggerFactory
|
||||||
|
.getLogger(CachingDirectoryFactory.class);
|
||||||
|
|
||||||
|
protected Map<String,CacheValue> byPathCache = new HashMap<String,CacheValue>();
|
||||||
|
|
||||||
|
protected Map<Directory,CacheValue> byDirectoryCache = new HashMap<Directory,CacheValue>();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see org.apache.solr.core.DirectoryFactory#close()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
synchronized (this) {
|
||||||
|
for (CacheValue val : byDirectoryCache.values()) {
|
||||||
|
val.directory.close();
|
||||||
|
}
|
||||||
|
byDirectoryCache.clear();
|
||||||
|
byPathCache.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void close(Directory directory) throws IOException {
|
||||||
|
synchronized (this) {
|
||||||
|
CacheValue cacheValue = byDirectoryCache.get(directory);
|
||||||
|
if (cacheValue == null) {
|
||||||
|
throw new IllegalArgumentException("Unknown directory: " + directory
|
||||||
|
+ " " + byDirectoryCache);
|
||||||
|
}
|
||||||
|
cacheValue.refCnt--;
|
||||||
|
if (cacheValue.refCnt == 0 && cacheValue.doneWithDir) {
|
||||||
|
directory.close();
|
||||||
|
byDirectoryCache.remove(directory);
|
||||||
|
byPathCache.remove(cacheValue.path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract Directory create(String path) throws IOException;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean exists(String path) {
|
||||||
|
// back compat behavior
|
||||||
|
File dirFile = new File(path);
|
||||||
|
return dirFile.canRead() && dirFile.list().length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see org.apache.solr.core.DirectoryFactory#get(java.lang.String,
|
||||||
|
* java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public final Directory get(String path, String rawLockType)
|
||||||
|
throws IOException {
|
||||||
|
return get(path, rawLockType, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see org.apache.solr.core.DirectoryFactory#get(java.lang.String,
|
||||||
|
* java.lang.String, boolean)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public final Directory get(String path, String rawLockType, boolean forceNew)
|
||||||
|
throws IOException {
|
||||||
|
String fullPath = new File(path).getAbsolutePath();
|
||||||
|
synchronized (this) {
|
||||||
|
CacheValue cacheValue = byPathCache.get(fullPath);
|
||||||
|
Directory directory = null;
|
||||||
|
if (cacheValue != null) {
|
||||||
|
directory = cacheValue.directory;
|
||||||
|
if (forceNew) {
|
||||||
|
cacheValue.doneWithDir = true;
|
||||||
|
if (cacheValue.refCnt == 0) {
|
||||||
|
close(cacheValue.directory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (directory == null || forceNew) {
|
||||||
|
directory = create(fullPath);
|
||||||
|
|
||||||
|
CacheValue newCacheValue = new CacheValue();
|
||||||
|
newCacheValue.directory = directory;
|
||||||
|
newCacheValue.path = fullPath;
|
||||||
|
|
||||||
|
injectLockFactory(directory, path, rawLockType);
|
||||||
|
|
||||||
|
byDirectoryCache.put(directory, newCacheValue);
|
||||||
|
byPathCache.put(fullPath, newCacheValue);
|
||||||
|
} else {
|
||||||
|
cacheValue.refCnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return directory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see
|
||||||
|
* org.apache.solr.core.DirectoryFactory#incRef(org.apache.lucene.store.Directory
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
public void incRef(Directory directory) {
|
||||||
|
synchronized (this) {
|
||||||
|
CacheValue cacheValue = byDirectoryCache.get(directory);
|
||||||
|
if (cacheValue == null) {
|
||||||
|
throw new IllegalArgumentException("Unknown directory: " + directory);
|
||||||
|
}
|
||||||
|
|
||||||
|
cacheValue.refCnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(NamedList args) {}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see
|
||||||
|
* org.apache.solr.core.DirectoryFactory#release(org.apache.lucene.store.Directory
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void release(Directory directory) throws IOException {
|
||||||
|
if (directory == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
close(directory);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param dir
|
||||||
|
* @param lockPath
|
||||||
|
* @param rawLockType
|
||||||
|
* @return
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private static Directory injectLockFactory(Directory dir, String lockPath,
|
||||||
|
String rawLockType) throws IOException {
|
||||||
|
if (null == rawLockType) {
|
||||||
|
// we default to "simple" for backwards compatibility
|
||||||
|
log.warn("No lockType configured for " + dir + " assuming 'simple'");
|
||||||
|
rawLockType = "simple";
|
||||||
|
}
|
||||||
|
final String lockType = rawLockType.toLowerCase(Locale.ENGLISH).trim();
|
||||||
|
|
||||||
|
if ("simple".equals(lockType)) {
|
||||||
|
// multiple SimpleFSLockFactory instances should be OK
|
||||||
|
dir.setLockFactory(new SimpleFSLockFactory(lockPath));
|
||||||
|
} else if ("native".equals(lockType)) {
|
||||||
|
dir.setLockFactory(new NativeFSLockFactory(lockPath));
|
||||||
|
} else if ("single".equals(lockType)) {
|
||||||
|
if (!(dir.getLockFactory() instanceof SingleInstanceLockFactory)) dir
|
||||||
|
.setLockFactory(new SingleInstanceLockFactory());
|
||||||
|
} else if ("none".equals(lockType)) {
|
||||||
|
// Recipe for disaster
|
||||||
|
log.error("CONFIGURATION WARNING: locks are disabled on " + dir);
|
||||||
|
dir.setLockFactory(NoLockFactory.getNoLockFactory());
|
||||||
|
} else {
|
||||||
|
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
|
||||||
|
"Unrecognized lockType: " + rawLockType);
|
||||||
|
}
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
package org.apache.solr.core;
|
package org.apache.solr.core;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
@ -16,33 +17,84 @@ package org.apache.solr.core;
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.apache.lucene.store.Directory;
|
import org.apache.lucene.store.Directory;
|
||||||
import org.apache.solr.common.util.NamedList;
|
|
||||||
import org.apache.solr.util.plugin.NamedListInitializedPlugin;
|
import org.apache.solr.util.plugin.NamedListInitializedPlugin;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides access to a Directory implementation.
|
* Provides access to a Directory implementation. You must release every
|
||||||
*
|
* Directory that you get.
|
||||||
*/
|
*/
|
||||||
public abstract class DirectoryFactory implements NamedListInitializedPlugin {
|
public abstract class DirectoryFactory implements NamedListInitializedPlugin,
|
||||||
|
Closeable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens a Lucene directory
|
* Close the this and all of the Directories it contains.
|
||||||
*
|
*
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public abstract Directory open(String path) throws IOException;
|
public abstract void close() throws IOException;
|
||||||
|
|
||||||
public boolean exists(String path) {
|
/**
|
||||||
// back compat behavior
|
* Creates a new Directory for a given path.
|
||||||
File dirFile = new File(path);
|
*
|
||||||
return dirFile.canRead();
|
* @param path
|
||||||
}
|
* @return
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
protected abstract Directory create(String path) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if a Directory exists for a given path.
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public abstract boolean exists(String path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Directory for a given path, using the specified rawLockType.
|
||||||
|
* Will return the same Directory instance for the same path.
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* @param rawLockType
|
||||||
|
* @return
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public abstract Directory get(String path, String rawLockType)
|
||||||
|
throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Directory for a given path, using the specified rawLockType.
|
||||||
|
* Will return the same Directory instance for the same path unless forceNew,
|
||||||
|
* in which case a new Directory is returned.
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* @param rawLockType
|
||||||
|
* @param forceNew
|
||||||
|
* @return
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public abstract Directory get(String path, String rawLockType,
|
||||||
|
boolean forceNew) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increment the number of references to the given Directory. You must call
|
||||||
|
* release for every call to this method.
|
||||||
|
*
|
||||||
|
* @param directory
|
||||||
|
*/
|
||||||
|
public abstract void incRef(Directory directory);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Releases the Directory so that it may be closed when it is no longer
|
||||||
|
* referenced.
|
||||||
|
*
|
||||||
|
* @param directory
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public abstract void release(Directory directory) throws IOException;
|
||||||
|
|
||||||
public void init(NamedList args) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,23 +38,11 @@ import java.io.IOException;
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
public class MMapDirectoryFactory extends DirectoryFactory {
|
public class MMapDirectoryFactory extends CachingDirectoryFactory {
|
||||||
private transient static Logger log = LoggerFactory.getLogger(MMapDirectoryFactory.class);
|
private transient static Logger log = LoggerFactory.getLogger(MMapDirectoryFactory.class);
|
||||||
boolean unmapHack;
|
boolean unmapHack;
|
||||||
private int maxChunk;
|
private int maxChunk;
|
||||||
|
|
||||||
@Override
|
|
||||||
public Directory open(String path) throws IOException {
|
|
||||||
MMapDirectory mapDirectory = new MMapDirectory(new File(path));
|
|
||||||
try {
|
|
||||||
mapDirectory.setUseUnmap(unmapHack);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn("Unmap not supported on this JVM, continuing on without setting unmap", e);
|
|
||||||
}
|
|
||||||
mapDirectory.setMaxChunkSize(maxChunk);
|
|
||||||
return mapDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(NamedList args) {
|
public void init(NamedList args) {
|
||||||
SolrParams params = SolrParams.toSolrParams( args );
|
SolrParams params = SolrParams.toSolrParams( args );
|
||||||
|
@ -64,4 +52,16 @@ public class MMapDirectoryFactory extends DirectoryFactory {
|
||||||
}
|
}
|
||||||
unmapHack = params.getBool("unmap", true);
|
unmapHack = params.getBool("unmap", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Directory create(String path) throws IOException {
|
||||||
|
MMapDirectory mapDirectory = new MMapDirectory(new File(path));
|
||||||
|
try {
|
||||||
|
mapDirectory.setUseUnmap(unmapHack);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("Unmap not supported on this JVM, continuing on without setting unmap", e);
|
||||||
|
}
|
||||||
|
mapDirectory.setMaxChunkSize(maxChunk);
|
||||||
|
return mapDirectory;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,11 @@ import java.io.IOException;
|
||||||
* Factory to instantiate {@link org.apache.lucene.store.NIOFSDirectory}
|
* Factory to instantiate {@link org.apache.lucene.store.NIOFSDirectory}
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
public class NIOFSDirectoryFactory extends DirectoryFactory {
|
public class NIOFSDirectoryFactory extends CachingDirectoryFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Directory open(String path) throws IOException {
|
protected Directory create(String path) throws IOException {
|
||||||
|
|
||||||
return new NIOFSDirectory(new File(path));
|
return new NIOFSDirectory(new File(path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,48 +17,21 @@
|
||||||
|
|
||||||
package org.apache.solr.core;
|
package org.apache.solr.core;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
import org.apache.lucene.store.Directory;
|
import org.apache.lucene.store.Directory;
|
||||||
import org.apache.lucene.store.IOContext;
|
import org.apache.lucene.store.FSDirectory;
|
||||||
import org.apache.lucene.store.RAMDirectory;
|
import org.apache.lucene.store.NRTCachingDirectory;
|
||||||
|
|
||||||
public class RefCntRamDirectory extends RAMDirectory {
|
/**
|
||||||
|
* Factory to instantiate {@link org.apache.lucene.store.NRTCachingDirectory}
|
||||||
private final AtomicInteger refCount = new AtomicInteger();
|
*/
|
||||||
|
public class NRTCachingDirectoryFactory extends StandardDirectoryFactory {
|
||||||
public RefCntRamDirectory() {
|
|
||||||
super();
|
|
||||||
refCount.set(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RefCntRamDirectory(Directory dir) throws IOException {
|
|
||||||
this();
|
|
||||||
for (String file : dir.listAll()) {
|
|
||||||
dir.copy(this, file, file, IOContext.DEFAULT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void incRef() {
|
|
||||||
ensureOpen();
|
|
||||||
refCount.incrementAndGet();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void decRef() {
|
|
||||||
ensureOpen();
|
|
||||||
if (refCount.getAndDecrement() == 1) {
|
|
||||||
super.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final synchronized void close() {
|
protected Directory create(String path) throws IOException {
|
||||||
decRef();
|
return new NRTCachingDirectory(FSDirectory.open(new File(path)), 4, 48);
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isOpen() {
|
|
||||||
return isOpen;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -19,37 +19,30 @@ package org.apache.solr.core;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.lucene.store.Directory;
|
import org.apache.lucene.store.Directory;
|
||||||
|
import org.apache.lucene.store.RAMDirectory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Directory provider for using lucene RAMDirectory
|
* Factory to instantiate {@link org.apache.lucene.store.RAMDirectory}
|
||||||
*/
|
*/
|
||||||
public class RAMDirectoryFactory extends StandardDirectoryFactory {
|
public class RAMDirectoryFactory extends StandardDirectoryFactory {
|
||||||
private static Map<String, RefCntRamDirectory> directories = new HashMap<String, RefCntRamDirectory>();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Directory open(String path) throws IOException {
|
protected Directory create(String path) throws IOException {
|
||||||
synchronized (RAMDirectoryFactory.class) {
|
return new RAMDirectory();
|
||||||
RefCntRamDirectory directory = directories.get(path);
|
|
||||||
if (directory == null || !directory.isOpen()) {
|
|
||||||
directory = (RefCntRamDirectory) openNew(path);
|
|
||||||
directories.put(path, directory);
|
|
||||||
} else {
|
|
||||||
directory.incRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
return directory;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean exists(String path) {
|
public boolean exists(String path) {
|
||||||
synchronized (RAMDirectoryFactory.class) {
|
String fullPath = new File(path).getAbsolutePath();
|
||||||
RefCntRamDirectory directory = directories.get(path);
|
synchronized (DirectoryFactory.class) {
|
||||||
if (directory == null || !directory.isOpen()) {
|
CacheValue cacheValue = byPathCache.get(fullPath);
|
||||||
|
Directory directory = null;
|
||||||
|
if (cacheValue != null) {
|
||||||
|
directory = cacheValue.directory;
|
||||||
|
}
|
||||||
|
if (directory == null) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
|
@ -57,19 +50,4 @@ public class RAMDirectoryFactory extends StandardDirectoryFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Non-public for unit-test access only. Do not use directly
|
|
||||||
*/
|
|
||||||
Directory openNew(String path) throws IOException {
|
|
||||||
Directory directory;
|
|
||||||
File dirFile = new File(path);
|
|
||||||
boolean indexExists = dirFile.canRead();
|
|
||||||
if (indexExists) {
|
|
||||||
Directory dir = super.open(path);
|
|
||||||
directory = new RefCntRamDirectory(dir);
|
|
||||||
} else {
|
|
||||||
directory = new RefCntRamDirectory();
|
|
||||||
}
|
|
||||||
return directory;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,10 @@ import java.io.IOException;
|
||||||
* Factory to instantiate {@link org.apache.lucene.store.SimpleFSDirectory}
|
* Factory to instantiate {@link org.apache.lucene.store.SimpleFSDirectory}
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
public class SimpleFSDirectoryFactory extends DirectoryFactory {
|
public class SimpleFSDirectoryFactory extends CachingDirectoryFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Directory open(String path) throws IOException {
|
protected Directory create(String path) throws IOException {
|
||||||
return new SimpleFSDirectory(new File(path));
|
return new SimpleFSDirectory(new File(path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -320,7 +320,7 @@ public final class SolrCore implements SolrInfoMBean {
|
||||||
|
|
||||||
// gets a non-caching searcher
|
// gets a non-caching searcher
|
||||||
public SolrIndexSearcher newSearcher(String name, boolean readOnly) throws IOException {
|
public SolrIndexSearcher newSearcher(String name, boolean readOnly) throws IOException {
|
||||||
return new SolrIndexSearcher(this, schema, name, directoryFactory.open(getIndexDir()), readOnly, false);
|
return new SolrIndexSearcher(this, getNewIndexDir(), schema, getSolrConfig().mainIndexConfig, name, readOnly, false, directoryFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -355,7 +355,6 @@ public final class SolrCore implements SolrInfoMBean {
|
||||||
|
|
||||||
void initIndex() {
|
void initIndex() {
|
||||||
try {
|
try {
|
||||||
initDirectoryFactory();
|
|
||||||
String indexDir = getNewIndexDir();
|
String indexDir = getNewIndexDir();
|
||||||
boolean indexExists = getDirectoryFactory().exists(indexDir);
|
boolean indexExists = getDirectoryFactory().exists(indexDir);
|
||||||
boolean firstTime;
|
boolean firstTime;
|
||||||
|
@ -369,13 +368,13 @@ public final class SolrCore implements SolrInfoMBean {
|
||||||
if (indexExists && firstTime && removeLocks) {
|
if (indexExists && firstTime && removeLocks) {
|
||||||
// to remove locks, the directory must already exist... so we create it
|
// to remove locks, the directory must already exist... so we create it
|
||||||
// if it didn't exist already...
|
// if it didn't exist already...
|
||||||
Directory dir = SolrIndexWriter.getDirectory(indexDir, getDirectoryFactory(), solrConfig.mainIndexConfig);
|
Directory dir = directoryFactory.get(indexDir, getSolrConfig().mainIndexConfig.lockType);
|
||||||
if (dir != null) {
|
if (dir != null) {
|
||||||
if (IndexWriter.isLocked(dir)) {
|
if (IndexWriter.isLocked(dir)) {
|
||||||
log.warn(logid+"WARNING: Solr index directory '" + indexDir+ "' is locked. Unlocking...");
|
log.warn(logid+"WARNING: Solr index directory '" + indexDir+ "' is locked. Unlocking...");
|
||||||
IndexWriter.unlock(dir);
|
IndexWriter.unlock(dir);
|
||||||
}
|
}
|
||||||
dir.close();
|
directoryFactory.release(dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,7 +383,7 @@ public final class SolrCore implements SolrInfoMBean {
|
||||||
log.warn(logid+"Solr index directory '" + new File(indexDir) + "' doesn't exist."
|
log.warn(logid+"Solr index directory '" + new File(indexDir) + "' doesn't exist."
|
||||||
+ " Creating new index...");
|
+ " Creating new index...");
|
||||||
|
|
||||||
SolrIndexWriter writer = new SolrIndexWriter("SolrCore.initIndex", indexDir, getDirectoryFactory(), true, schema, solrConfig.mainIndexConfig, solrDelPolicy, codecProvider);
|
SolrIndexWriter writer = new SolrIndexWriter("SolrCore.initIndex", indexDir, getDirectoryFactory(), true, schema, solrConfig.mainIndexConfig, solrDelPolicy, codecProvider, false);
|
||||||
writer.close();
|
writer.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -490,20 +489,18 @@ public final class SolrCore implements SolrInfoMBean {
|
||||||
* @since solr 1.0
|
* @since solr 1.0
|
||||||
*/
|
*/
|
||||||
public SolrCore(String dataDir, IndexSchema schema) throws ParserConfigurationException, IOException, SAXException {
|
public SolrCore(String dataDir, IndexSchema schema) throws ParserConfigurationException, IOException, SAXException {
|
||||||
this(null, dataDir, new SolrConfig(), schema, null );
|
this(null, dataDir, new SolrConfig(), schema, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new core and register it in the list of cores.
|
* Creates a new core and register it in the list of cores.
|
||||||
* If a core with the same name already exists, it will be stopped and replaced by this one.
|
* If a core with the same name already exists, it will be stopped and replaced by this one.
|
||||||
*
|
*@param dataDir the index directory
|
||||||
* @param name
|
*@param config a solr config instance
|
||||||
* @param dataDir the index directory
|
*@param schema a solr schema instance
|
||||||
* @param config a solr config instance
|
*@param updateHandler
|
||||||
* @param schema a solr schema instance
|
*
|
||||||
* @param cd
|
*@since solr 1.3
|
||||||
*
|
|
||||||
* @since solr 1.3
|
|
||||||
*/
|
*/
|
||||||
public SolrCore(String name, String dataDir, SolrConfig config, IndexSchema schema, CoreDescriptor cd) {
|
public SolrCore(String name, String dataDir, SolrConfig config, IndexSchema schema, CoreDescriptor cd) {
|
||||||
this(name, dataDir, config, schema, cd, null);
|
this(name, dataDir, config, schema, cd, null);
|
||||||
|
@ -559,6 +556,13 @@ public final class SolrCore implements SolrInfoMBean {
|
||||||
initDeletionPolicy();
|
initDeletionPolicy();
|
||||||
|
|
||||||
this.codecProvider = initCodecProvider(solrConfig, schema);
|
this.codecProvider = initCodecProvider(solrConfig, schema);
|
||||||
|
|
||||||
|
if (updateHandler == null) {
|
||||||
|
initDirectoryFactory();
|
||||||
|
} else {
|
||||||
|
directoryFactory = updateHandler.getIndexWriterProvider().getDirectoryFactory();
|
||||||
|
}
|
||||||
|
|
||||||
initIndex();
|
initIndex();
|
||||||
|
|
||||||
initWriters();
|
initWriters();
|
||||||
|
@ -601,7 +605,6 @@ public final class SolrCore implements SolrInfoMBean {
|
||||||
this.updateHandler = createUpdateHandler(updateHandlerClass == null ? DirectUpdateHandler2.class
|
this.updateHandler = createUpdateHandler(updateHandlerClass == null ? DirectUpdateHandler2.class
|
||||||
.getName() : updateHandlerClass);
|
.getName() : updateHandlerClass);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
this.updateHandler = createUpdateHandler(
|
this.updateHandler = createUpdateHandler(
|
||||||
updateHandlerClass == null ? DirectUpdateHandler2.class.getName()
|
updateHandlerClass == null ? DirectUpdateHandler2.class.getName()
|
||||||
: updateHandlerClass, updateHandler);
|
: updateHandlerClass, updateHandler);
|
||||||
|
@ -737,11 +740,7 @@ public final class SolrCore implements SolrInfoMBean {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
SolrException.log(log, e);
|
SolrException.log(log, e);
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
updateHandler.close();
|
|
||||||
} catch (Exception e) {
|
|
||||||
SolrException.log(log,e);
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
searcherExecutor.shutdown();
|
searcherExecutor.shutdown();
|
||||||
if (!searcherExecutor.awaitTermination(60, TimeUnit.SECONDS)) {
|
if (!searcherExecutor.awaitTermination(60, TimeUnit.SECONDS)) {
|
||||||
|
@ -763,6 +762,12 @@ public final class SolrCore implements SolrInfoMBean {
|
||||||
SolrException.log(log,e);
|
SolrException.log(log,e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
updateHandler.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
SolrException.log(log,e);
|
||||||
|
}
|
||||||
|
|
||||||
if( closeHooks != null ) {
|
if( closeHooks != null ) {
|
||||||
for( CloseHook hook : closeHooks ) {
|
for( CloseHook hook : closeHooks ) {
|
||||||
try {
|
try {
|
||||||
|
@ -1114,12 +1119,11 @@ public final class SolrCore implements SolrInfoMBean {
|
||||||
currentReader.incRef();
|
currentReader.incRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = new SolrIndexSearcher(this, schema, "main", newReader, true, true);
|
tmp = new SolrIndexSearcher(this, schema, "main", newReader, true, true, true, directoryFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
IndexReader reader = getIndexReaderFactory().newReader(getDirectoryFactory().open(newIndexDir), true);
|
tmp = new SolrIndexSearcher(this, newIndexDir, schema, getSolrConfig().mainIndexConfig, "main", true, true, directoryFactory);
|
||||||
tmp = new SolrIndexSearcher(this, schema, "main", reader, true, true);
|
|
||||||
}
|
}
|
||||||
} catch (Throwable th) {
|
} catch (Throwable th) {
|
||||||
synchronized(searcherLock) {
|
synchronized(searcherLock) {
|
||||||
|
|
|
@ -23,13 +23,14 @@ import org.apache.lucene.store.Directory;
|
||||||
import org.apache.lucene.store.FSDirectory;
|
import org.apache.lucene.store.FSDirectory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Directory provider which mimics original Solr FSDirectory based behavior.
|
* Directory provider which mimics original Solr
|
||||||
|
* {@link org.apache.lucene.store.FSDirectory} based behavior.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class StandardDirectoryFactory extends DirectoryFactory {
|
public class StandardDirectoryFactory extends CachingDirectoryFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Directory open(String path) throws IOException {
|
protected Directory create(String path) throws IOException {
|
||||||
return FSDirectory.open(new File(path));
|
return FSDirectory.open(new File(path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ package org.apache.solr.handler.admin;
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.lucene.index.IndexReader;
|
import org.apache.lucene.index.IndexReader;
|
||||||
|
import org.apache.lucene.store.Directory;
|
||||||
import org.apache.lucene.util.IOUtils;
|
import org.apache.lucene.util.IOUtils;
|
||||||
import org.apache.solr.cloud.CloudDescriptor;
|
import org.apache.solr.cloud.CloudDescriptor;
|
||||||
import org.apache.solr.common.SolrException;
|
import org.apache.solr.common.SolrException;
|
||||||
|
@ -183,6 +184,7 @@ public class CoreAdminHandler extends RequestHandlerBase {
|
||||||
RefCounted<SolrIndexSearcher>[] searchers = null;
|
RefCounted<SolrIndexSearcher>[] searchers = null;
|
||||||
// stores readers created from indexDir param values
|
// stores readers created from indexDir param values
|
||||||
IndexReader[] readersToBeClosed = null;
|
IndexReader[] readersToBeClosed = null;
|
||||||
|
Directory[] dirsToBeReleased = null;
|
||||||
if (core != null) {
|
if (core != null) {
|
||||||
try {
|
try {
|
||||||
String[] dirNames = params.getParams(CoreAdminParams.INDEX_DIR);
|
String[] dirNames = params.getParams(CoreAdminParams.INDEX_DIR);
|
||||||
|
@ -203,9 +205,12 @@ public class CoreAdminHandler extends RequestHandlerBase {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
readersToBeClosed = new IndexReader[dirNames.length];
|
readersToBeClosed = new IndexReader[dirNames.length];
|
||||||
|
dirsToBeReleased = new Directory[dirNames.length];
|
||||||
DirectoryFactory dirFactory = core.getDirectoryFactory();
|
DirectoryFactory dirFactory = core.getDirectoryFactory();
|
||||||
for (int i = 0; i < dirNames.length; i++) {
|
for (int i = 0; i < dirNames.length; i++) {
|
||||||
readersToBeClosed[i] = IndexReader.open(dirFactory.open(dirNames[i]), true);
|
Directory dir = dirFactory.get(dirNames[i], core.getSolrConfig().mainIndexConfig.lockType);
|
||||||
|
dirsToBeReleased[i] = dir;
|
||||||
|
readersToBeClosed[i] = IndexReader.open(dir, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,6 +246,12 @@ public class CoreAdminHandler extends RequestHandlerBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (readersToBeClosed != null) IOUtils.closeSafely(true, readersToBeClosed);
|
if (readersToBeClosed != null) IOUtils.closeSafely(true, readersToBeClosed);
|
||||||
|
if (dirsToBeReleased != null) {
|
||||||
|
for (Directory dir : dirsToBeReleased) {
|
||||||
|
DirectoryFactory dirFactory = core.getDirectoryFactory();
|
||||||
|
dirFactory.release(dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (wrappedReq != null) wrappedReq.close();
|
if (wrappedReq != null) wrappedReq.close();
|
||||||
core.close();
|
core.close();
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,12 +17,51 @@
|
||||||
|
|
||||||
package org.apache.solr.search;
|
package org.apache.solr.search;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
import org.apache.lucene.document.Document;
|
import org.apache.lucene.document.Document;
|
||||||
import org.apache.lucene.document.FieldSelector;
|
import org.apache.lucene.document.FieldSelector;
|
||||||
import org.apache.lucene.document.FieldSelectorResult;
|
import org.apache.lucene.document.FieldSelectorResult;
|
||||||
import org.apache.lucene.index.*;
|
import org.apache.lucene.index.DocsEnum;
|
||||||
|
import org.apache.lucene.index.Fields;
|
||||||
|
import org.apache.lucene.index.IndexReader;
|
||||||
import org.apache.lucene.index.IndexReader.AtomicReaderContext;
|
import org.apache.lucene.index.IndexReader.AtomicReaderContext;
|
||||||
import org.apache.lucene.search.*;
|
import org.apache.lucene.index.MultiDocsEnum;
|
||||||
|
import org.apache.lucene.index.MultiFields;
|
||||||
|
import org.apache.lucene.index.Term;
|
||||||
|
import org.apache.lucene.index.Terms;
|
||||||
|
import org.apache.lucene.index.TermsEnum;
|
||||||
|
import org.apache.lucene.search.Collector;
|
||||||
|
import org.apache.lucene.search.DocIdSet;
|
||||||
|
import org.apache.lucene.search.DocIdSetIterator;
|
||||||
|
import org.apache.lucene.search.Explanation;
|
||||||
|
import org.apache.lucene.search.Filter;
|
||||||
|
import org.apache.lucene.search.IndexSearcher;
|
||||||
|
import org.apache.lucene.search.MatchAllDocsQuery;
|
||||||
|
import org.apache.lucene.search.Query;
|
||||||
|
import org.apache.lucene.search.ScoreDoc;
|
||||||
|
import org.apache.lucene.search.Scorer;
|
||||||
|
import org.apache.lucene.search.Sort;
|
||||||
|
import org.apache.lucene.search.SortField;
|
||||||
|
import org.apache.lucene.search.TermQuery;
|
||||||
|
import org.apache.lucene.search.TimeLimitingCollector;
|
||||||
|
import org.apache.lucene.search.TopDocs;
|
||||||
|
import org.apache.lucene.search.TopDocsCollector;
|
||||||
|
import org.apache.lucene.search.TopFieldCollector;
|
||||||
|
import org.apache.lucene.search.TopScoreDocCollector;
|
||||||
|
import org.apache.lucene.search.Weight;
|
||||||
import org.apache.lucene.store.Directory;
|
import org.apache.lucene.store.Directory;
|
||||||
import org.apache.lucene.store.FSDirectory;
|
import org.apache.lucene.store.FSDirectory;
|
||||||
import org.apache.lucene.util.Bits;
|
import org.apache.lucene.util.Bits;
|
||||||
|
@ -31,6 +70,7 @@ import org.apache.lucene.util.OpenBitSet;
|
||||||
import org.apache.solr.common.params.ModifiableSolrParams;
|
import org.apache.solr.common.params.ModifiableSolrParams;
|
||||||
import org.apache.solr.common.util.NamedList;
|
import org.apache.solr.common.util.NamedList;
|
||||||
import org.apache.solr.common.util.SimpleOrderedMap;
|
import org.apache.solr.common.util.SimpleOrderedMap;
|
||||||
|
import org.apache.solr.core.DirectoryFactory;
|
||||||
import org.apache.solr.core.SolrConfig;
|
import org.apache.solr.core.SolrConfig;
|
||||||
import org.apache.solr.core.SolrCore;
|
import org.apache.solr.core.SolrCore;
|
||||||
import org.apache.solr.core.SolrInfoMBean;
|
import org.apache.solr.core.SolrInfoMBean;
|
||||||
|
@ -41,14 +81,10 @@ import org.apache.solr.request.UnInvertedField;
|
||||||
import org.apache.solr.response.SolrQueryResponse;
|
import org.apache.solr.response.SolrQueryResponse;
|
||||||
import org.apache.solr.schema.IndexSchema;
|
import org.apache.solr.schema.IndexSchema;
|
||||||
import org.apache.solr.schema.SchemaField;
|
import org.apache.solr.schema.SchemaField;
|
||||||
|
import org.apache.solr.update.SolrIndexConfig;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SolrIndexSearcher adds schema awareness and caching functionality
|
* SolrIndexSearcher adds schema awareness and caching functionality
|
||||||
|
@ -99,40 +135,31 @@ public class SolrIndexSearcher extends IndexSearcher implements SolrInfoMBean {
|
||||||
|
|
||||||
private final Collection<String> fieldNames;
|
private final Collection<String> fieldNames;
|
||||||
private Collection<String> storedHighlightFieldNames;
|
private Collection<String> storedHighlightFieldNames;
|
||||||
|
private DirectoryFactory directoryFactory;
|
||||||
|
|
||||||
/*
|
|
||||||
* Creates a searcher searching the index in the provided directory. Note:
|
|
||||||
* uses the main IndexReaderFactory for the specified SolrCore.
|
|
||||||
*
|
|
||||||
* @see SolrCore#getMainIndexReaderFactory
|
|
||||||
*/
|
|
||||||
public SolrIndexSearcher(SolrCore core, IndexSchema schema, String name,
|
|
||||||
Directory directory, boolean enableCache) throws IOException {
|
|
||||||
this(core, schema,name, core.getIndexReaderFactory().newReader(directory, false), true, enableCache);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Creates a searcher searching the index in the provided directory. */
|
public SolrIndexSearcher(SolrCore core, String path, IndexSchema schema, SolrIndexConfig config, String name, boolean readOnly, boolean enableCache, DirectoryFactory directoryFactory) throws IOException {
|
||||||
public SolrIndexSearcher(SolrCore core, IndexSchema schema, String name, Directory directory, boolean readOnly, boolean enableCache) throws IOException {
|
// we don't need to reserve the directory because we get it from the factory
|
||||||
this(core, schema,name, core.getIndexReaderFactory().newReader(directory, readOnly), true, enableCache);
|
this(core, schema,name, core.getIndexReaderFactory().newReader(directoryFactory.get(path, config.lockType), readOnly), true, enableCache, false, directoryFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Creates a searcher searching the provided index. */
|
public SolrIndexSearcher(SolrCore core, IndexSchema schema, String name, IndexReader r, boolean closeReader, boolean enableCache, boolean reserveDirectory, DirectoryFactory directoryFactory) {
|
||||||
public SolrIndexSearcher(SolrCore core, IndexSchema schema, String name, IndexReader r, boolean enableCache) {
|
|
||||||
this(core, schema,name,r, false, enableCache);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public SolrIndexSearcher(SolrCore core, IndexSchema schema, String name, IndexReader r, boolean closeReader, boolean enableCache) {
|
|
||||||
super(r);
|
super(r);
|
||||||
|
this.directoryFactory = directoryFactory;
|
||||||
this.reader = getIndexReader();
|
this.reader = getIndexReader();
|
||||||
this.core = core;
|
this.core = core;
|
||||||
this.schema = schema;
|
this.schema = schema;
|
||||||
this.name = "Searcher@" + Integer.toHexString(hashCode()) + (name!=null ? " "+name : "");
|
this.name = "Searcher@" + Integer.toHexString(hashCode()) + (name!=null ? " "+name : "");
|
||||||
log.info("Opening " + this.name);
|
log.info("Opening " + this.name);
|
||||||
|
|
||||||
if (r.directory() instanceof FSDirectory) {
|
Directory dir = r.directory();
|
||||||
FSDirectory fsDirectory = (FSDirectory) r.directory();
|
|
||||||
|
if (reserveDirectory) {
|
||||||
|
// keep the directory from being released while we use it
|
||||||
|
directoryFactory.incRef(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dir instanceof FSDirectory) {
|
||||||
|
FSDirectory fsDirectory = (FSDirectory) dir;
|
||||||
indexDir = fsDirectory.getDirectory().getAbsolutePath();
|
indexDir = fsDirectory.getDirectory().getAbsolutePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,7 +215,6 @@ public class SolrIndexSearcher extends IndexSearcher implements SolrInfoMBean {
|
||||||
numOpens.incrementAndGet();
|
numOpens.incrementAndGet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return name;
|
return name;
|
||||||
|
@ -241,6 +267,10 @@ public class SolrIndexSearcher extends IndexSearcher implements SolrInfoMBean {
|
||||||
cache.close();
|
cache.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
directoryFactory.release(getIndexReader().directory());
|
||||||
|
|
||||||
|
|
||||||
// do this at the end so it only gets done if there are no exceptions
|
// do this at the end so it only gets done if there are no exceptions
|
||||||
numCloses.incrementAndGet();
|
numCloses.incrementAndGet();
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@ final class CommitTracker implements Runnable {
|
||||||
pending.cancel(true);
|
pending.cancel(true);
|
||||||
pending = null;
|
pending = null;
|
||||||
}
|
}
|
||||||
scheduler.shutdown();
|
scheduler.shutdownNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** schedule individual commits */
|
/** schedule individual commits */
|
||||||
|
|
|
@ -20,20 +20,22 @@ package org.apache.solr.update;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.apache.lucene.index.IndexWriter;
|
import org.apache.lucene.index.IndexWriter;
|
||||||
|
import org.apache.solr.core.DirectoryFactory;
|
||||||
import org.apache.solr.core.SolrCore;
|
import org.apache.solr.core.SolrCore;
|
||||||
|
|
||||||
public final class DefaultIndexWriterProvider implements IndexWriterProvider {
|
public final class DefaultSolrCoreState extends SolrCoreState {
|
||||||
private int refCnt = 1;
|
private int refCnt = 1;
|
||||||
private IndexWriter indexWriter = null;
|
private SolrIndexWriter indexWriter = null;
|
||||||
|
private DirectoryFactory directoryFactory;
|
||||||
public DefaultIndexWriterProvider() {
|
|
||||||
|
|
||||||
|
public DefaultSolrCoreState(DirectoryFactory directoryFactory) {
|
||||||
|
this.directoryFactory = directoryFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized IndexWriter getIndexWriter(SolrCore core) throws IOException {
|
public synchronized IndexWriter getIndexWriter(SolrCore core) throws IOException {
|
||||||
if (indexWriter == null) {
|
if (indexWriter == null) {
|
||||||
indexWriter = createMainIndexWriter(core, "DirectUpdateHandler2", false);
|
indexWriter = createMainIndexWriter(core, "DirectUpdateHandler2", false, false);
|
||||||
}
|
}
|
||||||
return indexWriter;
|
return indexWriter;
|
||||||
}
|
}
|
||||||
|
@ -44,14 +46,17 @@ public final class DefaultIndexWriterProvider implements IndexWriterProvider {
|
||||||
indexWriter.close();
|
indexWriter.close();
|
||||||
}
|
}
|
||||||
indexWriter = createMainIndexWriter(core, "DirectUpdateHandler2",
|
indexWriter = createMainIndexWriter(core, "DirectUpdateHandler2",
|
||||||
false);
|
false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void decref() throws IOException {
|
public synchronized void decref() throws IOException {
|
||||||
refCnt--;
|
refCnt--;
|
||||||
if (refCnt == 0 && indexWriter != null) {
|
if (refCnt == 0) {
|
||||||
indexWriter.close();
|
if (indexWriter != null) {
|
||||||
|
indexWriter.close();
|
||||||
|
}
|
||||||
|
directoryFactory.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,10 +75,15 @@ public final class DefaultIndexWriterProvider implements IndexWriterProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SolrIndexWriter createMainIndexWriter(SolrCore core, String name,
|
protected SolrIndexWriter createMainIndexWriter(SolrCore core, String name,
|
||||||
boolean removeAllExisting) throws IOException {
|
boolean removeAllExisting, boolean forceNewDirectory) throws IOException {
|
||||||
return new SolrIndexWriter(name, core.getNewIndexDir(),
|
return new SolrIndexWriter(name, core.getNewIndexDir(),
|
||||||
core.getDirectoryFactory(), removeAllExisting, core.getSchema(),
|
core.getDirectoryFactory(), removeAllExisting, core.getSchema(),
|
||||||
core.getSolrConfig().mainIndexConfig, core.getDeletionPolicy(), core.getCodecProvider());
|
core.getSolrConfig().mainIndexConfig, core.getDeletionPolicy(), core.getCodecProvider(), forceNewDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DirectoryFactory getDirectoryFactory() {
|
||||||
|
return directoryFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -52,7 +52,7 @@ import org.apache.solr.search.SolrIndexSearcher;
|
||||||
* directly to the main Lucene index as opposed to adding to a separate smaller index.
|
* directly to the main Lucene index as opposed to adding to a separate smaller index.
|
||||||
*/
|
*/
|
||||||
public class DirectUpdateHandler2 extends UpdateHandler {
|
public class DirectUpdateHandler2 extends UpdateHandler {
|
||||||
protected IndexWriterProvider indexWriterProvider;
|
protected SolrCoreState indexWriterProvider;
|
||||||
|
|
||||||
// stats
|
// stats
|
||||||
AtomicLong addCommands = new AtomicLong();
|
AtomicLong addCommands = new AtomicLong();
|
||||||
|
@ -77,7 +77,7 @@ public class DirectUpdateHandler2 extends UpdateHandler {
|
||||||
public DirectUpdateHandler2(SolrCore core) throws IOException {
|
public DirectUpdateHandler2(SolrCore core) throws IOException {
|
||||||
super(core);
|
super(core);
|
||||||
|
|
||||||
indexWriterProvider = new DefaultIndexWriterProvider();
|
indexWriterProvider = new DefaultSolrCoreState(core.getDirectoryFactory());
|
||||||
|
|
||||||
UpdateHandlerInfo updateHandlerInfo = core.getSolrConfig()
|
UpdateHandlerInfo updateHandlerInfo = core.getSolrConfig()
|
||||||
.getUpdateHandlerInfo();
|
.getUpdateHandlerInfo();
|
||||||
|
@ -97,7 +97,7 @@ public class DirectUpdateHandler2 extends UpdateHandler {
|
||||||
} else {
|
} else {
|
||||||
// the impl has changed, so we cannot use the old state - decref it
|
// the impl has changed, so we cannot use the old state - decref it
|
||||||
updateHandler.decref();
|
updateHandler.decref();
|
||||||
indexWriterProvider = new DefaultIndexWriterProvider();
|
indexWriterProvider = new DefaultSolrCoreState(core.getDirectoryFactory());
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateHandlerInfo updateHandlerInfo = core.getSolrConfig()
|
UpdateHandlerInfo updateHandlerInfo = core.getSolrConfig()
|
||||||
|
@ -348,8 +348,8 @@ public class DirectUpdateHandler2 extends UpdateHandler {
|
||||||
if (newReader == currentReader) {
|
if (newReader == currentReader) {
|
||||||
currentReader.incRef();
|
currentReader.incRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new SolrIndexSearcher(core, schema, "main", newReader, true, true);
|
return new SolrIndexSearcher(core, schema, "main", newReader, true, true, true, core.getDirectoryFactory());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -401,6 +401,7 @@ public class DirectUpdateHandler2 extends UpdateHandler {
|
||||||
softCommitTracker.close();
|
softCommitTracker.close();
|
||||||
|
|
||||||
numDocsPending.set(0);
|
numDocsPending.set(0);
|
||||||
|
|
||||||
indexWriterProvider.decref();
|
indexWriterProvider.decref();
|
||||||
|
|
||||||
log.info("closed " + this);
|
log.info("closed " + this);
|
||||||
|
@ -478,7 +479,7 @@ public class DirectUpdateHandler2 extends UpdateHandler {
|
||||||
return "DirectUpdateHandler2" + getStatistics();
|
return "DirectUpdateHandler2" + getStatistics();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IndexWriterProvider getIndexWriterProvider() {
|
public SolrCoreState getIndexWriterProvider() {
|
||||||
return indexWriterProvider;
|
return indexWriterProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
package org.apache.solr.update;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.apache.lucene.index.IndexWriter;
|
||||||
|
import org.apache.solr.core.DirectoryFactory;
|
||||||
|
import org.apache.solr.core.SolrCore;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The state in this class can be easily shared between SolrCores across
|
||||||
|
* SolrCore reloads.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public abstract class SolrCoreState {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force the creation of a new IndexWriter using the settings from the given
|
||||||
|
* SolrCore.
|
||||||
|
*
|
||||||
|
* @param core
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public abstract void newIndexWriter(SolrCore core) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current IndexWriter. If a new IndexWriter must be created, use the
|
||||||
|
* settings from the given {@link SolrCore}.
|
||||||
|
*
|
||||||
|
* @param core
|
||||||
|
* @return
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public abstract IndexWriter getIndexWriter(SolrCore core) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrement the number of references to this state. When then number of
|
||||||
|
* references hits 0, the state will close.
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public abstract void decref() throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increment the number of references to this state.
|
||||||
|
*/
|
||||||
|
public abstract void incref();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rollback the current IndexWriter. When creating the new IndexWriter use the
|
||||||
|
* settings from the given {@link SolrCore}.
|
||||||
|
*
|
||||||
|
* @param core
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public abstract void rollbackIndexWriter(SolrCore core) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the {@link DirectoryFactory} that should be used.
|
||||||
|
*/
|
||||||
|
public abstract DirectoryFactory getDirectoryFactory();
|
||||||
|
|
||||||
|
}
|
|
@ -17,16 +17,6 @@
|
||||||
|
|
||||||
package org.apache.solr.update;
|
package org.apache.solr.update;
|
||||||
|
|
||||||
import org.apache.lucene.index.*;
|
|
||||||
import org.apache.lucene.index.codecs.CodecProvider;
|
|
||||||
import org.apache.lucene.store.*;
|
|
||||||
import org.apache.solr.common.SolrException;
|
|
||||||
import org.apache.solr.core.DirectoryFactory;
|
|
||||||
import org.apache.solr.schema.IndexSchema;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -34,9 +24,18 @@ import java.io.OutputStream;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
import org.apache.lucene.index.IndexDeletionPolicy;
|
||||||
|
import org.apache.lucene.index.IndexWriter;
|
||||||
|
import org.apache.lucene.index.IndexWriterConfig;
|
||||||
|
import org.apache.lucene.index.codecs.CodecProvider;
|
||||||
|
import org.apache.lucene.store.Directory;
|
||||||
|
import org.apache.solr.core.DirectoryFactory;
|
||||||
|
import org.apache.solr.schema.IndexSchema;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An IndexWriter that is configured via Solr config mechanisms.
|
* An IndexWriter that is configured via Solr config mechanisms.
|
||||||
*
|
*
|
||||||
|
@ -51,41 +50,11 @@ public class SolrIndexWriter extends IndexWriter {
|
||||||
|
|
||||||
String name;
|
String name;
|
||||||
private PrintStream infoStream;
|
private PrintStream infoStream;
|
||||||
|
private DirectoryFactory directoryFactory;
|
||||||
|
|
||||||
public static Directory getDirectory(String path, DirectoryFactory directoryFactory, SolrIndexConfig config) throws IOException {
|
public SolrIndexWriter(String name, String path, DirectoryFactory directoryFactory, boolean create, IndexSchema schema, SolrIndexConfig config, IndexDeletionPolicy delPolicy, CodecProvider codecProvider, boolean forceNewDirectory) throws IOException {
|
||||||
|
|
||||||
Directory d = directoryFactory.open(path);
|
|
||||||
|
|
||||||
String rawLockType = (null == config) ? null : config.lockType;
|
|
||||||
if (null == rawLockType) {
|
|
||||||
// we default to "simple" for backwards compatibility
|
|
||||||
log.warn("No lockType configured for " + path + " assuming 'simple'");
|
|
||||||
rawLockType = "simple";
|
|
||||||
}
|
|
||||||
final String lockType = rawLockType.toLowerCase(Locale.ENGLISH).trim();
|
|
||||||
|
|
||||||
if ("simple".equals(lockType)) {
|
|
||||||
// multiple SimpleFSLockFactory instances should be OK
|
|
||||||
d.setLockFactory(new SimpleFSLockFactory(path));
|
|
||||||
} else if ("native".equals(lockType)) {
|
|
||||||
d.setLockFactory(new NativeFSLockFactory(path));
|
|
||||||
} else if ("single".equals(lockType)) {
|
|
||||||
if (!(d.getLockFactory() instanceof SingleInstanceLockFactory))
|
|
||||||
d.setLockFactory(new SingleInstanceLockFactory());
|
|
||||||
} else if ("none".equals(lockType)) {
|
|
||||||
// Recipe for disaster
|
|
||||||
log.error("CONFIGURATION WARNING: locks are disabled on " + path);
|
|
||||||
d.setLockFactory(NoLockFactory.getNoLockFactory());
|
|
||||||
} else {
|
|
||||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
|
|
||||||
"Unrecognized lockType: " + rawLockType);
|
|
||||||
}
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SolrIndexWriter(String name, String path, DirectoryFactory dirFactory, boolean create, IndexSchema schema, SolrIndexConfig config, IndexDeletionPolicy delPolicy, CodecProvider codecProvider) throws IOException {
|
|
||||||
super(
|
super(
|
||||||
getDirectory(path, dirFactory, config),
|
directoryFactory.get(path, config.lockType, forceNewDirectory),
|
||||||
config.toIndexWriterConfig(schema).
|
config.toIndexWriterConfig(schema).
|
||||||
setOpenMode(create ? IndexWriterConfig.OpenMode.CREATE : IndexWriterConfig.OpenMode.APPEND).
|
setOpenMode(create ? IndexWriterConfig.OpenMode.CREATE : IndexWriterConfig.OpenMode.APPEND).
|
||||||
setIndexDeletionPolicy(delPolicy).setCodecProvider(codecProvider)
|
setIndexDeletionPolicy(delPolicy).setCodecProvider(codecProvider)
|
||||||
|
@ -93,10 +62,11 @@ public class SolrIndexWriter extends IndexWriter {
|
||||||
log.debug("Opened Writer " + name);
|
log.debug("Opened Writer " + name);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
|
||||||
|
this.directoryFactory = directoryFactory;
|
||||||
setInfoStream(config);
|
setInfoStream(config);
|
||||||
numOpens.incrementAndGet();
|
numOpens.incrementAndGet();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setInfoStream(SolrIndexConfig config)
|
private void setInfoStream(SolrIndexConfig config)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
String infoStreamFile = config.infoStreamFile;
|
String infoStreamFile = config.infoStreamFile;
|
||||||
|
@ -142,9 +112,13 @@ public class SolrIndexWriter extends IndexWriter {
|
||||||
* ****
|
* ****
|
||||||
*/
|
*/
|
||||||
private volatile boolean isClosed = false;
|
private volatile boolean isClosed = false;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
log.debug("Closing Writer " + name);
|
log.debug("Closing Writer " + name);
|
||||||
|
Directory directory = getDirectory();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
super.close();
|
super.close();
|
||||||
if(infoStream != null) {
|
if(infoStream != null) {
|
||||||
|
@ -152,6 +126,9 @@ public class SolrIndexWriter extends IndexWriter {
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
isClosed = true;
|
isClosed = true;
|
||||||
|
|
||||||
|
directoryFactory.release(directory);
|
||||||
|
|
||||||
numCloses.incrementAndGet();
|
numCloses.incrementAndGet();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,25 +18,20 @@
|
||||||
package org.apache.solr.update;
|
package org.apache.solr.update;
|
||||||
|
|
||||||
|
|
||||||
import org.apache.lucene.index.IndexReader.AtomicReaderContext;
|
|
||||||
import org.apache.lucene.index.Term;
|
|
||||||
import org.apache.lucene.document.Document;
|
|
||||||
import org.apache.lucene.document.Fieldable;
|
|
||||||
import org.apache.lucene.search.Collector;
|
|
||||||
import org.apache.lucene.search.Scorer;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import java.util.Vector;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
import org.apache.solr.search.SolrIndexSearcher;
|
import org.apache.solr.core.PluginInfo;
|
||||||
|
import org.apache.solr.core.SolrCore;
|
||||||
|
import org.apache.solr.core.SolrEventListener;
|
||||||
|
import org.apache.solr.core.SolrInfoMBean;
|
||||||
|
import org.apache.solr.schema.FieldType;
|
||||||
import org.apache.solr.schema.IndexSchema;
|
import org.apache.solr.schema.IndexSchema;
|
||||||
import org.apache.solr.schema.SchemaField;
|
import org.apache.solr.schema.SchemaField;
|
||||||
import org.apache.solr.schema.FieldType;
|
import org.apache.solr.search.SolrIndexSearcher;
|
||||||
import org.apache.solr.common.SolrException;
|
|
||||||
import org.apache.solr.util.plugin.SolrCoreAware;
|
import org.apache.solr.util.plugin.SolrCoreAware;
|
||||||
import org.apache.solr.core.*;
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>UpdateHandler</code> handles requests to change the index
|
* <code>UpdateHandler</code> handles requests to change the index
|
||||||
|
@ -129,6 +124,7 @@ public abstract class UpdateHandler implements SolrInfoMBean {
|
||||||
*/
|
*/
|
||||||
public abstract void newIndexWriter() throws IOException;
|
public abstract void newIndexWriter() throws IOException;
|
||||||
|
|
||||||
|
public abstract SolrCoreState getIndexWriterProvider();
|
||||||
|
|
||||||
public abstract int addDoc(AddUpdateCommand cmd) throws IOException;
|
public abstract int addDoc(AddUpdateCommand cmd) throws IOException;
|
||||||
public abstract void delete(DeleteUpdateCommand cmd) throws IOException;
|
public abstract void delete(DeleteUpdateCommand cmd) throws IOException;
|
||||||
|
|
|
@ -59,7 +59,6 @@ public class TestSolrCoreProperties extends LuceneTestCase {
|
||||||
@Override
|
@Override
|
||||||
public void tearDown() throws Exception {
|
public void tearDown() throws Exception {
|
||||||
solrJetty.stop();
|
solrJetty.stop();
|
||||||
SolrTestCaseJ4.closeDirectories();
|
|
||||||
AbstractSolrTestCase.recurseDelete(homeDir);
|
AbstractSolrTestCase.recurseDelete(homeDir);
|
||||||
super.tearDown();
|
super.tearDown();
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,20 +41,16 @@ public class AlternateDirectoryTest extends SolrTestCaseJ4 {
|
||||||
assertQ(req("q","*:*","qt","standard"));
|
assertQ(req("q","*:*","qt","standard"));
|
||||||
assertTrue(TestFSDirectoryFactory.openCalled);
|
assertTrue(TestFSDirectoryFactory.openCalled);
|
||||||
assertTrue(TestIndexReaderFactory.newReaderCalled);
|
assertTrue(TestIndexReaderFactory.newReaderCalled);
|
||||||
TestFSDirectoryFactory.dir.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static public class TestFSDirectoryFactory extends DirectoryFactory {
|
static public class TestFSDirectoryFactory extends CachingDirectoryFactory {
|
||||||
public static volatile boolean openCalled = false;
|
public static volatile boolean openCalled = false;
|
||||||
public static volatile Directory dir;
|
public static volatile Directory dir;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Directory open(String path) throws IOException {
|
public Directory create(String path) throws IOException {
|
||||||
openCalled = true;
|
openCalled = true;
|
||||||
// need to close the directory, or otherwise the test fails.
|
|
||||||
if (dir != null) {
|
|
||||||
dir.close();
|
|
||||||
}
|
|
||||||
return dir = newFSDirectory(new File(path));
|
return dir = newFSDirectory(new File(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,11 +17,12 @@
|
||||||
|
|
||||||
package org.apache.solr.core;
|
package org.apache.solr.core;
|
||||||
|
|
||||||
import org.apache.lucene.store.Directory;
|
|
||||||
import org.apache.lucene.store.SingleInstanceLockFactory;
|
|
||||||
import org.apache.lucene.util.LuceneTestCase;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.apache.lucene.store.Directory;
|
||||||
|
import org.apache.lucene.store.RAMDirectory;
|
||||||
|
import org.apache.lucene.util.LuceneTestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test-case for RAMDirectoryFactory
|
* Test-case for RAMDirectoryFactory
|
||||||
*/
|
*/
|
||||||
|
@ -33,28 +34,28 @@ public class RAMDirectoryFactoryTest extends LuceneTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dotestOpenReturnsTheSameForSamePath() throws IOException {
|
private void dotestOpenReturnsTheSameForSamePath() throws IOException {
|
||||||
final Directory directory = new RefCntRamDirectory();
|
final Directory directory = new RAMDirectory();
|
||||||
RAMDirectoryFactory factory = new RAMDirectoryFactory() {
|
RAMDirectoryFactory factory = new RAMDirectoryFactory() {
|
||||||
@Override
|
@Override
|
||||||
Directory openNew(String path) throws IOException {
|
protected Directory create(String path) throws IOException {
|
||||||
return directory;
|
return directory;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
String path = "/fake/path";
|
String path = "/fake/path";
|
||||||
Directory dir1 = factory.open(path);
|
Directory dir1 = factory.get(path, null);
|
||||||
Directory dir2 = factory.open(path);
|
Directory dir2 = factory.get(path, null);
|
||||||
assertEquals("RAMDirectoryFactory should not create new instance of RefCntRamDirectory " +
|
assertEquals("RAMDirectoryFactory should not create new instance of RefCntRamDirectory " +
|
||||||
"every time open() is called for the same path", directory, dir1);
|
"every time open() is called for the same path", dir1, dir2);
|
||||||
assertEquals("RAMDirectoryFactory should not create new instance of RefCntRamDirectory " +
|
|
||||||
"every time open() is called for the same path", directory, dir2);
|
factory.release(dir1);
|
||||||
dir1.close();
|
factory.release(dir2);
|
||||||
dir2.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dotestOpenSucceedForEmptyDir() throws IOException {
|
private void dotestOpenSucceedForEmptyDir() throws IOException {
|
||||||
RAMDirectoryFactory factory = new RAMDirectoryFactory();
|
RAMDirectoryFactory factory = new RAMDirectoryFactory();
|
||||||
Directory dir = factory.open("/fake/path");
|
Directory dir = factory.get("/fake/path", null);
|
||||||
assertNotNull("RAMDirectoryFactory should create RefCntRamDirectory even if the path doen't lead " +
|
assertNotNull("RAMDirectoryFactory should create RefCntRamDirectory even if the path doen't lead " +
|
||||||
"to index directory on the file system", dir);
|
"to index directory on the file system", dir);
|
||||||
|
factory.release(dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,10 +18,9 @@
|
||||||
package org.apache.solr.core;
|
package org.apache.solr.core;
|
||||||
|
|
||||||
import org.apache.solr.SolrTestCaseJ4;
|
import org.apache.solr.SolrTestCaseJ4;
|
||||||
|
import org.apache.solr.common.params.EventParams;
|
||||||
import org.apache.solr.search.SolrIndexSearcher;
|
import org.apache.solr.search.SolrIndexSearcher;
|
||||||
import org.apache.solr.util.RefCounted;
|
import org.apache.solr.util.RefCounted;
|
||||||
import org.apache.solr.common.params.EventParams;
|
|
||||||
import org.apache.lucene.store.Directory;
|
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -75,8 +74,8 @@ public class TestQuerySenderListener extends SolrTestCaseJ4 {
|
||||||
String evt = mock.req.getParams().get(EventParams.EVENT);
|
String evt = mock.req.getParams().get(EventParams.EVENT);
|
||||||
assertNotNull("Event is null", evt);
|
assertNotNull("Event is null", evt);
|
||||||
assertTrue(evt + " is not equal to " + EventParams.FIRST_SEARCHER, evt.equals(EventParams.FIRST_SEARCHER) == true);
|
assertTrue(evt + " is not equal to " + EventParams.FIRST_SEARCHER, evt.equals(EventParams.FIRST_SEARCHER) == true);
|
||||||
Directory dir = currentSearcher.getIndexReader().directory();
|
|
||||||
SolrIndexSearcher newSearcher = new SolrIndexSearcher(core, core.getSchema(), "testQuerySenderListener", dir, true, false);
|
SolrIndexSearcher newSearcher = new SolrIndexSearcher(core, core.getNewIndexDir(), core.getSchema(), core.getSolrConfig().mainIndexConfig, "testQuerySenderListener", true, false, core.getDirectoryFactory());
|
||||||
|
|
||||||
qsl.newSearcher(newSearcher, currentSearcher);
|
qsl.newSearcher(newSearcher, currentSearcher);
|
||||||
evt = mock.req.getParams().get(EventParams.EVENT);
|
evt = mock.req.getParams().get(EventParams.EVENT);
|
||||||
|
|
|
@ -17,11 +17,8 @@ package org.apache.solr.core;
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import org.apache.lucene.store.Directory;
|
|
||||||
import org.apache.solr.SolrTestCaseJ4;
|
import org.apache.solr.SolrTestCaseJ4;
|
||||||
import org.apache.solr.common.params.EventParams;
|
|
||||||
import org.apache.solr.search.SolrIndexSearcher;
|
import org.apache.solr.search.SolrIndexSearcher;
|
||||||
import org.apache.solr.search.TestExtendedDismaxParser;
|
|
||||||
import org.apache.solr.util.RefCounted;
|
import org.apache.solr.util.RefCounted;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -78,8 +75,7 @@ public class TestQuerySenderNoQuery extends SolrTestCaseJ4 {
|
||||||
assertNotNull("Mock is null", mock);
|
assertNotNull("Mock is null", mock);
|
||||||
assertNull("Req (firstsearcher) is not null", mock.req);
|
assertNull("Req (firstsearcher) is not null", mock.req);
|
||||||
|
|
||||||
Directory dir = currentSearcher.getIndexReader().directory();
|
SolrIndexSearcher newSearcher = new SolrIndexSearcher(core, core.getNewIndexDir(), core.getSchema(), core.getSolrConfig().mainIndexConfig, "testQuerySenderNoQuery", true, false, core.getDirectoryFactory());
|
||||||
SolrIndexSearcher newSearcher = new SolrIndexSearcher(core, core.getSchema(), "testQuerySenderNoQuery", dir, true, false);
|
|
||||||
|
|
||||||
qsl.newSearcher(newSearcher, currentSearcher); // get newSearcher.
|
qsl.newSearcher(newSearcher, currentSearcher); // get newSearcher.
|
||||||
assertNull("Req (newsearcher) is not null", mock.req);
|
assertNull("Req (newsearcher) is not null", mock.req);
|
||||||
|
|
|
@ -373,7 +373,7 @@ public class AutoCommitTest extends AbstractSolrTestCase {
|
||||||
|
|
||||||
// too low of a number can cause a slow host to commit before the test code checks that it
|
// too low of a number can cause a slow host to commit before the test code checks that it
|
||||||
// isn't there... causing a failure at "shouldn't find any"
|
// isn't there... causing a failure at "shouldn't find any"
|
||||||
softTracker.timeUpperBound = 1000;
|
softTracker.timeUpperBound = 1200;
|
||||||
softTracker.docsUpperBound = -1;
|
softTracker.docsUpperBound = -1;
|
||||||
hardTracker.timeUpperBound = 3000;
|
hardTracker.timeUpperBound = 3000;
|
||||||
hardTracker.docsUpperBound = -1;
|
hardTracker.docsUpperBound = -1;
|
||||||
|
@ -435,8 +435,12 @@ public class AutoCommitTest extends AbstractSolrTestCase {
|
||||||
req.setContentStreams( toContentStreams(
|
req.setContentStreams( toContentStreams(
|
||||||
adoc("id", "531", "field_t", "what's inside?", "subject", "info"), null ) );
|
adoc("id", "531", "field_t", "what's inside?", "subject", "info"), null ) );
|
||||||
handler.handleRequest( req, rsp );
|
handler.handleRequest( req, rsp );
|
||||||
assertEquals( 2, softTracker.getCommitCount() );
|
|
||||||
assertEquals( 1, hardTracker.getCommitCount() );
|
// depending on timing, you might see 2 or 3 soft commits
|
||||||
|
int softCommitCnt = softTracker.getCommitCount();
|
||||||
|
assertTrue("commit cnt:" + softCommitCnt, softCommitCnt == 2
|
||||||
|
|| softCommitCnt == 3);
|
||||||
|
assertEquals(1, hardTracker.getCommitCount());
|
||||||
|
|
||||||
assertQ("now it should", req("id:500") ,"//result[@numFound=1]" );
|
assertQ("now it should", req("id:500") ,"//result[@numFound=1]" );
|
||||||
assertQ("but not this", req("id:531") ,"//result[@numFound=0]" );
|
assertQ("but not this", req("id:531") ,"//result[@numFound=0]" );
|
||||||
|
|
|
@ -17,19 +17,18 @@
|
||||||
|
|
||||||
package org.apache.solr.client.solrj;
|
package org.apache.solr.client.solrj;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.apache.solr.client.solrj.request.AbstractUpdateRequest;
|
import org.apache.solr.client.solrj.request.AbstractUpdateRequest;
|
||||||
import org.apache.solr.client.solrj.request.CoreAdminRequest;
|
import org.apache.solr.client.solrj.request.CoreAdminRequest;
|
||||||
import org.apache.solr.client.solrj.request.QueryRequest;
|
import org.apache.solr.client.solrj.request.QueryRequest;
|
||||||
import org.apache.solr.client.solrj.request.UpdateRequest;
|
import org.apache.solr.client.solrj.request.UpdateRequest;
|
||||||
import org.apache.solr.client.solrj.request.UpdateRequest.ACTION;
|
|
||||||
import org.apache.solr.common.SolrInputDocument;
|
import org.apache.solr.common.SolrInputDocument;
|
||||||
import org.apache.solr.core.CoreContainer;
|
import org.apache.solr.core.CoreContainer;
|
||||||
import org.apache.solr.core.SolrCore;
|
import org.apache.solr.core.SolrCore;
|
||||||
import org.apache.solr.util.ExternalPaths;
|
import org.apache.solr.util.ExternalPaths;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract base class for testing merge indexes command
|
* Abstract base class for testing merge indexes command
|
||||||
*
|
*
|
||||||
|
@ -39,6 +38,7 @@ import java.io.IOException;
|
||||||
public abstract class MergeIndexesExampleTestBase extends SolrExampleTestBase {
|
public abstract class MergeIndexesExampleTestBase extends SolrExampleTestBase {
|
||||||
// protected static final CoreContainer cores = new CoreContainer();
|
// protected static final CoreContainer cores = new CoreContainer();
|
||||||
protected static CoreContainer cores;
|
protected static CoreContainer cores;
|
||||||
|
private String saveProp;
|
||||||
private File dataDir2;
|
private File dataDir2;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -56,7 +56,9 @@ public abstract class MergeIndexesExampleTestBase extends SolrExampleTestBase {
|
||||||
return getSolrHome() + "/core0/conf/solrconfig.xml";
|
return getSolrHome() + "/core0/conf/solrconfig.xml";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
|
saveProp = System.getProperty("solr.directoryFactory");
|
||||||
System.setProperty("solr.directoryFactory", "solr.StandardDirectoryFactory");
|
System.setProperty("solr.directoryFactory", "solr.StandardDirectoryFactory");
|
||||||
super.setUp();
|
super.setUp();
|
||||||
|
|
||||||
|
@ -80,13 +82,15 @@ public abstract class MergeIndexesExampleTestBase extends SolrExampleTestBase {
|
||||||
|
|
||||||
String skip = System.getProperty("solr.test.leavedatadir");
|
String skip = System.getProperty("solr.test.leavedatadir");
|
||||||
if (null != skip && 0 != skip.trim().length()) {
|
if (null != skip && 0 != skip.trim().length()) {
|
||||||
System.err.println("NOTE: per solr.test.leavedatadir, dataDir2 will not be removed: " + dataDir2.getAbsolutePath());
|
System.err.println("NOTE: per solr.test.leavedatadir, dataDir will not be removed: " + dataDir.getAbsolutePath());
|
||||||
} else {
|
} else {
|
||||||
if (!recurseDelete(dataDir2)) {
|
if (!recurseDelete(dataDir)) {
|
||||||
System.err.println("!!!! WARNING: best effort to remove " + dataDir.getAbsolutePath() + " FAILED !!!!!");
|
System.err.println("!!!! WARNING: best effort to remove " + dataDir.getAbsolutePath() + " FAILED !!!!!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (saveProp == null) System.clearProperty("solr.directoryFactory");
|
||||||
|
else System.setProperty("solr.directoryFactory", saveProp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
package org.apache.solr.client.solrj;
|
package org.apache.solr.client.solrj;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
import org.apache.solr.client.solrj.request.CoreAdminRequest;
|
import org.apache.solr.client.solrj.request.CoreAdminRequest;
|
||||||
import org.apache.solr.client.solrj.request.QueryRequest;
|
import org.apache.solr.client.solrj.request.QueryRequest;
|
||||||
import org.apache.solr.client.solrj.request.UpdateRequest;
|
import org.apache.solr.client.solrj.request.UpdateRequest;
|
||||||
|
@ -26,12 +28,9 @@ import org.apache.solr.common.SolrInputDocument;
|
||||||
import org.apache.solr.common.util.NamedList;
|
import org.apache.solr.common.util.NamedList;
|
||||||
import org.apache.solr.core.CoreContainer;
|
import org.apache.solr.core.CoreContainer;
|
||||||
import org.apache.solr.core.SolrCore;
|
import org.apache.solr.core.SolrCore;
|
||||||
import org.apache.solr.request.SolrRequestInfo;
|
|
||||||
import org.apache.solr.util.ExternalPaths;
|
import org.apache.solr.util.ExternalPaths;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -42,7 +41,7 @@ public abstract class MultiCoreExampleTestBase extends SolrExampleTestBase
|
||||||
// protected static final CoreContainer cores = new CoreContainer();
|
// protected static final CoreContainer cores = new CoreContainer();
|
||||||
protected static CoreContainer cores;
|
protected static CoreContainer cores;
|
||||||
private File dataDir2;
|
private File dataDir2;
|
||||||
|
|
||||||
@Override public String getSolrHome() { return ExternalPaths.EXAMPLE_MULTICORE_HOME; }
|
@Override public String getSolrHome() { return ExternalPaths.EXAMPLE_MULTICORE_HOME; }
|
||||||
|
|
||||||
@Override public String getSchemaFile() { return getSolrHome()+"/core0/conf/schema.xml"; }
|
@Override public String getSchemaFile() { return getSolrHome()+"/core0/conf/schema.xml"; }
|
||||||
|
|
|
@ -77,7 +77,6 @@ public class JettyWebappTest extends LuceneTestCase
|
||||||
try {
|
try {
|
||||||
server.stop();
|
server.stop();
|
||||||
} catch( Exception ex ) {}
|
} catch( Exception ex ) {}
|
||||||
SolrTestCaseJ4.closeDirectories();
|
|
||||||
super.tearDown();
|
super.tearDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,16 +76,6 @@ public abstract class SolrTestCaseJ4 extends LuceneTestCase {
|
||||||
endTrackingSearchers();
|
endTrackingSearchers();
|
||||||
endTrackingWriters();
|
endTrackingWriters();
|
||||||
}
|
}
|
||||||
|
|
||||||
// SOLR-2279: hack to shut these directories down
|
|
||||||
// we still keep the ability to track open index files this way
|
|
||||||
public static void closeDirectories() throws Exception {
|
|
||||||
for (MockDirectoryWrapper d : stores.keySet()) {
|
|
||||||
if (d.isOpen()) {
|
|
||||||
d.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
|
@ -302,7 +292,6 @@ public abstract class SolrTestCaseJ4 extends LuceneTestCase {
|
||||||
public static void deleteCore() throws Exception {
|
public static void deleteCore() throws Exception {
|
||||||
log.info("###deleteCore" );
|
log.info("###deleteCore" );
|
||||||
if (h != null) { h.close(); }
|
if (h != null) { h.close(); }
|
||||||
closeDirectories();
|
|
||||||
if (dataDir != null) {
|
if (dataDir != null) {
|
||||||
String skip = System.getProperty("solr.test.leavedatadir");
|
String skip = System.getProperty("solr.test.leavedatadir");
|
||||||
if (null != skip && 0 != skip.trim().length()) {
|
if (null != skip && 0 != skip.trim().length()) {
|
||||||
|
|
|
@ -26,10 +26,10 @@ import org.apache.lucene.util.LuceneTestCase;
|
||||||
/**
|
/**
|
||||||
* Opens a directory with {@link LuceneTestCase#newFSDirectory(File)}
|
* Opens a directory with {@link LuceneTestCase#newFSDirectory(File)}
|
||||||
*/
|
*/
|
||||||
public class MockDirectoryFactory extends DirectoryFactory {
|
public class MockDirectoryFactory extends CachingDirectoryFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Directory open(String path) throws IOException {
|
public Directory create(String path) throws IOException {
|
||||||
return LuceneTestCase.newFSDirectory(new File(path));
|
return LuceneTestCase.newFSDirectory(new File(path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,7 +193,6 @@ public abstract class AbstractSolrTestCase extends LuceneTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h != null) { h.close(); }
|
if (h != null) { h.close(); }
|
||||||
SolrTestCaseJ4.closeDirectories();
|
|
||||||
String skip = System.getProperty("solr.test.leavedatadir");
|
String skip = System.getProperty("solr.test.leavedatadir");
|
||||||
if (null != skip && 0 != skip.trim().length()) {
|
if (null != skip && 0 != skip.trim().length()) {
|
||||||
System.err.println("NOTE: per solr.test.leavedatadir, dataDir will not be removed: " + dataDir.getAbsolutePath());
|
System.err.println("NOTE: per solr.test.leavedatadir, dataDir will not be removed: " + dataDir.getAbsolutePath());
|
||||||
|
|
Loading…
Reference in New Issue