Example #1
0
 /// <summary> Write a stream to a store. </summary>
 /// <remarks> Reads forward from the current position of the stream. </remarks>
 public static Task <WrittenBlob> WriteAsync(
     this IWriteOnlyStore store,
     Stream stream,
     CancellationToken cancel)
 =>
 // Default buffer size is 4MB, because Azure Storage likes it.
 store.WriteAsync(stream, 4 * 1024 * 1024, cancel);
Example #2
0
 /// <summary> Write a buffer of bytes to the store. </summary>
 public static async Task <WrittenBlob> WriteAsync(
     this IWriteOnlyStore store,
     byte[] buffer,
     int offset,
     int count,
     CancellationToken cancel)
 {
     using (var writer = store.StartWriting())
         return(await writer.WriteAndCommitAsync(buffer, offset, count, cancel).ConfigureAwait(false));
 }
Example #3
0
        private static async Task <WrittenBlob> ImportBlobUnchecked(this IWriteOnlyStore store, IReadBlobRef srcBlob, CancellationToken cancel)
        {
            using (var writer = store.StartWriting())
            {
                using (var reader = await srcBlob.OpenAsync(cancel).ConfigureAwait(false))
                {
                    await writer.WriteAsync(reader.ReadAsync, null, cancel).ConfigureAwait(false);
                }

                return(await writer.CommitAsync(cancel).ConfigureAwait(false));
            }
        }
Example #4
0
        /// <summary>
        /// Copies blobs from <paramref name="source"/> store to <paramref name="destination"/> store.
        /// Also, this checks that the blobs exist, and that there is no error in the hash of those blobs.
        /// When these checks fail, an exception is raised, and the task fails.
        /// </summary>
        /// <param name="hashes">designates the blobs to be copied</param>
        /// <param name="accountId">the account of <paramref name="source"/> store. only helps with error messages</param>
        /// <returns></returns>
        public static async Task <WrittenBlob[]> ImportBlobs(
            this IWriteOnlyStore destination,
            IReadOnlyStore source,
            IReadOnlyCollection <Hash> hashes,
            long?accountId           = null,
            CancellationToken cancel = default)
        {
            var checkExistTasks = hashes.Select(
                h => source[h].ExistsAsync(cancel)
                ).ToArray();

            bool[] exist = await Task.WhenAll(checkExistTasks);

            int i = 0;

            foreach (var h in hashes)
            {
                if (!exist[i])
                {
                    throw new NoSuchBlobException(accountId?.ToString() ?? "<unknown>", h);
                }
            }

            var copyTasks = hashes.Select(
                h => destination.ImportBlobUnchecked(source[h], cancel)).ToArray();

            var writtenBlobs = await Task.WhenAll(copyTasks).ConfigureAwait(false);

            List <(Hash orig, Hash result)> badHashes = null;

            i = 0;
            foreach (var orig in hashes)
            {
                var blob = writtenBlobs[i++];
                if (!blob.Hash.Equals(orig))
                {
                    badHashes = badHashes ?? new List <(Hash orig, Hash result)>();
                    badHashes.Add((orig, blob.Hash));
                }
            }

            if (badHashes != null)
            {
                string details = string.Join("\n", badHashes.Select(_ => $"  {accountId}/{_.orig}: {_.result}"));
                throw new Exception("Bad hash(es) detected: " + details);
            }

            return(writtenBlobs);
        }
Example #5
0
        /// <summary> Write a stream to a store. </summary>
        /// <remarks> Reads forward from the current position of the stream. </remarks>
        public static async Task <WrittenBlob> WriteAsync(
            this IWriteOnlyStore store,
            Stream stream,
            int bufferSize,
            CancellationToken cancel)
        {
            // Don't allocate memory we don't need.
            if (stream.CanSeek && stream.Length < bufferSize)
            {
                bufferSize = (int)stream.Length;
            }

            using (var writer = store.StartWriting())
            {
                var buffer = new byte[bufferSize];
                await WriteAsync(writer, stream, buffer, null, true, cancel).ConfigureAwait(false);

                return(await writer.CommitAsync(cancel).ConfigureAwait(false));
            }
        }
Example #6
0
 /// <summary> Write an entire buffer of bytes to the store. </summary>
 public static Task <WrittenBlob> WriteAsync(
     this IWriteOnlyStore store,
     byte[] buffer,
     CancellationToken cancel)
 =>
 store.WriteAsync(buffer, 0, buffer.Length, cancel);