public DataPage GetDataPage(uint pageID) { if (pageID == Header.LastPageID) // Page does not exists in disk { var dataPage = new DataPage(pageID); return dataPage; } else { return PageFactory.GetDataPage(pageID, Reader, false); } }
internal FileDBStream(Engine engine, Guid id) { _engine = engine; var indexNode = _engine.Search(id); if (indexNode != null) { _streamLength = indexNode.FileLength; _currentPage = PageFactory.GetDataPage(indexNode.DataPageID, engine.Reader, false); _info = new EntryInfo(indexNode); } }
public static void ReadFromFile(DataPage dataPage, BinaryReader reader, bool onlyHeader) { // Seek the stream on first byte from data page long initPos = reader.Seek(Header.HEADER_SIZE + ((long)dataPage.PageID * BasePage.PAGE_SIZE)); if (reader.ReadByte() != (byte)PageType.Data) throw new FileDBException("PageID {0} is not a Data Page", dataPage.PageID); dataPage.NextPageID = reader.ReadUInt32(); dataPage.IsEmpty = reader.ReadBoolean(); dataPage.DataBlockLength = reader.ReadInt16(); // If page is empty or onlyHeader parameter, I don't read data content if (!dataPage.IsEmpty && !onlyHeader) { // Seek the stream at the end of page header reader.Seek(initPos + DataPage.HEADER_SIZE); // Read all bytes from page dataPage.DataBlock = reader.ReadBytes(dataPage.DataBlockLength); } }
// Take a new data page on sequence and update the last public static DataPage GetNewDataPage(DataPage basePage, Engine engine) { if (basePage.NextPageID != uint.MaxValue) { PageFactory.WriteToFile(basePage, engine.Writer); // Write last page on disk var dataPage = PageFactory.GetDataPage(basePage.NextPageID, engine.Reader, false); engine.Header.FreeDataPageID = dataPage.NextPageID; if (engine.Header.FreeDataPageID == uint.MaxValue) engine.Header.LastFreeDataPageID = uint.MaxValue; return dataPage; } else { var pageID = ++engine.Header.LastPageID; DataPage newPage = new DataPage(pageID); basePage.NextPageID = newPage.PageID; PageFactory.WriteToFile(basePage, engine.Writer); // Write last page on disk return newPage; } }
public override int Read(byte[] buffer, int offset, int count) { int bytesLeft = count; while (_currentPage != null && bytesLeft > 0) { int bytesToCopy = Math.Min(bytesLeft, _currentPage.DataBlockLength - _positionInPage); Buffer.BlockCopy(_currentPage.DataBlock, _positionInPage, buffer, offset, bytesToCopy); _positionInPage += bytesToCopy; bytesLeft -= bytesToCopy; offset += bytesToCopy; _streamPosition += bytesToCopy; if (_positionInPage >= _currentPage.DataBlockLength) { _positionInPage = 0; if (_currentPage.NextPageID == uint.MaxValue) _currentPage = null; else _currentPage = PageFactory.GetDataPage(_currentPage.NextPageID, _engine.Reader, false); } } return count - bytesLeft; }
public static DataPage GetDataPage(uint pageID, BinaryReader reader, bool onlyHeader) { var dataPage = new DataPage(pageID); ReadFromFile(dataPage, reader, onlyHeader); return dataPage; }
public static void WriteToFile(DataPage dataPage, BinaryWriter writer) { // Seek the stream on first byte from data page long initPos = writer.Seek(Header.HEADER_SIZE + ((long)dataPage.PageID * BasePage.PAGE_SIZE)); // Write data page header writer.Write((byte)dataPage.Type); writer.Write(dataPage.NextPageID); writer.Write(dataPage.IsEmpty); writer.Write(dataPage.DataBlockLength); // I will only save data content if the page is not empty if (!dataPage.IsEmpty) { // Seek the stream at the end of page header writer.Seek(initPos + DataPage.HEADER_SIZE); writer.Write(dataPage.DataBlock, 0, (int)dataPage.DataBlockLength); } }
public static void InsertFile(IndexNode node, EntryInfo enInfo, Stream stream, Engine engine) { var buffer = new byte[DataPage.DATA_PER_PAGE]; int dataFreeInPage = DataPage.DATA_PER_PAGE; int writePos = 0; int read = 0; DataPage dataPage = engine.GetDataPage(node.DataPageID); if (!dataPage.IsEmpty) // This is never to happend!! { throw new FileDBException("Page {0} is not empty", dataPage.PageID); } //----------------------- //write metadata //1. datetime of file DateTime filedtm = enInfo.FileDateTime; //-------------------------- writePos = WriteByte(dataPage.DataBlock, 0, 1); //marker - 1 writePos = WriteInt64(dataPage.DataBlock, writePos, filedtm.ToBinary()); //data part //-------------------------- //2. long filename (if has long filename) //----------------------- if (enInfo.HasLongFileName) { //write full filename here byte[] longFileNameBuff = System.Text.Encoding.UTF8.GetBytes(enInfo.FileUrl); int buffLen = longFileNameBuff.Length; if (buffLen > 512) { //for this version *** throw new Exception("file name must not longer than 512 bytes"); } writePos = WriteByte(dataPage.DataBlock, writePos, 2); //marker 2 long filename //-------- writePos = WriteUInt16(dataPage.DataBlock, writePos, (ushort)buffLen); //2 bytes length of buffer writePos = WriteBuffer(dataPage.DataBlock, writePos, longFileNameBuff); //buffer //-------- } dataPage.IsEmpty = false; dataPage.DataBlockLength = (short)writePos; dataFreeInPage -= writePos; node.FileMetaDataLength = (ushort)writePos; //----------------------- bool isFirstRound = true; uint fileLength = 0; while ((read = stream.Read(buffer, 0, dataFreeInPage)) > 0) { //if we have some data to write fileLength += (uint)read; if (!isFirstRound) { dataPage = GetNewDataPage(dataPage, engine); if (!dataPage.IsEmpty) // This is never to happend!! { throw new FileDBException("Page {0} is not empty", dataPage.PageID); } } writePos = WriteBuffer(dataPage.DataBlock, writePos, buffer, read); dataPage.IsEmpty = false; dataPage.DataBlockLength = (short)writePos; //---------------------------------------------- //reset for next dataFreeInPage = DataPage.DATA_PER_PAGE; writePos = 0; isFirstRound = false; //---------------------------------------------- } // If the last page point to another one, i need to fix that if (dataPage.NextPageID != uint.MaxValue) { engine.Header.FreeDataPageID = dataPage.NextPageID; dataPage.NextPageID = uint.MaxValue; } // Save the last page on disk PageFactory.WriteToFile(dataPage, engine.Writer); // Save on node index that file length node.FileLength = fileLength; }