Example #1
0
        private bool IsLockAvailable(bool checkExternalHolderOnly, out NamedPipeMessages.LockData existingExternalHolder)
        {
            lock (this.acquisitionLock)
            {
                if (!checkExternalHolderOnly &&
                    this.currentLockHolder.IsGSD)
                {
                    existingExternalHolder = null;
                    return(false);
                }

                bool externalHolderTerminatedWithoutReleasingLock;
                existingExternalHolder = this.currentLockHolder.GetExternalHolder(
                    out externalHolderTerminatedWithoutReleasingLock);

                if (externalHolderTerminatedWithoutReleasingLock)
                {
                    this.ReleaseLockForTerminatedProcess(existingExternalHolder.PID);
                    this.tracer.SetGitCommandSessionId(string.Empty);
                    existingExternalHolder = null;
                }

                return(existingExternalHolder == null);
            }
        }
Example #2
0
        /// <summary>
        /// Allow GSD to acquire the lock.
        /// </summary>
        /// <returns>True if GSD was able to acquire the lock or if it already held it. False othwerwise.</returns>
        public bool TryAcquireLockForGSD()
        {
            EventMetadata metadata = new EventMetadata();

            try
            {
                lock (this.acquisitionLock)
                {
                    if (this.currentLockHolder.IsGSD)
                    {
                        return(true);
                    }

                    NamedPipeMessages.LockData existingExternalHolder = this.GetExternalHolder();
                    if (existingExternalHolder != null)
                    {
                        metadata.Add("CurrentLockHolder", existingExternalHolder.ToString());
                        metadata.Add("Result", "Denied");
                        return(false);
                    }

                    this.currentLockHolder.AcquireForGSD();
                    metadata.Add("Result", "Accepted");
                    return(true);
                }
            }
            finally
            {
                this.tracer.RelatedEvent(EventLevel.Verbose, "TryAcquireLockInternal", metadata);
            }
        }
        public bool IsReadyForExternalAcquireLockRequests(NamedPipeMessages.LockData requester, out string denyMessage)
        {
            if (!this.IsMounted)
            {
                denyMessage = "Waiting for mount to complete";
                return(false);
            }

            if (this.BackgroundOperationCount != 0)
            {
                denyMessage = "Waiting for GVFS to release the lock";
                return(false);
            }

            if (!this.GitIndexProjection.IsProjectionParseComplete())
            {
                denyMessage = "Waiting for GVFS to parse index and update placeholder files";
                return(false);
            }

            if (!this.gitStatusCache.IsReadyForExternalAcquireLockRequests(requester, out denyMessage))
            {
                return(false);
            }

            // Even though we're returning true and saying it's safe to ask for the lock
            // there is no guarantee that the lock will be acquired, because GVFS itself
            // could obtain the lock before the external holder gets it. Setting up an
            // appropriate error message in case that happens
            denyMessage = "Waiting for GVFS to release the lock";

            return(true);
        }
Example #4
0
        public string GetLockedGitCommand()
        {
            NamedPipeMessages.LockData currentHolder = this.lockHolder;
            if (currentHolder != null)
            {
                return(currentHolder.ParsedCommand);
            }

            return(null);
        }
Example #5
0
            public void AcquireForExternalRequestor(NamedPipeMessages.LockData externalLockHolder)
            {
                if (this.IsGSD ||
                    this.externalLockHolder != null)
                {
                    throw new InvalidOperationException("Cannot acquire a lock that is already held");
                }

                this.externalLockHolder = externalLockHolder;
            }
