//public virtual void Dispose() //{ // if (_stream != null) // { // _stream.Dispose(); // _stream = null; // // after release stream, delete datafile // FileHelper.TryDelete(_filename); // } //} #endregion #region Read/Write /// <summary> /// Read page bytes from disk /// </summary> public virtual byte[] ReadPage(uint pageID) { // if stream are not initialized but need header, create new header if (_stream == null && pageID == 0) { var header = new HeaderPage { LastPageID = 1 }; return(header.WritePage()); } else if (_stream == null) { InternalInitialize(); } var buffer = new byte[BasePage.PAGE_SIZE]; var position = BasePage.GetSizeOfPages(pageID); // position cursor if (_stream.Position != position) { _stream.Seek(position, SeekOrigin.Begin); } // read bytes from data file _stream.Read(buffer, 0, BasePage.PAGE_SIZE); return(buffer); }
//public void Dispose() //{ // // dispose datafile and journal file // _disk.Dispose(); // // dispose crypto // if (_crypto != null) _crypto.Dispose(); //} /// <summary> /// Initialize new datafile with header page + lock reserved area zone /// </summary> public static void CreateDatabase(Stream stream, string password = null, long initialSize = 0) { // calculate how many empty pages will be added on disk var emptyPages = initialSize == 0 ? 0 : (initialSize - (2 * BasePage.PAGE_SIZE)) / BasePage.PAGE_SIZE; // if too small size (less than 2 pages), assume no initial size if (emptyPages < 0) { emptyPages = 0; } // create a new header page in bytes (keep second page empty) var header = new HeaderPage { LastPageID = initialSize == 0 ? 1 : (uint)emptyPages + 1, FreeEmptyPageID = initialSize == 0 ? uint.MaxValue : 2 }; if (password != null) { header.Password = AesEncryption.HashSHA1(password); header.Salt = AesEncryption.Salt(); } // point to begin file stream.Seek(0, SeekOrigin.Begin); // get header page in bytes var buffer = header.WritePage(); stream.Write(buffer, 0, BasePage.PAGE_SIZE); // write second page as an empty AREA (it's not a page) just to use as lock control stream.Write(new byte[BasePage.PAGE_SIZE], 0, BasePage.PAGE_SIZE); // create crypto class if has password var crypto = password != null ? new AesEncryption(password, header.Salt) : null; // if initial size is defined, lets create empty pages in a linked list if (emptyPages > 0) { stream.SetLength(initialSize); var pageID = 1u; while (++pageID < (emptyPages + 2)) { var empty = new EmptyPage(pageID) { PrevPageID = pageID == 2 ? 0 : pageID - 1, NextPageID = pageID == emptyPages + 1 ? uint.MaxValue : pageID + 1 }; var bytes = empty.WritePage(); if (password != null) { bytes = crypto.Encrypt(bytes); } stream.Write(bytes, 0, BasePage.PAGE_SIZE); } } if (crypto != null) { crypto.Dispose(); } }