Esempio n. 1
0
 private int GetParameterCount(EventMetadata eventData)
 {
     int paramCount;
     if(eventData.Parameters == null)
     {
         paramCount = eventData.ParameterTypes.Length;
     }
     else
     {
         paramCount = eventData.Parameters.Length;
     }
     
     return paramCount;
 }
Esempio n. 2
0
 public EventEnvelope(TEvent @event, EventMetadata metadata) : base(@event, metadata)
 {
 }
Esempio n. 3
0
            private void EnsureLocalCacheIsHealthy(
                ITracer tracer,
                GVFSEnlistment enlistment,
                RetryConfig retryConfig,
                ServerGVFSConfig serverGVFSConfig,
                CacheServerInfo cacheServer)
            {
                if (!Directory.Exists(enlistment.LocalCacheRoot))
                {
                    try
                    {
                        tracer.RelatedInfo($"{nameof(this.EnsureLocalCacheIsHealthy)}: Local cache root: {enlistment.LocalCacheRoot} missing, recreating it");
                        Directory.CreateDirectory(enlistment.LocalCacheRoot);
                    }
                    catch (Exception e)
                    {
                        EventMetadata metadata = new EventMetadata();
                        metadata.Add("Exception", e.ToString());
                        metadata.Add("enlistment.LocalCacheRoot", enlistment.LocalCacheRoot);
                        tracer.RelatedError(metadata, $"{nameof(this.EnsureLocalCacheIsHealthy)}: Exception while trying to create local cache root");

                        this.ReportErrorAndExit(tracer, "Failed to create local cache: " + enlistment.LocalCacheRoot);
                    }
                }

                // Validate that the GitObjectsRoot directory is on disk, and that the GVFS repo is configured to use it.
                // If the directory is missing (and cannot be found in the mapping file) a new key for the repo will be added
                // to the mapping file and used for BOTH the GitObjectsRoot and BlobSizesRoot
                PhysicalFileSystem fileSystem = new PhysicalFileSystem();

                if (Directory.Exists(enlistment.GitObjectsRoot))
                {
                    bool gitObjectsRootInAlternates = false;

                    string alternatesFilePath = this.GetAlternatesPath(enlistment);
                    if (File.Exists(alternatesFilePath))
                    {
                        try
                        {
                            using (Stream stream = fileSystem.OpenFileStream(
                                       alternatesFilePath,
                                       FileMode.Open,
                                       FileAccess.Read,
                                       FileShare.ReadWrite,
                                       callFlushFileBuffers: false))
                            {
                                using (StreamReader reader = new StreamReader(stream))
                                {
                                    while (!reader.EndOfStream)
                                    {
                                        string alternatesLine = reader.ReadLine();
                                        if (string.Equals(alternatesLine, enlistment.GitObjectsRoot, StringComparison.OrdinalIgnoreCase))
                                        {
                                            gitObjectsRootInAlternates = true;
                                        }
                                    }
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            EventMetadata exceptionMetadata = new EventMetadata();
                            exceptionMetadata.Add("Exception", e.ToString());
                            tracer.RelatedError(exceptionMetadata, $"{nameof(this.EnsureLocalCacheIsHealthy)}: Exception while trying to validate alternates file");

                            this.ReportErrorAndExit(tracer, $"Failed to validate that alternates file includes git objects root: {e.Message}");
                        }
                    }
                    else
                    {
                        tracer.RelatedInfo($"{nameof(this.EnsureLocalCacheIsHealthy)}: Alternates file not found");
                    }

                    if (!gitObjectsRootInAlternates)
                    {
                        tracer.RelatedInfo($"{nameof(this.EnsureLocalCacheIsHealthy)}: GitObjectsRoot ({enlistment.GitObjectsRoot}) missing from alternates files, recreating alternates");
                        string error;
                        if (!this.TryCreateAlternatesFile(fileSystem, enlistment, out error))
                        {
                            this.ReportErrorAndExit(tracer, $"Failed to update alternates file to include git objects root: {error}");
                        }
                    }
                }
                else
                {
                    tracer.RelatedInfo($"{nameof(this.EnsureLocalCacheIsHealthy)}: GitObjectsRoot ({enlistment.GitObjectsRoot}) missing, determining new root");

                    if (cacheServer == null)
                    {
                        cacheServer = CacheServerResolver.GetCacheServerFromConfig(enlistment);
                    }

                    string error;
                    if (serverGVFSConfig == null)
                    {
                        if (retryConfig == null)
                        {
                            if (!RetryConfig.TryLoadFromGitConfig(tracer, enlistment, out retryConfig, out error))
                            {
                                this.ReportErrorAndExit(tracer, "Failed to determine GVFS timeout and max retries: " + error);
                            }
                        }

                        serverGVFSConfig = this.QueryGVFSConfig(tracer, enlistment, retryConfig);
                    }

                    string             localCacheKey;
                    LocalCacheResolver localCacheResolver = new LocalCacheResolver(enlistment);
                    if (!localCacheResolver.TryGetLocalCacheKeyFromLocalConfigOrRemoteCacheServers(
                            tracer,
                            serverGVFSConfig,
                            cacheServer,
                            enlistment.LocalCacheRoot,
                            localCacheKey: out localCacheKey,
                            errorMessage: out error))
                    {
                        this.ReportErrorAndExit(tracer, $"Previous git objects root ({enlistment.GitObjectsRoot}) not found, and failed to determine new local cache key: {error}");
                    }

                    EventMetadata metadata = new EventMetadata();
                    metadata.Add("localCacheRoot", enlistment.LocalCacheRoot);
                    metadata.Add("localCacheKey", localCacheKey);
                    metadata.Add(TracingConstants.MessageKey.InfoMessage, "Initializing and persisting updated paths");
                    tracer.RelatedEvent(EventLevel.Informational, "GVFSVerb_EnsureLocalCacheIsHealthy_InitializePathsFromKey", metadata);
                    enlistment.InitializeCachePathsFromKey(enlistment.LocalCacheRoot, localCacheKey);

                    tracer.RelatedInfo($"{nameof(this.EnsureLocalCacheIsHealthy)}: Creating GitObjectsRoot ({enlistment.GitObjectsRoot}), GitPackRoot ({enlistment.GitPackRoot}), and BlobSizesRoot ({enlistment.BlobSizesRoot})");
                    try
                    {
                        Directory.CreateDirectory(enlistment.GitObjectsRoot);
                        Directory.CreateDirectory(enlistment.GitPackRoot);
                    }
                    catch (Exception e)
                    {
                        EventMetadata exceptionMetadata = new EventMetadata();
                        exceptionMetadata.Add("Exception", e.ToString());
                        exceptionMetadata.Add("enlistment.LocalCacheRoot", enlistment.LocalCacheRoot);
                        exceptionMetadata.Add("enlistment.GitObjectsRoot", enlistment.GitObjectsRoot);
                        exceptionMetadata.Add("enlistment.GitPackRoot", enlistment.GitPackRoot);
                        exceptionMetadata.Add("enlistment.BlobSizesRoot", enlistment.BlobSizesRoot);
                        tracer.RelatedError(exceptionMetadata, $"{nameof(this.InitializeLocalCacheAndObjectsPaths)}: Exception while trying to create objects, pack, and sizes folders");

                        this.ReportErrorAndExit(tracer, "Failed to create objects, pack, and sizes folders");
                    }

                    tracer.RelatedInfo($"{nameof(this.EnsureLocalCacheIsHealthy)}: Creating new alternates file");
                    if (!this.TryCreateAlternatesFile(fileSystem, enlistment, out error))
                    {
                        this.ReportErrorAndExit(tracer, $"Failed to update alterates file with new objects path: {error}");
                    }

                    tracer.RelatedInfo($"{nameof(this.EnsureLocalCacheIsHealthy)}: Saving git objects root ({enlistment.GitObjectsRoot}) in repo metadata");
                    RepoMetadata.Instance.SetGitObjectsRoot(enlistment.GitObjectsRoot);

                    tracer.RelatedInfo($"{nameof(this.EnsureLocalCacheIsHealthy)}: Saving blob sizes root ({enlistment.BlobSizesRoot}) in repo metadata");
                    RepoMetadata.Instance.SetBlobSizesRoot(enlistment.BlobSizesRoot);
                }

                // Validate that the BlobSizesRoot folder is on disk.
                // Note that if a user performed an action that resulted in the entire .gvfscache being deleted, the code above
                // for validating GitObjectsRoot will have already taken care of generating a new key and setting a new enlistment.BlobSizesRoot path
                if (!Directory.Exists(enlistment.BlobSizesRoot))
                {
                    tracer.RelatedInfo($"{nameof(this.EnsureLocalCacheIsHealthy)}: BlobSizesRoot ({enlistment.BlobSizesRoot}) not found, re-creating");
                    try
                    {
                        Directory.CreateDirectory(enlistment.BlobSizesRoot);
                    }
                    catch (Exception e)
                    {
                        EventMetadata exceptionMetadata = new EventMetadata();
                        exceptionMetadata.Add("Exception", e.ToString());
                        exceptionMetadata.Add("enlistment.BlobSizesRoot", enlistment.BlobSizesRoot);
                        tracer.RelatedError(exceptionMetadata, $"{nameof(this.InitializeLocalCacheAndObjectsPaths)}: Exception while trying to create blob sizes folder");

                        this.ReportErrorAndExit(tracer, "Failed to create blob sizes folder");
                    }
                }
            }
Esempio n. 4
0
        private static bool TryCopyNativeLibToAppDirectory(ITracer tracer, PhysicalFileSystem fileSystem, string gvfsAppDirectory)
        {
            string installFilePath;
            string appFilePath;

            GetNativeLibPaths(gvfsAppDirectory, out installFilePath, out appFilePath);

            EventMetadata pathMetadata = CreateEventMetadata();

            pathMetadata.Add(nameof(gvfsAppDirectory), gvfsAppDirectory);
            pathMetadata.Add(nameof(installFilePath), installFilePath);
            pathMetadata.Add(nameof(appFilePath), appFilePath);

            if (fileSystem.FileExists(installFilePath))
            {
                tracer.RelatedEvent(EventLevel.Informational, $"{nameof(TryCopyNativeLibToAppDirectory)}_CopyingNativeLib", pathMetadata);

                try
                {
                    fileSystem.CopyFile(installFilePath, appFilePath, overwrite: true);

                    try
                    {
                        Common.NativeMethods.FlushFileBuffers(appFilePath);
                    }
                    catch (Win32Exception e)
                    {
                        EventMetadata metadata = CreateEventMetadata(e);
                        metadata.Add(nameof(appFilePath), appFilePath);
                        metadata.Add(nameof(installFilePath), installFilePath);
                        tracer.RelatedWarning(metadata, $"{nameof(TryCopyNativeLibToAppDirectory)}: Win32Exception while trying to flush file buffers", Keywords.Telemetry);
                    }
                }
                catch (UnauthorizedAccessException e)
                {
                    EventMetadata metadata = CreateEventMetadata(e);
                    tracer.RelatedError(metadata, $"{nameof(TryCopyNativeLibToAppDirectory)}: UnauthorizedAccessException caught while trying to copy native lib");
                    return(false);
                }
                catch (DirectoryNotFoundException e)
                {
                    EventMetadata metadata = CreateEventMetadata(e);
                    tracer.RelatedError(metadata, $"{nameof(TryCopyNativeLibToAppDirectory)}: DirectoryNotFoundException caught while trying to copy native lib");
                    return(false);
                }
                catch (FileNotFoundException e)
                {
                    EventMetadata metadata = CreateEventMetadata(e);
                    tracer.RelatedError(metadata, $"{nameof(TryCopyNativeLibToAppDirectory)}: FileNotFoundException caught while trying to copy native lib");
                    return(false);
                }
                catch (IOException e)
                {
                    EventMetadata metadata = CreateEventMetadata(e);
                    tracer.RelatedWarning(metadata, $"{nameof(TryCopyNativeLibToAppDirectory)}: IOException caught while trying to copy native lib");

                    if (fileSystem.FileExists(appFilePath))
                    {
                        tracer.RelatedWarning(
                            CreateEventMetadata(),
                            "Could not copy native lib to app directory, but file already exists, continuing with install",
                            Keywords.Telemetry);
                    }
                    else
                    {
                        tracer.RelatedError($"{nameof(TryCopyNativeLibToAppDirectory)}: Failed to copy native lib to app directory");
                        return(false);
                    }
                }
            }
            else
            {
                tracer.RelatedError(pathMetadata, $"{nameof(TryCopyNativeLibToAppDirectory)}: Native lib does not exist in install directory");
                return(false);
            }

            return(true);
        }
Esempio n. 5
0
        private void OnNewConnection(IAsyncResult ar, bool createNewThreadIfSynchronous)
        {
            if (createNewThreadIfSynchronous &&
                ar.CompletedSynchronously)
            {
                // if this callback got called synchronously, we must not do any blocking IO on this thread
                // or we will block the original caller. Moving to a new thread so that it will be safe
                // to call a blocking Read on the NamedPipeServerStream

                new Thread(() => this.OnNewConnection(ar, createNewThreadIfSynchronous: false)).Start();
                return;
            }

            this.listeningPipe = null;
            bool connectionBroken = false;

            NamedPipeServerStream pipe = (NamedPipeServerStream)ar.AsyncState;

            try
            {
                try
                {
                    pipe.EndWaitForConnection(ar);
                }
                catch (IOException e)
                {
                    connectionBroken = true;

                    EventMetadata metadata = new EventMetadata();
                    metadata.Add("Area", "NamedPipeServer");
                    metadata.Add("Exception", e.ToString());
                    metadata.Add(TracingConstants.MessageKey.WarningMessage, "OnNewConnection: Connection broken");
                    this.tracer.RelatedEvent(EventLevel.Warning, "OnNewConnectionn_EndWaitForConnection_IOException", metadata);
                }
                catch (Exception e)
                {
                    this.LogErrorAndExit("OnNewConnection caught unhandled exception, exiting process", e);
                }

                if (!this.isStopping)
                {
                    this.OpenListeningPipe();

                    if (!connectionBroken)
                    {
                        try
                        {
                            this.handleConnection(new Connection(pipe, this.tracer, () => this.isStopping));
                        }
                        catch (Exception e)
                        {
                            this.LogErrorAndExit("Unhandled exception in connection handler", e);
                        }
                    }
                }
            }
            finally
            {
                pipe.Dispose();
            }
        }
Esempio n. 6
0
 private Type GetDataType(EventMetadata eventData, int parameterId)
 {
     Type dataType;
     if(eventData.Parameters == null)
     {
         dataType = EventTypeToType(eventData.ParameterTypes[parameterId]);
     }
     else
     {
         dataType = eventData.Parameters[parameterId].ParameterType;
     }
     
     return dataType;
 }
Esempio n. 7
0
        /// <summary>
        /// Uses a <see cref="PrefetchPacksDeserializer"/> to read the packs from the stream.
        /// </summary>
        private RetryWrapper <GitObjectsHttpRequestor.GitObjectTaskResult> .CallbackResult DeserializePrefetchPacks(
            GitEndPointResponseData response,
            ref long latestTimestamp,
            ref long bytesDownloaded,
            ref List <string> packIndexes,
            GitProcess gitProcess)
        {
            if (packIndexes == null)
            {
                packIndexes = new List <string>();
            }

            using (ITracer activity = this.Tracer.StartActivity("DeserializePrefetchPacks", EventLevel.Informational))
            {
                PrefetchPacksDeserializer deserializer = new PrefetchPacksDeserializer(response.Stream);

                string tempPackFolderPath = Path.Combine(this.Enlistment.GitPackRoot, TempPackFolder);
                this.fileSystem.CreateDirectory(tempPackFolderPath);

                List <TempPrefetchPackAndIdx> tempPacks = new List <TempPrefetchPackAndIdx>();
                foreach (PrefetchPacksDeserializer.PackAndIndex pack in deserializer.EnumeratePacks())
                {
                    // The advertised size may not match the actual, on-disk size.
                    long indexLength = 0;
                    long packLength;

                    // Write the temp and index to a temp folder to avoid putting corrupt files in the pack folder
                    // Once the files are validated and flushed they can be moved to the pack folder
                    string packName     = string.Format("{0}-{1}-{2}.pack", GVFSConstants.PrefetchPackPrefix, pack.Timestamp, pack.UniqueId);
                    string packTempPath = Path.Combine(tempPackFolderPath, packName);
                    string idxName      = string.Format("{0}-{1}-{2}.idx", GVFSConstants.PrefetchPackPrefix, pack.Timestamp, pack.UniqueId);
                    string idxTempPath  = Path.Combine(tempPackFolderPath, idxName);

                    EventMetadata data = CreateEventMetadata();
                    data["timestamp"] = pack.Timestamp.ToString();
                    data["uniqueId"]  = pack.UniqueId;
                    activity.RelatedEvent(EventLevel.Informational, "Receiving Pack/Index", data);

                    // Write the pack
                    // If it fails, TryWriteTempFile cleans up the file and we retry the prefetch
                    Task packFlushTask;
                    if (!this.TryWriteTempFile(activity, pack.PackStream, packTempPath, out packLength, out packFlushTask))
                    {
                        bytesDownloaded += packLength;
                        return(new RetryWrapper <GitObjectsHttpRequestor.GitObjectTaskResult> .CallbackResult(null, true));
                    }

                    bytesDownloaded += packLength;

                    // We will try to build an index if the server does not send one
                    if (pack.IndexStream == null)
                    {
                        GitProcess.Result result;
                        if (!this.TryBuildIndex(activity, packTempPath, out result, gitProcess))
                        {
                            if (packFlushTask != null)
                            {
                                packFlushTask.Wait();
                            }

                            // Move whatever has been successfully downloaded so far
                            Exception moveException;
                            this.TryFlushAndMoveTempPacks(tempPacks, ref latestTimestamp, out moveException);

                            return(new RetryWrapper <GitObjectsHttpRequestor.GitObjectTaskResult> .CallbackResult(null, true));
                        }

                        tempPacks.Add(new TempPrefetchPackAndIdx(pack.Timestamp, packName, packTempPath, packFlushTask, idxName, idxTempPath, idxFlushTask: null));
                    }
                    else
                    {
                        Task indexFlushTask;
                        if (this.TryWriteTempFile(activity, pack.IndexStream, idxTempPath, out indexLength, out indexFlushTask))
                        {
                            tempPacks.Add(new TempPrefetchPackAndIdx(pack.Timestamp, packName, packTempPath, packFlushTask, idxName, idxTempPath, indexFlushTask));
                        }
                        else
                        {
                            bytesDownloaded += indexLength;

                            // Try to build the index manually, then retry the prefetch
                            GitProcess.Result result;
                            if (this.TryBuildIndex(activity, packTempPath, out result, gitProcess))
                            {
                                // If we were able to recreate the failed index
                                // we can start the prefetch at the next timestamp
                                tempPacks.Add(new TempPrefetchPackAndIdx(pack.Timestamp, packName, packTempPath, packFlushTask, idxName, idxTempPath, idxFlushTask: null));
                            }
                            else
                            {
                                if (packFlushTask != null)
                                {
                                    packFlushTask.Wait();
                                }
                            }

                            // Move whatever has been successfully downloaded so far
                            Exception moveException;
                            this.TryFlushAndMoveTempPacks(tempPacks, ref latestTimestamp, out moveException);

                            // The download stream will not be in a good state if the index download fails.
                            // So we have to restart the prefetch
                            return(new RetryWrapper <GitObjectsHttpRequestor.GitObjectTaskResult> .CallbackResult(null, true));
                        }
                    }

                    bytesDownloaded += indexLength;
                }

                Exception exception = null;
                if (!this.TryFlushAndMoveTempPacks(tempPacks, ref latestTimestamp, out exception))
                {
                    return(new RetryWrapper <GitObjectsHttpRequestor.GitObjectTaskResult> .CallbackResult(exception, true));
                }

                foreach (TempPrefetchPackAndIdx tempPack in tempPacks)
                {
                    packIndexes.Add(tempPack.IdxName);
                }

                return(new RetryWrapper <GitObjectsHttpRequestor.GitObjectTaskResult> .CallbackResult(
                           new GitObjectsHttpRequestor.GitObjectTaskResult(success: true)));
            }
        }
Esempio n. 8
0
        private Result CreatePlaceholders(string directoryRelativePath, IEnumerable <ProjectedFileInfo> projectedItems, string triggeringProcessName)
        {
            foreach (ProjectedFileInfo fileInfo in projectedItems)
            {
                string childRelativePath = Path.Combine(directoryRelativePath, fileInfo.Name);

                string           sha;
                FileSystemResult fileSystemResult;
                if (fileInfo.IsFolder)
                {
                    sha = string.Empty;
                    fileSystemResult = this.WritePlaceholderDirectory(childRelativePath);
                }
                else
                {
                    sha = fileInfo.Sha.ToString();

                    // Writing placeholders on Mac does not require a file size
                    fileSystemResult = this.WritePlaceholderFile(childRelativePath, DummyFileSize, sha);
                }

                Result result = (Result)fileSystemResult.RawResult;
                if (result != Result.Success)
                {
                    EventMetadata metadata = this.CreateEventMetadata(childRelativePath);
                    metadata.Add("fileInfo.Name", fileInfo.Name);
                    metadata.Add("fileInfo.Size", fileInfo.Size);
                    metadata.Add("fileInfo.IsFolder", fileInfo.IsFolder);
                    metadata.Add(nameof(result), result.ToString());
                    metadata.Add(nameof(sha), sha);
                    this.Context.Tracer.RelatedError(metadata, $"{nameof(this.CreatePlaceholders)}: Write placeholder failed");

                    if (result == Result.EIOError)
                    {
                        // If there is an IO error writing the placeholder then the file might already exist and it needs to
                        // be added to the modified paths so that git will show any differences or errors when interacting with the file
                        // This will happen in the include mode when the user creates a file that is already in the files that
                        // should be projected but we are trying to create the placeholder after it has already been created
                        this.FileSystemCallbacks.OnFileConvertedToFull(childRelativePath);
                    }
                    else
                    {
                        return(result);
                    }
                }
                else
                {
                    if (fileInfo.IsFolder)
                    {
                        this.FileSystemCallbacks.OnPlaceholderFolderCreated(childRelativePath, triggeringProcessName);
                    }
                    else
                    {
                        this.FileSystemCallbacks.OnPlaceholderFileCreated(childRelativePath, sha, triggeringProcessName);
                    }
                }
            }

            this.FileSystemCallbacks.OnPlaceholderFolderExpanded(directoryRelativePath);

            return(Result.Success);
        }
Esempio n. 9
0
        private void HandleAllDirectoryOperations()
        {
            DiffTreeResult treeOp;

            while (this.diff.DirectoryOperations.TryDequeue(out treeOp))
            {
                if (this.HasFailures)
                {
                    return;
                }

                switch (treeOp.Operation)
                {
                case DiffTreeResult.Operations.Modify:
                case DiffTreeResult.Operations.Add:
                    try
                    {
                        Directory.CreateDirectory(treeOp.TargetPath);
                    }
                    catch (Exception ex)
                    {
                        EventMetadata metadata = new EventMetadata();
                        metadata.Add("Operation", "CreateDirectory");
                        metadata.Add(nameof(treeOp.TargetPath), treeOp.TargetPath);
                        this.tracer.RelatedError(metadata, ex.Message);
                        this.HasFailures = true;
                    }

                    break;

                case DiffTreeResult.Operations.Delete:
                    try
                    {
                        if (Directory.Exists(treeOp.TargetPath))
                        {
                            this.fileSystem.DeleteDirectory(treeOp.TargetPath);
                        }
                    }
                    catch (Exception ex)
                    {
                        // We are deleting directories and subdirectories in parallel
                        if (Directory.Exists(treeOp.TargetPath))
                        {
                            EventMetadata metadata = new EventMetadata();
                            metadata.Add("Operation", "DeleteDirectory");
                            metadata.Add(nameof(treeOp.TargetPath), treeOp.TargetPath);
                            this.tracer.RelatedError(metadata, ex.Message);
                            this.HasFailures = true;
                        }
                    }

                    break;

                default:
                    this.tracer.RelatedError("Ignoring unexpected Tree Operation {0}: {1}", treeOp.TargetPath, treeOp.Operation);
                    continue;
                }

                if (Interlocked.Increment(ref this.directoryOpCount) % NumOperationsPerStatus == 0)
                {
                    EventMetadata metadata = new EventMetadata();
                    metadata.Add("DirectoryOperationsQueued", this.diff.DirectoryOperations.Count);
                    metadata.Add("DirectoryOperationsCompleted", this.directoryOpCount);
                    this.tracer.RelatedEvent(EventLevel.Informational, "CheckoutStatus", metadata);
                }
            }
        }
Esempio n. 10
0
        private void EnqueueOperationsFromDiffTreeLine(ITracer activity, string repoRoot, string line)
        {
            if (!line.StartsWith(":"))
            {
                // Diff-tree starts with metadata we can ignore.
                // Real diff lines always start with a colon
                return;
            }

            DiffTreeResult result = DiffTreeResult.ParseFromDiffTreeLine(line, repoRoot);

            if (!this.ResultIsInWhitelist(result))
            {
                return;
            }

            if (result.Operation == DiffTreeResult.Operations.Unknown ||
                result.Operation == DiffTreeResult.Operations.Unmerged)
            {
                EventMetadata metadata = new EventMetadata();
                metadata.Add("Path", result.TargetFilename);
                metadata.Add("ErrorMessage", "Unexpected diff operation: " + result.Operation);
                activity.RelatedError(metadata);
                this.HasFailures = true;
                return;
            }

            // Separate and enqueue all directory operations first.
            if (result.SourceIsDirectory || result.TargetIsDirectory)
            {
                switch (result.Operation)
                {
                case DiffTreeResult.Operations.Delete:
                    if (!this.stagedDirectoryOperations.Add(result))
                    {
                        EventMetadata metadata = new EventMetadata();
                        metadata.Add("Filename", result.TargetFilename);
                        metadata.Add("Message", "A case change was attempted. It will not be reflected in the working directory.");
                        activity.RelatedEvent(EventLevel.Warning, "CaseConflict", metadata);
                    }

                    break;

                case DiffTreeResult.Operations.RenameEdit:
                    if (!this.stagedDirectoryOperations.Add(result))
                    {
                        // This could happen if a directory was deleted and an existing directory was renamed to replace it, but with a different case.
                        EventMetadata metadata = new EventMetadata();
                        metadata.Add("Filename", result.TargetFilename);
                        metadata.Add("Message", "A case change was attempted. It will not be reflected in the working directory.");
                        activity.RelatedEvent(EventLevel.Warning, "CaseConflict", metadata);

                        // The target of RenameEdit is always akin to an Add, so replacing the delete is the safer thing to do.
                        this.stagedDirectoryOperations.Remove(result);
                        this.stagedDirectoryOperations.Add(result);
                    }

                    if (!result.TargetIsDirectory)
                    {
                        // Handle when a directory becomes a file.
                        // Files becoming directories is handled by HandleAllDirectoryOperations
                        this.EnqueueFileAddOperation(activity, result);
                    }

                    break;

                case DiffTreeResult.Operations.Add:
                case DiffTreeResult.Operations.Modify:
                case DiffTreeResult.Operations.CopyEdit:
                    if (!this.stagedDirectoryOperations.Add(result))
                    {
                        EventMetadata metadata = new EventMetadata();
                        metadata.Add("Filename", result.TargetFilename);
                        metadata.Add("Message", "A case change was attempted. It will not be reflected in the working directory.");
                        activity.RelatedEvent(EventLevel.Warning, "CaseConflict", metadata);

                        // Replace the delete with the add to make sure we don't delete a folder from under ourselves
                        this.stagedDirectoryOperations.Remove(result);
                        this.stagedDirectoryOperations.Add(result);
                    }

                    break;

                default:
                    activity.RelatedError("Unexpected diff operation from line: {0}", line);
                    break;
                }
            }
            else
            {
                switch (result.Operation)
                {
                case DiffTreeResult.Operations.Delete:
                    this.EnqueueFileDeleteOperation(activity, result.TargetFilename);

                    break;

                case DiffTreeResult.Operations.RenameEdit:

                    this.EnqueueFileAddOperation(activity, result);
                    this.EnqueueFileDeleteOperation(activity, result.SourceFilename);

                    break;

                case DiffTreeResult.Operations.Modify:
                case DiffTreeResult.Operations.CopyEdit:
                case DiffTreeResult.Operations.Add:
                    this.EnqueueFileAddOperation(activity, result);
                    break;

                default:
                    activity.RelatedError("Unexpected diff operation from line: {0}", line);
                    break;
                }
            }
        }
Esempio n. 11
0
        private Result OnGetFileStream(
            ulong commandId,
            string relativePath,
            byte[] providerId,
            byte[] contentId,
            int triggeringProcessId,
            string triggeringProcessName,
            IntPtr fileHandle)
        {
            try
            {
                if (contentId == null)
                {
                    this.Context.Tracer.RelatedError($"{nameof(this.OnGetFileStream)} called with null contentId, path: " + relativePath);
                    return(Result.EInvalidOperation);
                }

                if (providerId == null)
                {
                    this.Context.Tracer.RelatedError($"{nameof(this.OnGetFileStream)} called with null epochId, path: " + relativePath);
                    return(Result.EInvalidOperation);
                }

                string sha = GetShaFromContentId(contentId);
                byte   placeholderVersion = GetPlaceholderVersionFromProviderId(providerId);

                EventMetadata metadata = this.CreateEventMetadata(relativePath);
                metadata.Add(nameof(triggeringProcessId), triggeringProcessId);
                metadata.Add(nameof(triggeringProcessName), triggeringProcessName);
                metadata.Add(nameof(sha), sha);
                metadata.Add(nameof(placeholderVersion), placeholderVersion);
                metadata.Add(nameof(commandId), commandId);
                ITracer activity = this.Context.Tracer.StartActivity("GetFileStream", EventLevel.Verbose, Keywords.Telemetry, metadata);

                if (placeholderVersion != FileSystemVirtualizer.PlaceholderVersion)
                {
                    activity.RelatedError(metadata, nameof(this.OnGetFileStream) + ": Unexpected placeholder version");
                    activity.Dispose();

                    // TODO(#1362): Is this the correct Result to return?
                    return(Result.EIOError);
                }

                try
                {
                    if (!this.GitObjects.TryCopyBlobContentStream(
                            sha,
                            CancellationToken.None,
                            GVFSGitObjects.RequestSource.FileStreamCallback,
                            (stream, blobLength) =>
                    {
                        // TODO(#1361): Find a better solution than reading from the stream one byte at at time
                        byte[] buffer = new byte[4096];
                        uint bufferIndex = 0;
                        int nextByte = stream.ReadByte();
                        int bytesWritten = 0;
                        while (nextByte != -1)
                        {
                            while (bufferIndex < buffer.Length && nextByte != -1)
                            {
                                buffer[bufferIndex] = (byte)nextByte;
                                nextByte = stream.ReadByte();
                                ++bufferIndex;
                            }

                            Result result = this.virtualizationInstance.WriteFileContents(
                                fileHandle,
                                buffer,
                                bufferIndex);
                            if (result != Result.Success)
                            {
                                activity.RelatedError(metadata, $"{nameof(this.virtualizationInstance.WriteFileContents)} failed, error: " + result.ToString("X") + "(" + result.ToString("G") + ")");
                                throw new GetFileStreamException(result);
                            }

                            if (bufferIndex == buffer.Length)
                            {
                                bufferIndex = 0;
                                bytesWritten += buffer.Length;
                            }
                        }
                        bytesWritten += Convert.ToInt32(bufferIndex);

                        if (bytesWritten != blobLength)
                        {
                            // If the read size does not match the expected size print an error and add the file to ModifiedPaths.dat
                            // This allows the user to see that something went wrong with file hydration
                            // Unfortunitely we must do this check *after* the file is hydrated since the header isn't corrupt for trunctated objects on mac
                            this.Context.Tracer.RelatedError($"Read {relativePath} to {bytesWritten}, not expected size of {blobLength}");
                            this.FileSystemCallbacks.OnFailedFileHydration(relativePath);
                        }
                    }))
                    {
                        activity.RelatedError(metadata, $"{nameof(this.OnGetFileStream)}: TryCopyBlobContentStream failed");

                        // TODO(#1362): Is this the correct Result to return?
                        return(Result.EFileNotFound);
                    }
                }
                catch (GetFileStreamException e)
                {
                    return(e.Result);
                }

                this.FileSystemCallbacks.OnPlaceholderFileHydrated(triggeringProcessName);
                return(Result.Success);
            }
            catch (Exception e)
            {
                EventMetadata metadata = this.CreateEventMetadata(relativePath, e);
                metadata.Add(nameof(triggeringProcessId), triggeringProcessId);
                metadata.Add(nameof(triggeringProcessName), triggeringProcessName);
                metadata.Add(nameof(commandId), commandId);
                this.LogUnhandledExceptionAndExit(nameof(this.OnGetFileStream), metadata);
            }

            return(Result.EIOError);
        }
Esempio n. 12
0
        private void UpdateHooks()
        {
            bool   copyReadObjectHook           = false;
            string enlistmentReadObjectHookPath = Path.Combine(this.enlistment.WorkingDirectoryRoot, GVFSConstants.DotGit.Hooks.ReadObjectPath + ".exe");
            string installedReadObjectHookPath  = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), GVFSConstants.GVFSReadObjectHookExecutableName);

            if (!File.Exists(installedReadObjectHookPath))
            {
                this.FailMountAndExit(GVFSConstants.GVFSReadObjectHookExecutableName + " cannot be found at {0}", installedReadObjectHookPath);
            }

            if (!File.Exists(enlistmentReadObjectHookPath))
            {
                copyReadObjectHook = true;

                EventMetadata metadata = new EventMetadata();
                metadata.Add("Area", "Mount");
                metadata.Add("enlistmentReadObjectHookPath", enlistmentReadObjectHookPath);
                metadata.Add("installedReadObjectHookPath", installedReadObjectHookPath);
                metadata.Add("Message", GVFSConstants.DotGit.Hooks.ReadObjectName + " not found in enlistment, copying from installation folder");
                this.tracer.RelatedEvent(EventLevel.Warning, "ReadObjectMissingFromEnlistment", metadata);
            }
            else
            {
                try
                {
                    FileVersionInfo enlistmentVersion = FileVersionInfo.GetVersionInfo(enlistmentReadObjectHookPath);
                    FileVersionInfo installedVersion  = FileVersionInfo.GetVersionInfo(installedReadObjectHookPath);
                    copyReadObjectHook = enlistmentVersion.FileVersion != installedVersion.FileVersion;
                }
                catch (Exception e)
                {
                    EventMetadata metadata = new EventMetadata();
                    metadata.Add("Area", "Mount");
                    metadata.Add("enlistmentReadObjectHookPath", enlistmentReadObjectHookPath);
                    metadata.Add("installedReadObjectHookPath", installedReadObjectHookPath);
                    metadata.Add("Exception", e.ToString());
                    metadata.Add("ErrorMessage", "Failed to compare " + GVFSConstants.DotGit.Hooks.ReadObjectName + " version");
                    this.tracer.RelatedError(metadata);
                    this.FailMountAndExit("Error comparing " + GVFSConstants.DotGit.Hooks.ReadObjectName + " versions, see log file for details");
                }
            }

            if (copyReadObjectHook)
            {
                try
                {
                    File.Copy(installedReadObjectHookPath, enlistmentReadObjectHookPath, overwrite: true);
                }
                catch (Exception e)
                {
                    EventMetadata metadata = new EventMetadata();
                    metadata.Add("Area", "Mount");
                    metadata.Add("enlistmentReadObjectHookPath", enlistmentReadObjectHookPath);
                    metadata.Add("installedReadObjectHookPath", installedReadObjectHookPath);
                    metadata.Add("Exception", e.ToString());
                    metadata.Add("ErrorMessage", "Failed to copy " + GVFSConstants.DotGit.Hooks.ReadObjectName + " to enlistment");
                    this.tracer.RelatedError(metadata);
                    this.FailMountAndExit("Error copying " + GVFSConstants.DotGit.Hooks.ReadObjectName + " to enlistment, see log file for details");
                }
            }
        }
