Beispiel #1
0
        public void CanInvalidateCleanCache()
        {
            this.enlistmentDirectory.CreateFile(Path.Combine(this.gvfsMetadataPath, GVFSConstants.DotGVFS.GitStatusCache.CachePath), "Git status cache contents", createDirectories: true);
            using (GitStatusCache statusCache = new GitStatusCache(this.context, TimeSpan.Zero))
            {
                statusCache.Initialize();
                statusCache.IsCacheReadyAndUpToDate().ShouldBeFalse();

                // Refresh the cache to put it into the clean state.
                statusCache.RefreshAndWait();

                bool result = statusCache.IsReadyForExternalAcquireLockRequests(statusCommandLockData, out _);

                result.ShouldBeTrue();
                statusCache.IsCacheReadyAndUpToDate().ShouldBeTrue();

                // Invalidate the cache, and make sure that it transistions into
                // the dirty state, and that commands are still allowed through.
                statusCache.Invalidate();
                statusCache.IsCacheReadyAndUpToDate().ShouldBeFalse();

                result = statusCache.IsReadyForExternalAcquireLockRequests(statusCommandLockData, out _);
                result.ShouldBeTrue();

                // After checking if we are ready for external lock requests, cache should still be dirty
                statusCache.IsCacheReadyAndUpToDate().ShouldBeFalse();

                statusCache.Shutdown();
            }
        }
Beispiel #2
0
        private void MountAndStartWorkingDirectoryCallbacks(CacheServerInfo cache)
        {
            string error;

            if (!this.context.Enlistment.Authentication.TryInitialize(this.context.Tracer, this.context.Enlistment, out error))
            {
                this.FailMountAndExit("Failed to obtain git credentials: " + error);
            }

            GitObjectsHttpRequestor objectRequestor = new GitObjectsHttpRequestor(this.context.Tracer, this.context.Enlistment, cache, this.retryConfig);

            this.gitObjects = new GVFSGitObjects(this.context, objectRequestor);
            FileSystemVirtualizer virtualizer = this.CreateOrReportAndExit(() => GVFSPlatformLoader.CreateFileSystemVirtualizer(this.context, this.gitObjects), "Failed to create src folder virtualizer");

            GitStatusCache gitStatusCache = (!this.context.Unattended && GVFSPlatform.Instance.IsGitStatusCacheSupported()) ? new GitStatusCache(this.context, this.gitStatusCacheConfig) : null;

            if (gitStatusCache != null)
            {
                this.tracer.RelatedInfo("Git status cache enabled. Backoff time: {0}ms", this.gitStatusCacheConfig.BackoffTime.TotalMilliseconds);
            }
            else
            {
                this.tracer.RelatedInfo("Git status cache is not enabled");
            }

            this.fileSystemCallbacks  = this.CreateOrReportAndExit(() => new FileSystemCallbacks(this.context, this.gitObjects, RepoMetadata.Instance, virtualizer, gitStatusCache), "Failed to create src folder callback listener");
            this.maintenanceScheduler = this.CreateOrReportAndExit(() => new GitMaintenanceScheduler(this.context, this.gitObjects), "Failed to start maintenance scheduler");

            int majorVersion;
            int minorVersion;

            if (!RepoMetadata.Instance.TryGetOnDiskLayoutVersion(out majorVersion, out minorVersion, out error))
            {
                this.FailMountAndExit("Error: {0}", error);
            }

            if (majorVersion != GVFSPlatform.Instance.DiskLayoutUpgrade.Version.CurrentMajorVersion)
            {
                this.FailMountAndExit(
                    "Error: On disk version ({0}) does not match current version ({1})",
                    majorVersion,
                    GVFSPlatform.Instance.DiskLayoutUpgrade.Version.CurrentMajorVersion);
            }

            try
            {
                if (!this.fileSystemCallbacks.TryStart(out error))
                {
                    this.FailMountAndExit("Error: {0}. \r\nPlease confirm that gvfs clone completed without error.", error);
                }
            }
            catch (Exception e)
            {
                this.FailMountAndExit("Failed to initialize src folder callbacks. {0}", e.ToString());
            }

            this.heartbeat = new HeartbeatThread(this.tracer, this.fileSystemCallbacks);
            this.heartbeat.Start();
        }
        public void Dispose()
        {
            if (this.BlobSizes != null)
            {
                this.BlobSizes.Dispose();
                this.BlobSizes = null;
            }

            if (this.fileSystemVirtualizer != null)
            {
                this.fileSystemVirtualizer.Dispose();
                this.fileSystemVirtualizer = null;
            }

            if (this.GitIndexProjection != null)
            {
                this.GitIndexProjection.Dispose();
                this.GitIndexProjection = null;
            }

            if (this.modifiedPaths != null)
            {
                this.modifiedPaths.Dispose();
                this.modifiedPaths = null;
            }

            if (this.gitStatusCache != null)
            {
                this.gitStatusCache.Dispose();
                this.gitStatusCache = null;
            }

            if (this.backgroundFileSystemTaskRunner != null)
            {
                this.backgroundFileSystemTaskRunner.Dispose();
                this.backgroundFileSystemTaskRunner = null;
            }

            if (this.context != null)
            {
                this.context.Dispose();
                this.context = null;
            }
        }
