]> source.dussan.org Git - gitblit.git/commitdiff
Use versioned index directories for repository indices.
authorFlorian Zschocke <florian.zschocke@devolo.de>
Sun, 5 Mar 2017 16:11:50 +0000 (17:11 +0100)
committerFlorian Zschocke <florian.zschocke@devolo.de>
Sun, 5 Mar 2017 19:27:37 +0000 (20:27 +0100)
Change from the index version of a repository index being stored in a config
file to also using index directories with the version in the name. For that,
`LuceneRepoIndexStore` is added, which adds the fixed `lucene` part to the path.
It also gives out the location of the `lucene.conf` file, which is now stored in
the index directory. This way it is automatically deleted when the directory is
deleted.

I believe that it should also provide means to store branch aliases and tips,
i.e. hide the config file completely. But this isn't implemented with this
commit, the `LuceneService` is still aware that a config file is used.

src/main/java/com/gitblit/service/LuceneRepoIndexStore.java [new file with mode: 0644]
src/main/java/com/gitblit/service/LuceneService.java
src/test/java/com/gitblit/service/LuceneRepoIndexStoreTest.java [new file with mode: 0644]

diff --git a/src/main/java/com/gitblit/service/LuceneRepoIndexStore.java b/src/main/java/com/gitblit/service/LuceneRepoIndexStore.java
new file mode 100644 (file)
index 0000000..ff7d088
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2017 gitblit.com.
+ *
+ * Licensed 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.
+ */
+
+package com.gitblit.service;
+
+import java.io.File;
+
+import com.gitblit.utils.LuceneIndexStore;
+
+/**
+ * @author Florian Zschocke
+ *
+ * @since 1.9.0
+ */
+class LuceneRepoIndexStore extends LuceneIndexStore
+{
+
+       private static final String LUCENE_DIR = "lucene";
+       private static final String CONF_FILE = "gb_lucene.conf";
+
+
+       /**
+        * @param repositoryFolder
+        *                      The directory of the repository for this index
+        * @param indexVersion
+        *                      Version of the index definition
+        */
+       public LuceneRepoIndexStore(File repositoryFolder, int indexVersion) {
+               super(new File(repositoryFolder, LUCENE_DIR), indexVersion);
+       }
+
+
+       /**
+        * Get the index config File.
+        *
+        * @return      The index config File
+        */
+       public File getConfigFile() {
+               return new File(this.indexFolder, CONF_FILE);
+       }
+
+}
index 9b97ad5b31b7641f650467666d69da5faa66e21a..906a0b5e60f7d34ac942a0a8c6bbbb1906dcc6aa 100644 (file)
@@ -117,10 +117,6 @@ public class LuceneService implements Runnable {
        private static final String FIELD_DATE = "date";\r
        private static final String FIELD_TAG = "tag";\r
 \r
-       private static final String CONF_FILE = "lucene.conf";\r
-       private static final String LUCENE_DIR = "lucene";\r
-       private static final String CONF_INDEX = "index";\r
-       private static final String CONF_VERSION = "version";\r
        private static final String CONF_ALIAS = "aliases";\r
        private static final String CONF_BRANCH = "branches";\r
 \r
@@ -290,26 +286,13 @@ public class LuceneService implements Runnable {
         * @return true, if successful\r
         */\r
        public boolean deleteIndex(String repositoryName) {\r
-               try {\r
-                       // close any open writer/searcher\r
-                       close(repositoryName);\r
-\r
-                       // delete the index folder\r
-                       File repositoryFolder = FileKey.resolve(new File(repositoriesFolder, repositoryName), FS.DETECTED);\r
-                       File luceneIndex = new File(repositoryFolder, LUCENE_DIR);\r
-                       if (luceneIndex.exists()) {\r
-                               org.eclipse.jgit.util.FileUtils.delete(luceneIndex,\r
-                                               org.eclipse.jgit.util.FileUtils.RECURSIVE);\r
-                       }\r
-                       // delete the config file\r
-                       File luceneConfig = new File(repositoryFolder, CONF_FILE);\r
-                       if (luceneConfig.exists()) {\r
-                               luceneConfig.delete();\r
-                       }\r
-                       return true;\r
-               } catch (IOException e) {\r
-                       throw new RuntimeException(e);\r
-               }\r
+               // close any open writer/searcher\r
+               close(repositoryName);\r
+\r
+               // delete the index folder\r
+               File repositoryFolder = FileKey.resolve(new File(repositoriesFolder, repositoryName), FS.DETECTED);\r
+               LuceneRepoIndexStore luceneIndex = new LuceneRepoIndexStore(repositoryFolder, INDEX_VERSION);\r
+               return luceneIndex.delete();\r
        }\r
 \r
        /**\r
@@ -383,29 +366,20 @@ public class LuceneService implements Runnable {
         * @return a config object\r
         */\r
        private FileBasedConfig getConfig(Repository repository) {\r
-               File file = new File(repository.getDirectory(), CONF_FILE);\r
-               FileBasedConfig config = new FileBasedConfig(file, FS.detect());\r
+               LuceneRepoIndexStore luceneIndex = new LuceneRepoIndexStore(repository.getDirectory(), INDEX_VERSION);\r
+               FileBasedConfig config = new FileBasedConfig(luceneIndex.getConfigFile(), FS.detect());\r
                return config;\r
        }\r
 \r
        /**\r
-        * Reads the Lucene config file for the repository to check the index\r
-        * version. If the index version is different, then rebuild the repository\r
-        * index.\r
+        * Checks if an index exists for the repository, that is compatible with\r
+        * INDEX_VERSION and the Lucene version.\r
         *\r
         * @param repository\r
-        * @return true of the on-disk index format is different than INDEX_VERSION\r
+        * @return true if no index is found for the repository, false otherwise.\r
         */\r
        private boolean shouldReindex(Repository repository) {\r
-               try {\r
-                       FileBasedConfig config = getConfig(repository);\r
-                       config.load();\r
-                       int indexVersion = config.getInt(CONF_INDEX, CONF_VERSION, 0);\r
-                       // reindex if versions do not match\r
-                       return indexVersion != INDEX_VERSION;\r
-               } catch (Throwable t) {\r
-               }\r
-               return true;\r
+               return ! (new LuceneRepoIndexStore(repository.getDirectory(), INDEX_VERSION).hasIndex());\r
        }\r
 \r
 \r
@@ -615,7 +589,6 @@ public class LuceneService implements Runnable {
                        reader.close();\r
 \r
                        // commit all changes and reset the searcher\r
-                       config.setInt(CONF_INDEX, null, CONF_VERSION, INDEX_VERSION);\r
                        config.save();\r
                        writer.commit();\r
                        resetIndexSearcher(model.name);\r
@@ -844,7 +817,6 @@ public class LuceneService implements Runnable {
                                }\r
 \r
                                // update the config\r
-                               config.setInt(CONF_INDEX, null, CONF_VERSION, INDEX_VERSION);\r
                                config.setString(CONF_ALIAS, null, keyName, branchName);\r
                                config.setString(CONF_BRANCH, null, keyName, branch.getObjectId().getName());\r
                                config.save();\r
@@ -962,14 +934,11 @@ public class LuceneService implements Runnable {
         */\r
        private IndexWriter getIndexWriter(String repository) throws IOException {\r
                IndexWriter indexWriter = writers.get(repository);\r
-               File repositoryFolder = FileKey.resolve(new File(repositoriesFolder, repository), FS.DETECTED);\r
-               File indexFolder = new File(repositoryFolder, LUCENE_DIR);\r
-               Directory directory = FSDirectory.open(indexFolder.toPath());\r
-\r
                if (indexWriter == null) {\r
-                       if (!indexFolder.exists()) {\r
-                               indexFolder.mkdirs();\r
-                       }\r
+                       File repositoryFolder = FileKey.resolve(new File(repositoriesFolder, repository), FS.DETECTED);\r
+                       LuceneRepoIndexStore indexStore = new LuceneRepoIndexStore(repositoryFolder, INDEX_VERSION);\r
+                       indexStore.create();\r
+                       Directory directory = FSDirectory.open(indexStore.getPath());\r
                        StandardAnalyzer analyzer = new StandardAnalyzer();\r
                        IndexWriterConfig config = new IndexWriterConfig(analyzer);\r
                        config.setOpenMode(OpenMode.CREATE_OR_APPEND);\r
diff --git a/src/test/java/com/gitblit/service/LuceneRepoIndexStoreTest.java b/src/test/java/com/gitblit/service/LuceneRepoIndexStoreTest.java
new file mode 100644 (file)
index 0000000..baac351
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2017 gitblit.com.
+ *
+ * Licensed 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.
+ */
+
+package com.gitblit.service;
+
+import static org.junit.Assert.*;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Path;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import com.gitblit.utils.LuceneIndexStore;
+
+/**
+ * @author Florian Zschocke
+ *
+ */
+public class LuceneRepoIndexStoreTest
+{
+
+       private static final int LUCENE_VERSION = LuceneIndexStore.LUCENE_CODEC_VERSION;
+       private static final String LUCENE_DIR = "lucene";
+
+
+       @Rule
+       public TemporaryFolder baseFolder = new TemporaryFolder();
+
+
+       private String getIndexDir(int version)
+       {
+               return version + "_" + LUCENE_VERSION;
+       }
+
+
+       private String getLuceneIndexDir(int version)
+       {
+               return LUCENE_DIR + "/" + version + "_" + LUCENE_VERSION;
+       }
+
+
+       @Test
+       public void testGetConfigFile() throws IOException
+       {
+               int version = 1;
+               File repositoryFolder = baseFolder.getRoot();
+               LuceneRepoIndexStore li = new LuceneRepoIndexStore(repositoryFolder, version);
+               File confFile= li.getConfigFile();
+               File luceneDir = new File(repositoryFolder, getLuceneIndexDir(version) + "/gb_lucene.conf");
+               assertEquals(luceneDir, confFile);
+       }
+
+
+       @Test
+       public void testCreate()
+       {
+               int version = 0;
+               File repositoryFolder = baseFolder.getRoot();
+               File luceneDir = new File(repositoryFolder, getLuceneIndexDir(version));
+               assertFalse("Precondition failure: directory exists already", new File(repositoryFolder, LUCENE_DIR).exists());
+               assertFalse("Precondition failure: directory exists already", luceneDir.exists());
+
+               LuceneIndexStore li = new LuceneRepoIndexStore(repositoryFolder, version);
+               li.create();
+
+               assertTrue(luceneDir.exists());
+               assertTrue(luceneDir.isDirectory());
+       }
+
+       @Test
+       public void testCreateIndexDir()
+       {
+               int version = 7777;
+               File repositoryFolder = baseFolder.getRoot();
+               try {
+                       baseFolder.newFolder(LUCENE_DIR);
+               } catch (IOException e) {
+                       fail("Failed in setup of folder: " + e);
+               }
+               File luceneDir = new File(repositoryFolder, getLuceneIndexDir(version));
+
+               assertTrue("Precondition failure: directory does not exist", new File(repositoryFolder, LUCENE_DIR).exists());
+               assertFalse("Precondition failure: directory exists already", luceneDir.exists());
+
+               LuceneIndexStore li = new LuceneRepoIndexStore(repositoryFolder, version);
+               li.create();
+
+               assertTrue(luceneDir.exists());
+               assertTrue(luceneDir.isDirectory());
+
+               // Make sure nothing else was created.
+               assertEquals(0, luceneDir.list().length);
+               assertEquals(1, luceneDir.getParentFile().list().length);
+       }
+
+       @Test
+       public void testCreateIfNecessary()
+       {
+               int version = 7777888;
+               File repositoryFolder = baseFolder.getRoot();
+               File luceneDir = null;
+               try {
+                       luceneDir = baseFolder.newFolder(LUCENE_DIR, getIndexDir(version));
+               } catch (IOException e) {
+                       fail("Failed in setup of folder: " + e);
+               }
+               assertTrue("Precondition failure: directory does not exist", new File(repositoryFolder, LUCENE_DIR).exists());
+               assertTrue("Precondition failure: directory does not exist", luceneDir.exists());
+
+               LuceneIndexStore li = new LuceneRepoIndexStore(repositoryFolder, version);
+               li.create();
+
+               assertTrue(luceneDir.exists());
+               assertTrue(luceneDir.isDirectory());
+
+               // Make sure nothing else was created.
+               assertEquals(0, luceneDir.list().length);
+               assertEquals(1, luceneDir.getParentFile().list().length);
+       }
+
+
+       @Test
+       public void testDelete()
+       {
+               int version = 111222333;
+
+               File repositoryFolder = baseFolder.getRoot();
+               File luceneDir = null;
+               try {
+                       luceneDir = baseFolder.newFolder(LUCENE_DIR, getIndexDir(version));
+               } catch (IOException e) {
+                       fail("Failed in setup of folder: " + e);
+               }
+               assertTrue("Precondition failure: directory does not exist", luceneDir.exists());
+
+               LuceneIndexStore li = new LuceneRepoIndexStore(repositoryFolder, version);
+               assertTrue(li.delete());
+
+               assertFalse(luceneDir.exists());
+               assertTrue(new File(repositoryFolder, LUCENE_DIR).exists());
+       }
+
+
+       @Test
+       public void testDeleteNotExist()
+       {
+               int version = 0;
+
+               File repositoryFolder = baseFolder.getRoot();
+               try {
+                       baseFolder.newFolder(LUCENE_DIR);
+               } catch (IOException e) {
+                       fail("Failed in setup of folder: " + e);
+               }
+               File luceneDir = new File(repositoryFolder, getLuceneIndexDir(version));
+               assertTrue("Precondition failure: directory does not exist", new File(repositoryFolder, LUCENE_DIR).exists());
+               assertFalse("Precondition failure: directory does exist", luceneDir.exists());
+
+               LuceneIndexStore li = new LuceneRepoIndexStore(repositoryFolder, version);
+               assertTrue(li.delete());
+
+               assertFalse(luceneDir.exists());
+               assertTrue(new File(repositoryFolder, LUCENE_DIR).exists());
+       }
+
+
+       @Test
+       public void testDeleteWithFiles()
+       {
+               int version = 5;
+
+               File repositoryFolder = baseFolder.getRoot();
+               File luceneFolder = new File(baseFolder.getRoot(), LUCENE_DIR);
+               File luceneDir = null;
+
+               File otherDir = new File(luceneFolder, version + "_10");
+               File dbFile = null;
+               try {
+                       luceneDir = baseFolder.newFolder(LUCENE_DIR, getIndexDir(version));
+                       File file = new File(luceneDir, "_file1");
+                       file.createNewFile();
+                       file = new File(luceneDir, "_file2.db");
+                       file.createNewFile();
+                       file = new File(luceneDir, "conf.conf");
+                       file.createNewFile();
+
+                       otherDir.mkdirs();
+                       dbFile = new File(otherDir, "_file2.db");
+                       dbFile.createNewFile();
+                       file = new File(otherDir, "conf.conf");
+                       file.createNewFile();
+               }
+               catch (IOException e) {
+                       fail("Failed in setup of folder: " + e);
+               }
+               assertTrue("Precondition failure: index directory does not exist", luceneDir.exists());
+               assertTrue("Precondition failure: other index directory does not exist", otherDir.exists());
+
+               LuceneIndexStore li = new LuceneRepoIndexStore(repositoryFolder, version);
+               li.delete();
+
+               assertFalse(luceneDir.exists());
+               assertTrue(luceneFolder.exists());
+               assertTrue(otherDir.exists());
+               assertTrue(dbFile.exists());
+       }
+
+
+
+       @Test
+       public void testGetPath() throws IOException
+       {
+               int version = 7;
+               File repositoryFolder = baseFolder.getRoot();
+               LuceneIndexStore li = new LuceneRepoIndexStore(repositoryFolder, version);
+               Path dir = li.getPath();
+               File luceneDir = new File(repositoryFolder, getLuceneIndexDir(version));
+               assertEquals(luceneDir.toPath(), dir);
+       }
+
+
+       @Test
+       public void testHasIndex() throws IOException
+       {
+               int version = 0;
+               File luceneFolder = new File(baseFolder.getRoot(), "lucene");
+
+               LuceneIndexStore li = new LuceneRepoIndexStore(luceneFolder, version);
+               assertFalse(li.hasIndex());
+
+               baseFolder.newFolder("lucene");
+               li = new LuceneIndexStore(luceneFolder, version);
+               assertFalse(li.hasIndex());
+
+               File luceneDir = baseFolder.newFolder("lucene", getIndexDir(version));
+               li = new LuceneIndexStore(luceneFolder, version);
+               assertFalse(li.hasIndex());
+
+               new File(luceneDir, "write.lock").createNewFile();
+               li = new LuceneIndexStore(luceneFolder, version);
+               assertFalse(li.hasIndex());
+
+               new File(luceneDir, "segments_1").createNewFile();
+               li = new LuceneIndexStore(luceneFolder, version);
+               System.out.println("Check " + luceneDir);
+               assertTrue(li.hasIndex());
+
+       }
+
+
+}