SOLR-3156: Check for Lucene directory locks at startup.

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1304359 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Martijn van Groningen 2012-03-23 14:12:24 +00:00
parent 4ba2d0b972
commit e36ee74921
5 changed files with 188 additions and 13 deletions

View File

@ -760,6 +760,9 @@ Other Changes
* SOLR-2712: expecting fl=score to return all fields is now deprecated. * SOLR-2712: expecting fl=score to return all fields is now deprecated.
In solr 4.0, this will only return the score. (ryan) In solr 4.0, this will only return the score. (ryan)
* SOLR-3156: Check for Lucene directory locks at startup. In previous versions
this check was only performed during modifying (e.g. adding and deleting
documents) the index. (Luca Cavanna via Martijn van Groningen)
Build Build
---------------------- ----------------------

View File

@ -17,12 +17,14 @@
package org.apache.solr.core; package org.apache.solr.core;
import org.apache.commons.io.IOUtils;
import org.apache.lucene.codecs.Codec; import org.apache.lucene.codecs.Codec;
import org.apache.lucene.index.IndexDeletionPolicy;
import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexDeletionPolicy;
import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.store.Directory; import org.apache.lucene.store.Directory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.CommonParams; import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.CommonParams.EchoParamStyle; import org.apache.solr.common.params.CommonParams.EchoParamStyle;
@ -31,7 +33,8 @@ 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.handler.admin.ShowFileRequestHandler; import org.apache.solr.handler.admin.ShowFileRequestHandler;
import org.apache.solr.handler.component.*; import org.apache.solr.handler.component.*;
import org.apache.solr.request.*; import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.response.*; import org.apache.solr.response.*;
import org.apache.solr.response.transform.TransformerFactory; import org.apache.solr.response.transform.TransformerFactory;
import org.apache.solr.schema.IndexSchema; import org.apache.solr.schema.IndexSchema;
@ -45,23 +48,20 @@ import org.apache.solr.update.UpdateHandler;
import org.apache.solr.update.processor.*; import org.apache.solr.update.processor.*;
import org.apache.solr.util.RefCounted; import org.apache.solr.util.RefCounted;
import org.apache.solr.util.plugin.NamedListInitializedPlugin; import org.apache.solr.util.plugin.NamedListInitializedPlugin;
import org.apache.solr.util.plugin.SolrCoreAware;
import org.apache.solr.util.plugin.PluginInfoInitialized; import org.apache.solr.util.plugin.PluginInfoInitialized;
import org.apache.commons.io.IOUtils; import org.apache.solr.util.plugin.SolrCoreAware;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import java.io.*; import java.io.*;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.util.*; import java.util.*;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URL;
import java.lang.reflect.Constructor;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
@ -366,14 +366,19 @@ public final class SolrCore implements SolrInfoMBean {
initIndexReaderFactory(); initIndexReaderFactory();
if (indexExists && firstTime && removeLocks) { if (indexExists && firstTime) {
// 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 = directoryFactory.get(indexDir, getSolrConfig().mainIndexConfig.lockType); 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..."); if (removeLocks) {
IndexWriter.unlock(dir); log.warn(logid + "WARNING: Solr index directory '{}' is locked. Unlocking...", indexDir);
IndexWriter.unlock(dir);
} else {
log.error(logid + "Solr index directory '{}' is locked. Throwing exception", indexDir);
throw new LockObtainFailedException("Index locked for write for core " + name);
}
} }
directoryFactory.release(dir); directoryFactory.release(dir);
} }

View File

@ -0,0 +1,33 @@
<?xml version="1.0" ?>
<!--
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.
-->
<config>
<!--
Config file used by SolrCoreCheckLockOnStartupTest#testNativeLockErrorOnStartup
It requires the native lockType
-->
<jmx />
<dataDir>${solr.data.dir:}</dataDir>
<luceneMatchVersion>${tests.luceneMatchVersion:LUCENE_CURRENT}</luceneMatchVersion>
<indexDefaults>
<lockType>native</lockType>
</indexDefaults>
</config>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" ?>
<!--
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.
-->
<config>
<!--
Config file used by SolrCoreCheckLockOnStartupTest#testSimpleLockErrorOnStartup
It requires the simple lockType
-->
<jmx />
<dataDir>${solr.data.dir:}</dataDir>
<luceneMatchVersion>${tests.luceneMatchVersion:LUCENE_CURRENT}</luceneMatchVersion>
<indexDefaults>
<lockType>simple</lockType>
</indexDefaults>
</config>

View File

@ -0,0 +1,101 @@
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 org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.store.NativeFSLockFactory;
import org.apache.lucene.store.SimpleFSLockFactory;
import org.apache.lucene.util.Version;
import org.apache.solr.SolrTestCaseJ4;
import org.junit.Before;
import org.junit.Test;
import java.io.File;
public class SolrCoreCheckLockOnStartupTest extends SolrTestCaseJ4 {
@Before
public void setUp() throws Exception {
super.setUp();
System.setProperty("solr.directoryFactory", "org.apache.solr.core.SimpleFSDirectoryFactory");
//explicitly creates the temp dataDir so we know where the index will be located
createTempDir();
IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_40, null);
Directory directory = newFSDirectory(new File(dataDir, "index"));
//creates a new index on the known location
new IndexWriter(
directory,
indexWriterConfig.setOpenMode(IndexWriterConfig.OpenMode.CREATE)
).close();
directory.close();
}
@Test
public void testSimpleLockErrorOnStartup() throws Exception {
Directory directory = newFSDirectory(new File(dataDir, "index"), new SimpleFSLockFactory());
//creates a new IndexWriter without releasing the lock yet
IndexWriter indexWriter = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_40, null));
try {
//opening a new core on the same index
initCore("solrconfig-simplelock.xml", "schema.xml");
fail("Expected " + LockObtainFailedException.class.getSimpleName());
} catch (Throwable t) {
assertTrue(t instanceof RuntimeException);
assertNotNull(t.getCause());
assertTrue(t.getCause() instanceof RuntimeException);
assertNotNull(t.getCause().getCause());
assertTrue(t.getCause().getCause() instanceof LockObtainFailedException);
} finally {
indexWriter.close();
directory.close();
deleteCore();
}
}
@Test
public void testNativeLockErrorOnStartup() throws Exception {
Directory directory = newFSDirectory(new File(dataDir, "index"), new NativeFSLockFactory());
//creates a new IndexWriter without releasing the lock yet
IndexWriter indexWriter = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_40, null));
try {
//opening a new core on the same index
initCore("solrconfig-nativelock.xml", "schema.xml");
fail("Expected " + LockObtainFailedException.class.getSimpleName());
} catch(Throwable t) {
assertTrue(t instanceof RuntimeException);
assertNotNull(t.getCause());
assertTrue(t.getCause() instanceof RuntimeException);
assertNotNull(t.getCause().getCause());
assertTrue(t.getCause().getCause() instanceof LockObtainFailedException);
} finally {
indexWriter.close();
directory.close();
deleteCore();
}
}
}