コード例 #1
0
        public Task<DriverWriteResult> WriteAsync(long position, IEnumerable<RawEvent> events, CancellationToken cancel = new CancellationToken())
        {
            var written = false;

            if (_file.Length == position)
            {
                written = true;
                _file.Seek(0, SeekOrigin.End);

                using (var w = new BinaryWriter(_file, Encoding.UTF8, true))
                foreach (var e in events)
                    EventFormat.Write(w, e);
            }

            return Task.FromResult(new DriverWriteResult(_file.Length, written));
        }
コード例 #2
0
        internal DriverWriteResult Write(long position, IEnumerable <RawEvent> events)
        {
            var written = false;

            if (_file.Length == position)
            {
                written = true;
                _file.Seek(0, SeekOrigin.End);

                using (var w = new BinaryWriter(_file, Encoding.UTF8, true))
                    foreach (var e in events)
                    {
                        EventFormat.Write(w, e);
                    }
            }

            return(new DriverWriteResult(_file.Length, written));
        }
コード例 #3
0
        public async Task <DriverWriteResult> WriteAsync(long position, IEnumerable <RawEvent> events, CancellationToken cancel = new CancellationToken())
        {
            // Caller knows something we don't? Refresh!
            if (position > _lastKnownPosition)
            {
                _lastKnownPosition = await RefreshCache(cancel);
            }

            // Quick early-out with no Azure request involved.
            if (position < _lastKnownPosition)
            {
                return(new DriverWriteResult(_lastKnownPosition, false));
            }

            // This should only happen very rarely, but it still needs to be done.
            if (_blobs.Count == 0)
            {
                await CreateLastBlob(cancel);
            }

            // Generate appended payload

            byte[] payload;
            using (var stream = new MemoryStream())
                using (var writer = new BinaryWriter(stream))
                {
                    foreach (var e in events)
                    {
                        EventFormat.Write(writer, e);
                    }

                    payload = stream.ToArray();
                }

            // Nothing to write, but still check position
            if (payload.Length == 0)
            {
                _lastKnownPosition = await RefreshCache(cancel);

                return(new DriverWriteResult(_lastKnownPosition, position == _lastKnownPosition));
            }

            // Attempt write to last blob.
            bool collision;

            try
            {
                var   offset = _firstPosition[_blobs.Count - 1];
                await _blobs[_blobs.Count - 1].AppendTransactionalAsync(payload, position - offset, cancel);

                _lastKnownPosition = position + payload.Length;

                return(new DriverWriteResult(_lastKnownPosition, true));
            }
            catch (StorageException e)
            {
                if (!e.IsCollision() && !e.IsMaxReached())
                {
                    throw;
                }

                collision = e.IsCollision();
            }

            // Collision means we do not have the proper _lastKnownPosition, so refresh
            // the cache and return a failure.
            if (collision)
            {
                return(new DriverWriteResult(await RefreshCache(cancel), false));
            }

            // Too many appends can be solved by creating a new blob and appending to it.
            // The append code is similar but subtly different, so we just rewrite it
            // below.
            await CreateLastBlob(cancel);

            try
            {
                await _blobs[_blobs.Count - 1].AppendTransactionalAsync(payload, 0, cancel);

                _lastKnownPosition = position + payload.Length;

                return(new DriverWriteResult(_lastKnownPosition, true));
            }
            catch (StorageException e)
            {
                // Only a collision can stop us here, no max-appends-reached should
                // happen when appending at position 0.
                if (!e.IsCollision())
                {
                    throw;
                }
            }

            // Collision here means someone else already created the new blob and appended
            // to it, so refresh everything and report failure.
            return(new DriverWriteResult(await RefreshCache(cancel), false));
        }