Esempio n. 13
0
 private Type GetDataType(EventMetadata eventData, int parameterId)
 {
     return(eventData.Parameters[parameterId].ParameterType);
 }
Esempio n. 14
0
 private int GetParameterCount(EventMetadata eventData)
 {
     return(eventData.Parameters.Length);
 }
Esempio n. 15
0
        // Use reflection to look at the attributes of a class, and generate a manifest for it (as UTF8) and
        // return the UTF8 bytes.  It also sets up the code:EventData structures needed to dispatch events
        // at run time.  'source' is the event source to place the descriptors.  If it is null,
        // then the descriptors are not creaed, and just the manifest is generated.  
        private static byte[] CreateManifestAndDescriptors(Type eventSourceType, string eventSourceDllName, EventSource source)
        {
            MethodInfo[] methods = eventSourceType.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
            EventAttribute defaultEventAttribute;
            int eventId = 1;        // The number given to an event that does not have a explicitly given ID. 
            EventMetadata[] eventData = null;
            Dictionary<string, string> eventsByName = null;
            if (source != null)
                eventData = new EventMetadata[methods.Length];

            // See if we have localization information.  
            ResourceManager resources = null;
            EventSourceAttribute eventSourceAttrib = (EventSourceAttribute)GetCustomAttributeHelper(eventSourceType, typeof(EventSourceAttribute));
            if (eventSourceAttrib != null && eventSourceAttrib.LocalizationResources != null)
                resources = new ResourceManager(eventSourceAttrib.LocalizationResources, eventSourceType.Assembly);

            ManifestBuilder manifest = new ManifestBuilder(GetName(eventSourceType), GetGuid(eventSourceType), eventSourceDllName, resources);

            // Collect task, opcode, keyword and channel information
#if FEATURE_MANAGED_ETW_CHANNELS
            foreach (var providerEnumKind in new string[] { "Keywords", "Tasks", "Opcodes", "Channels" })
#else
            foreach (var providerEnumKind in new string[] { "Keywords", "Tasks", "Opcodes" })
#endif
            {
                Type nestedType = eventSourceType.GetNestedType(providerEnumKind);
                if (nestedType != null)
                {
                    foreach (FieldInfo staticField in nestedType.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static))
                    {
                        AddProviderEnumKind(manifest, staticField, providerEnumKind);
                    }
                }
            }

            for (int i = 0; i < methods.Length; i++)
            {
                MethodInfo method = methods[i];
                ParameterInfo[] args = method.GetParameters();

                // Get the EventDescriptor (from the Custom attributes)
                EventAttribute eventAttribute = (EventAttribute)GetCustomAttributeHelper(method, typeof(EventAttribute));

                // Methods that don't return void can't be events.  
                if (method.ReturnType != typeof(void))
                {
                    if (eventAttribute != null)
                        throw new ArgumentException(Environment.GetResourceString("EventSource_AttributeOnNonVoid", method.Name));
                    continue;
                }
                if (method.IsVirtual || method.IsStatic)
                {
                    continue;
                }

                if (eventAttribute == null)
                {
                    // If we explictly mark the method as not being an event, then honor that.  
                    if (GetCustomAttributeHelper(method, typeof(NonEventAttribute)) != null)
                        continue;

                    defaultEventAttribute = new EventAttribute(eventId);
                    eventAttribute = defaultEventAttribute;
                }
                else if (eventAttribute.EventId <= 0)
                    throw new ArgumentException(Environment.GetResourceString("EventSource_NeedPositiveId"));
                else if ((ulong)eventAttribute.Keywords >= 0x0000100000000000UL)
                    throw new ArgumentException(Environment.GetResourceString("EventSource_ReservedKeywords"));
                eventId++;

                // Auto-assign tasks, starting with the highest task number and working back 
                if (eventAttribute.Opcode == EventOpcode.Info && eventAttribute.Task == EventTask.None)
                    eventAttribute.Task = (EventTask)(0xFFFE - eventAttribute.EventId);

                manifest.StartEvent(method.Name, eventAttribute);
                for (int fieldIdx = 0; fieldIdx < args.Length; fieldIdx++)
                {
                    // If the first parameter is 'RelatedActivityId' then skip it.  
                    if (fieldIdx == 0 && args[fieldIdx].ParameterType == typeof(Guid) && 
                        string.Compare(args[fieldIdx].Name, "RelatedActivityId", StringComparison.OrdinalIgnoreCase) == 0)
                        continue;
                    manifest.AddEventParameter(args[fieldIdx].ParameterType, args[fieldIdx].Name);
                }
                manifest.EndEvent();

                if (source != null)
                {
                    // Do checking for user errors (optional, but nto a big deal so we do it).  
                    DebugCheckEvent(ref eventsByName, eventData, method, eventAttribute);
                    AddEventDescriptor(ref eventData, method.Name, eventAttribute, args);
                }
            }

            if (source != null)
            {
                TrimEventDescriptors(ref eventData);
                source.m_eventData = eventData;     // officaly initialize it. We do this at most once (it is racy otherwise). 
            }

            return manifest.CreateManifest();
        }
        private void ProcessBackgroundOperations()
        {
            TBackgroundOperation backgroundOperation;

            while (true)
            {
                AcquireGitLockResult acquireLockResult = AcquireGitLockResult.ShuttingDown;

                try
                {
                    this.wakeUpThread.WaitOne();

                    if (this.isStopping)
                    {
                        return;
                    }

                    acquireLockResult = this.WaitToAcquireGitLock();
                    switch (acquireLockResult)
                    {
                    case AcquireGitLockResult.LockAcquired:
                        break;

                    case AcquireGitLockResult.ShuttingDown:
                        return;

                    default:
                        this.LogErrorAndExit("Invalid AcquireGitLockResult result");
                        return;
                    }

                    this.RunCallbackUntilSuccess(this.preCallback, "PreCallback");

                    int tasksProcessed = 0;
                    while (this.backgroundOperations.TryPeek(out backgroundOperation))
                    {
                        if (tasksProcessed % LogUpdateTaskThreshold == 0 &&
                            (tasksProcessed >= LogUpdateTaskThreshold || this.backgroundOperations.Count >= LogUpdateTaskThreshold))
                        {
                            this.LogTaskProcessingStatus(tasksProcessed);
                        }

                        if (this.isStopping)
                        {
                            // If we are stopping, then GVFlt has already been shut down
                            // Some of the queued background tasks may require GVFlt, and so it is unsafe to
                            // proceed.  GVFS will resume any queued tasks next time it is mounted
                            this.persistence.Flush();
                            return;
                        }

                        CallbackResult callbackResult = this.callback(backgroundOperation);
                        switch (callbackResult)
                        {
                        case CallbackResult.Success:
                            this.backgroundOperations.TryDequeue(out backgroundOperation);
                            this.persistence.Remove(backgroundOperation.Id);
                            ++tasksProcessed;
                            break;

                        case CallbackResult.RetryableError:
                            if (!this.isStopping)
                            {
                                Thread.Sleep(ActionRetryDelayMS);
                            }

                            break;

                        case CallbackResult.FatalError:
                            this.LogErrorAndExit("Callback encountered fatal error, exiting process");
                            break;

                        default:
                            this.LogErrorAndExit("Invalid background operation result");
                            break;
                        }
                    }

                    this.persistence.Flush();

                    if (tasksProcessed >= LogUpdateTaskThreshold)
                    {
                        EventMetadata metadata = new EventMetadata();
                        metadata.Add("BackgroundOperations", EtwArea);
                        metadata.Add("TasksProcessed", tasksProcessed);
                        metadata.Add("Message", "Processing background tasks complete");
                        this.context.Tracer.RelatedEvent(EventLevel.Informational, "TaskProcessingStatus", metadata);
                    }

                    if (this.isStopping)
                    {
                        return;
                    }
                }
                catch (Exception e)
                {
                    this.LogErrorAndExit("ProcessBackgroundOperations caught unhandled exception, exiting process", e);
                }
                finally
                {
                    if (acquireLockResult == AcquireGitLockResult.LockAcquired)
                    {
                        this.RunCallbackUntilSuccess(this.postCallback, "PostCallback");
                        this.ReleaseGitLockIfNecessary();
                    }
                }
            }
        }
