Пример #1
0
        /// <summary>
        /// Find all indexNodes that are greater/equals than value
        /// </summary>
        public IEnumerable <IndexNode> FindGreaterThan(CollectionIndex index, object value, bool includeValue = false)
        {
            // find first indexNode
            var node = this.FindOne(index, value, true);

            if (node == null)
            {
                yield break;
            }

            var key = new IndexKey(value);

            // move until next is last
            while (node != null)
            {
                var diff = node.Key.CompareTo(key);

                if (diff == 1 || (includeValue && diff == 0))
                {
                    yield return(node);
                }

                node = this.GetNode(node.Next[0]);
            }
        }
Пример #2
0
        /// <summary>
        /// Find all nodes less than value (can be inclusive)
        /// </summary>
        public IEnumerable <IndexNode> FindLessThan(CollectionIndex index, object value, bool includeValue = false)
        {
            var key = new IndexKey(value);

            foreach (var node in this.FindAll(index))
            {
                var diff = node.Key.CompareTo(key);

                if (diff == 1 || (!includeValue && diff == 0))
                {
                    break;
                }

                yield return(node);
            }
        }
Пример #3
0
        /// <summary>
        /// Find nodes between start and end and (inclusive)
        /// </summary>
        public IEnumerable <IndexNode> FindBetween(CollectionIndex index, object start, object end)
        {
            // find first indexNode
            var node = this.FindOne(index, start, true);
            var key  = new IndexKey(end);

            // navigate using next[0] do next node - if less or equals returns
            while (node != null)
            {
                var diff = node.Key.CompareTo(key);

                if (diff <= 0)
                {
                    yield return(node);
                }

                node = this.GetNode(node.Next[0]);
            }
        }
Пример #4
0
        /// <summary>
        /// Find first indexNode that match with value - if not found, can return first greater (used for greaterThan/Between)
        /// </summary>
        public IndexNode FindOne(CollectionIndex index, object value, bool greater = false)
        {
            var cur = this.GetNode(index.HeadNode);
            var key = new IndexKey(value);

            for (int i = IndexNode.MAX_LEVEL_LENGTH - 1; i >= 0; i--)
            {
                for (; cur.Next[i].IsEmpty == false; cur = this.GetNode(cur.Next[i]))
                {
                    var next = this.GetNode(cur.Next[i]);
                    var diff = next.Key.CompareTo(key);

                    if (diff == 1 && (i > 0 || !greater))
                    {
                        break;
                    }
                    if (diff == 1 && i == 0 && greater)
                    {
                        return(next);
                    }

                    // if equals, test for duplicates
                    if (diff == 0)
                    {
                        var last = next;
                        while (next.Key.CompareTo(key) == 0)
                        {
                            last = next;
                            if (index.HeadNode.Equals(next.Prev[0]))
                            {
                                break;
                            }
                            next = this.GetNode(next.Prev[0]);
                        }

                        return(last);
                    }
                }
            }

            return(null);
        }
Пример #5
0
        /// <summary>
        /// Find all indexNodes that match with value
        /// </summary>
        public IEnumerable <IndexNode> FindEquals(CollectionIndex index, object value)
        {
            // find first indexNode
            var node = this.FindOne(index, value);

            if (node == null)
            {
                yield break;
            }

            yield return(node);

            var key = new IndexKey(value);

            // navigate using next[0] do next node - if equals, returns
            while (!node.Next[0].IsEmpty && ((node = this.GetNode(node.Next[0])).Key.CompareTo(key) == 0))
            {
                yield return(node);
            }
        }
Пример #6
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.ExtendData   = data;
                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 > DataPage.RESERVED_BYTES, dataPage, col, ref col.FreeDataPageID);

            col.DocumentCount++;

            col.IsDirty = true;

            return(block);
        }
Пример #7
0
        public static T Deserialize <T>(IndexKey key, byte[] data)
        {
            if (data == null || data.Length == 0)
            {
                throw new ArgumentNullException("data");
            }

            object doc;

            if (typeof(T) == typeof(BsonDocument))
            {
                var dict = fastBinaryJSON.BJSON.Parse(data);

                doc = new BsonDocument((Dictionary <string, object>)dict);
            }
            else
            {
                doc = fastBinaryJSON.BJSON.ToObject <T>(data);
            }

            SetIdValue(doc, key.Value);

            return((T)doc);
        }
