/// <summary> /// Create a new index and returns head page address (skip list) /// </summary> public CollectionIndex CreateIndex(CollectionIndex index) { // get a new index page for first index page var page = _pager.NewPage <IndexPage>(); // create a empty node with full max level var node = new IndexNode(IndexNode.MAX_LEVEL_LENGTH) { Key = new IndexKey(null), Page = page }; node.Position = new PageAddress(page.PageID, 0); // add as first node page.Nodes.Add(node.Position.Index, node); // add indexPage on freelist if has space _pager.AddOrRemoveToFreeList(true, page, index.Page, ref index.FreeIndexPageID); // point the head node to this new node position index.HeadNode = node.Position; index.Page.IsDirty = true; page.IsDirty = true; return(index); }
/// <summary> /// Insert data inside a datapage. Returns dataPageID that indicates the first page /// </summary> public DataBlock Insert(CollectionPage col, byte[] data) { // need to extend (data is bigger than 1 page) var extend = (data.Length + DataBlock.DATA_BLOCK_FIXED_SIZE) > BasePage.PAGE_AVAILABLE_BYTES; // if extend, just search for a page with BLOCK_SIZE available var dataPage = _pager.GetFreePage <DataPage>(col.FreeDataPageID, extend ? DataBlock.DATA_BLOCK_FIXED_SIZE : data.Length + DataBlock.DATA_BLOCK_FIXED_SIZE); // create a new block with first empty index on DataPage var block = new DataBlock { Position = new PageAddress(dataPage.PageID, dataPage.DataBlocks.NextIndex()), Page = dataPage }; // if extend, store all bytes on extended page. if (extend) { var extendPage = _pager.NewPage <ExtendPage>(); block.ExtendPageID = extendPage.PageID; this.StoreExtendData(extendPage, data); } else { block.Data = data; } // add dataBlock to this page dataPage.DataBlocks.Add(block.Position.Index, block); // update freebytes + items count dataPage.UpdateItemCount(); // set page as dirty _pager.SetDirty(dataPage); // add/remove dataPage on freelist if has space _pager.AddOrRemoveToFreeList(dataPage.FreeBytes > DataPage.DATA_RESERVED_BYTES, dataPage, col, ref col.FreeDataPageID); // increase document count in collection col.DocumentCount++; // set collection page as dirty _pager.SetDirty(col); return(block); }
/// <summary> /// Create a new index and returns head page address (skip list) /// </summary> public CollectionIndex CreateIndex(CollectionPage col) { // get index slot var index = col.GetFreeIndex(); // get a new index page for first index page var page = _pager.NewPage <IndexPage>(); // create a empty node with full max level var head = new IndexNode(IndexNode.MAX_LEVEL_LENGTH) { Key = BsonValue.MinValue, KeyLength = (ushort)BsonValue.MinValue.GetBytesCount(false), Slot = (byte)index.Slot, Page = page, Position = new PageAddress(page.PageID, 0) }; // add as first node page.Nodes.Add(head.Position.Index, head); // update freebytes + item count (for head) page.UpdateItemCount(); // set index page as dirty _pager.SetDirty(index.Page); // add indexPage on freelist if has space _pager.AddOrRemoveToFreeList(true, page, index.Page, ref index.FreeIndexPageID); // point the head/tail node to this new node position index.HeadNode = head.Position; // insert tail node var tail = this.AddNode(index, BsonValue.MaxValue, IndexNode.MAX_LEVEL_LENGTH, null); index.TailNode = tail.Position; return(index); }
/// <summary> /// Insert data inside a datapage. Returns dataPageID that idicates the first page /// </summary> public DataBlock Insert(CollectionPage col, IndexKey key, byte[] data) { // need to extend (data is bigger than 1 page) var extend = (data.Length + key.Length + DataBlock.DATA_BLOCK_FIXED_SIZE) > BasePage.PAGE_AVAILABLE_BYTES; // if extend, just search for a page with BLOCK_SIZE avaiable var dataPage = _pager.GetFreePage <DataPage>(col.FreeDataPageID, extend ? DataBlock.DATA_BLOCK_FIXED_SIZE : key.Length + data.Length + DataBlock.DATA_BLOCK_FIXED_SIZE); // create a new block with first empty index on DataPage var block = new DataBlock { Position = new PageAddress(dataPage.PageID, dataPage.DataBlocks.NextIndex()), Page = dataPage, Key = key }; // if extend, store all bytes on extended page. if (extend) { var extendPage = _pager.NewPage <ExtendPage>(); block.ExtendPageID = extendPage.PageID; this.StoreExtendData(extendPage, data); } else { block.Data = data; } // add dataBlock to this page dataPage.DataBlocks.Add(block.Position.Index, block); dataPage.IsDirty = true; // add/remove dataPage on freelist if has space _pager.AddOrRemoveToFreeList(dataPage.FreeBytes > BasePage.RESERVED_BYTES, dataPage, col, ref col.FreeDataPageID); col.DocumentCount++; col.IsDirty = true; return(block); }
/// <summary> /// Add a new collection. Check if name the not exists /// </summary> public CollectionPage Add(string name) { if (string.IsNullOrEmpty(name)) { throw new ArgumentNullException("name"); } if (!CollectionPage.NamePattern.IsMatch(name)) { throw LiteException.InvalidFormat("CollectionName", name); } // test collection limit var pages = _pager.GetSeqPages <CollectionPage>(_cache.Header.FirstCollectionPageID); if (pages.Count() >= CollectionPage.MAX_COLLECTIONS) { throw LiteException.CollectionLimitExceeded(CollectionPage.MAX_COLLECTIONS); } var col = _pager.NewPage <CollectionPage>(); // add page in collection list _pager.AddOrRemoveToFreeList(true, col, _cache.Header, ref _cache.Header.FirstCollectionPageID); col.CollectionName = name; col.IsDirty = true; // create PK index var pk = _indexer.CreateIndex(col); pk.Field = "_id"; pk.Options = new IndexOptions { Unique = true }; return(col); }