/// <summary>
        /// Load page content based on page buffer
        /// </summary>
        public void LoadPage()
        {
            // check database file format
            var info = _buffer.ReadString(P_HEADER_INFO, HEADER_INFO.Length);
            var ver  = _buffer[P_FILE_VERSION];

            if (string.CompareOrdinal(info, HEADER_INFO) != 0 || ver != FILE_VERSION)
            {
                throw LiteException.InvalidDatabase();
            }

            // CreateTime is readonly
            this.FreeEmptyPageList = _buffer.ReadUInt32(P_FREE_EMPTY_PAGE_ID);
            this.LastPageID        = _buffer.ReadUInt32(P_LAST_PAGE_ID);

            // initialize engine pragmas
            this.Pragmas = new EnginePragmas(_buffer, this);

            // create new buffer area to store BsonDocument collections
            var area = _buffer.Slice(P_COLLECTIONS, COLLECTIONS_SIZE);

            using (var r = new BufferReader(new[] { area }, false))
            {
                _collections = r.ReadDocument();
            }

            _isCollectionsChanged = false;
        }
Exemple #2
0
        protected override void ReadContent(ByteReader reader)
        {
            var info = reader.ReadString(HEADER_INFO.Length);
            var ver  = reader.ReadByte();

            if (info != HEADER_INFO)
            {
                throw LiteException.InvalidDatabase();
            }
            if (ver != FILE_VERSION)
            {
                throw LiteException.InvalidDatabaseVersion(ver);
            }

            this.ChangeID        = reader.ReadUInt16();
            this.FreeEmptyPageID = reader.ReadUInt32();
            this.LastPageID      = reader.ReadUInt32();
            this.DbVersion       = reader.ReadUInt16();
            this.Password        = reader.ReadBytes(this.Password.Length);

            // read page collections references (position on end of page)
            var cols = reader.ReadByte();

            for (var i = 0; i < cols; i++)
            {
                this.CollectionPages.Add(reader.ReadString(), reader.ReadUInt32());
            }
        }
Exemple #3
0
        /// <summary>
        /// Read a page with correct instance page object. Checks for pageType
        /// </summary>
        public static BasePage ReadPage(byte[] buffer)
        {
            var reader = new ByteReader(buffer);

            var pageID   = reader.ReadUInt32();
            var pageType = (PageType)reader.ReadByte();

            if (pageID == 0 && (byte)pageType > 5)
            {
                throw LiteException.InvalidDatabase();
            }

            var page = CreateInstance(pageID, pageType);

            page.ReadHeader(reader);
            page.ReadContent(reader);

            page.DiskData = buffer;

            return(page);
        }