Пример #8
0
        /// <summary>
        /// Insert a new node index inside a index. Use skip list
        /// </summary>
        public IndexNode AddNode(CollectionIndex index, object value)
        {
            // create persist value - used on key
            var key = new IndexKey(value);

            var level = this.FlipCoin();

            // creating a new index node
            var node = new IndexNode(level)
            {
                Key = key
            };

            // get a free page to insert my index node
            var page = _pager.GetFreePage <IndexPage>(index.FreeIndexPageID, node.Length);

            node.Position = new PageAddress(page.PageID, page.Nodes.NextIndex());
            node.Page     = page;

            // add index node to page
            page.Nodes.Add(node.Position.Index, node);

            // now, let's link my index node on right place
            var cur = this.GetNode(index.HeadNode);

            // scan from top left
            for (int i = IndexNode.MAX_LEVEL_LENGTH - 1; i >= 0; i--)
            {
                // for(; <while_not_this>; <do_this>) { ... }
                for (; cur.Next[i].IsEmpty == false; cur = this.GetNode(cur.Next[i]))
                {
                    // read next node to compare
                    var diff = this.GetNode(cur.Next[i]).Key.CompareTo(key);

                    // if unique and diff = 0, throw index exception (must rollback transaction - others nodes can be dirty)
                    if (diff == 0 && index.Unique)
                    {
                        throw new LiteException(string.Format("Cannot insert duplicate key in unique index '{0}'. The duplicate value is '{1}'.", index.Field, value));
                    }

                    if (diff == 1)
                    {
                        break;
                    }
                }

                if (i <= (level - 1)) // level == length
                {
                    // cur = current (imediatte before - prev)
                    // node = new inserted node
                    // next = next node (where cur is poiting)

                    node.Next[i] = cur.Next[i];
                    node.Prev[i] = cur.Position;
                    cur.Next[i]  = node.Position;

                    var next = this.GetNode(node.Next[i]);

                    if (next != null)
                    {
                        next.Prev[i] = node.Position;

                        next.Page.IsDirty = true;
                    }

                    cur.Page.IsDirty = true;
                }
            }

            // add/remove indexPage on freelist if has space
            _pager.AddOrRemoveToFreeList(page.FreeBytes > IndexPage.RESERVED_BYTES, page, index.Page, ref index.FreeIndexPageID);

            page.IsDirty = true;

            return(node);
        }
Пример #9
0
 public static string Dump(this IndexKey value)
 {
     return(string.Format("{0}{1}{0}", value.Type == IndexDataType.String ? "'" : "", value.ToString()));
 }
Пример #10
0
        public static void Write(this BinaryWriter writer, IndexKey obj)
        {
            writer.Write((byte)obj.Type);

            // int
            if (obj.Type == IndexDataType.Byte)
            {
                writer.Write((Byte)obj.Value);
            }
            else if (obj.Type == IndexDataType.Int16)
            {
                writer.Write((Int16)obj.Value);
            }
            else if (obj.Type == IndexDataType.UInt16)
            {
                writer.Write((UInt16)obj.Value);
            }
            else if (obj.Type == IndexDataType.Int32)
            {
                writer.Write((Int32)obj.Value);
            }
            else if (obj.Type == IndexDataType.UInt32)
            {
                writer.Write((UInt32)obj.Value);
            }
            else if (obj.Type == IndexDataType.Int64)
            {
                writer.Write((Int64)obj.Value);
            }
            else if (obj.Type == IndexDataType.UInt64)
            {
                writer.Write((UInt64)obj.Value);
            }

            // decimal
            else if (obj.Type == IndexDataType.Single)
            {
                writer.Write((Single)obj.Value);
            }
            else if (obj.Type == IndexDataType.Double)
            {
                writer.Write((Double)obj.Value);
            }
            else if (obj.Type == IndexDataType.Decimal)
            {
                writer.Write((Decimal)obj.Value);
            }

            // string
            else if (obj.Type == IndexDataType.String)
            {
                var length = (byte)Encoding.UTF8.GetByteCount((String)obj.Value);
                writer.Write(length);
                writer.Write((String)obj.Value, length);
            }

            // other
            else if (obj.Type == IndexDataType.Boolean)
            {
                writer.Write((Boolean)obj.Value);
            }
            else if (obj.Type == IndexDataType.DateTime)
            {
                writer.Write((DateTime)obj.Value);
            }
            else if (obj.Type == IndexDataType.Guid)
            {
                writer.Write((Guid)obj.Value);
            }

            // otherwise is null
        }