Пример #1
0
        public void Test_Indexer()
        {
            var slice = new SliceWriter();

            slice.WriteFixed64(0xBADC0FFEE0DDF00DUL);

            Assert.That(slice[0], Is.EqualTo(0x0D));
            Assert.That(slice[1], Is.EqualTo(0xF0));
            Assert.That(slice[2], Is.EqualTo(0xDD));
            Assert.That(slice[3], Is.EqualTo(0xE0));
            Assert.That(slice[4], Is.EqualTo(0xFE));
            Assert.That(slice[5], Is.EqualTo(0x0F));
            Assert.That(slice[6], Is.EqualTo(0xDC));
            Assert.That(slice[7], Is.EqualTo(0xBA));

            Assert.That(slice[-1], Is.EqualTo(0xBA));
            Assert.That(slice[-2], Is.EqualTo(0xDC));
            Assert.That(slice[-3], Is.EqualTo(0x0F));
            Assert.That(slice[-4], Is.EqualTo(0xFE));
            Assert.That(slice[-5], Is.EqualTo(0xE0));
            Assert.That(slice[-6], Is.EqualTo(0xDD));
            Assert.That(slice[-7], Is.EqualTo(0xF0));
            Assert.That(slice[-8], Is.EqualTo(0x0D));

            Assert.That(() => slice[8], Throws.InstanceOf <IndexOutOfRangeException>());
            Assert.That(() => slice[-9], Throws.InstanceOf <IndexOutOfRangeException>());
        }
        /// <summary>Write the header to the file</summary>
        /// <param name="headerFlags"></param>
        /// <param name="uid"></param>
        /// <param name="sequence"></param>
        /// <param name="count"></param>
        /// <param name="timestamp"></param>
        /// <param name="attributes"></param>
        /// <remarks>This needs to be called before writing any level to the file</remarks>
        public Task WriteHeaderAsync(SnapshotFormat.Flags headerFlags, Uuid128 uid, ulong sequence, long count, long timestamp, IDictionary <string, IFdbTuple> attributes)
        {
            // The header will be use on ore more "pages", to simplify the job of loading / peeking at a stream content (no need for fancy buffering, just need to read 4K pages)
            // > The last page is padded with 0xAAs to detect corruption.

            m_uid       = uid;
            m_sequence  = sequence;
            m_itemCount = count;
            m_timestamp = timestamp;

            // HEADER
            // - DB_HEADER (64 bytes)
            // - DB ATTRIBUTES (variable size list of k/v)
            // - END_MARKER + HEADER_CRC
            // - PADDING (to fill last page)

            // DB Header

            // "PNDB"
            m_writer.WriteFixed32(SnapshotFormat.HEADER_MAGIC_NUMBER);
            // v1.0
            m_writer.WriteFixed16(1);             // major
            m_writer.WriteFixed16(0);             // minor
            // FLAGS
            m_writer.WriteFixed64((ulong)headerFlags);
            // Database ID
            m_writer.WriteBytes(uid.ToSlice());
            // Database Version
            m_writer.WriteFixed64(sequence);
            // Number of items in the database
            m_writer.WriteFixed64((ulong)count);
            // Database Timestamp
            m_writer.WriteFixed64((ulong)timestamp);
            // Page Size
            m_writer.WriteFixed32(SnapshotFormat.PAGE_SIZE);
            // Header Size (not known yet and will be filled in later)
            int offsetToHeaderSize = m_writer.Skip(4);

            // we should be at the 64 byte mark
            Contract.Assert(m_writer.Position == SnapshotFormat.HEADER_METADATA_BYTES);

            // DB Attributes
            m_writer.WriteFixed32((uint)attributes.Count);
            foreach (var kvp in attributes)
            {
                // Name
                m_writer.WriteVarbytes(Slice.FromString(kvp.Key));

                // Value
                m_writer.WriteVarbytes(kvp.Value.ToSlice());
            }

            // Mark the end of the header
            m_writer.WriteFixed32(uint.MaxValue);

            // we now have the size of the header, and can fill in the blank
            var headerEnd = m_writer.Position;

            m_writer.Position = offsetToHeaderSize;
            // write the header size (includes the CRC)
            m_writer.WriteFixed32((uint)checked (headerEnd + SnapshotFormat.HEADER_CRC_SIZE));
            m_writer.Position = headerEnd;

            // now we can compute the actual CRC
            uint headerChecksum = SnapshotFormat.ComputeChecksum(m_writer.ToSlice());

            m_writer.WriteFixed32(headerChecksum);
            m_headerChecksum = headerChecksum;

            // optional padding to fill the rest of the page
            PadPageIfNeeded(SnapshotFormat.PAGE_SIZE, 0xFD);

            return(TaskHelpers.CompletedTask);
        }