示例#1
0
        /// <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);
        }
示例#2
0
        /// <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");
            }
            //TODO why? if(!Regex.IsMatch(name, CollectionPage.NAME_PATTERN)) throw new LiteException("Invalid collection name. Use only letters, numbers and _");

            var pages = _pager.GetSeqPages <CollectionPage>(1); // PageID 1 = Master Collection

            if (pages.FirstOrDefault(x => x.CollectionName.Equals(name, StringComparison.InvariantCultureIgnoreCase)) != null)
            {
                throw new ArgumentException("Collection name already exists (names are case unsensitive)");
            }

            if (pages.Count() >= CollectionPage.MAX_COLLECTIONS)
            {
                throw new LiteException("This database exceded max collections: " + CollectionPage.MAX_COLLECTIONS);
            }

            var col = _pager.NewPage <CollectionPage>(pages.Last());

            col.CollectionName = name;
            col.IsDirty        = true;

            // create PK index
            var pk = _indexer.CreateIndex(col.PK);

            pk.Field  = "_id";
            pk.Unique = true;

            return(col);
        }
示例#3
0
        /// <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);
        }
示例#4
0
        /// <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);
        }
示例#5
0
        /// <summary>
        /// Add a new collection. Check if name the not exists
        /// </summary>
        public CollectionPage Add(string name)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException(nameof(name));
            }
            if (!CollectionPage.NamePattern.IsMatch(name))
            {
                throw LiteException.InvalidFormat(name);
            }

            _log.Write(Logger.COMMAND, "creating new collection '{0}'", name);

            // get header marked as dirty because I will use header after (and NewPage can get another header instance)
            var header = _pager.GetPage <HeaderPage>(0);

            // check limit count (8 bytes per collection = 4 to string length, 4 for uint pageID)
            if (header.CollectionPages.Sum(x => x.Key.Length + 8) + name.Length + 8 >= CollectionPage.MAX_COLLECTIONS_SIZE)
            {
                throw LiteException.CollectionLimitExceeded(CollectionPage.MAX_COLLECTIONS_SIZE);
            }

            // get new collection page (marked as dirty)
            var col = _pager.NewPage <CollectionPage>();

            // add this page to header page collection
            header.CollectionPages.Add(name, col.PageID);

            col.CollectionName = name;

            // set header page as dirty
            _pager.SetDirty(header);

            // create PK index
            var pk = _indexer.CreateIndex(col);

            pk.Field      = "_id";
            pk.Expression = "$._id";
            pk.Unique     = true;

            return(col);
        }
示例#6
0
        /// <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);
        }
示例#7
0
        /// <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);
            }

            // get header marked as dirty because I will use header after (and NewPage can get another header instance)
            var header = _pager.GetPage <HeaderPage>(0, true);

            // check limit count
            if (header.CollectionPages.Count >= CollectionPage.MAX_COLLECTIONS)
            {
                throw LiteException.CollectionLimitExceeded(CollectionPage.MAX_COLLECTIONS);
            }

            // get new collection page (marked as dirty)
            var col = _pager.NewPage <CollectionPage>();

            // add this page to header page collection
            header.CollectionPages.Add(name.Trim().ToLower(), col.PageID);

            col.CollectionName = name;

            // create PK index
            var pk = _indexer.CreateIndex(col);

            pk.Field   = "_id";
            pk.Options = new IndexOptions {
                Unique = true
            };

            return(col);
        }
示例#8
0
        /// <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);
        }