Esempio n. 17
0
 // Helper used by code:CreateManifestAndDescriptors that trims the m_eventData array to the correct
 // size after all event descriptors have been added. 
 private static void TrimEventDescriptors(ref EventMetadata[] eventData)
 {
     int idx = eventData.Length;
     while (0 < idx)
     {
         --idx;
         if (eventData[idx].Descriptor.EventId != 0)
             break;
     }
     if (eventData.Length - idx > 2)      // allow one wasted slot. 
     {
         EventMetadata[] newValues = new EventMetadata[idx + 1];
         Array.Copy(eventData, newValues, newValues.Length);
         eventData = newValues;
     }
 }
Esempio n. 18
0
        private Result TryClone(
            JsonTracer tracer,
            GVFSEnlistment enlistment,
            CacheServerInfo cacheServer,
            RetryConfig retryConfig,
            ServerGVFSConfig serverGVFSConfig,
            string resolvedLocalCacheRoot)
        {
            Result pipeResult;

            using (NamedPipeServer pipeServer = this.StartNamedPipe(tracer, enlistment, out pipeResult))
            {
                if (!pipeResult.Success)
                {
                    return(pipeResult);
                }

                using (GitObjectsHttpRequestor objectRequestor = new GitObjectsHttpRequestor(tracer, enlistment, cacheServer, retryConfig))
                {
                    GitRefs refs = objectRequestor.QueryInfoRefs(this.SingleBranch ? this.Branch : null);

                    if (refs == null)
                    {
                        return(new Result("Could not query info/refs from: " + Uri.EscapeUriString(enlistment.RepoUrl)));
                    }

                    if (this.Branch == null)
                    {
                        this.Branch = refs.GetDefaultBranch();

                        EventMetadata metadata = new EventMetadata();
                        metadata.Add("Branch", this.Branch);
                        tracer.RelatedEvent(EventLevel.Informational, "CloneDefaultRemoteBranch", metadata);
                    }
                    else
                    {
                        if (!refs.HasBranch(this.Branch))
                        {
                            EventMetadata metadata = new EventMetadata();
                            metadata.Add("Branch", this.Branch);
                            tracer.RelatedEvent(EventLevel.Warning, "CloneBranchDoesNotExist", metadata);

                            string errorMessage = string.Format("Remote branch {0} not found in upstream origin", this.Branch);
                            return(new Result(errorMessage));
                        }
                    }

                    if (!enlistment.TryCreateEnlistmentFolders())
                    {
                        string error = "Could not create enlistment directory";
                        tracer.RelatedError(error);
                        return(new Result(error));
                    }

                    string localCacheError;
                    if (!this.TryDetermineLocalCacheAndInitializePaths(tracer, enlistment, serverGVFSConfig, cacheServer, resolvedLocalCacheRoot, out localCacheError))
                    {
                        tracer.RelatedError(localCacheError);
                        return(new Result(localCacheError));
                    }

                    Directory.CreateDirectory(enlistment.GitObjectsRoot);
                    Directory.CreateDirectory(enlistment.GitPackRoot);
                    Directory.CreateDirectory(enlistment.BlobSizesRoot);

                    return(this.CreateClone(tracer, enlistment, objectRequestor, refs, this.Branch));
                }
            }
        }
