Esempio n. 1
0
        public static async Task <SyntaxTreeIndex?> LoadAsync(
            HostWorkspaceServices services, DocumentKey documentKey, Checksum?checksum, StorageDatabase database, StringTable stringTable, CancellationToken cancellationToken)
        {
            try
            {
                var persistentStorageService = services.GetPersistentStorageService(database);

                var storage = await persistentStorageService.GetStorageAsync(documentKey.Project.Solution, checkBranchId : false, cancellationToken).ConfigureAwait(false);

                await using var _ = storage.ConfigureAwait(false);

                // attempt to load from persisted state
                using var stream = await storage.ReadStreamAsync(documentKey, PersistenceName, checksum, cancellationToken).ConfigureAwait(false);

                using var reader = ObjectReader.TryGetReader(stream, cancellationToken: cancellationToken);
                if (reader != null)
                {
                    return(ReadFrom(stringTable, reader, checksum));
                }
            }
            catch (Exception e) when(IOUtilities.IsNormalIOException(e))
            {
                // Storage APIs can throw arbitrary exceptions.
            }

            return(null);
        }
        private static async Task <T> TryLoadOrCreateAsync <T>(
            HostWorkspaceServices services,
            SolutionKey solutionKey,
            Checksum checksum,
            StorageDatabase database,
            bool loadOnly,
            Func <Task <T> > createAsync,
            string keySuffix,
            Func <ObjectReader, T> tryReadObject,
            CancellationToken cancellationToken) where T : class, IObjectWritable, IChecksummedObject
        {
            using (Logger.LogBlock(FunctionId.SymbolTreeInfo_TryLoadOrCreate, cancellationToken))
            {
                if (checksum == null)
                {
                    return(loadOnly ? null : await CreateWithLoggingAsync().ConfigureAwait(false));
                }

                // Ok, we can use persistence.  First try to load from the persistence service.
                var persistentStorageService = services.GetPersistentStorageService(database);

                var storage = await persistentStorageService.GetStorageAsync(solutionKey, checkBranchId : false, cancellationToken).ConfigureAwait(false);

                await using var _ = storage.ConfigureAwait(false);

                // Get the unique key to identify our data.
                var key = PrefixMetadataSymbolTreeInfo + keySuffix;
                using (var stream = await storage.ReadStreamAsync(key, checksum, cancellationToken).ConfigureAwait(false))
                    using (var reader = ObjectReader.TryGetReader(stream, cancellationToken: cancellationToken))
                    {
                        if (reader != null)
                        {
                            // We have some previously persisted data.  Attempt to read it back.
                            // If we're able to, and the version of the persisted data matches
                            // our version, then we can reuse this instance.
                            var read = tryReadObject(reader);
                            if (read != null)
                            {
                                // If we were able to read something in, it's checksum better
                                // have matched the checksum we expected.
                                Debug.Assert(read.Checksum == checksum);
                                return(read);
                            }
                        }
                    }

                cancellationToken.ThrowIfCancellationRequested();

                // Couldn't read from the persistence service.  If we've been asked to only load
                // data and not create new instances in their absence, then there's nothing left
                // to do at this point.
                if (loadOnly)
                {
                    return(null);
                }

                // Now, try to create a new instance and write it to the persistence service.
                var result = await CreateWithLoggingAsync().ConfigureAwait(false);

                Contract.ThrowIfNull(result);

                using (var stream = SerializableBytes.CreateWritableStream())
                {
                    using (var writer = new ObjectWriter(stream, leaveOpen: true, cancellationToken))
                    {
                        result.WriteTo(writer);
                    }

                    stream.Position = 0;

                    await storage.WriteStreamAsync(key, stream, checksum, cancellationToken).ConfigureAwait(false);
                }

                return(result);
            }

            async Task <T> CreateWithLoggingAsync()
            {
                using (Logger.LogBlock(FunctionId.SymbolTreeInfo_Create, cancellationToken))
                {
                    return(await createAsync().ConfigureAwait(false));
                }
            }
        }