Example #6
0
        /// <summary>
        /// The GitStatusCache gets a chance to approve / deny requests for a
        /// command to take the GVFS lock. The GitStatusCache will only block
        /// if the command is a status command and there is a blocking error
        /// that might affect the correctness of the result.
        /// </summary>
        public virtual bool IsReadyForExternalAcquireLockRequests(
            NamedPipeMessages.LockData requester,
            out string infoMessage)
        {
            infoMessage = null;
            if (!this.isInitialized)
            {
                return(true);
            }

            GitCommandLineParser gitCommand = new GitCommandLineParser(requester.ParsedCommand);

            if (!gitCommand.IsVerb(GitCommandLineParser.Verbs.Status) ||
                gitCommand.IsSerializedStatus())
            {
                return(true);
            }

            bool shouldAllowExternalRequest = true;
            bool isCacheReady = false;

            lock (this.cacheFileLock)
            {
                if (this.IsCacheReadyAndUpToDate())
                {
                    isCacheReady = true;
                }
                else
                {
                    if (!this.TryDeleteStatusCacheFile())
                    {
                        shouldAllowExternalRequest = false;
                        infoMessage = string.Format("Unable to delete stale status cache file at: {0}", this.serializedGitStatusFilePath);
                    }
                }
            }

            if (isCacheReady)
            {
                this.statistics.RecordCacheReady();
            }
            else
            {
                this.statistics.RecordCacheNotReady();
            }

            if (!shouldAllowExternalRequest)
            {
                this.statistics.RecordBlockedRequest();
            }

            this.context.Tracer.RelatedInfo("GitStatusCache.IsReadyForExternalAcquireLockRequests: isCacheReady: {0}, shouldAllowRequest: {1}", isCacheReady, shouldAllowExternalRequest);

            return(shouldAllowExternalRequest);
        }
Example #7
0
        private void HandleLockRequest(string messageBody, NamedPipeServer.Connection connection)
        {
            NamedPipeMessages.AcquireLock.Response response;

            NamedPipeMessages.LockRequest request   = new NamedPipeMessages.LockRequest(messageBody);
            NamedPipeMessages.LockData    requester = request.RequestData;
            if (this.currentState == MountState.Unmounting)
            {
                response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.UnmountInProgressResult);

                EventMetadata metadata = new EventMetadata();
                metadata.Add("LockRequest", requester.ToString());
                metadata.Add(TracingConstants.MessageKey.InfoMessage, "Request denied, unmount in progress");
                this.tracer.RelatedEvent(EventLevel.Informational, "HandleLockRequest_UnmountInProgress", metadata);
            }
            else if (this.currentState != MountState.Ready)
            {
                response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.MountNotReadyResult);
            }
            else
            {
                bool lockAcquired = false;

                NamedPipeMessages.LockData existingExternalHolder = null;
                string denyGVFSMessage = null;

                bool lockAvailable = this.context.Repository.GVFSLock.IsLockAvailableForExternalRequestor(out existingExternalHolder);
                bool isReadyForExternalLockRequests = this.fileSystemCallbacks.IsReadyForExternalAcquireLockRequests(requester, out denyGVFSMessage);

                if (!requester.CheckAvailabilityOnly && isReadyForExternalLockRequests)
                {
                    lockAcquired = this.context.Repository.GVFSLock.TryAcquireLockForExternalRequestor(requester, out existingExternalHolder);
                }

                if (requester.CheckAvailabilityOnly && lockAvailable && isReadyForExternalLockRequests)
                {
                    response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.AvailableResult);
                }
                else if (lockAcquired)
                {
                    response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.AcceptResult);
                    this.tracer.SetGitCommandSessionId(requester.GitCommandSessionId);
                }
                else if (existingExternalHolder == null)
                {
                    response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.DenyGVFSResult, responseData: null, denyGVFSMessage: denyGVFSMessage);
                }
                else
                {
                    response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.DenyGitResult, existingExternalHolder);
                }
            }

            connection.TrySendResponse(response.CreateMessage());
        }
