Beispiel #1
0
        public void two()
        {
            var l = new AppendList <int>();

            l.Append(10);
            l.Append(42);

            Assert.Equal(2, l.Count);
            Assert.Equal(10, l[0]);
            Assert.Equal(42, l[1]);
        }
Beispiel #2
0
        public async Task smoke_test()
        {
            // Append and read repeatedly, trying to cause an
            // access violation.

            for (var c = 0; c < 1000; ++c)
            {
                var l = new AppendList <int>();

                var t1 = Task.Run(() =>
                {
                    for (var i = 0; i < 100000; ++i)
                    {
                        l.Append(i * 3);
                    }
                });

                var t2 = Task.Run(() =>
                {
                    for (var i = 0; i < 100000; ++i)
                    {
                        while (i >= l.Count)
                        {
                            Thread.Yield();
                        }

                        Assert.Equal(i * 3, l[i]);
                    }
                });

                await t1;
                await t2;
            }
        }
Beispiel #3
0
        /// <summary> Construct from a read-only file. </summary>
        /// <remarks>
        ///     Used when recovering files written by a previous program
        ///     instance from their locations.
        /// </remarks>
        public BlockFile(IFileMemory file, uint fileId)
        {
            _pinner = new Pinner();
            _file   = file ?? throw new ArgumentNullException(nameof(file));
            FileId  = fileId;

            _flags = new AppendList <ReadFlag>();

            var offset = 0L;

            while (offset < _file.Length)
            {
                var     block  = AtOffset(offset);
                ref var header = ref block.Header;

                if (header.Rank != _flags.Count || header.ContentLength < 0 ||
                    header.ContentLength + BlockHeader.Size > _file.Length)
                {
                    // The header of the block appears broken. Do not include
                    // it in the list, and stop scanning (since we don't know
                    // how far to jump ahead).
                    break;
                }

                var thisOffset = offset;
                _flags.Append(ReadFlag.Triggered(() => VerifyAtOffset(thisOffset)));

                offset += block.RelativeOffsetToNextBlock;
            }
Beispiel #4
0
        /// <summary>
        ///     Attempts to schedule a write of the specified length into the file.
        /// </summary>
        /// <returns>
        ///     A valid block address representing the location where the written
        ///     block will be found, or a 'None' address if the file does not
        ///     currently have enough room for this.
        /// </returns>
        /// <remarks>
        ///     The provided writer will be invoked at some point in the future.
        ///
        ///     Thread-safe.
        /// </remarks>
        public BlockAddress TryScheduleWrite(
            uint realm,
            Hash hash,
            int length,
            WithSpan.ReadWrite writer)
        {
            if (length < 0)
            {
                throw new ArgumentException($"Negative length: {length}", nameof(length));
            }
            int  rank;
            long offset;

            lock (_syncRoot)
            {
                offset  = _offset;
                _offset = BlockAddress.Ceiling(offset + BlockHeader.Size + length);

                if (_offset > _file.Length)
                {
                    // Since this file is about to be flushed and closed,
                    // because it's "full enough", we prevent additional writes.
                    _offset = _file.Length;
                    return(BlockAddress.None);
                }

                rank = _flags.Count;
                _flags.Append(ReadFlag.Triggered(() => PerformWrite(offset, writer)));
            }

            // We touched '_offset' and '_flags' in the critical section, the remaining
            // work on the actual byte span can be done without mutex.

            var     span   = _file.AsMemory(offset, BlockHeader.Size).Span;
            ref var header = ref MemoryMarshal.Cast <byte, BlockHeader>(span)[0];
Beispiel #5
0
        public void one()
        {
            var l = new AppendList <int>();

            l.Append(10);

            Assert.Equal(1, l.Count);
            Assert.Equal(10, l[0]);
        }