Пример #1
0
        /// <summary> Write the contents of a stream to a writer. </summary>
        /// <param name="writer"> To be written to. </param>
        /// <param name="stream"> To be read from. </param>
        /// <param name="buffer"> Temporary buffer for copying data. </param>
        /// <param name="buffer2">
        ///     Optional secondary buffer. If null, the function may allocate a
        ///     secondary buffer itself. In both cases, the secondary buffer will
        ///     be returned by the function (if null, and none was created, then
        ///     null will be returned).
        /// </param>
        /// <param name="thenCommit">
        ///     If true, commit the writer after writing the last buffer.
        /// </param>
        /// <param name="cancel"></param>
        private static async Task <byte[]> WriteAsync(
            StoreWriter writer,
            Stream stream,
            byte[] buffer,
            byte[] buffer2,
            bool thenCommit,
            CancellationToken cancel)
        {
            var bufferSize = buffer.Length;

            // The task that writes data in the background. Returns the buffer it
            // was using when it ends and doesn't need to buffer anymore, so that
            // it can be reused in a double-buffering scheme.
            var writing = Task.FromResult(buffer2);

            while (true)        // Read all pages and write them
            {
                var offset = 0; // Current offset within 'buffer'
                int read;       // Bytes returned by last 'ReadAsync', zero if EoS

                do              // Read a page of size 'bufferSize'
                {
                    offset += read = await stream
                                     .ReadAsync(buffer, offset, bufferSize - offset, cancel)
                                     .ConfigureAwait(false);
                } while (offset < bufferSize && read > 0);

                if (offset == 0)
                {
                    break;
                }

                var isLast = read == 0;

                // Swap buffers and start writing.
                var next = await writing.ConfigureAwait(false);

                writing = InternalWrite(writer, buffer, offset, isLast && thenCommit, cancel);

                if (isLast)
                {
                    break;
                }

                // Allocate a second buffer, but only if we need one
                buffer = next ?? (buffer2 = new byte[bufferSize]);
            }

            await writing.ConfigureAwait(false);

            return(buffer2);
        }
Пример #2
0
        /// <see cref="WriteAsync(IWriteOnlyStore,Stream,int,CancellationToken)"/>
        private static async Task <byte[]> InternalWrite(StoreWriter writer, byte[] buffer, int count, bool thenCommit, CancellationToken cancel)
        {
            // This method returns the byte array to facilitate the control flow.
            // This way, the byte array is reserved until the write task completes.

            if (thenCommit)
            {
                await writer.WriteAndCommitAsync(buffer, 0, count, cancel);
            }
            else
            {
                await writer.WriteAsync(buffer, 0, count, cancel);
            }

            return(buffer);
        }
Пример #3
0
 public BufferedCASStream(StoreWriter w, bool commit = true)
 {
     _w      = w;
     _commit = commit;
 }