1919
2020package org .elasticsearch .env ;
2121
22- import java .io .UncheckedIOException ;
23- import java .util .Iterator ;
24- import java .util .stream .Collectors ;
25- import java .util .stream .Stream ;
26- import org .apache .logging .log4j .Logger ;
2722import org .apache .logging .log4j .LogManager ;
23+ import org .apache .logging .log4j .Logger ;
2824import org .apache .logging .log4j .message .ParameterizedMessage ;
2925import org .apache .lucene .index .IndexWriter ;
3026import org .apache .lucene .index .SegmentInfos ;
3430import org .apache .lucene .store .LockObtainFailedException ;
3531import org .apache .lucene .store .NativeFSLockFactory ;
3632import org .apache .lucene .store .SimpleFSDirectory ;
37- import org .elasticsearch .common .CheckedFunction ;
38- import org .elasticsearch .common .lease .Releasable ;
39- import org .elasticsearch .core .internal .io .IOUtils ;
4033import org .elasticsearch .ElasticsearchException ;
4134import org .elasticsearch .cluster .metadata .IndexMetaData ;
4235import org .elasticsearch .cluster .node .DiscoveryNode ;
36+ import org .elasticsearch .common .CheckedFunction ;
4337import org .elasticsearch .common .Randomness ;
4438import org .elasticsearch .common .SuppressForbidden ;
4539import org .elasticsearch .common .UUIDs ;
4640import org .elasticsearch .common .io .FileSystemUtils ;
41+ import org .elasticsearch .common .lease .Releasable ;
4742import org .elasticsearch .common .settings .Setting ;
4843import org .elasticsearch .common .settings .Setting .Property ;
4944import org .elasticsearch .common .settings .Settings ;
5045import org .elasticsearch .common .unit .ByteSizeValue ;
5146import org .elasticsearch .common .unit .TimeValue ;
5247import org .elasticsearch .common .xcontent .NamedXContentRegistry ;
48+ import org .elasticsearch .core .internal .io .IOUtils ;
5349import org .elasticsearch .gateway .MetaDataStateFormat ;
5450import org .elasticsearch .index .Index ;
5551import org .elasticsearch .index .IndexSettings ;
6359
6460import java .io .Closeable ;
6561import java .io .IOException ;
62+ import java .io .UncheckedIOException ;
6663import java .nio .file .AtomicMoveNotSupportedException ;
6764import java .nio .file .DirectoryStream ;
6865import java .nio .file .FileStore ;
7471import java .util .Collection ;
7572import java .util .HashMap ;
7673import java .util .HashSet ;
74+ import java .util .Iterator ;
7775import java .util .List ;
7876import java .util .Locale ;
7977import java .util .Map ;
8482import java .util .concurrent .atomic .AtomicBoolean ;
8583import java .util .concurrent .atomic .AtomicReference ;
8684import java .util .function .Predicate ;
85+ import java .util .stream .Collectors ;
86+ import java .util .stream .Stream ;
8787
8888import static java .util .Collections .unmodifiableSet ;
8989
@@ -440,7 +440,7 @@ private static String toString(Collection<String> items) {
440440 public void deleteShardDirectorySafe (ShardId shardId , IndexSettings indexSettings ) throws IOException , ShardLockObtainFailedException {
441441 final Path [] paths = availableShardPaths (shardId );
442442 logger .trace ("deleting shard {} directory, paths: [{}]" , shardId , paths );
443- try (ShardLock lock = shardLock (shardId )) {
443+ try (ShardLock lock = shardLock (shardId , "shard deletion under lock" )) {
444444 deleteShardDirectoryUnderLock (lock , indexSettings );
445445 }
446446 }
@@ -532,7 +532,7 @@ private static boolean assertPathsDoNotExist(final Path[] paths) {
532532
533533 private boolean isShardLocked (ShardId id ) {
534534 try {
535- shardLock (id , 0 ).close ();
535+ shardLock (id , "checking if shard is locked" ).close ();
536536 return false ;
537537 } catch (ShardLockObtainFailedException ex ) {
538538 return true ;
@@ -551,7 +551,7 @@ private boolean isShardLocked(ShardId id) {
551551 */
552552 public void deleteIndexDirectorySafe (Index index , long lockTimeoutMS , IndexSettings indexSettings )
553553 throws IOException , ShardLockObtainFailedException {
554- final List <ShardLock > locks = lockAllForIndex (index , indexSettings , lockTimeoutMS );
554+ final List <ShardLock > locks = lockAllForIndex (index , indexSettings , "deleting index directory" , lockTimeoutMS );
555555 try {
556556 deleteIndexDirectoryUnderLock (index , indexSettings );
557557 } finally {
@@ -586,7 +586,8 @@ public void deleteIndexDirectoryUnderLock(Index index, IndexSettings indexSettin
586586 * @param lockTimeoutMS how long to wait for acquiring the indices shard locks
587587 * @return the {@link ShardLock} instances for this index.
588588 */
589- public List <ShardLock > lockAllForIndex (Index index , IndexSettings settings , long lockTimeoutMS ) throws ShardLockObtainFailedException {
589+ public List <ShardLock > lockAllForIndex (final Index index , final IndexSettings settings ,
590+ final String lockDetails , final long lockTimeoutMS ) throws ShardLockObtainFailedException {
590591 final int numShards = settings .getNumberOfShards ();
591592 if (numShards <= 0 ) {
592593 throw new IllegalArgumentException ("settings must contain a non-null > 0 number of shards" );
@@ -598,7 +599,7 @@ public List<ShardLock> lockAllForIndex(Index index, IndexSettings settings, long
598599 try {
599600 for (int i = 0 ; i < numShards ; i ++) {
600601 long timeoutLeftMS = Math .max (0 , lockTimeoutMS - TimeValue .nsecToMSec ((System .nanoTime () - startTimeNS )));
601- allLocks .add (shardLock (new ShardId (index , i ), timeoutLeftMS ));
602+ allLocks .add (shardLock (new ShardId (index , i ), lockDetails , timeoutLeftMS ));
602603 }
603604 success = true ;
604605 } finally {
@@ -619,10 +620,11 @@ public List<ShardLock> lockAllForIndex(Index index, IndexSettings settings, long
619620 * Note: this method will return immediately if the lock can't be acquired.
620621 *
621622 * @param id the shard ID to lock
623+ * @param details information about why the shard is being locked
622624 * @return the shard lock. Call {@link ShardLock#close()} to release the lock
623625 */
624- public ShardLock shardLock (ShardId id ) throws ShardLockObtainFailedException {
625- return shardLock (id , 0 );
626+ public ShardLock shardLock (ShardId id , final String details ) throws ShardLockObtainFailedException {
627+ return shardLock (id , details , 0 );
626628 }
627629
628630 /**
@@ -631,11 +633,13 @@ public ShardLock shardLock(ShardId id) throws ShardLockObtainFailedException {
631633 * or recover from a different shard instance into it. If the shard lock can not be acquired
632634 * a {@link ShardLockObtainFailedException} is thrown
633635 * @param shardId the shard ID to lock
636+ * @param details information about why the shard is being locked
634637 * @param lockTimeoutMS the lock timeout in milliseconds
635638 * @return the shard lock. Call {@link ShardLock#close()} to release the lock
636639 */
637- public ShardLock shardLock (final ShardId shardId , long lockTimeoutMS ) throws ShardLockObtainFailedException {
638- logger .trace ("acquiring node shardlock on [{}], timeout [{}]" , shardId , lockTimeoutMS );
640+ public ShardLock shardLock (final ShardId shardId , final String details ,
641+ final long lockTimeoutMS ) throws ShardLockObtainFailedException {
642+ logger .trace ("acquiring node shardlock on [{}], timeout [{}], details [{}]" , shardId , lockTimeoutMS , details );
639643 final InternalShardLock shardLock ;
640644 final boolean acquired ;
641645 synchronized (shardLocks ) {
@@ -644,15 +648,15 @@ public ShardLock shardLock(final ShardId shardId, long lockTimeoutMS) throws Sha
644648 shardLock .incWaitCount ();
645649 acquired = false ;
646650 } else {
647- shardLock = new InternalShardLock (shardId );
651+ shardLock = new InternalShardLock (shardId , details );
648652 shardLocks .put (shardId , shardLock );
649653 acquired = true ;
650654 }
651655 }
652656 if (acquired == false ) {
653657 boolean success = false ;
654658 try {
655- shardLock .acquire (lockTimeoutMS );
659+ shardLock .acquire (lockTimeoutMS , details );
656660 success = true ;
657661 } finally {
658662 if (success == false ) {
@@ -671,11 +675,11 @@ protected void closeInternal() {
671675 }
672676
673677 /**
674- * A functional interface that people can use to reference {@link #shardLock(ShardId, long)}
678+ * A functional interface that people can use to reference {@link #shardLock(ShardId, String, long)}
675679 */
676680 @ FunctionalInterface
677681 public interface ShardLocker {
678- ShardLock lock (ShardId shardId , long lockTimeoutMS ) throws ShardLockObtainFailedException ;
682+ ShardLock lock (ShardId shardId , String lockDetails , long lockTimeoutMS ) throws ShardLockObtainFailedException ;
679683 }
680684
681685 /**
@@ -698,11 +702,13 @@ private final class InternalShardLock {
698702 */
699703 private final Semaphore mutex = new Semaphore (1 );
700704 private int waitCount = 1 ; // guarded by shardLocks
705+ private String lockDetails ;
701706 private final ShardId shardId ;
702707
703- InternalShardLock (ShardId shardId ) {
708+ InternalShardLock (final ShardId shardId , final String details ) {
704709 this .shardId = shardId ;
705710 mutex .acquireUninterruptibly ();
711+ lockDetails = details ;
706712 }
707713
708714 protected void release () {
@@ -730,11 +736,14 @@ private void decWaitCount() {
730736 }
731737 }
732738
733- void acquire (long timeoutInMillis ) throws ShardLockObtainFailedException {
739+ void acquire (long timeoutInMillis , final String details ) throws ShardLockObtainFailedException {
734740 try {
735- if (mutex .tryAcquire (timeoutInMillis , TimeUnit .MILLISECONDS ) == false ) {
741+ if (mutex .tryAcquire (timeoutInMillis , TimeUnit .MILLISECONDS )) {
742+ lockDetails = details ;
743+ } else {
736744 throw new ShardLockObtainFailedException (shardId ,
737- "obtaining shard lock timed out after " + timeoutInMillis + "ms" );
745+ "obtaining shard lock timed out after " + timeoutInMillis + "ms, previous lock details: [" + lockDetails +
746+ "] trying to lock for [" + details + "]" );
738747 }
739748 } catch (InterruptedException e ) {
740749 Thread .currentThread ().interrupt ();
0 commit comments