Esempio n. 19
0
 private Type GetDataType(EventMetadata eventData, int parameterId)
 {
     return eventData.Parameters[parameterId].ParameterType;
 }
Esempio n. 20
0
        private Result CreateClone(
            ITracer tracer,
            GVFSEnlistment enlistment,
            GitObjectsHttpRequestor objectRequestor,
            GitRefs refs,
            string branch)
        {
            Result initRepoResult = this.TryInitRepo(tracer, refs, enlistment);

            if (!initRepoResult.Success)
            {
                return(initRepoResult);
            }

            PhysicalFileSystem fileSystem = new PhysicalFileSystem();
            string             errorMessage;

            if (!this.TryCreateAlternatesFile(fileSystem, enlistment, out errorMessage))
            {
                return(new Result("Error configuring alternate: " + errorMessage));
            }

            GitRepo        gitRepo    = new GitRepo(tracer, enlistment, fileSystem);
            GVFSContext    context    = new GVFSContext(tracer, fileSystem, gitRepo, enlistment);
            GVFSGitObjects gitObjects = new GVFSGitObjects(context, objectRequestor);

            if (!this.TryDownloadCommit(
                    refs.GetTipCommitId(branch),
                    enlistment,
                    objectRequestor,
                    gitObjects,
                    gitRepo,
                    out errorMessage))
            {
                return(new Result(errorMessage));
            }

            if (!GVFSVerb.TrySetRequiredGitConfigSettings(enlistment) ||
                !GVFSVerb.TrySetOptionalGitConfigSettings(enlistment))
            {
                return(new Result("Unable to configure git repo"));
            }

            CacheServerResolver cacheServerResolver = new CacheServerResolver(tracer, enlistment);

            if (!cacheServerResolver.TrySaveUrlToLocalConfig(objectRequestor.CacheServer, out errorMessage))
            {
                return(new Result("Unable to configure cache server: " + errorMessage));
            }

            GitProcess git = new GitProcess(enlistment);
            string     originBranchName = "origin/" + branch;

            GitProcess.Result createBranchResult = git.CreateBranchWithUpstream(branch, originBranchName);
            if (createBranchResult.HasErrors)
            {
                return(new Result("Unable to create branch '" + originBranchName + "': " + createBranchResult.Errors + "\r\n" + createBranchResult.Output));
            }

            File.WriteAllText(
                Path.Combine(enlistment.WorkingDirectoryRoot, GVFSConstants.DotGit.Head),
                "ref: refs/heads/" + branch);

            if (!this.TryDownloadRootGitAttributes(enlistment, gitObjects, gitRepo, out errorMessage))
            {
                return(new Result(errorMessage));
            }

            this.CreateGitScript(enlistment);

            string installHooksError;

            if (!HooksInstaller.InstallHooks(context, out installHooksError))
            {
                tracer.RelatedError(installHooksError);
                return(new Result(installHooksError));
            }

            GitProcess.Result forceCheckoutResult = git.ForceCheckout(branch);
            if (forceCheckoutResult.HasErrors && forceCheckoutResult.Errors.IndexOf("unable to read tree") > 0)
            {
                // It is possible to have the above TryDownloadCommit() fail because we
                // already have the commit and root tree we intend to check out, but
                // don't have a tree further down the working directory. If we fail
                // checkout here, its' because we don't have these trees and the
                // read-object hook is not available yet. Force downloading the commit
                // again and retry the checkout.

                if (!this.TryDownloadCommit(
                        refs.GetTipCommitId(branch),
                        enlistment,
                        objectRequestor,
                        gitObjects,
                        gitRepo,
                        out errorMessage,
                        checkLocalObjectCache: false))
                {
                    return(new Result(errorMessage));
                }

                forceCheckoutResult = git.ForceCheckout(branch);
            }

            if (forceCheckoutResult.HasErrors)
            {
                string[]      errorLines     = forceCheckoutResult.Errors.Split('\n');
                StringBuilder checkoutErrors = new StringBuilder();
                foreach (string gitError in errorLines)
                {
                    if (IsForceCheckoutErrorCloneFailure(gitError))
                    {
                        checkoutErrors.AppendLine(gitError);
                    }
                }

                if (checkoutErrors.Length > 0)
                {
                    string error = "Could not complete checkout of branch: " + branch + ", " + checkoutErrors.ToString();
                    tracer.RelatedError(error);
                    return(new Result(error));
                }
            }

            if (!RepoMetadata.TryInitialize(tracer, enlistment.DotGVFSRoot, out errorMessage))
            {
                tracer.RelatedError(errorMessage);
                return(new Result(errorMessage));
            }

            try
            {
                RepoMetadata.Instance.SaveCloneMetadata(tracer, enlistment);
                this.LogEnlistmentInfoAndSetConfigValues(tracer, git, enlistment);
            }
            catch (Exception e)
            {
                tracer.RelatedError(e.ToString());
                return(new Result(e.Message));
            }
            finally
            {
                RepoMetadata.Shutdown();
            }

            // Prepare the working directory folder for GVFS last to ensure that gvfs mount will fail if gvfs clone has failed
            Exception exception;
            string    prepFileSystemError;

            if (!GVFSPlatform.Instance.KernelDriver.TryPrepareFolderForCallbacks(enlistment.WorkingDirectoryRoot, out prepFileSystemError, out exception))
            {
                EventMetadata metadata = new EventMetadata();
                metadata.Add(nameof(prepFileSystemError), prepFileSystemError);
                if (exception != null)
                {
                    metadata.Add("Exception", exception.ToString());
                }

                tracer.RelatedError(metadata, $"{nameof(this.CreateClone)}: TryPrepareFolderForCallbacks failed");
                return(new Result(prepFileSystemError));
            }

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

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

            this.placeHolderCreationCount = new ConcurrentDictionary <string, PlaceHolderCreateCounter>(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);

            this.backgroundFileSystemTaskRunner = backgroundFileSystemTaskRunner ?? new BackgroundFileSystemTaskRunner(
                this.context,
                this.PreBackgroundOperation,
                this.ExecuteBackgroundOperation,
                this.PostBackgroundOperation,
                Path.Combine(context.Enlistment.DotGVFSRoot, GVFSConstants.DotGVFS.Databases.BackgroundFileSystemTasks));

            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);
        }