Exemple #4
0
        /// <summary>
        /// Read all database pages from v7 structure into a flexible BsonDocument - only read what really needs
        /// </summary>
        private BsonDocument ReadPage(uint pageID)
        {
            if (pageID * V7_PAGE_SIZE > _stream.Length)
            {
                return(null);
            }

            _stream.Position = pageID * V7_PAGE_SIZE; // v7 uses 4k page size

            _stream.Read(_buffer, 0, V7_PAGE_SIZE);

            // decrypt encrypted page (except header page - header are plain data)
            if (_aes != null && pageID > 0)
            {
                _buffer = _aes.Decrypt(_buffer);
            }

            var reader = new ByteReader(_buffer);

            // reading page header
            var page = new BsonDocument
            {
                ["pageID"]     = (int)reader.ReadUInt32(),
                ["pageType"]   = (int)reader.ReadByte(),
                ["prevPageID"] = (int)reader.ReadUInt32(),
                ["nextPageID"] = (int)reader.ReadUInt32(),
                ["itemCount"]  = (int)reader.ReadUInt16()
            };

            // skip freeByte + reserved
            reader.ReadBytes(2 + 8);

            #region Header (1)

            // read header
            if (page["pageType"] == 1)
            {
                var info = reader.ReadString(27);
                var ver  = reader.ReadByte();

                if (string.CompareOrdinal(info, HeaderPage.HEADER_INFO) != 0 || ver != 7)
                {
                    throw LiteException.InvalidDatabase();
                }

                // skip ChangeID + FreeEmptyPageID + LastPageID
                reader.ReadBytes(2 + 4 + 4);
                page["userVersion"] = (int)reader.ReadUInt16();
                page["password"]    = reader.ReadBytes(20);
                page["salt"]        = reader.ReadBytes(16);
                page["collections"] = new BsonDocument();

                var cols = reader.ReadByte();

                for (var i = 0; i < cols; i++)
                {
                    var name      = reader.ReadString();
                    var colPageID = reader.ReadUInt32();

                    page["collections"][name] = (int)colPageID;
                }
            }

            #endregion

            #region Collection (2)

            // collection page
            else if (page["pageType"] == 2)
            {
                page["collectionName"] = reader.ReadString();
                page["indexes"]        = new BsonArray();
                reader.ReadBytes(12);

                for (var i = 0; i < 16; i++)
                {
                    var index = new BsonDocument();

                    var field = reader.ReadString();
                    var eq    = field.IndexOf('=');

                    if (eq > 0)
                    {
                        index["name"]       = field.Substring(0, eq);
                        index["expression"] = field.Substring(eq + 1);
                    }
                    else
                    {
                        index["name"]       = field;
                        index["expression"] = "$." + field;
                    }

                    index["unique"]     = reader.ReadBoolean();
                    index["headPageID"] = (int)reader.ReadUInt32();

                    // skip HeadNode (index) + TailNode + FreeIndexPageID
                    reader.ReadBytes(2 + 6 + 4);

                    if (field.Length > 0)
                    {
                        page["indexes"].AsArray.Add(index);
                    }
                }
            }

            #endregion

            #region Index (3)

            else if (page["pageType"] == 3)
            {
                page["nodes"] = new BsonArray();

                for (var i = 0; i < page["itemCount"].AsInt32; i++)
                {
                    var node = new BsonDocument
                    {
                        ["index"] = (int)reader.ReadUInt16()
                    };

                    var levels = reader.ReadByte();

                    // skip Slot + PrevNode + NextNode
                    reader.ReadBytes(1 + 6 + 6);

                    var length = reader.ReadUInt16();

                    // skip DataType + KeyValue
                    reader.ReadBytes(1 + length);

                    node["dataBlock"] = new BsonDocument
                    {
                        ["pageID"] = (int)reader.ReadUInt32(),
                        ["index"]  = (int)reader.ReadUInt16()
                    };

                    // reading Prev[0]
                    node["prev"] = new BsonDocument
                    {
                        ["pageID"] = (int)reader.ReadUInt32(),
                        ["index"]  = (int)reader.ReadUInt16()
                    };

                    // reading Next[0]
                    node["next"] = new BsonDocument
                    {
                        ["pageID"] = (int)reader.ReadUInt32(),
                        ["index"]  = (int)reader.ReadUInt16()
                    };

                    // skip Prev/Next[1..N]
                    reader.ReadBytes((levels - 1) * (6 + 6));

                    page["nodes"].AsArray.Add(node);
                }
            }

            #endregion

            #region Data (4)

            else if (page["pageType"] == 4)
            {
                page["blocks"] = new BsonArray();

                for (var i = 0; i < page["itemCount"].AsInt32; i++)
                {
                    var block = new BsonDocument
                    {
                        ["index"]        = (int)reader.ReadUInt16(),
                        ["extendPageID"] = (int)reader.ReadUInt32()
                    };

                    var length = reader.ReadUInt16();

                    block["data"] = reader.ReadBytes(length);

                    page["blocks"].AsArray.Add(block);
                }
            }

            #endregion

            #region Extend (5)

            else if (page["pageType"] == 5)
            {
                page["data"] = reader.ReadBytes(page["itemCount"].AsInt32);
            }

            #endregion

            return(page);
        }