Beispiel #4
0
        public void CacheFileErrorShouldBlock()
        {
            this.fileSystem.DeleteFileThrowsException = true;
            this.enlistmentDirectory.CreateFile(Path.Combine(this.gvfsMetadataPath, GVFSConstants.DotGVFS.GitStatusCache.CachePath), "Git status cache contents", createDirectories: true);

            using (GitStatusCache statusCache = new GitStatusCache(this.context, TimeSpan.Zero))
            {
                statusCache.Initialize();

                statusCache.IsCacheReadyAndUpToDate().ShouldBeFalse();

                bool isReady = statusCache.IsReadyForExternalAcquireLockRequests(statusCommandLockData, out _);
                isReady.ShouldBeFalse();

                statusCache.IsCacheReadyAndUpToDate().ShouldBeFalse();

                statusCache.Shutdown();
            }
        }
        private void MountAndStartWorkingDirectoryCallbacks(CacheServerInfo cache)
        {
            string error;

            if (!this.context.Enlistment.Authentication.TryInitialize(this.context.Tracer, this.context.Enlistment, out error))
            {
                this.FailMountAndExit("Failed to obtain git credentials: " + error);
            }

            GitObjectsHttpRequestor objectRequestor = new GitObjectsHttpRequestor(this.context.Tracer, this.context.Enlistment, cache, this.retryConfig);

            this.gitObjects = new GSDGitObjects(this.context, objectRequestor);

            GitStatusCache gitStatusCache = (!this.context.Unattended && GSDPlatform.Instance.IsGitStatusCacheSupported()) ? new GitStatusCache(this.context, this.gitStatusCacheConfig) : null;

            if (gitStatusCache != null)
            {
                this.tracer.RelatedInfo("Git status cache enabled. Backoff time: {0}ms", this.gitStatusCacheConfig.BackoffTime.TotalMilliseconds);
            }
            else
            {
                this.tracer.RelatedInfo("Git status cache is not enabled");
            }

            this.maintenanceScheduler = this.CreateOrReportAndExit(() => new GitMaintenanceScheduler(this.context, this.gitObjects), "Failed to start maintenance scheduler");

            int majorVersion;
            int minorVersion;

            if (!RepoMetadata.Instance.TryGetOnDiskLayoutVersion(out majorVersion, out minorVersion, out error))
            {
                this.FailMountAndExit("Error: {0}", error);
            }

            if (majorVersion != GSDPlatform.Instance.DiskLayoutUpgrade.Version.CurrentMajorVersion)
            {
                this.FailMountAndExit(
                    "Error: On disk version ({0}) does not match current version ({1})",
                    majorVersion,
                    GSDPlatform.Instance.DiskLayoutUpgrade.Version.CurrentMajorVersion);
            }
        }
Beispiel #6
0
        public void OnExecute(CommandEventArgs e)
        {
            if (_commandService == null)
            {
                _commandService = e.GetService <IAnkhCommandService>();
            }
            if (_fileCache == null)
            {
                _fileCache = e.GetService <GitStatusCache>(typeof(IGitStatusCache));
            }

            _commandService.TockCommand(e.Command);

            if (e.Command == AnkhCommand.GitCacheFinishTasks)
            {
                _fileCache.OnCleanup();
            }
            else
            {
                _fileCache.BroadcastChanges();
            }
        }
Beispiel #7
0
        public void CanRefreshCache()
        {
            this.enlistmentDirectory.CreateFile(Path.Combine(this.gvfsMetadataPath, GVFSConstants.DotGVFS.GitStatusCache.CachePath), "Git status cache contents", createDirectories: true);
            using (GitStatusCache statusCache = new GitStatusCache(this.context, TimeSpan.Zero))
            {
                statusCache.Initialize();

                statusCache.IsCacheReadyAndUpToDate().ShouldBeFalse();

                string message;
                bool   result = statusCache.IsReadyForExternalAcquireLockRequests(statusCommandLockData, out message);
                result.ShouldBeTrue();

                statusCache.RefreshAndWait();

                result = statusCache.IsReadyForExternalAcquireLockRequests(statusCommandLockData, out message);
                result.ShouldBeTrue();

                statusCache.IsCacheReadyAndUpToDate().ShouldBeTrue();

                statusCache.Shutdown();
            }
        }
