/// <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); } }
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()); }
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()); }
/// <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); } }
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); } } }
/// <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); } }
/// <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); } }