public bool TryPopulateSizeLocally(
                ITracer tracer,
                GVFSGitObjects gitObjects,
                BlobSizes.BlobSizesConnection blobSizesConnection,
                Dictionary<string, long> availableSizes,
                out string missingSha)
            {
                missingSha = null;
                long blobLength = 0;

                Sha1Id sha1Id = new Sha1Id(this.shaBytes1through8, this.shaBytes9Through16, this.shaBytes17Through20);
                string shaString = null;

                if (availableSizes != null)
                {
                    shaString = this.ConvertShaToString();
                    if (availableSizes.TryGetValue(shaString, out blobLength))
                    {
                        this.Size = blobLength;
                        return true;
                    }
                }

                try
                {
                    if (blobSizesConnection.TryGetSize(sha1Id, out blobLength))
                    {
                        this.Size = blobLength;
                        return true;
                    }
                }
                catch (BlobSizesException e)
                {
                    EventMetadata metadata = CreateEventMetadata(e);
                    missingSha = this.ConvertShaToString();
                    metadata.Add(nameof(missingSha), missingSha);
                    tracer.RelatedWarning(metadata, $"{nameof(this.TryPopulateSizeLocally)}: Exception while trying to get file size", Keywords.Telemetry);
                }

                if (missingSha == null)
                {
                    missingSha = (shaString == null) ? this.ConvertShaToString() : shaString;
                }

                if (gitObjects.TryGetBlobSizeLocally(missingSha, out blobLength))
                {
                    this.Size = blobLength;

                    // There is no flush for this value because it's already local, so there's little loss if it doesn't get persisted
                    // But it's faster to wait for some remote call to batch this value into a different flush
                    blobSizesConnection.BlobSizesDatabase.AddSize(sha1Id, blobLength);
                    return true;
                }

                return false;
            }
Example #2
0
        private void PopulateNamedEntrySizes(
            GVFSGitObjects gitObjects,
            PersistentDictionary <string, long> blobSizes,
            string parentVirtualPath,
            GVFSContext context,
            IEnumerable <GitTreeEntry> entries)
        {
            List <GitTreeEntry> blobs = entries.Where(e => e.IsBlob).ToList();

            // Then try to find as many blob sizes locally as possible.
            List <GitTreeEntry> entriesMissingSizes = new List <GitTreeEntry>();

            foreach (GitTreeEntry namedEntry in blobs.Where(b => b.Size == 0))
            {
                long blobLength = 0;
                if (blobSizes.TryGetValue(namedEntry.Sha, out blobLength))
                {
                    namedEntry.Size = blobLength;
                }
                else if (gitObjects.TryGetBlobSizeLocally(namedEntry.Sha, out blobLength))
                {
                    namedEntry.Size           = blobLength;
                    blobSizes[namedEntry.Sha] = blobLength;
                }
                else
                {
                    entriesMissingSizes.Add(namedEntry);
                }
            }

            // Anything remaining should come from the remote.
            if (entriesMissingSizes.Count > 0)
            {
                Dictionary <string, long> objectLengths = gitObjects.GetFileSizes(entriesMissingSizes.Select(e => e.Sha).Distinct()).ToDictionary(s => s.Id, s => s.Size, StringComparer.OrdinalIgnoreCase);
                foreach (GitTreeEntry namedEntry in entriesMissingSizes)
                {
                    long blobLength = 0;
                    if (objectLengths.TryGetValue(namedEntry.Sha, out blobLength))
                    {
                        namedEntry.Size           = blobLength;
                        blobSizes[namedEntry.Sha] = blobLength;
                    }
                    else
                    {
                        EventMetadata metadata = new EventMetadata();
                        metadata.Add("ErrorMessage", "GvFltException: Failed to download size for: " + namedEntry.Name + ", SHA: " + namedEntry.Sha);
                        context.Tracer.RelatedError(metadata, Keywords.Network);
                        throw new GvFltException(StatusCode.StatusFileNotAvailable);
                    }
                }
            }
        }