|  | 
| 41 | 41 | import org.elasticsearch.common.Randomness; | 
| 42 | 42 | import org.elasticsearch.common.SuppressForbidden; | 
| 43 | 43 | import org.elasticsearch.common.UUIDs; | 
|  | 44 | +import org.elasticsearch.common.collect.Tuple; | 
| 44 | 45 | import org.elasticsearch.common.io.FileSystemUtils; | 
| 45 | 46 | import org.elasticsearch.common.lease.Releasable; | 
| 46 | 47 | import org.elasticsearch.common.settings.Setting; | 
| @@ -786,6 +787,11 @@ protected void closeInternal() { | 
| 786 | 787 |                 shardLock.release(); | 
| 787 | 788 |                 logger.trace("released shard lock for [{}]", shardId); | 
| 788 | 789 |             } | 
|  | 790 | + | 
|  | 791 | +            @Override | 
|  | 792 | +            public void setDetails(String details) { | 
|  | 793 | +                shardLock.setDetails(details); | 
|  | 794 | +            } | 
| 789 | 795 |         }; | 
| 790 | 796 |     } | 
| 791 | 797 | 
 | 
| @@ -817,13 +823,13 @@ private final class InternalShardLock { | 
| 817 | 823 |          */ | 
| 818 | 824 |         private final Semaphore mutex = new Semaphore(1); | 
| 819 | 825 |         private int waitCount = 1; // guarded by shardLocks | 
| 820 |  | -        private String lockDetails; | 
| 821 | 826 |         private final ShardId shardId; | 
|  | 827 | +        private volatile Tuple<Long, String> lockDetails; | 
| 822 | 828 | 
 | 
| 823 | 829 |         InternalShardLock(final ShardId shardId, final String details) { | 
| 824 | 830 |             this.shardId = shardId; | 
| 825 | 831 |             mutex.acquireUninterruptibly(); | 
| 826 |  | -            lockDetails = details; | 
|  | 832 | +            lockDetails = Tuple.tuple(System.nanoTime(), details); | 
| 827 | 833 |         } | 
| 828 | 834 | 
 | 
| 829 | 835 |         protected void release() { | 
| @@ -854,17 +860,23 @@ private void decWaitCount() { | 
| 854 | 860 |         void acquire(long timeoutInMillis, final String details) throws ShardLockObtainFailedException { | 
| 855 | 861 |             try { | 
| 856 | 862 |                 if (mutex.tryAcquire(timeoutInMillis, TimeUnit.MILLISECONDS)) { | 
| 857 |  | -                    lockDetails = details; | 
|  | 863 | +                    setDetails(details); | 
| 858 | 864 |                 } else { | 
|  | 865 | +                    final Tuple<Long, String> lockDetails = this.lockDetails; // single volatile read | 
| 859 | 866 |                     throw new ShardLockObtainFailedException(shardId, | 
| 860 |  | -                        "obtaining shard lock timed out after " + timeoutInMillis + "ms, previous lock details: [" + lockDetails + | 
| 861 |  | -                            "] trying to lock for [" + details + "]"); | 
|  | 867 | +                        "obtaining shard lock for [" + details + "] timed out after [" + timeoutInMillis + | 
|  | 868 | +                        "ms], lock already held for [" + lockDetails.v2() + "] with age [" + | 
|  | 869 | +                        TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - lockDetails.v1()) + "ms]"); | 
| 862 | 870 |                 } | 
| 863 | 871 |             } catch (InterruptedException e) { | 
| 864 | 872 |                 Thread.currentThread().interrupt(); | 
| 865 | 873 |                 throw new ShardLockObtainFailedException(shardId, "thread interrupted while trying to obtain shard lock", e); | 
| 866 | 874 |             } | 
| 867 | 875 |         } | 
|  | 876 | + | 
|  | 877 | +        public void setDetails(String details) { | 
|  | 878 | +            lockDetails = Tuple.tuple(System.nanoTime(), details); | 
|  | 879 | +        } | 
| 868 | 880 |     } | 
| 869 | 881 | 
 | 
| 870 | 882 |     public boolean hasNodeFile() { | 
|  | 
0 commit comments