Skip to content

Commit

Permalink
Remove dead GVFSLock and GitStatusCache code
Browse files Browse the repository at this point in the history
  • Loading branch information
wilbaker committed Aug 8, 2019
1 parent 3f0732c commit cedeeaa
Show file tree
Hide file tree
Showing 17 changed files with 51 additions and 1,765 deletions.
5 changes: 0 additions & 5 deletions GVFS/GVFS.Common/GVFSConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,6 @@ public static class LocalGVFSConfig
public const string OrgInfoServerUrl = "upgrade.orgInfoServerUrl";
}

public static class GitStatusCache
{
public const string EnableGitStatusCacheTokenFile = "EnableGitStatusCacheToken.dat";
}

public static class Service
{
public const string ServiceName = "GVFS.Service";
Expand Down
308 changes: 1 addition & 307 deletions GVFS/GVFS.Common/GVFSLock.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
using GVFS.Common.NamedPipes;
using GVFS.Common.Tracing;
using System;
using System.Diagnostics;
using System.Threading;

namespace GVFS.Common
{
public partial class GVFSLock
public class GVFSLock
{
private readonly object acquisitionLock = new object();
private readonly ITracer tracer;
private readonly LockHolder currentLockHolder = new LockHolder();

public GVFSLock(ITracer tracer)
{
Expand All @@ -24,238 +21,6 @@ public ActiveGitCommandStats Stats
private set;
}

/// <summary>
/// Allows external callers (non-GVFS) 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.IsGVFS)
{
metadata.Add("CurrentLockHolder", "GVFS");
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>
/// Allow GVFS to acquire the lock.
/// </summary>
/// <returns>True if GVFS was able to acquire the lock or if it already held it. False othwerwise.</returns>
public bool TryAcquireLockForGVFS()
{
EventMetadata metadata = new EventMetadata();
try
{
lock (this.acquisitionLock)
{
if (this.currentLockHolder.IsGVFS)
{
return true;
}

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

this.currentLockHolder.AcquireForGVFS();
metadata.Add("Result", "Accepted");
return true;
}
}
finally
{
this.tracer.RelatedEvent(EventLevel.Verbose, "TryAcquireLockInternal", metadata);
}
}

public void ReleaseLockHeldByGVFS()
{
lock (this.acquisitionLock)
{
if (!this.currentLockHolder.IsGVFS)
{
throw new InvalidOperationException("Cannot release lock that is not held by GVFS");
}

this.tracer.RelatedEvent(EventLevel.Verbose, nameof(this.ReleaseLockHeldByGVFS), new EventMetadata());
this.currentLockHolder.Release();
}
}

public bool ReleaseLockHeldByExternalProcess(int pid)
{
return this.ReleaseExternalLock(pid, nameof(this.ReleaseLockHeldByExternalProcess));
}

public NamedPipeMessages.LockData GetExternalHolder()
{
NamedPipeMessages.LockData externalHolder;
this.IsLockAvailable(checkExternalHolderOnly: true, existingExternalHolder: out externalHolder);

return externalHolder;
}

public bool IsLockAvailableForExternalRequestor(out NamedPipeMessages.LockData existingExternalHolder)
{
return this.IsLockAvailable(checkExternalHolderOnly: false, existingExternalHolder: out existingExternalHolder);
}

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;
}

public string GetStatus()
{
lock (this.acquisitionLock)
{
if (this.currentLockHolder.IsGVFS)
{
return "Held by GVFS.";
}

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

return "Free";
}

private bool IsLockAvailable(bool checkExternalHolderOnly, out NamedPipeMessages.LockData existingExternalHolder)
{
lock (this.acquisitionLock)
{
if (!checkExternalHolderOnly &&
this.currentLockHolder.IsGVFS)
{
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;
}
}

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.
NamedPipeMessages.LockData previousExternalHolder = this.currentLockHolder.GetExternalHolder();

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

private void ReleaseLockForTerminatedProcess(int pid)
{
this.ReleaseExternalLock(pid, "ExternalLockHolderExited");
}

// The lock release event is a convenient place to record stats about things that happened while a git command was running,
// such as duration/count of object downloads during a git command, cache hits during a git command, etc.
public class ActiveGitCommandStats
Expand Down Expand Up @@ -364,76 +129,5 @@ public void AddStatsToTelemetry(EventMetadata metadata)
metadata.Add("SizeQueryTimeMS", this.sizeQueryTimeMs);
}
}

/// <summary>
/// This class manages the state of which process currently owns the GVFS lock. This code is complicated because
/// the lock can be held by us or by an external process, and because the external process that holds the lock
/// can terminate without releasing the lock. If that happens, we implicitly release the lock the next time we
/// check to see who is holding it.
///
/// The goal of this class is to make it impossible for the rest of GVFSLock to read the external holder without being
/// aware of the fact that it could have terminated.
///
/// This class assumes that the caller is handling all synchronization.
/// </summary>
private class LockHolder
{
private NamedPipeMessages.LockData externalLockHolder;

public bool IsFree
{
get { return !this.IsGVFS && this.externalLockHolder == null; }
}

public bool IsGVFS
{
get; private set;
}

public void AcquireForGVFS()
{
if (this.externalLockHolder != null)
{
throw new InvalidOperationException("Cannot acquire for GVFS because there is an external holder");
}

this.IsGVFS = true;
}

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

this.externalLockHolder = externalLockHolder;
}

public void Release()
{
this.IsGVFS = false;
this.externalLockHolder = null;
}

public NamedPipeMessages.LockData GetExternalHolder()
{
return this.externalLockHolder;
}

public NamedPipeMessages.LockData GetExternalHolder(out bool externalHolderTerminatedWithoutReleasingLock)
{
externalHolderTerminatedWithoutReleasingLock = false;

if (this.externalLockHolder != null)
{
int pid = this.externalLockHolder.PID;
externalHolderTerminatedWithoutReleasingLock = !GVFSPlatform.Instance.IsProcessActive(pid);
}

return this.externalLockHolder;
}
}
}
}
2 changes: 0 additions & 2 deletions GVFS/GVFS.Common/GVFSPlatform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,6 @@ public static void Register(GVFSPlatform platform)
public abstract bool TryGetGVFSEnlistmentRoot(string directory, out string enlistmentRoot, out string errorMessage);
public abstract bool TryGetDefaultLocalCacheRoot(string enlistmentRoot, out string localCacheRoot, out string localCacheRootError);

public abstract bool IsGitStatusCacheSupported();

public abstract FileBasedLock CreateFileBasedLock(
PhysicalFileSystem fileSystem,
ITracer tracer,
Expand Down
Loading

0 comments on commit cedeeaa

Please sign in to comment.