Esempio n. 22
0
 /// <summary>
 /// Add the standard ScalarVerb metadata to the specified EventMetadata
 /// </summary>
 /// <param name="metadata">
 /// EventMetadata to which verb data will be added
 /// </param>
 /// <returns>
 /// The specified EventMetadata (updated to include verb metadata)
 /// </returns>
 protected EventMetadata AddVerbDataToMetadata(EventMetadata metadata)
 {
     metadata["Area"] = $"{this.VerbName}_Verb";
     metadata["Verb"] = this.VerbName;
     return(metadata);
 }
Esempio n. 23
0
        private static bool TryEnableProjFSOptionalFeature(ITracer tracer, PhysicalFileSystem fileSystem, out bool isProjFSFeatureAvailable)
        {
            EventMetadata metadata = CreateEventMetadata();

            const int ProjFSNotAnOptionalFeature = 2;
            const int ProjFSEnabled  = 3;
            const int ProjFSDisabled = 4;

            ProcessResult getOptionalFeatureResult = CallPowershellCommand(
                "$var=(Get-WindowsOptionalFeature -Online -FeatureName " + OptionalFeatureName + ");  if($var -eq $null){exit " +
                ProjFSNotAnOptionalFeature + "}else{if($var.State -eq 'Enabled'){exit " + ProjFSEnabled + "}else{exit " + ProjFSDisabled + "}}");

            isProjFSFeatureAvailable = true;
            bool projFSEnabled = false;

            switch (getOptionalFeatureResult.ExitCode)
            {
            case ProjFSNotAnOptionalFeature:
                metadata.Add("getOptionalFeatureResult.Output", getOptionalFeatureResult.Output);
                metadata.Add("getOptionalFeatureResult.Errors", getOptionalFeatureResult.Errors);
                tracer.RelatedWarning(metadata, $"{nameof(TryEnableProjFSOptionalFeature)}: {OptionalFeatureName} optional feature is missing");

                isProjFSFeatureAvailable = false;
                break;

            case ProjFSEnabled:
                tracer.RelatedEvent(
                    EventLevel.Informational,
                    $"{nameof(TryEnableProjFSOptionalFeature)}_ClientProjFSAlreadyEnabled",
                    metadata,
                    Keywords.Network);
                projFSEnabled = true;
                break;

            case ProjFSDisabled:
                ProcessResult enableOptionalFeatureResult = CallPowershellCommand("try {Enable-WindowsOptionalFeature -Online -FeatureName " + OptionalFeatureName + " -NoRestart}catch{exit 1}");
                metadata.Add("enableOptionalFeatureResult.Output", enableOptionalFeatureResult.Output.Trim().Replace("\r\n", ","));
                metadata.Add("enableOptionalFeatureResult.Errors", enableOptionalFeatureResult.Errors);

                if (enableOptionalFeatureResult.ExitCode == 0)
                {
                    metadata.Add(TracingConstants.MessageKey.InfoMessage, "Enabled ProjFS optional feature");
                    tracer.RelatedEvent(EventLevel.Informational, $"{nameof(TryEnableProjFSOptionalFeature)}_ClientProjFSDisabled", metadata);
                    projFSEnabled = true;
                    break;
                }

                metadata.Add("enableOptionalFeatureResult.ExitCode", enableOptionalFeatureResult.ExitCode);
                tracer.RelatedError(metadata, $"{nameof(TryEnableProjFSOptionalFeature)}: Failed to enable optional feature");
                break;

            default:
                metadata.Add("getOptionalFeatureResult.ExitCode", getOptionalFeatureResult.ExitCode);
                metadata.Add("getOptionalFeatureResult.Output", getOptionalFeatureResult.Output);
                metadata.Add("getOptionalFeatureResult.Errors", getOptionalFeatureResult.Errors);
                tracer.RelatedError(metadata, $"{nameof(TryEnableProjFSOptionalFeature)}: Unexpected result");
                isProjFSFeatureAvailable = false;
                break;
            }

            if (projFSEnabled)
            {
                if (IsNativeLibInstalled(tracer, fileSystem))
                {
                    return(true);
                }

                tracer.RelatedError($"{nameof(TryEnableProjFSOptionalFeature)}: {OptionalFeatureName} enabled, but native ProjFS library is not on path");
            }

            return(false);
        }
Esempio n. 24
0
        public static bool TryGetMaxGoodPrefetchTimestamp(
            ITracer tracer,
            GVFSEnlistment enlistment,
            PhysicalFileSystem fileSystem,
            GitObjects gitObjects,
            out long maxGoodTimestamp,
            out string error)
        {
            fileSystem.CreateDirectory(enlistment.GitPackRoot);

            string[] packs = gitObjects.ReadPackFileNames(enlistment.GitPackRoot, GVFSConstants.PrefetchPackPrefix);
            List <PrefetchPackInfo> orderedPacks = packs
                                                   .Where(pack => GetTimestamp(pack).HasValue)
                                                   .Select(pack => new PrefetchPackInfo(GetTimestamp(pack).Value, pack))
                                                   .OrderBy(packInfo => packInfo.Timestamp)
                                                   .ToList();

            maxGoodTimestamp = -1;

            int firstBadPack = -1;

            for (int i = 0; i < orderedPacks.Count; ++i)
            {
                long   timestamp = orderedPacks[i].Timestamp;
                string packPath  = orderedPacks[i].Path;
                string idxPath   = Path.ChangeExtension(packPath, ".idx");
                if (!fileSystem.FileExists(idxPath))
                {
                    EventMetadata metadata = new EventMetadata();
                    metadata.Add("pack", packPath);
                    metadata.Add("idxPath", idxPath);
                    metadata.Add("timestamp", timestamp);
                    GitProcess.Result indexResult = gitObjects.IndexPackFile(packPath);
                    if (indexResult.HasErrors)
                    {
                        firstBadPack = i;

                        metadata.Add("Errors", indexResult.Errors);
                        tracer.RelatedWarning(metadata, $"{nameof(TryGetMaxGoodPrefetchTimestamp)}: Found pack file that's missing idx file, and failed to regenerate idx");
                        break;
                    }
                    else
                    {
                        maxGoodTimestamp = timestamp;

                        metadata.Add(TracingConstants.MessageKey.InfoMessage, $"{nameof(TryGetMaxGoodPrefetchTimestamp)}: Found pack file that's missing idx file, and regenerated idx");
                        tracer.RelatedEvent(EventLevel.Informational, $"{nameof(TryGetMaxGoodPrefetchTimestamp)}_RebuildIdx", metadata);
                    }
                }
                else
                {
                    maxGoodTimestamp = timestamp;
                }
            }

            if (firstBadPack != -1)
            {
                const int MaxDeleteRetries      = 200; // 200 * IoFailureRetryDelayMS (50ms) = 10 seconds
                const int RetryLoggingThreshold = 40;  // 40 * IoFailureRetryDelayMS (50ms) = 2 seconds

                // Delete packs and indexes in reverse order so that if prefetch is killed, subseqeuent prefetch commands will
                // find the right starting spot.
                for (int i = orderedPacks.Count - 1; i >= firstBadPack; --i)
                {
                    string packPath = orderedPacks[i].Path;
                    string idxPath  = Path.ChangeExtension(packPath, ".idx");

                    EventMetadata metadata = new EventMetadata();
                    metadata.Add("path", idxPath);
                    metadata.Add(TracingConstants.MessageKey.InfoMessage, $"{nameof(TryGetMaxGoodPrefetchTimestamp)} deleting bad idx file");
                    tracer.RelatedEvent(EventLevel.Informational, $"{nameof(TryGetMaxGoodPrefetchTimestamp)}_DeleteBadIdx", metadata);
                    if (!fileSystem.TryWaitForDelete(tracer, idxPath, IoFailureRetryDelayMS, MaxDeleteRetries, RetryLoggingThreshold))
                    {
                        error = $"Unable to delete {idxPath}";
                        return(false);
                    }

                    metadata = new EventMetadata();
                    metadata.Add("path", packPath);
                    metadata.Add(TracingConstants.MessageKey.InfoMessage, $"{nameof(TryGetMaxGoodPrefetchTimestamp)} deleting bad pack file");
                    tracer.RelatedEvent(EventLevel.Informational, $"{nameof(TryGetMaxGoodPrefetchTimestamp)}_DeleteBadPack", metadata);
                    if (!fileSystem.TryWaitForDelete(tracer, packPath, IoFailureRetryDelayMS, MaxDeleteRetries, RetryLoggingThreshold))
                    {
                        error = $"Unable to delete {packPath}";
                        return(false);
                    }
                }
            }

            error = null;
            return(true);
        }