Beispiel #8
0
        public void HandlesExceptionsCreatingDirectory(Exception exceptionToThrow)
        {
            this.enlistmentDirectory.CreateFile(Path.Combine(this.gvfsMetadataPath, GSDConstants.DotGSD.GitStatusCache.CachePath), "Git status cache contents", createDirectories: true);
            this.fileSystem.ExceptionThrownByCreateDirectory = exceptionToThrow;
            using (GitStatusCache statusCache = new GitStatusCache(this.context, TimeSpan.Zero))
            {
                statusCache.Initialize();

                statusCache.IsCacheReadyAndUpToDate().ShouldBeFalse();

                string message;
                bool   result = statusCache.IsReadyForExternalAcquireLockRequests(statusCommandLockData, out message);
                result.ShouldBeTrue();

                statusCache.RefreshAndWait();

                result = statusCache.IsReadyForExternalAcquireLockRequests(statusCommandLockData, out message);
                result.ShouldBeTrue();

                statusCache.IsCacheReadyAndUpToDate().ShouldBeFalse();

                statusCache.Shutdown();
            }
        }
        public FileSystemCallbacks(
            GVFSContext context,
            GVFSGitObjects gitObjects,
            RepoMetadata repoMetadata,
            BlobSizes blobSizes,
            GitIndexProjection gitIndexProjection,
            BackgroundFileSystemTaskRunner backgroundFileSystemTaskRunner,
            FileSystemVirtualizer fileSystemVirtualizer,
            GitStatusCache gitStatusCache = null)
        {
            this.logsHeadFileProperties = null;
            this.postFetchJobLock       = new object();

            this.context               = context;
            this.gitObjects            = gitObjects;
            this.fileSystemVirtualizer = fileSystemVirtualizer;

            this.placeHolderCreationCount       = new ConcurrentDictionary <string, PlaceHolderCreateCounter>(StringComparer.OrdinalIgnoreCase);
            this.newlyCreatedFileAndFolderPaths = new ConcurrentHashSet <string>(StringComparer.OrdinalIgnoreCase);

            string error;

            if (!ModifiedPathsDatabase.TryLoadOrCreate(
                    this.context.Tracer,
                    Path.Combine(this.context.Enlistment.DotGVFSRoot, GVFSConstants.DotGVFS.Databases.ModifiedPaths),
                    this.context.FileSystem,
                    out this.modifiedPaths,
                    out error))
            {
                throw new InvalidRepoException(error);
            }

            this.BlobSizes = blobSizes;
            this.BlobSizes.Initialize();

            PlaceholderListDatabase placeholders;

            if (!PlaceholderListDatabase.TryCreate(
                    this.context.Tracer,
                    Path.Combine(this.context.Enlistment.DotGVFSRoot, GVFSConstants.DotGVFS.Databases.PlaceholderList),
                    this.context.FileSystem,
                    out placeholders,
                    out error))
            {
                throw new InvalidRepoException(error);
            }

            this.GitIndexProjection = gitIndexProjection ?? new GitIndexProjection(
                context,
                gitObjects,
                this.BlobSizes,
                repoMetadata,
                fileSystemVirtualizer,
                placeholders,
                this.modifiedPaths);

            if (backgroundFileSystemTaskRunner != null)
            {
                this.backgroundFileSystemTaskRunner = backgroundFileSystemTaskRunner;
                this.backgroundFileSystemTaskRunner.SetCallbacks(
                    this.PreBackgroundOperation,
                    this.ExecuteBackgroundOperation,
                    this.PostBackgroundOperation);
            }
            else
            {
                this.backgroundFileSystemTaskRunner = new BackgroundFileSystemTaskRunner(
                    this.context,
                    this.PreBackgroundOperation,
                    this.ExecuteBackgroundOperation,
                    this.PostBackgroundOperation,
                    Path.Combine(context.Enlistment.DotGVFSRoot, GVFSConstants.DotGVFS.Databases.BackgroundFileSystemTasks));
            }

            this.enableGitStatusCache = gitStatusCache != null;

            // If the status cache is not enabled, create a dummy GitStatusCache that will never be initialized
            // This lets us from having to add null checks to callsites into GitStatusCache.
            this.gitStatusCache = gitStatusCache ?? new GitStatusCache(context, TimeSpan.Zero);

            this.logsHeadPath = Path.Combine(this.context.Enlistment.WorkingDirectoryRoot, GVFSConstants.DotGit.Logs.Head);

            EventMetadata metadata = new EventMetadata();

            metadata.Add("placeholders.Count", placeholders.EstimatedCount);
            metadata.Add("background.Count", this.backgroundFileSystemTaskRunner.Count);
            metadata.Add(TracingConstants.MessageKey.InfoMessage, $"{nameof(FileSystemCallbacks)} created");
            this.context.Tracer.RelatedEvent(EventLevel.Informational, $"{nameof(FileSystemCallbacks)}_Constructor", metadata);
        }
 public FileSystemCallbacks(GVFSContext context, GVFSGitObjects gitObjects, RepoMetadata repoMetadata, FileSystemVirtualizer fileSystemVirtualizer, GitStatusCache gitStatusCache)
     : this(
         context,
         gitObjects,
         repoMetadata,
         new BlobSizes(context.Enlistment.BlobSizesRoot, context.FileSystem, context.Tracer),
         gitIndexProjection : null,
         backgroundFileSystemTaskRunner : null,
         fileSystemVirtualizer : fileSystemVirtualizer,
         gitStatusCache : gitStatusCache)
 {
 }