xref: /OpenGrok/opengrok-indexer/src/main/java/org/opengrok/indexer/index/IndexCheck.java (revision 1b93561956b1fb47c6797767615e69b0b4fefced)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * See LICENSE.txt included in this distribution for the specific
9  * language governing permissions and limitations under the License.
10  *
11  * When distributing Covered Code, include this CDDL HEADER in each
12  * file and include the License file at LICENSE.txt.
13  * If applicable, add the following below this CDDL HEADER, with the
14  * fields enclosed by brackets "[]" replaced with your own identifying
15  * information: Portions Copyright [yyyy] [name of copyright owner]
16  *
17  * CDDL HEADER END
18  */
19 
20 /*
21  * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
22  * Portions Copyright (c) 2018, Chris Fraire <cfraire@me.com>.
23  */
24 package org.opengrok.indexer.index;
25 
26 import java.io.File;
27 import java.io.IOException;
28 import java.util.Collection;
29 import java.util.logging.Level;
30 import java.util.logging.Logger;
31 import org.apache.lucene.index.SegmentInfos;
32 import org.apache.lucene.store.Directory;
33 import org.apache.lucene.store.FSDirectory;
34 import org.apache.lucene.store.LockFactory;
35 import org.apache.lucene.store.NativeFSLockFactory;
36 import org.apache.lucene.util.Version;
37 import org.jetbrains.annotations.NotNull;
38 import org.opengrok.indexer.configuration.Configuration;
39 import org.opengrok.indexer.logger.LoggerFactory;
40 
41 /**
42  * Index checker.
43  *
44  * @author Vladimír Kotal
45  */
46 public class IndexCheck {
47     private static final Logger LOGGER = LoggerFactory.getLogger(IndexCheck.class);
48 
49     /**
50      * Exception thrown when index version does not match Lucene version.
51      */
52     public static class IndexVersionException extends Exception {
53 
54         private static final long serialVersionUID = 5693446916108385595L;
55 
56         private final int luceneIndexVersion;
57         private final int indexVersion;
58 
IndexVersionException(String s, int luceneIndexVersion, int indexVersion)59         public IndexVersionException(String s, int luceneIndexVersion, int indexVersion) {
60             super(s);
61 
62             this.indexVersion = indexVersion;
63             this.luceneIndexVersion = luceneIndexVersion;
64         }
65 
66         @Override
toString()67         public String toString() {
68             return getMessage() + ": " + String.format("Lucene version = %d", luceneIndexVersion) + ", " +
69                     String.format("index version = %d", indexVersion);
70         }
71     }
72 
IndexCheck()73     private IndexCheck() {
74         // utility class
75     }
76 
77     /**
78      * Check if version of index(es) matches major Lucene version.
79      * @param configuration configuration based on which to perform the check
80      * @param subFilesList collection of paths. If non-empty, only projects matching these paths will be checked.
81      * @return true on success, false on failure
82      */
check(@otNull Configuration configuration, Collection<String> subFilesList)83     public static boolean check(@NotNull Configuration configuration, Collection<String> subFilesList) {
84         File indexRoot = new File(configuration.getDataRoot(), IndexDatabase.INDEX_DIR);
85         LOGGER.log(Level.FINE, "Checking for Lucene index version mismatch in {0}", indexRoot);
86         int ret = 0;
87 
88         if (!subFilesList.isEmpty()) {
89             // Assumes projects are enabled.
90             for (String projectName : subFilesList) {
91                 LOGGER.log(Level.FINER,
92                         "Checking Lucene index version in project {0}",
93                         projectName);
94                 ret |= checkDirNoExceptions(new File(indexRoot, projectName));
95             }
96         } else {
97             if (configuration.isProjectsEnabled()) {
98                 for (String projectName : configuration.getProjects().keySet()) {
99                     LOGGER.log(Level.FINER,
100                             "Checking Lucene index version in project {0}",
101                             projectName);
102                     ret |= checkDirNoExceptions(new File(indexRoot, projectName));
103                 }
104             } else {
105                 LOGGER.log(Level.FINER, "Checking Lucene index version in {0}",
106                         indexRoot);
107                 ret |= checkDirNoExceptions(indexRoot);
108             }
109         }
110 
111         return ret == 0;
112     }
113 
checkDirNoExceptions(File dir)114     private static int checkDirNoExceptions(File dir) {
115         try {
116             checkDir(dir);
117         } catch (Exception e) {
118             LOGGER.log(Level.WARNING, "Index check for directory " + dir + " failed", e);
119             return 1;
120         }
121 
122         return 0;
123     }
124 
125     /**
126      * Check index in given directory. It assumes that that all commits (if any)
127      * in the Lucene segment file were done with the same version.
128      *
129      * @param dir directory with index
130      * @throws IOException if the directory cannot be opened
131      * @throws IndexVersionException if the version of the index does not match Lucene index version
132      */
checkDir(File dir)133     public static void checkDir(File dir) throws IndexVersionException, IOException {
134         LockFactory lockFactory = NativeFSLockFactory.INSTANCE;
135         int segVersion;
136 
137         try (Directory indexDirectory = FSDirectory.open(dir.toPath(), lockFactory)) {
138             SegmentInfos segInfos = SegmentInfos.readLatestCommit(indexDirectory);
139             segVersion = segInfos.getIndexCreatedVersionMajor();
140         }
141 
142         if (segVersion != Version.LATEST.major) {
143             throw new IndexVersionException(
144                 String.format("Directory %s has index version discrepancy", dir),
145                     Version.LATEST.major, segVersion);
146         }
147     }
148 }
149