Example #8
0
        private void HandleLockRequest(string messageBody, NamedPipeServer.Connection connection)
        {
            NamedPipeMessages.AcquireLock.Response response;
            NamedPipeMessages.LockData             externalHolder;

            NamedPipeMessages.LockRequest request   = new NamedPipeMessages.LockRequest(messageBody);
            NamedPipeMessages.LockData    requester = request.RequestData;
            if (request == null)
            {
                response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.UnknownRequest, requester);
            }
            else if (this.currentState == MountState.Unmounting)
            {
                response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.UnmountInProgressResult);

                EventMetadata metadata = new EventMetadata();
                metadata.Add("LockRequest", requester.ToString());
                metadata.Add(TracingConstants.MessageKey.InfoMessage, "Request denied, unmount in progress");
                this.tracer.RelatedEvent(EventLevel.Informational, "HandleLockRequest_UnmountInProgress", metadata);
            }
            else if (this.currentState != MountState.Ready)
            {
                response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.MountNotReadyResult);
            }
            else
            {
                bool   lockAcquired = false;
                string denyMessage;
                if (this.gvfltCallbacks.IsReadyForExternalAcquireLockRequests(requester, out denyMessage))
                {
                    lockAcquired = this.context.Repository.GVFSLock.TryAcquireLock(requester, out externalHolder);
                }
                else
                {
                    // There might be an external lock holder, and it should be reported to the user
                    externalHolder = this.context.Repository.GVFSLock.GetExternalLockHolder();
                }

                if (lockAcquired)
                {
                    response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.AcceptResult);
                }
                else if (externalHolder == null)
                {
                    response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.DenyGVFSResult, responseData: null, denyGVFSMessage: denyMessage);
                }
                else
                {
                    response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.DenyGitResult, externalHolder);
                }
            }

            connection.TrySendResponse(response.CreateMessage());
        }
Example #9
0
        public void TryAcquireLockForExternalRequestor_WhenExternalLock()
        {
            MockPlatform mockPlatform = (MockPlatform)GVFSPlatform.Instance;
            GVFSLock     gvfsLock     = this.AcquireDefaultLock(mockPlatform);

            NamedPipeMessages.LockData newLockData = new NamedPipeMessages.LockData(4321, false, false, "git new");
            NamedPipeMessages.LockData existingExternalHolder;
            gvfsLock.TryAcquireLockForExternalRequestor(newLockData, out existingExternalHolder).ShouldBeFalse();
            this.ValidateLockHeld(gvfsLock, DefaultLockData);
            this.ValidateExistingExternalHolder(DefaultLockData, existingExternalHolder);
            mockPlatform.ActiveProcesses.Remove(DefaultLockData.PID);
        }
Example #10
0
        public string GetLockedGitCommand()
        {
            // In this code path, we don't care if the process terminated without releasing the lock. The calling code
            // is asking us about this lock so that it can determine if git was the cause of certain IO events. Even
            // if the git process has terminated, the answer to that question does not change.
            NamedPipeMessages.LockData currentHolder = this.currentLockHolder.GetExternalHolder();

            if (currentHolder != null)
            {
                return(currentHolder.ParsedCommand);
            }

            return(null);
        }
Example #11
0
        /// <summary>
        /// Allows external callers (non-GVFS) to acquire the lock.
        /// </summary>
        /// <param name="requester">The data for the external acquisition request.</param>
        /// <param name="holder">The current holder of the lock if the acquisition fails.</param>
        /// <returns>True if the lock was acquired, false otherwise.</returns>
        public bool TryAcquireLock(
            NamedPipeMessages.LockData requester,
            out NamedPipeMessages.LockData holder)
        {
            EventMetadata metadata   = new EventMetadata();
            EventLevel    eventLevel = EventLevel.Verbose;

            metadata.Add("LockRequest", requester.ToString());
            metadata.Add("IsElevated", requester.IsElevated);

            holder = null;

            try
            {
                lock (this.acquisitionLock)
                {
                    if (this.IsLockedByGVFS)
                    {
                        metadata.Add("CurrentLockHolder", "GVFS");
                        metadata.Add("Result", "Denied");

                        return(false);
                    }

                    if (this.IsExternalLockHolderAlive() &&
                        this.lockHolder.PID != requester.PID)
                    {
                        metadata.Add("CurrentLockHolder", this.lockHolder.ToString());
                        metadata.Add("Result", "Denied");

                        holder = this.lockHolder;
                        return(false);
                    }

                    metadata.Add("Result", "Accepted");
                    eventLevel = EventLevel.Informational;

                    this.lockHolder = requester;
                    this.externalLockReleased.Reset();
                    this.stats = new Stats();

                    return(true);
                }
            }
            finally
            {
                this.tracer.RelatedEvent(eventLevel, "TryAcquireLockExternal", metadata);
            }
        }