Esempio n. 25
0
        private int ExecuteWithExitCode()
        {
            // CmdParser doesn't strip quotes, and Path.Combine will throw
            this.GitBinPath = this.GitBinPath.Replace("\"", string.Empty);
            if (!GitProcess.GitExists(this.GitBinPath))
            {
                Console.WriteLine(
                    "Could not find git.exe {0}",
                    !string.IsNullOrWhiteSpace(this.GitBinPath) ? "at " + this.GitBinPath : "on %PATH%");
                return(ExitFailure);
            }

            if (this.Commit != null && this.Branch != null)
            {
                Console.WriteLine("Cannot specify both a commit sha and a branch name.");
                return(ExitFailure);
            }

            this.CacheServerUrl = Enlistment.StripObjectsEndpointSuffix(this.CacheServerUrl);

            this.SearchThreadCount   = this.SearchThreadCount > 0 ? this.SearchThreadCount : Environment.ProcessorCount;
            this.DownloadThreadCount = this.DownloadThreadCount > 0 ? this.DownloadThreadCount : Math.Min(Environment.ProcessorCount, MaxDefaultDownloadThreads);
            this.IndexThreadCount    = this.IndexThreadCount > 0 ? this.IndexThreadCount : Environment.ProcessorCount;
            this.CheckoutThreadCount = this.CheckoutThreadCount > 0 ? this.CheckoutThreadCount : Environment.ProcessorCount;

            this.GitBinPath = !string.IsNullOrWhiteSpace(this.GitBinPath) ? this.GitBinPath : GitProcess.GetInstalledGitBinPath();

            GitEnlistment enlistment = GitEnlistment.CreateFromCurrentDirectory(this.CacheServerUrl, this.GitBinPath);

            if (enlistment == null)
            {
                Console.WriteLine("Must be run within a git repo");
                return(ExitFailure);
            }

            string commitish = this.Commit ?? this.Branch;

            if (string.IsNullOrWhiteSpace(commitish))
            {
                GitProcess.Result result = new GitProcess(enlistment).GetCurrentBranchName();
                if (result.HasErrors || string.IsNullOrWhiteSpace(result.Output))
                {
                    Console.WriteLine("Could not retrieve current branch name: " + result.Errors);
                    return(ExitFailure);
                }

                commitish = result.Output.Trim();
            }

            Guid parentActivityId = Guid.Empty;

            if (!string.IsNullOrWhiteSpace(this.ParentActivityId) && !Guid.TryParse(this.ParentActivityId, out parentActivityId))
            {
                Console.WriteLine("The ParentActivityId provided (" + this.ParentActivityId + ") is not a valid GUID.");
            }

            using (JsonEtwTracer tracer = new JsonEtwTracer("Microsoft.Git.FastFetch", parentActivityId, "FastFetch"))
            {
                if (this.Verbose)
                {
                    tracer.AddConsoleEventListener(EventLevel.Informational, Keywords.Any);
                }

                string fastfetchLogFile = Enlistment.GetNewLogFileName(enlistment.FastFetchLogRoot, "fastfetch");
                tracer.AddLogFileEventListener(fastfetchLogFile, EventLevel.Informational, Keywords.Any);
                tracer.WriteStartEvent(
                    enlistment.EnlistmentRoot,
                    enlistment.RepoUrl,
                    enlistment.CacheServerUrl,
                    new EventMetadata
                {
                    { "TargetCommitish", commitish },
                    { "Checkout", this.Checkout },
                });

                FetchHelper fetchHelper = this.GetFetchHelper(tracer, enlistment);
                fetchHelper.MaxRetries = this.MaxRetries;

                if (!FetchHelper.TryLoadPathWhitelist(tracer, this.PathWhitelist, this.PathWhitelistFile, enlistment, fetchHelper.PathWhitelist))
                {
                    return(ExitFailure);
                }

                bool isSuccess;

                try
                {
                    Func <bool> doPrefetch =
                        () =>
                    {
                        try
                        {
                            bool isBranch = this.Commit == null;
                            fetchHelper.FastFetch(commitish, isBranch);
                            return(!fetchHelper.HasFailures);
                        }
                        catch (FetchHelper.FetchException e)
                        {
                            tracer.RelatedError(e.Message);
                            return(false);
                        }
                    };
                    if (this.Verbose)
                    {
                        isSuccess = doPrefetch();
                    }
                    else
                    {
                        isSuccess = ConsoleHelper.ShowStatusWhileRunning(
                            doPrefetch,
                            "Fetching",
                            output: Console.Out,
                            showSpinner: !Console.IsOutputRedirected);

                        Console.WriteLine();
                        Console.WriteLine("FastFetch is complete. See the full logs at " + fastfetchLogFile);
                    }

                    isSuccess &= !fetchHelper.HasFailures;
                }
                catch (AggregateException e)
                {
                    isSuccess = false;
                    foreach (Exception ex in e.Flatten().InnerExceptions)
                    {
                        tracer.RelatedError(ex.ToString());
                    }
                }
                catch (Exception e)
                {
                    isSuccess = false;
                    tracer.RelatedError(e.ToString());
                }

                EventMetadata stopMetadata = new EventMetadata();
                stopMetadata.Add("Success", isSuccess);
                tracer.Stop(stopMetadata);

                return(isSuccess ? ExitSuccess : ExitFailure);
            }
        }
        private void LoadEventDescriptor()
        {
            if (_idSpecified)
            {
                List <EventMetadata> matchedEvents = new();
                foreach (EventMetadata emd in _providerMetadata.Events)
                {
                    if (emd.Id == _id)
                    {
                        matchedEvents.Add(emd);
                    }
                }

                if (matchedEvents.Count == 0)
                {
                    string msg = string.Format(CultureInfo.InvariantCulture,
                                               _resourceMgr.GetString("IncorrectEventId"),
                                               _id,
                                               _providerName);
                    throw new EventWriteException(msg);
                }

                EventMetadata matchedEvent = null;
                if (!_versionSpecified && matchedEvents.Count == 1)
                {
                    matchedEvent = matchedEvents[0];
                }
                else
                {
                    if (_versionSpecified)
                    {
                        foreach (EventMetadata emd in matchedEvents)
                        {
                            if (emd.Version == _version)
                            {
                                matchedEvent = emd;
                                break;
                            }
                        }

                        if (matchedEvent == null)
                        {
                            string msg = string.Format(CultureInfo.InvariantCulture,
                                                       _resourceMgr.GetString("IncorrectEventVersion"),
                                                       _version,
                                                       _id,
                                                       _providerName);

                            throw new EventWriteException(msg);
                        }
                    }
                    else
                    {
                        string msg = string.Format(CultureInfo.InvariantCulture,
                                                   _resourceMgr.GetString("VersionNotSpecified"),
                                                   _id,
                                                   _providerName);

                        throw new EventWriteException(msg);
                    }
                }

                VerifyTemplate(matchedEvent);
                _eventDescriptor = CreateEventDescriptor(_providerMetadata, matchedEvent);
            }
            else
            {
                throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("EventIdNotSpecified")), "Id");
            }
        }
Esempio n. 27
0
 private Connected(Guid aggregateGuid, string effectiveDateTime, string baseContentGuid,
                   EventMetadata metadata, double temperature, double heatSetpoint, double coolSetpoint, string mode, string systemStatus, double?humidity, int version)
     : this(aggregateGuid, DateTimeOffset.Parse(effectiveDateTime), metadata, temperature, heatSetpoint, coolSetpoint, mode, systemStatus, humidity)
 {
     ExpectedVersion = version;
 }
        private static EventDescriptor CreateEventDescriptor(ProviderMetadata providerMetaData, EventMetadata emd)
        {
            long keywords = 0;

            foreach (EventKeyword keyword in emd.Keywords)
            {
                keywords |= keyword.Value;
            }

            byte channel = 0;

            foreach (EventLogLink logLink in providerMetaData.LogLinks)
            {
                if (string.Equals(logLink.LogName, emd.LogLink.LogName, StringComparison.OrdinalIgnoreCase))
                {
                    break;
                }
                channel++;
            }

            return(new EventDescriptor(
                       (int)emd.Id,
                       emd.Version,
                       channel,
                       (byte)emd.Level.Value,
                       (byte)emd.Opcode.Value,
                       emd.Task.Value,
                       keywords));
        }
Esempio n. 29
0
        protected override void Execute(GVFSEnlistment enlistment)
        {
            using (JsonEtwTracer tracer = new JsonEtwTracer(GVFSConstants.GVFSEtwProviderName, "Prefetch"))
            {
                if (this.Verbose)
                {
                    tracer.AddDiagnosticConsoleEventListener(EventLevel.Informational, Keywords.Any);
                }

                string cacheServerUrl = CacheServerResolver.GetUrlFromConfig(enlistment);

                tracer.AddLogFileEventListener(
                    GVFSEnlistment.GetNewGVFSLogFileName(enlistment.GVFSLogsRoot, GVFSConstants.LogFileTypes.Prefetch),
                    EventLevel.Informational,
                    Keywords.Any);
                tracer.WriteStartEvent(
                    enlistment.EnlistmentRoot,
                    enlistment.RepoUrl,
                    cacheServerUrl,
                    enlistment.GitObjectsRoot);

                RetryConfig retryConfig = this.GetRetryConfig(tracer, enlistment, TimeSpan.FromMinutes(RetryConfig.FetchAndCloneTimeoutMinutes));

                CacheServerInfo cacheServer = this.ResolvedCacheServer;
                if (!this.SkipVersionCheck)
                {
                    string authErrorMessage;
                    if (!this.ShowStatusWhileRunning(
                            () => enlistment.Authentication.TryRefreshCredentials(tracer, out authErrorMessage),
                            "Authenticating"))
                    {
                        this.ReportErrorAndExit(tracer, "Unable to prefetch because authentication failed");
                    }

                    GVFSConfig gvfsConfig = this.QueryGVFSConfig(tracer, enlistment, retryConfig);

                    CacheServerResolver cacheServerResolver = new CacheServerResolver(tracer, enlistment);
                    cacheServer = cacheServerResolver.ResolveNameFromRemote(cacheServerUrl, gvfsConfig);

                    this.ValidateClientVersions(tracer, enlistment, gvfsConfig, showWarnings: false);
                }

                try
                {
                    EventMetadata metadata = new EventMetadata();
                    metadata.Add("Commits", this.Commits);
                    metadata.Add("Files", this.Files);
                    metadata.Add("Folders", this.Folders);
                    metadata.Add("FoldersListFile", this.FoldersListFile);
                    tracer.RelatedEvent(EventLevel.Informational, "PerformPrefetch", metadata);

                    GitObjectsHttpRequestor objectRequestor = new GitObjectsHttpRequestor(tracer, enlistment, cacheServer, retryConfig);

                    if (this.Commits)
                    {
                        if (!string.IsNullOrWhiteSpace(this.Files) ||
                            !string.IsNullOrWhiteSpace(this.Folders) ||
                            !string.IsNullOrWhiteSpace(this.FoldersListFile))
                        {
                            this.ReportErrorAndExit(tracer, "You cannot prefetch commits and blobs at the same time.");
                        }

                        this.PrefetchCommits(tracer, enlistment, objectRequestor, cacheServer);
                    }
                    else
                    {
                        this.PrefetchBlobs(tracer, enlistment, objectRequestor, cacheServer);
                    }
                }
                catch (VerbAbortedException)
                {
                    throw;
                }
                catch (AggregateException aggregateException)
                {
                    this.Output.WriteLine(
                        "Cannot prefetch {0}. " + ConsoleHelper.GetGVFSLogMessage(enlistment.EnlistmentRoot),
                        enlistment.EnlistmentRoot);
                    foreach (Exception innerException in aggregateException.Flatten().InnerExceptions)
                    {
                        tracer.RelatedError(
                            new EventMetadata
                        {
                            { "Verb", typeof(PrefetchVerb).Name },
                            { "Exception", innerException.ToString() }
                        },
                            $"Unhandled {innerException.GetType().Name}: {innerException.Message}");
                    }

                    Environment.ExitCode = (int)ReturnCode.GenericError;
                }
                catch (Exception e)
                {
                    this.Output.WriteLine(
                        "Cannot prefetch {0}. " + ConsoleHelper.GetGVFSLogMessage(enlistment.EnlistmentRoot),
                        enlistment.EnlistmentRoot);
                    tracer.RelatedError(
                        new EventMetadata
                    {
                        { "Verb", typeof(PrefetchVerb).Name },
                        { "Exception", e.ToString() }
                    },
                        $"Unhandled {e.GetType().Name}: {e.Message}");
                }
            }
        }
        public override FileSystemResult UpdatePlaceholderIfNeeded(
            string relativePath,
            DateTime creationTime,
            DateTime lastAccessTime,
            DateTime lastWriteTime,
            DateTime changeTime,
            uint fileAttributes,
            long endOfFile,
            string shaContentId,
            UpdatePlaceholderType updateFlags,
            out UpdateFailureReason failureReason)
        {
            UpdateFailureCause failureCause = UpdateFailureCause.NoFailure;

            // TODO(Mac): Add functional tests that include:
            //     - Mode + content changes between commits
            //     - Mode only changes (without any change to content, see issue #223)
            GitIndexProjection.FileType fileType;
            ushort fileMode;

            this.FileSystemCallbacks.GitIndexProjection.GetFileTypeAndMode(relativePath, out fileType, out fileMode);

            if (fileType == GitIndexProjection.FileType.Regular)
            {
                Result result = this.virtualizationInstance.UpdatePlaceholderIfNeeded(
                    relativePath,
                    PlaceholderVersionId,
                    ToVersionIdByteArray(ConvertShaToContentId(shaContentId)),
                    (ulong)endOfFile,
                    fileMode,
                    (UpdateType)updateFlags,
                    out failureCause);

                failureReason = (UpdateFailureReason)failureCause;
                return(new FileSystemResult(ResultToFSResult(result), unchecked ((int)result)));
            }
            else if (fileType == GitIndexProjection.FileType.SymLink)
            {
                string symLinkTarget;
                if (this.TryGetSymLinkTarget(shaContentId, out symLinkTarget))
                {
                    Result result = this.virtualizationInstance.ReplacePlaceholderFileWithSymLink(
                        relativePath,
                        symLinkTarget,
                        (UpdateType)updateFlags,
                        out failureCause);

                    this.FileSystemCallbacks.OnFileSymLinkCreated(relativePath);

                    failureReason = (UpdateFailureReason)failureCause;
                    return(new FileSystemResult(ResultToFSResult(result), unchecked ((int)result)));
                }

                EventMetadata metadata = this.CreateEventMetadata(relativePath);
                metadata.Add(nameof(shaContentId), shaContentId);
                this.Context.Tracer.RelatedError(metadata, $"{nameof(this.UpdatePlaceholderIfNeeded)}: Failed to read contents of symlink object");
                failureReason = UpdateFailureReason.NoFailure;
                return(new FileSystemResult(FSResult.IOError, 0));
            }
            else
            {
                EventMetadata metadata = this.CreateEventMetadata(relativePath);
                metadata.Add(nameof(fileType), fileType);
                metadata.Add(nameof(fileMode), fileMode);
                this.Context.Tracer.RelatedError(metadata, $"{nameof(this.UpdatePlaceholderIfNeeded)}: Unsupported fileType");
                failureReason = UpdateFailureReason.NoFailure;
                return(new FileSystemResult(FSResult.IOError, 0));
            }
        }
