9696import java .util .Map ;
9797import java .util .concurrent .TimeUnit ;
9898import java .util .concurrent .atomic .AtomicBoolean ;
99+ import java .util .concurrent .locks .ReentrantLock ;
99100import java .util .concurrent .locks .ReentrantReadWriteLock ;
100101import java .util .zip .CRC32 ;
101102import java .util .zip .Checksum ;
@@ -223,7 +224,8 @@ final void ensureOpen() {
223224 * {@link #readMetadataSnapshot(Path, ShardId, NodeEnvironment.ShardLocker, Logger)} to read a meta data while locking
224225 * {@link IndexShard#snapshotStoreMetadata()} to safely read from an existing shard
225226 * {@link IndexShard#acquireIndexCommit(boolean)} to get an {@link IndexCommit} which is safe to use but has to be freed
226- *
227+ * @param commit the index commit to read the snapshot from or <code>null</code> if the latest snapshot should be read from the
228+ * directory
227229 * @throws CorruptIndexException if the lucene index is corrupted. This can be caused by a checksum mismatch or an
228230 * unexpected exception when opening the index reading the segments file.
229231 * @throws IndexFormatTooOldException if the lucene index is too old to be opened.
@@ -233,16 +235,47 @@ final void ensureOpen() {
233235 * @throws IndexNotFoundException if the commit point can't be found in this store
234236 */
235237 public MetadataSnapshot getMetadata (IndexCommit commit ) throws IOException {
238+ return getMetadata (commit , false );
239+ }
240+
241+ /**
242+ * Returns a new MetadataSnapshot for the given commit. If the given commit is <code>null</code>
243+ * the latest commit point is used.
244+ *
245+ * Note that this method requires the caller verify it has the right to access the store and
246+ * no concurrent file changes are happening. If in doubt, you probably want to use one of the following:
247+ *
248+ * {@link #readMetadataSnapshot(Path, ShardId, NodeEnvironment.ShardLocker, Logger)} to read a meta data while locking
249+ * {@link IndexShard#snapshotStoreMetadata()} to safely read from an existing shard
250+ * {@link IndexShard#acquireIndexCommit(boolean)} to get an {@link IndexCommit} which is safe to use but has to be freed
251+ *
252+ * @param commit the index commit to read the snapshot from or <code>null</code> if the latest snapshot should be read from the
253+ * directory
254+ * @param lockDirectory if <code>true</code> the index writer lock will be obtained before reading the snapshot. This should
255+ * only be used if there is no started shard using this store.
256+ * @throws CorruptIndexException if the lucene index is corrupted. This can be caused by a checksum mismatch or an
257+ * unexpected exception when opening the index reading the segments file.
258+ * @throws IndexFormatTooOldException if the lucene index is too old to be opened.
259+ * @throws IndexFormatTooNewException if the lucene index is too new to be opened.
260+ * @throws FileNotFoundException if one or more files referenced by a commit are not present.
261+ * @throws NoSuchFileException if one or more files referenced by a commit are not present.
262+ * @throws IndexNotFoundException if the commit point can't be found in this store
263+ */
264+ public MetadataSnapshot getMetadata (IndexCommit commit , boolean lockDirectory ) throws IOException {
236265 ensureOpen ();
237266 failIfCorrupted ();
238- metadataLock .readLock ().lock ();
239- try {
267+ assert lockDirectory ? commit == null : true : "IW lock should not be obtained if there is a commit point available" ;
268+ // if we lock the directory we also acquire the write lock since that makes sure that nobody else tries to lock the IW
269+ // on this store at the same time.
270+ java .util .concurrent .locks .Lock lock = lockDirectory ? metadataLock .writeLock () : metadataLock .readLock ();
271+ lock .lock ();
272+ try (Closeable ignored = lockDirectory ? directory .obtainLock (IndexWriter .WRITE_LOCK_NAME ) : () -> {} ) {
240273 return new MetadataSnapshot (commit , directory , logger );
241274 } catch (CorruptIndexException | IndexFormatTooOldException | IndexFormatTooNewException ex ) {
242275 markStoreCorrupted (ex );
243276 throw ex ;
244277 } finally {
245- metadataLock . readLock () .unlock ();
278+ lock .unlock ();
246279 }
247280 }
248281
0 commit comments