Example #12
0
        public string GetStatus()
        {
            if (this.IsLockedByGVFS)
            {
                return("Held by GVFS.");
            }

            NamedPipeMessages.LockData currentHolder = this.lockHolder;
            if (currentHolder != null)
            {
                return(string.Format("Held by {0} (PID:{1})", currentHolder.ParsedCommand, currentHolder.PID));
            }

            return("Free");
        }
Example #13
0
 private void ValidateLock(
     GVFSLock gvfsLock,
     NamedPipeMessages.LockData expected,
     string expectedStatus,
     string expectedGitCommand,
     bool expectedIsAvailable)
 {
     gvfsLock.GetStatus().ShouldEqual(expectedStatus);
     NamedPipeMessages.LockData existingHolder;
     gvfsLock.IsLockAvailableForExternalRequestor(out existingHolder).ShouldEqual(expectedIsAvailable);
     this.ValidateExistingExternalHolder(expected, existingHolder);
     gvfsLock.GetLockedGitCommand().ShouldEqual(expectedGitCommand);
     NamedPipeMessages.LockData externalHolder = gvfsLock.GetExternalHolder();
     this.ValidateExistingExternalHolder(expected, externalHolder);
 }
Example #14
0
        private bool ReleaseExternalLock(int pid, string eventName)
        {
            lock (this.acquisitionLock)
            {
                EventMetadata metadata = new EventMetadata();

                try
                {
                    if (this.currentLockHolder.IsGVFS)
                    {
                        metadata.Add("IsLockedByGVFS", "true");
                        return(false);
                    }

                    // We don't care if the process has already terminated. We're just trying to record the info for the last holder.
                    bool externalHolderTerminatedWithoutReleasingLock;
                    NamedPipeMessages.LockData previousExternalHolder = this.currentLockHolder.GetExternalHolder(
                        out externalHolderTerminatedWithoutReleasingLock);

                    if (previousExternalHolder == null)
                    {
                        metadata.Add("Result", "Failed (no current holder, requested PID=" + pid + ")");
                        return(false);
                    }

                    metadata.Add("CurrentLockHolder", previousExternalHolder.ToString());
                    metadata.Add("IsElevated", previousExternalHolder.IsElevated);
                    metadata.Add(nameof(RepoMetadata.Instance.EnlistmentId), RepoMetadata.Instance.EnlistmentId);

                    if (previousExternalHolder.PID != pid)
                    {
                        metadata.Add("pid", pid);
                        metadata.Add("Result", "Failed (wrong PID)");
                        return(false);
                    }

                    this.currentLockHolder.Release();
                    metadata.Add("Result", "Released");
                    this.Stats.AddStatsToTelemetry(metadata);

                    return(true);
                }
                finally
                {
                    this.tracer.RelatedEvent(EventLevel.Informational, eventName, metadata, Keywords.Telemetry);
                }
            }
        }
Example #15
0
 private void ValidateExistingExternalHolder(NamedPipeMessages.LockData expected, NamedPipeMessages.LockData actual)
 {
     if (actual != null)
     {
         expected.ShouldNotBeNull();
         actual.ShouldNotBeNull();
         actual.PID.ShouldEqual(expected.PID);
         actual.IsElevated.ShouldEqual(expected.IsElevated);
         actual.CheckAvailabilityOnly.ShouldEqual(expected.CheckAvailabilityOnly);
         actual.ParsedCommand.ShouldEqual(expected.ParsedCommand);
     }
     else
     {
         expected.ShouldBeNull();
     }
 }
