예제 #1
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);
            }
        }
예제 #2
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());
        }
예제 #3
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());
        }
예제 #4
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);
            }
        }
예제 #5
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);
                }
            }
        }
예제 #6
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);
            }
        }
예제 #7
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);
            }
        }