private Page DiskReadPage(string tableName, int pageIndex, int fileId)
        {
            string filename = DatabaseName + "." + tableName + ".data." + fileId;
            DataFileHeader tableDataFileHeader = ReadDataFileHeader(tableName, fileId);

            if (pageIndex >= tableDataFileHeader.TotalPageNum)
                throw new ApplicationException("pageIndex");

            var p = new Page(tableDataFileHeader)
            {
                FileId = fileId,
                PageIndex = pageIndex,
                PageSize = tableDataFileHeader.PageSize,
                TableName = tableName,
                DataFileName = filename,
            };

            using (var fileStream = new FileStream(filename, FileMode.Open))
            {
                fileStream.Seek(DataFileHeaderSize + pageIndex * p.PageSize, SeekOrigin.Begin);
                var pageData = new byte[p.PageSize];
                fileStream.Read(pageData, 0, p.PageSize);
                p.Decode(pageData);
            }

            return p;
        }
        private void DiskWritePage(string tableName, Page page, int fileId)
        {
            string filename = DatabaseName + "." + page.TableName + ".data." + fileId;
            DataFileHeader tableDataFileHeader = ReadDataFileHeader(tableName, page.FileId);

            if (page.PageIndex >= tableDataFileHeader.TotalPageNum)
                throw new ApplicationException("pageIndex");

            page.FileId = fileId;

            using (var fileStream = new FileStream(filename, FileMode.Open))
            {
                fileStream.Seek(DataFileHeaderSize + page.PageIndex * page.PageSize, SeekOrigin.Begin);
                byte[] pageData = page.Encode();
                fileStream.Write(pageData, 0, page.PageSize);
                fileStream.Flush();
            }
        }
        /// <summary>
        /// Write page into the shadow and create an updated page tableName for it
        /// </summary>
        public void WritePage(Transaction tid, string tableName, string key, Page page)
        {
            EnsureInitialized();

            if (page.TableName != tableName)
                throw new ArgumentException("page deson't below to the tableName");

            //read active page tableName
            var pageTable = this.DiskReadPageTable(tableName);

            //modify page tableName
            var pageTableIndex = (from k in pageTable.RecordIndices where Trim(k.Key) == key select k).Single();
            pageTableIndex.ShadowFileId = pageTableIndex.ActiveFileId == 0 ? 1 : 0;

            if (pageTableIndex.PageIndex != page.PageIndex)
                throw new ApplicationException("index doesn't match the page");

            //save page into shadow
            DiskWritePage(tableName, page, pageTableIndex.ShadowFileId);

            //save page tableName file
            DiskWritePageTable(tableName, pageTable);
        }