private bool TryAcquireLockWithRetries(ITracer tracer, FileBasedLock mappingLock)
        {
            const int NumRetries = 100;
            const int WaitTimeMs = 100;

            for (int i = 0; i < NumRetries; ++i)
            {
                if (mappingLock.TryAcquireLockAndDeleteOnClose())
                {
                    return(true);
                }
                else if (i < NumRetries - 1)
                {
                    Thread.Sleep(WaitTimeMs);

                    if (i % 20 == 0)
                    {
                        tracer.RelatedInfo("Waiting to acquire local cacke metadata lock file");
                    }
                }
            }

            return(false);
        }
        public bool TryGetLocalCacheKeyFromLocalConfigOrRemoteCacheServers(
            ITracer tracer,
            GVFSConfig gvfsConfig,
            CacheServerInfo currentCacheServer,
            string localCacheRoot,
            out string localCacheKey,
            out string errorMessage)
        {
            if (gvfsConfig == null)
            {
                throw new ArgumentNullException(nameof(gvfsConfig));
            }

            localCacheKey = null;
            errorMessage  = string.Empty;

            try
            {
                // A lock is required because FileBasedDictionary is not multi-process safe, neither is the act of adding a new cache
                string lockPath = Path.Combine(localCacheRoot, MappingFile + ".lock");
                this.fileSystem.CreateDirectory(localCacheRoot);

                using (FileBasedLock mappingLock = new FileBasedLock(
                           this.fileSystem,
                           tracer,
                           lockPath,
                           this.enlistment.EnlistmentRoot,
                           overwriteExistingLock: true))
                {
                    if (!this.TryAcquireLockWithRetries(tracer, mappingLock))
                    {
                        errorMessage = "Failed to acquire lock file at " + lockPath;
                        tracer.RelatedError(nameof(this.TryGetLocalCacheKeyFromLocalConfigOrRemoteCacheServers) + ": " + errorMessage);
                        return(false);
                    }

                    FileBasedDictionary <string, string> mappingFile;
                    if (this.TryOpenMappingFile(tracer, localCacheRoot, out mappingFile, out errorMessage))
                    {
                        try
                        {
                            string mappingDataVersion;
                            if (mappingFile.TryGetValue(MappingVersionKey, out mappingDataVersion))
                            {
                                if (mappingDataVersion != CurrentMappingDataVersion)
                                {
                                    errorMessage = string.Format("Mapping file has different version than expected: {0} Actual: {1}", CurrentMappingDataVersion, mappingDataVersion);
                                    tracer.RelatedError(nameof(this.TryGetLocalCacheKeyFromLocalConfigOrRemoteCacheServers) + ": " + errorMessage);
                                    return(false);
                                }
                            }
                            else
                            {
                                mappingFile.SetValueAndFlush(MappingVersionKey, CurrentMappingDataVersion);
                            }

                            if (mappingFile.TryGetValue(this.ToMappingKey(this.enlistment.RepoUrl), out localCacheKey) ||
                                (currentCacheServer.HasValidUrl() && mappingFile.TryGetValue(this.ToMappingKey(currentCacheServer.Url), out localCacheKey)))
                            {
                                EventMetadata metadata = CreateEventMetadata();
                                metadata.Add("localCacheKey", localCacheKey);
                                metadata.Add("this.enlistment.RepoUrl", this.enlistment.RepoUrl);
                                metadata.Add("currentCacheServer", currentCacheServer.ToString());
                                metadata.Add(TracingConstants.MessageKey.InfoMessage, nameof(this.TryGetLocalCacheKeyFromLocalConfigOrRemoteCacheServers) + ": Found existing local cache key");
                                tracer.RelatedEvent(EventLevel.Informational, "LocalCacheResolver_ExistingKey", metadata);

                                return(true);
                            }
                            else
                            {
                                EventMetadata metadata = CreateEventMetadata();
                                metadata.Add("this.enlistment.RepoUrl", this.enlistment.RepoUrl);
                                metadata.Add("currentCacheServer", currentCacheServer.ToString());

                                string getLocalCacheKeyError;
                                if (this.TryGetLocalCacheKeyFromRemoteCacheServers(tracer, gvfsConfig, currentCacheServer, mappingFile, out localCacheKey, out getLocalCacheKeyError))
                                {
                                    metadata.Add("localCacheKey", localCacheKey);
                                    metadata.Add(TracingConstants.MessageKey.InfoMessage, nameof(this.TryGetLocalCacheKeyFromLocalConfigOrRemoteCacheServers) + ": Generated new local cache key");
                                    tracer.RelatedEvent(EventLevel.Informational, "LocalCacheResolver_NewKey", metadata);
                                    return(true);
                                }

                                metadata.Add("getLocalCacheKeyError", getLocalCacheKeyError);
                                tracer.RelatedError(metadata, nameof(this.TryGetLocalCacheKeyFromLocalConfigOrRemoteCacheServers) + ": TryGetLocalCacheKeyFromRemoteCacheServers failed");

                                errorMessage = "Failed to generate local cache key";
                                return(false);
                            }
                        }
                        finally
                        {
                            mappingFile.Dispose();
                        }
                    }

                    return(false);
                }
            }
            catch (Exception e)
            {
                EventMetadata metadata = CreateEventMetadata(e);
                metadata.Add("this.enlistment.RepoUrl", this.enlistment.RepoUrl);
                metadata.Add("currentCacheServer", currentCacheServer.ToString());
                tracer.RelatedError(metadata, nameof(this.TryGetLocalCacheKeyFromLocalConfigOrRemoteCacheServers) + ": Caught exception");

                errorMessage = string.Format("Exception while getting local cache key: {0}", e.Message);
                return(false);
            }
        }