Esempio n. 31
0
 private void ValidateEventOpcodeForTransfer(ref EventMetadata eventData)
 {
     if ((EventOpcode)eventData.Descriptor.Opcode != EventOpcode.Send &&
         (EventOpcode)eventData.Descriptor.Opcode != EventOpcode.Receive)
     {
         ThrowEventSourceException();
     }
 }
        /// <summary>
        /// Gets the target of the symbolic link.
        /// </summary>
        /// <param name="sha">SHA of the loose object containing the target path of the symbolic link</param>
        /// <param name="symLinkTarget">Target path of the symbolic link</param>
        private bool TryGetSymLinkTarget(string sha, out string symLinkTarget)
        {
            symLinkTarget = null;

            string symLinkBlobContents = null;

            try
            {
                if (!this.GitObjects.TryCopyBlobContentStream(
                        sha,
                        CancellationToken.None,
                        GVFSGitObjects.RequestSource.SymLinkCreation,
                        (stream, blobLength) =>
                {
                    byte[] buffer = new byte[SymLinkTargetBufferSize];
                    uint bufferIndex = 0;

                    // TODO(Mac): Find a better solution than reading from the stream one byte at at time
                    int nextByte = stream.ReadByte();
                    while (nextByte != -1)
                    {
                        while (bufferIndex < buffer.Length && nextByte != -1)
                        {
                            buffer[bufferIndex] = (byte)nextByte;
                            nextByte = stream.ReadByte();
                            ++bufferIndex;
                        }

                        if (bufferIndex < buffer.Length)
                        {
                            buffer[bufferIndex] = 0;
                            symLinkBlobContents = Encoding.UTF8.GetString(buffer);
                        }
                        else
                        {
                            buffer[bufferIndex - 1] = 0;

                            EventMetadata metadata = this.CreateEventMetadata();
                            metadata.Add(nameof(sha), sha);
                            metadata.Add("bufferContents", Encoding.UTF8.GetString(buffer));
                            this.Context.Tracer.RelatedError(metadata, $"{nameof(this.TryGetSymLinkTarget)}: SymLink target exceeds buffer size");

                            throw new GetSymLinkTargetException("SymLink target exceeds buffer size");
                        }
                    }
                }))
                {
                    EventMetadata metadata = this.CreateEventMetadata();
                    metadata.Add(nameof(sha), sha);
                    this.Context.Tracer.RelatedError(metadata, $"{nameof(this.TryGetSymLinkTarget)}: TryCopyBlobContentStream failed");

                    return(false);
                }
            }
            catch (GetSymLinkTargetException e)
            {
                EventMetadata metadata = this.CreateEventMetadata(relativePath: null, exception: e);
                metadata.Add(nameof(sha), sha);
                this.Context.Tracer.RelatedError(metadata, $"{nameof(this.TryGetSymLinkTarget)}: TryCopyBlobContentStream caught GetSymLinkTargetException");

                return(false);
            }
            catch (DecoderFallbackException e)
            {
                EventMetadata metadata = this.CreateEventMetadata(relativePath: null, exception: e);
                metadata.Add(nameof(sha), sha);
                this.Context.Tracer.RelatedError(metadata, $"{nameof(this.TryGetSymLinkTarget)}: TryCopyBlobContentStream caught DecoderFallbackException");

                return(false);
            }

            symLinkTarget = symLinkBlobContents;

            return(true);
        }
Esempio n. 33
0
        // Helper used by code:CreateManifestAndDescriptors to add a code:EventData descriptor for a method
        // with the code:EventAttribute 'eventAttribute'.  resourceManger may be null in which case we populate it
        // it is populated if we need to look up message resources
        private static void AddEventDescriptor(ref EventMetadata[] eventData, string eventName, 
                                EventAttribute eventAttribute, ParameterInfo[] eventParameters)
        {
            if (eventData == null || eventData.Length <= eventAttribute.EventId)
            {
                EventMetadata[] newValues = new EventMetadata[Math.Max(eventData.Length + 16, eventAttribute.EventId + 1)];
                Array.Copy(eventData, newValues, eventData.Length);
                eventData = newValues;
            }

            eventData[eventAttribute.EventId].Descriptor = new System.Diagnostics.Tracing.EventDescriptor(
                    eventAttribute.EventId,
                    eventAttribute.Version,
#if FEATURE_MANAGED_ETW_CHANNELS
                    (byte)eventAttribute.Channel,
#else
                    (byte)0,
#endif
                    (byte)eventAttribute.Level,
                    (byte)eventAttribute.Opcode,
                    (int)eventAttribute.Task,
                    (long)((ulong)eventAttribute.Keywords | SessionMask.All.ToEventKeywords()));

            eventData[eventAttribute.EventId].Name = eventName;
            eventData[eventAttribute.EventId].Parameters = eventParameters;
            eventData[eventAttribute.EventId].Message = eventAttribute.Message;
        }
        private Result OnGetFileStream(
            ulong commandId,
            string relativePath,
            byte[] providerId,
            byte[] contentId,
            int triggeringProcessId,
            string triggeringProcessName,
            IntPtr fileHandle)
        {
            try
            {
                if (contentId == null)
                {
                    this.Context.Tracer.RelatedError($"{nameof(this.OnGetFileStream)} called with null contentId, path: " + relativePath);
                    return(Result.EInvalidOperation);
                }

                if (providerId == null)
                {
                    this.Context.Tracer.RelatedError($"{nameof(this.OnGetFileStream)} called with null epochId, path: " + relativePath);
                    return(Result.EInvalidOperation);
                }

                string sha = GetShaFromContentId(contentId);
                byte   placeholderVersion = GetPlaceholderVersionFromProviderId(providerId);

                EventMetadata metadata = this.CreateEventMetadata(relativePath);
                metadata.Add(nameof(triggeringProcessId), triggeringProcessId);
                metadata.Add(nameof(triggeringProcessName), triggeringProcessName);
                metadata.Add(nameof(sha), sha);
                metadata.Add(nameof(placeholderVersion), placeholderVersion);
                metadata.Add(nameof(commandId), commandId);
                ITracer activity = this.Context.Tracer.StartActivity("GetFileStream", EventLevel.Verbose, Keywords.Telemetry, metadata);

                if (!this.FileSystemCallbacks.IsMounted)
                {
                    metadata.Add(TracingConstants.MessageKey.InfoMessage, $"{nameof(this.OnGetFileStream)} failed, mount has not yet completed");
                    activity.RelatedEvent(EventLevel.Informational, $"{nameof(this.OnGetFileStream)}_MountNotComplete", metadata);
                    activity.Dispose();

                    // TODO(Mac): Is this the correct Result to return?
                    return(Result.EIOError);
                }

                if (placeholderVersion != FileSystemVirtualizer.PlaceholderVersion)
                {
                    activity.RelatedError(metadata, nameof(this.OnGetFileStream) + ": Unexpected placeholder version");
                    activity.Dispose();

                    // TODO(Mac): Is this the correct Result to return?
                    return(Result.EIOError);
                }

                try
                {
                    if (!this.GitObjects.TryCopyBlobContentStream(
                            sha,
                            CancellationToken.None,
                            GVFSGitObjects.RequestSource.FileStreamCallback,
                            (stream, blobLength) =>
                    {
                        // TODO(Mac): Find a better solution than reading from the stream one byte at at time
                        byte[] buffer = new byte[4096];
                        uint bufferIndex = 0;
                        int nextByte = stream.ReadByte();
                        while (nextByte != -1)
                        {
                            while (bufferIndex < buffer.Length && nextByte != -1)
                            {
                                buffer[bufferIndex] = (byte)nextByte;
                                nextByte = stream.ReadByte();
                                ++bufferIndex;
                            }

                            Result result = this.virtualizationInstance.WriteFileContents(
                                fileHandle,
                                buffer,
                                bufferIndex);
                            if (result != Result.Success)
                            {
                                activity.RelatedError(metadata, $"{nameof(this.virtualizationInstance.WriteFileContents)} failed, error: " + result.ToString("X") + "(" + result.ToString("G") + ")");
                                throw new GetFileStreamException(result);
                            }

                            if (bufferIndex == buffer.Length)
                            {
                                bufferIndex = 0;
                            }
                        }
                    }))
                    {
                        activity.RelatedError(metadata, $"{nameof(this.OnGetFileStream)}: TryCopyBlobContentStream failed");

                        // TODO(Mac): Is this the correct Result to return?
                        return(Result.EFileNotFound);
                    }
                }
                catch (GetFileStreamException e)
                {
                    return(e.Result);
                }

                return(Result.Success);
            }
            catch (Exception e)
            {
                EventMetadata metadata = this.CreateEventMetadata(relativePath, e);
                metadata.Add(nameof(triggeringProcessId), triggeringProcessId);
                metadata.Add(nameof(triggeringProcessName), triggeringProcessName);
                metadata.Add(nameof(commandId), commandId);
                this.LogUnhandledExceptionAndExit(nameof(this.OnGetFileStream), metadata);
            }

            return(Result.EIOError);
        }
Esempio n. 35
0
        // Helper used by code:CreateManifestAndDescriptors to find user mistakes like reusing an event
        // index for two distinct events etc.  Throws exceptions when it finds something wrong. 
        private static void DebugCheckEvent(ref Dictionary<string, string> eventsByName,
            EventMetadata[] eventData, MethodInfo method, EventAttribute eventAttribute)
        {
            int eventArg = GetHelperCallFirstArg(method);
            if (eventArg >= 0 && eventAttribute.EventId != eventArg)
            {
                throw new ArgumentException(Environment.GetResourceString("EventSource_MismatchIdToWriteEvent", method.Name, eventAttribute.EventId, eventArg));
            }

            if (eventAttribute.EventId < eventData.Length && eventData[eventAttribute.EventId].Descriptor.EventId != 0)
            {
                throw new ArgumentException(Environment.GetResourceString("EventSource_EventIdReused", method.Name, eventAttribute.EventId));
            }

            if (eventsByName == null)
                eventsByName = new Dictionary<string, string>();

            if (eventsByName.ContainsKey(method.Name))
                throw new ArgumentException(Environment.GetResourceString("EventSource_EventNameReused", method.Name));

            eventsByName[method.Name] = method.Name;
        }
Esempio n. 36
0
        /// <summary>
        /// Rebuild the status cache. This will run the background status to
        /// generate status results, and update the serialized status cache
        /// file.
        /// </summary>
        private bool TryRebuildStatusCache()
        {
            try
            {
                this.context.FileSystem.CreateDirectory(this.context.Enlistment.GitStatusCacheFolder);
            }
            catch (Exception ex) when(ex is IOException || ex is UnauthorizedAccessException)
            {
                EventMetadata metadata = new EventMetadata();

                metadata.Add("Area", EtwArea);
                metadata.Add("Exception", ex.ToString());

                this.context.Tracer.RelatedWarning(
                    metadata,
                    string.Format("GitStatusCache is unable to create git status cache folder at {0}.", this.context.Enlistment.GitStatusCacheFolder));
                return(false);
            }

            // The status cache is regenerated on mount. This means that even if the write to temp file
            // and rename operation doesn't complete (due to a system crash), and there is a torn write,
            // GSD is still protected because a new status cache file will be generated on mount.
            string tmpStatusFilePath = Path.Combine(this.context.Enlistment.GitStatusCacheFolder, Path.GetRandomFileName() + "_status.tmp");

            GitProcess.Result statusResult = null;

            // Do not modify this block unless you completely understand the comments and code within
            {
                // We MUST set the state to Rebuilding _immediately before_ we call the `git status` command. That allows us to
                // check afterwards if anything happened during the status command that should invalidate the cache, and we
                // can discard its results if that happens.
                this.cacheState = CacheState.Rebuilding;

                GitProcess git = this.context.Enlistment.CreateGitProcess();
                statusResult = git.SerializeStatus(
                    allowObjectDownloads: true,
                    serializePath: tmpStatusFilePath);
            }

            bool rebuildSucceeded = false;

            if (statusResult.ExitCodeIsSuccess)
            {
                lock (this.cacheFileLock)
                {
                    // Only update the cache if our state is still Rebuilding. Otherwise, this indicates that another call
                    // to Invalidate came in, and moved the state back to Dirty.
                    if (this.cacheState == CacheState.Rebuilding)
                    {
                        rebuildSucceeded = this.MoveCacheFileToFinalLocation(tmpStatusFilePath);
                        if (rebuildSucceeded)
                        {
                            // We have to check the state once again, because it could have been invalidated while we were
                            // copying the file in the previous step. Here we do it as a CompareExchange to minimize any further races.
                            if (Interlocked.CompareExchange(ref this.cacheState, CacheState.Clean, CacheState.Rebuilding) != CacheState.Rebuilding)
                            {
                                // We did not succeed in setting the state to Clean. Note that we have already overwritten the on disk cache,
                                // but all users of the cache file first check the cacheState, and since the cacheState is not Clean, no one
                                // should ever read it.

                                rebuildSucceeded = false;
                            }
                        }

                        if (!rebuildSucceeded)
                        {
                            this.cacheState = CacheState.Dirty;
                        }
                    }
                }

                if (!rebuildSucceeded)
                {
                    try
                    {
                        this.context.FileSystem.DeleteFile(tmpStatusFilePath);
                    }
                    catch (Exception ex) when(ex is IOException || ex is UnauthorizedAccessException)
                    {
                        EventMetadata metadata = new EventMetadata();

                        metadata.Add("Area", EtwArea);
                        metadata.Add("Exception", ex.ToString());

                        this.context.Tracer.RelatedError(
                            metadata,
                            string.Format("GitStatusCache is unable to delete temporary status cache file at {0}.", tmpStatusFilePath));
                    }
                }
            }
            else
            {
                this.statistics.RecordBackgroundStatusScanError();
                this.context.Tracer.RelatedInfo("GitStatusCache.TryRebuildStatusCache: Error generating status: {0}", statusResult.Errors);
            }

            return(rebuildSucceeded);
        }