Example #16
0
        /// <summary>
        /// Allows external callers (non-GSD) to acquire the lock.
        /// </summary>
        /// <param name="requestor">The data for the external acquisition request.</param>
        /// <param name="existingExternalHolder">The current holder of the lock if the acquisition fails.</param>
        /// <returns>True if the lock was acquired, false otherwise.</returns>
        public bool TryAcquireLockForExternalRequestor(
            NamedPipeMessages.LockData requestor,
            out NamedPipeMessages.LockData existingExternalHolder)
        {
            EventMetadata metadata   = new EventMetadata();
            EventLevel    eventLevel = EventLevel.Verbose;

            metadata.Add("LockRequest", requestor.ToString());
            metadata.Add("IsElevated", requestor.IsElevated);

            existingExternalHolder = null;

            try
            {
                lock (this.acquisitionLock)
                {
                    if (this.currentLockHolder.IsGSD)
                    {
                        metadata.Add("CurrentLockHolder", "GSD");
                        metadata.Add("Result", "Denied");

                        return(false);
                    }

                    existingExternalHolder = this.GetExternalHolder();
                    if (existingExternalHolder != null)
                    {
                        metadata.Add("CurrentLockHolder", existingExternalHolder.ToString());
                        metadata.Add("Result", "Denied");

                        return(false);
                    }

                    metadata.Add("Result", "Accepted");
                    eventLevel = EventLevel.Informational;

                    this.currentLockHolder.AcquireForExternalRequestor(requestor);
                    this.Stats = new ActiveGitCommandStats();

                    return(true);
                }
            }
            finally
            {
                this.tracer.RelatedEvent(eventLevel, "TryAcquireLockExternal", metadata);
            }
        }
Example #17
0
        public void TryAcquireLockForExternalRequestor_WhenExternalLock()
        {
            Mock <ITracer> mockTracer = new Mock <ITracer>(MockBehavior.Strict);

            mockTracer.Setup(x => x.RelatedEvent(EventLevel.Informational, "TryAcquireLockExternal", It.IsAny <EventMetadata>()));
            mockTracer.Setup(x => x.RelatedEvent(EventLevel.Verbose, "TryAcquireLockExternal", It.IsAny <EventMetadata>()));
            MockPlatform mockPlatform = (MockPlatform)GVFSPlatform.Instance;
            GVFSLock     gvfsLock     = this.AcquireDefaultLock(mockPlatform, mockTracer.Object);

            NamedPipeMessages.LockData newLockData = new NamedPipeMessages.LockData(4321, false, false, "git new", "123");
            NamedPipeMessages.LockData existingExternalHolder;
            gvfsLock.TryAcquireLockForExternalRequestor(newLockData, out existingExternalHolder).ShouldBeFalse();
            this.ValidateLockHeld(gvfsLock, DefaultLockData);
            this.ValidateExistingExternalHolder(DefaultLockData, existingExternalHolder);
            mockPlatform.ActiveProcesses.Remove(DefaultLockData.PID);
            mockTracer.VerifyAll();
        }
Example #18
0
        public string GetStatus()
        {
            lock (this.acquisitionLock)
            {
                if (this.currentLockHolder.IsGSD)
                {
                    return("Held by GSD.");
                }

                NamedPipeMessages.LockData externalHolder = this.GetExternalHolder();
                if (externalHolder != null)
                {
                    return(string.Format("Held by {0} (PID:{1})", externalHolder.ParsedCommand, externalHolder.PID));
                }
            }

            return("Free");
        }
