/// <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);
        }