Esempio n. 37
0
 private int GetParameterCount(EventMetadata eventData)
 {
     return eventData.Parameters.Length;
 }
        private FileSystemTaskResult ExecuteBackgroundOperation(FileSystemTask gitUpdate)
        {
            EventMetadata metadata = new EventMetadata();

            FileSystemTaskResult result;

            switch (gitUpdate.Operation)
            {
            case FileSystemTask.OperationType.OnFileCreated:
            case FileSystemTask.OperationType.OnFailedPlaceholderDelete:
                metadata.Add("virtualPath", gitUpdate.VirtualPath);
                result = this.AddModifiedPathAndRemoveFromPlaceholderList(gitUpdate.VirtualPath);
                break;

            case FileSystemTask.OperationType.OnFileRenamed:
                metadata.Add("oldVirtualPath", gitUpdate.OldVirtualPath);
                metadata.Add("virtualPath", gitUpdate.VirtualPath);
                result = FileSystemTaskResult.Success;
                if (!string.IsNullOrEmpty(gitUpdate.OldVirtualPath) && !IsPathInsideDotGit(gitUpdate.OldVirtualPath))
                {
                    result = this.AddModifiedPathAndRemoveFromPlaceholderList(gitUpdate.OldVirtualPath);
                }

                if (result == FileSystemTaskResult.Success &&
                    !string.IsNullOrEmpty(gitUpdate.VirtualPath) &&
                    !IsPathInsideDotGit(gitUpdate.VirtualPath))
                {
                    result = this.AddModifiedPathAndRemoveFromPlaceholderList(gitUpdate.VirtualPath);
                }

                break;

            case FileSystemTask.OperationType.OnFileDeleted:
                metadata.Add("virtualPath", gitUpdate.VirtualPath);
                result = this.AddModifiedPathAndRemoveFromPlaceholderList(gitUpdate.VirtualPath);
                break;

            case FileSystemTask.OperationType.OnFileOverwritten:
            case FileSystemTask.OperationType.OnFileSuperseded:
            case FileSystemTask.OperationType.OnFileConvertedToFull:
            case FileSystemTask.OperationType.OnFailedPlaceholderUpdate:
                metadata.Add("virtualPath", gitUpdate.VirtualPath);
                result = this.AddModifiedPathAndRemoveFromPlaceholderList(gitUpdate.VirtualPath);
                break;

            case FileSystemTask.OperationType.OnFolderCreated:
                metadata.Add("virtualPath", gitUpdate.VirtualPath);
                result = this.TryAddModifiedPath(gitUpdate.VirtualPath, isFolder: true);
                break;

            case FileSystemTask.OperationType.OnFolderRenamed:
                result = FileSystemTaskResult.Success;
                metadata.Add("oldVirtualPath", gitUpdate.OldVirtualPath);
                metadata.Add("virtualPath", gitUpdate.VirtualPath);

                // An empty destination path means the folder was renamed to somewhere outside of the repo
                // Note that only full folders can be moved\renamed, and so there will already be a recursive
                // sparse-checkout entry for the virtualPath of the folder being moved (meaning that no
                // additional work is needed for any files\folders inside the folder being moved)
                if (!string.IsNullOrEmpty(gitUpdate.VirtualPath))
                {
                    result = this.TryAddModifiedPath(gitUpdate.VirtualPath, isFolder: true);
                    if (result == FileSystemTaskResult.Success)
                    {
                        Queue <string> relativeFolderPaths = new Queue <string>();
                        relativeFolderPaths.Enqueue(gitUpdate.VirtualPath);

                        // Add all the files in the renamed folder to the always_exclude file
                        while (relativeFolderPaths.Count > 0)
                        {
                            string folderPath = relativeFolderPaths.Dequeue();
                            if (result == FileSystemTaskResult.Success)
                            {
                                try
                                {
                                    foreach (DirectoryItemInfo itemInfo in this.context.FileSystem.ItemsInDirectory(Path.Combine(this.context.Enlistment.WorkingDirectoryRoot, folderPath)))
                                    {
                                        string itemVirtualPath = Path.Combine(folderPath, itemInfo.Name);
                                        if (itemInfo.IsDirectory)
                                        {
                                            relativeFolderPaths.Enqueue(itemVirtualPath);
                                        }
                                        else
                                        {
                                            string oldItemVirtualPath = gitUpdate.OldVirtualPath + itemVirtualPath.Substring(gitUpdate.VirtualPath.Length);
                                            result = this.TryAddModifiedPath(itemVirtualPath, isFolder: false);
                                        }
                                    }
                                }
                                catch (DirectoryNotFoundException)
                                {
                                    // DirectoryNotFoundException can occur when the renamed folder (or one of its children) is
                                    // deleted prior to the background thread running
                                    EventMetadata exceptionMetadata = new EventMetadata();
                                    exceptionMetadata.Add("Area", "ExecuteBackgroundOperation");
                                    exceptionMetadata.Add("Operation", gitUpdate.Operation.ToString());
                                    exceptionMetadata.Add("oldVirtualPath", gitUpdate.OldVirtualPath);
                                    exceptionMetadata.Add("virtualPath", gitUpdate.VirtualPath);
                                    exceptionMetadata.Add(TracingConstants.MessageKey.InfoMessage, "DirectoryNotFoundException while traversing folder path");
                                    exceptionMetadata.Add("folderPath", folderPath);
                                    this.context.Tracer.RelatedEvent(EventLevel.Informational, "DirectoryNotFoundWhileUpdatingAlwaysExclude", exceptionMetadata);
                                }
                                catch (IOException e)
                                {
                                    metadata.Add("Details", "IOException while traversing folder path");
                                    metadata.Add("folderPath", folderPath);
                                    metadata.Add("Exception", e.ToString());
                                    result = FileSystemTaskResult.RetryableError;
                                    break;
                                }
                                catch (UnauthorizedAccessException e)
                                {
                                    metadata.Add("Details", "UnauthorizedAccessException while traversing folder path");
                                    metadata.Add("folderPath", folderPath);
                                    metadata.Add("Exception", e.ToString());
                                    result = FileSystemTaskResult.RetryableError;
                                    break;
                                }
                            }
                            else
                            {
                                break;
                            }
                        }
                    }
                }

                break;

            case FileSystemTask.OperationType.OnFolderDeleted:
                metadata.Add("virtualPath", gitUpdate.VirtualPath);
                result = this.TryAddModifiedPath(gitUpdate.VirtualPath, isFolder: true);
                break;

            case FileSystemTask.OperationType.OnFolderFirstWrite:
                result = FileSystemTaskResult.Success;
                break;

            case FileSystemTask.OperationType.OnIndexWriteWithoutProjectionChange:
                result = this.GitIndexProjection.AddMissingModifiedFiles();
                break;

            case FileSystemTask.OperationType.OnPlaceholderCreationsBlockedForGit:
                this.GitIndexProjection.ClearNegativePathCacheIfPollutedByGit();
                result = FileSystemTaskResult.Success;
                break;

            default:
                throw new InvalidOperationException("Invalid background operation");
            }

            if (result != FileSystemTaskResult.Success)
            {
                metadata.Add("Area", "ExecuteBackgroundOperation");
                metadata.Add("Operation", gitUpdate.Operation.ToString());
                metadata.Add(TracingConstants.MessageKey.WarningMessage, "Background operation failed");
                metadata.Add(nameof(result), result.ToString());
                this.context.Tracer.RelatedEvent(EventLevel.Warning, "FailedBackgroundOperation", metadata);
            }

            return(result);
        }
Esempio n. 39
0
    public void Create( System.Collections.Generic.Dictionary<string,object> eventDict )
    {
        Debug.Log( "IgniteEvent:Create");

        if( eventDict.ContainsKey( "id" ) ) {
            this.Id = Convert.ToString( eventDict["id"] );
        }
        if( eventDict.ContainsKey( "startTime" ) ) {
            var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            long t = Convert.ToInt64 (eventDict["startTime"]);
            this.StartTime = epoch.AddSeconds(t);
        }
        if( eventDict.ContainsKey( "authorized" ) ) {
            this.Authorized = Convert.ToBoolean( eventDict["authorized"] );
        }
        if( eventDict.ContainsKey( "eventId" ) ) {
            this.EventId = Convert.ToString( eventDict["eventId"] );
        }
        if( eventDict.ContainsKey( "state" ) ) {
            this.State = Convert.ToString( eventDict["state"] );
        }
        if( eventDict.ContainsKey( "score" ) ) {
            this.Score = (float)Convert.ToDouble( eventDict["score"] );
        }
        if( eventDict.ContainsKey( "type" ) ) {
            this.Type = (IgniteEventType) Enum.Parse( typeof(IgniteEventType) , Convert.ToString( eventDict["type"] ) );
        }
        if( eventDict.ContainsKey( "endTime" ) ) {
            var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            long t = Convert.ToInt64 (eventDict["endTime"]);
            this.EndTime = epoch.AddSeconds(t);
        }
        if( eventDict.ContainsKey( "metadata" ) ) {
            System.Collections.Generic.Dictionary<string,object> eventMetadataDict = eventDict["metadata"] as System.Collections.Generic.Dictionary<string,object>;
            EventMetadata eventMetadata = new EventMetadata();
            if( eventMetadataDict.ContainsKey( "imageUrl" ) ) {
                eventMetadata.imageUrl = Convert.ToString( eventMetadataDict["imageUrl"] );
            }
            if( eventMetadataDict.ContainsKey( "name" ) ) {
                eventMetadata.Name = Convert.ToString( eventMetadataDict["name"] );
            }
            if( eventMetadataDict.ContainsKey( "gamedata" ) ) {
                eventMetadata.GameData = Convert.ToString( eventMetadataDict["gamedata"] );
            }
            this.Metadata = eventMetadata;
        }

        switch( this.Type ) {
            case IgniteEventType.leaderBoard:
            FuelSDKGroovePlanetIntegration.Instance.GetLeaderBoard( this.Id );
                activity = new IgniteLeaderBoard();
                break;
            case IgniteEventType.mission:
            FuelSDKGroovePlanetIntegration.Instance.GetMission( this.Id );
                activity = new IgniteMission();
                break;
            case IgniteEventType.quest:
            FuelSDKGroovePlanetIntegration.Instance.GetQuest( this.Id );
                activity = new IgniteQuest();
                break;
            default:
                break;
        }
    }
Esempio n. 40
0
        public virtual GitProcess.Result IndexPackFile(string packfilePath, GitProcess gitProcess)
        {
            string tempIdxPath = Path.ChangeExtension(packfilePath, TempIdxExtension);
            string idxPath     = Path.ChangeExtension(packfilePath, ".idx");

            Exception indexPackException = null;

            try
            {
                if (gitProcess == null)
                {
                    gitProcess = new GitProcess(this.Enlistment);
                }

                GitProcess.Result result = gitProcess.IndexPack(packfilePath, tempIdxPath);
                if (result.ExitCodeIsFailure)
                {
                    Exception exception;
                    if (!this.fileSystem.TryDeleteFile(tempIdxPath, exception: out exception))
                    {
                        EventMetadata metadata = CreateEventMetadata(exception);
                        metadata.Add("tempIdxPath", tempIdxPath);
                        this.Tracer.RelatedWarning(metadata, $"{nameof(this.IndexPackFile)}: Failed to cleanup temp idx file after index pack failure");
                    }
                }
                else
                {
                    if (this.Enlistment.FlushFileBuffersForPacks)
                    {
                        Exception exception;
                        string    error;
                        if (!this.TryFlushFileBuffers(tempIdxPath, out exception, out error))
                        {
                            EventMetadata metadata = CreateEventMetadata(exception);
                            metadata.Add("packfilePath", packfilePath);
                            metadata.Add("tempIndexPath", tempIdxPath);
                            metadata.Add("error", error);
                            this.Tracer.RelatedWarning(metadata, $"{nameof(this.IndexPackFile)}: Failed to flush temp idx file buffers");
                        }
                    }

                    this.fileSystem.MoveAndOverwriteFile(tempIdxPath, idxPath);
                }

                return(result);
            }
            catch (Win32Exception e)
            {
                indexPackException = e;
            }
            catch (IOException e)
            {
                indexPackException = e;
            }
            catch (UnauthorizedAccessException e)
            {
                indexPackException = e;
            }

            EventMetadata failureMetadata = CreateEventMetadata(indexPackException);

            failureMetadata.Add("packfilePath", packfilePath);
            failureMetadata.Add("tempIdxPath", tempIdxPath);
            failureMetadata.Add("idxPath", idxPath);

            this.fileSystem.TryDeleteFile(tempIdxPath, metadataKey: nameof(tempIdxPath), metadata: failureMetadata);
            this.fileSystem.TryDeleteFile(idxPath, metadataKey: nameof(idxPath), metadata: failureMetadata);

            this.Tracer.RelatedWarning(failureMetadata, $"{nameof(this.IndexPackFile): Exception caught while trying to index pack file}");

            return(new GitProcess.Result(
                       string.Empty,
                       indexPackException != null ? indexPackException.Message : "Failed to index pack file",
                       GitProcess.Result.GenericFailureCode));
        }