Example #19
0
        private void HandleLockRequest(string messageBody, NamedPipeServer.Connection connection)
        {
            NamedPipeMessages.AcquireLock.Response response;
            NamedPipeMessages.LockData             externalHolder;

            NamedPipeMessages.LockRequest request   = new NamedPipeMessages.LockRequest(messageBody);
            NamedPipeMessages.LockData    requester = request.RequestData;
            if (request == null)
            {
                response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.UnknownRequest, requester);
            }
            else if (this.currentState != MountState.Ready)
            {
                response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.MountNotReadyResult);
            }
            else
            {
                bool lockAcquired = false;
                if (this.gvfltCallbacks.IsReadyForExternalAcquireLockRequests())
                {
                    lockAcquired = this.gvfsLock.TryAcquireLock(requester, out externalHolder);
                }
                else
                {
                    // There might be an external lock holder, and it should be reported to the user
                    externalHolder = this.gvfsLock.GetExternalLockHolder();
                }

                if (lockAcquired)
                {
                    response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.AcceptResult);
                }
                else if (externalHolder == null)
                {
                    response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.DenyGVFSResult);
                }
                else
                {
                    response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.DenyGitResult, externalHolder);
                }
            }

            connection.TrySendResponse(response.CreateMessage());
        }
Example #20
0
        private bool ReleaseExternalLock(int pid, string eventName)
        {
            lock (this.acquisitionLock)
            {
                EventMetadata metadata = new EventMetadata();

                try
                {
                    if (this.isLockedByGVFS)
                    {
                        metadata.Add("IsLockedByGVFS", "true");
                        return(false);
                    }

                    if (this.externalLockHolder == null)
                    {
                        metadata.Add("Result", "Failed (no current holder, requested PID=" + pid + ")");
                        return(false);
                    }

                    metadata.Add("CurrentLockHolder", this.externalLockHolder.ToString());
                    metadata.Add("IsElevated", this.externalLockHolder.IsElevated);
                    metadata.Add(nameof(RepoMetadata.Instance.EnlistmentId), RepoMetadata.Instance.EnlistmentId);

                    if (this.externalLockHolder.PID != pid)
                    {
                        metadata.Add("pid", pid);
                        metadata.Add("Result", "Failed (wrong PID)");
                        return(false);
                    }

                    this.externalLockHolder = null;
                    metadata.Add("Result", "Released");
                    this.Stats.AddStatsToTelemetry(metadata);

                    return(true);
                }
                finally
                {
                    this.tracer.RelatedEvent(EventLevel.Informational, eventName, metadata, Keywords.Telemetry);
                }
            }
        }
Example #21
0
        private bool ReleaseExternalLock(int pid, string eventName)
        {
            lock (this.acquisitionLock)
            {
                EventMetadata metadata = new EventMetadata();

                try
                {
                    if (this.IsLockedByGVFS)
                    {
                        metadata.Add("IsLockedByGVFS", "true");
                        return(false);
                    }

                    if (this.lockHolder == null)
                    {
                        metadata.Add("Result", "Failed (no current holder, requested PID=" + pid + ")");
                        return(false);
                    }

                    metadata.Add("CurrentLockHolder", this.lockHolder.ToString());
                    metadata.Add("IsElevated", this.lockHolder.IsElevated);

                    if (this.lockHolder.PID != pid)
                    {
                        metadata.Add("pid", pid);
                        metadata.Add("Result", "Failed (wrong PID)");
                        return(false);
                    }

                    this.lockHolder = null;
                    this.processWatcher.StopWatching(pid);
                    this.externalLockReleased.Set();
                    metadata.Add("Result", "Released");
                    return(true);
                }
                finally
                {
                    this.tracer.RelatedEvent(EventLevel.Informational, eventName, metadata);
                }
            }
        }
