/// <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); // 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 }; stream.Write(empty.WritePage(), 0, BasePage.PAGE_SIZE); } } }
/// <summary> /// Delete an page using pageID - transform them in Empty Page and add to EmptyPageList /// If you delete a page, you can using same old instance of page - page will be converter to EmptyPage /// If need deleted page, use GetPage again /// </summary> public void DeletePage(uint pageID, bool addSequence = false) { // get all pages in sequence or a single one var pages = addSequence ? this.GetSeqPages <BasePage>(pageID).ToArray() : new BasePage[] { this.GetPage <BasePage>(pageID) }; // get my header page var header = this.GetPage <HeaderPage>(0); // adding all pages to FreeList foreach (var page in pages) { // create a new empty page based on a normal page var empty = new EmptyPage(page.PageID); // add empty page to cache (with now EmptyPage type) and mark as dirty this.SetDirty(empty); // add to empty free list this.AddOrRemoveToFreeList(true, empty, header, ref header.FreeEmptyPageID); } }
/// <summary> /// Delete an page using pageID - transform them in Empty Page and add to EmptyPageList /// If you delete a page, you can using same old instance of page - page will be converter to EmptyPage /// If need deleted page, use GetPage again /// [Set as Dirty] /// </summary> public void DeletePage(uint pageID, bool addSequence = false) { // get all pages in sequence or a single one var pages = addSequence ? GetSeqPages <BasePage>(pageID).ToArray() : new[] { GetPage <BasePage>(pageID) }; // get my header page var header = GetPage <HeaderPage>(0); // adding all pages to FreeList foreach (var page in pages) { // create a new empty page based on a normal page var empty = new EmptyPage(page); // mark page as dirty SetDirty(empty); // add to empty free list AddOrRemoveToFreeList(true, empty, header, ref header.FreeEmptyPageID); } }
public static void Dump(this EmptyPage page, StringBuilder sb) { sb.AppendFormat("(empty)"); }