Example #22
0
        public void TryAcquireLockForExternalRequestor_WhenExternalHolderTerminated()
        {
            Mock <ITracer> mockTracer = new Mock <ITracer>(MockBehavior.Strict);

            mockTracer.Setup(x => x.RelatedEvent(EventLevel.Informational, "TryAcquireLockExternal", It.IsAny <EventMetadata>()));
            mockTracer.Setup(x => x.RelatedEvent(EventLevel.Informational, "ExternalLockHolderExited", It.IsAny <EventMetadata>(), Keywords.Telemetry));
            mockTracer.Setup(x => x.SetGitCommandSessionId(string.Empty));
            MockPlatform mockPlatform = (MockPlatform)GVFSPlatform.Instance;
            GVFSLock     gvfsLock     = this.AcquireDefaultLock(mockPlatform, mockTracer.Object);

            mockPlatform.ActiveProcesses.Remove(DefaultLockData.PID);

            NamedPipeMessages.LockData newLockData = new NamedPipeMessages.LockData(4321, false, false, "git new", "123");
            mockPlatform.ActiveProcesses.Add(newLockData.PID);
            NamedPipeMessages.LockData existingExternalHolder;
            gvfsLock.TryAcquireLockForExternalRequestor(newLockData, out existingExternalHolder).ShouldBeTrue();
            existingExternalHolder.ShouldBeNull();
            this.ValidateLockHeld(gvfsLock, newLockData);
            mockTracer.VerifyAll();
        }
Example #23
0
        /// <summary>
        /// Allows external callers (non-GVFS) to acquire the lock.
        /// </summary>
        /// <param name="requester">The data for the external acquisition request.</param>
        /// <param name="holder">
        /// The current holder of the lock if the acquisition fails, or
        /// the input request if it succeeds.
        /// </param>
        /// <returns>True if the lock was acquired, false otherwise.</returns>
        public bool TryAcquireLock(
            NamedPipeMessages.LockData requester,
            out NamedPipeMessages.LockData holder)
        {
            EventMetadata metadata   = new EventMetadata();
            EventLevel    eventLevel = EventLevel.Verbose;

            metadata.Add("LockRequest", requester.ToString());
            try
            {
                lock (this.acquisitionLock)
                {
                    if (this.IsLockedByGVFS)
                    {
                        holder = null;
                        metadata.Add("CurrentLockHolder", "GVFS");
                        metadata.Add("Result", "Denied");

                        return(false);
                    }

                    if (this.lockHolder != null &&
                        this.lockHolder.PID != requester.PID)
                    {
                        holder = this.lockHolder;

                        metadata.Add("CurrentLockHolder", this.lockHolder.ToString());
                        metadata.Add("Result", "Denied");
                        return(false);
                    }

                    metadata.Add("Result", "Accepted");
                    eventLevel = EventLevel.Informational;

                    Process process;
                    if (ProcessHelper.TryGetProcess(requester.PID, out process))
                    {
                        this.processWatcher.WatchForTermination(requester.PID, GVFSConstants.CommandParentExecutableNames);

                        process.Dispose();
                        this.lockHolder = requester;
                        holder          = requester;
                        this.externalLockReleased.Reset();

                        return(true);
                    }
                    else
                    {
                        // Process is no longer running so let it
                        // succeed since the process non-existence
                        // signals the lock release.
                        if (process != null)
                        {
                            process.Dispose();
                        }

                        holder = null;
                        return(true);
                    }
                }
            }
            finally
            {
                this.tracer.RelatedEvent(eventLevel, "TryAcquireLockExternal", metadata);
            }
        }
Example #24
0
 public override bool IsReadyForExternalAcquireLockRequests(NamedPipeMessages.LockData requester, out string infoMessage)
 {
     infoMessage = string.Empty;
     return(true);
 }
Example #25
0
 private void ValidateLockHeld(GVFSLock gvfsLock, NamedPipeMessages.LockData expected)
 {
     this.ValidateLock(gvfsLock, expected, expectedStatus: $"Held by {expected.ParsedCommand} (PID:{expected.PID})", expectedGitCommand: expected.ParsedCommand, expectedIsAvailable: false);
 }
Example #26
0
 public bool IsLockAvailableForExternalRequestor(out NamedPipeMessages.LockData existingExternalHolder)
 {
     return(this.IsLockAvailable(checkExternalHolderOnly: false, existingExternalHolder: out existingExternalHolder));
 }
Example #27
0
 public void Release()
 {
     this.IsGSD = false;
     this.externalLockHolder = null;
 }