Example #1
0
        /// <summary>
        /// Read all documents from current collection with NO index use - read direct from free lists
        /// There is no document order
        /// </summary>
        public IEnumerable <BsonDocument> GetDocuments(string collection)
        {
            var colPage = this.ReadPage <CollectionPage>(_collections[collection]);

            for (var slot = 0; slot < PAGE_FREE_LIST_SLOTS; slot++)
            {
                var next = colPage.FreeDataPageList[slot];

                while (next != uint.MaxValue)
                {
                    var page = this.ReadPage <DataPage>(next);

                    foreach (var block in page.GetBlocks(true))
                    {
                        using (var r = new BufferReader(this.ReadBlocks(block)))
                        {
                            var doc = r.ReadDocument(null);

                            yield return(doc);
                        }
                    }

                    next = page.NextPageID;
                }
            }
        }
Example #2
0
        /// <summary>
        /// Load page content based on page buffer
        /// </summary>
        public void LoadPage()
        {
            // check database file format
            var info = _buffer.ReadString(P_HEADER_INFO, HEADER_INFO.Length);
            var ver  = _buffer[P_FILE_VERSION];

            if (string.CompareOrdinal(info, HEADER_INFO) != 0 || ver != FILE_VERSION)
            {
                throw LiteException.InvalidDatabase();
            }

            // CreateTime is readonly
            this.FreeEmptyPageList = _buffer.ReadUInt32(P_FREE_EMPTY_PAGE_ID);
            this.LastPageID        = _buffer.ReadUInt32(P_LAST_PAGE_ID);

            // initialize engine pragmas
            this.Pragmas = new EnginePragmas(_buffer, this);

            // create new buffer area to store BsonDocument collections
            var area = _buffer.Slice(P_COLLECTIONS, COLLECTIONS_SIZE);

            using (var r = new BufferReader(new[] { area }, false))
            {
                _collections = r.ReadDocument();
            }

            _isCollectionsChanged = false;
        }
Example #3
0
        public virtual BsonDocument Load(PageAddress rawId)
        {
            using (var reader = new BufferReader(_data.Read(rawId), _utcDate))
            {
                var doc = reader.ReadDocument(_fields);

                doc.RawId = rawId;

                return(doc);
            }
        }
Example #4
0
        /// <summary>
        /// Check for all document and deserialize to test if ok (use PK index)
        /// </summary>
        public int VerifyDocuments()
        {
            return(this.AutoTransaction(transaction =>
            {
                var counter = 0;

                foreach (var col in _header.GetCollections())
                {
                    var snapshot = transaction.CreateSnapshot(LockMode.Read, col.Key, false);
                    var data = new DataService(snapshot);

                    for (var slot = 0; slot < CollectionPage.PAGE_FREE_LIST_SLOTS; slot++)
                    {
                        var next = snapshot.CollectionPage.FreeDataPageID[slot];

                        while (next != uint.MaxValue)
                        {
                            var page = snapshot.GetPage <DataPage>(next);

                            foreach (var block in page.GetBlocks(true))
                            {
                                using (var r = new BufferReader(data.Read(block)))
                                {
                                    var doc = r.ReadDocument();

                                    counter++;
                                }
                            }

                            next = page.NextPageID;
                            transaction.Safepoint();
                        }
                    }
                }

                return counter;
            }));
        }
Example #5
0
        /// <summary>
        /// Read all documents from current collection with NO index use - read direct from free lists
        /// There is no document order
        /// </summary>
        public IEnumerable <BsonDocument> ReadAll(HashSet <string> fields = null)
        {
            for (var slot = 0; slot < CollectionPage.PAGE_FREE_LIST_SLOTS; slot++)
            {
                var next = _snapshot.CollectionPage.FreeDataPageID[slot];

                while (next != uint.MaxValue)
                {
                    var page = _snapshot.GetPage <DataPage>(next);

                    foreach (var block in page.GetBlocks(true))
                    {
                        using (var r = new BufferReader(this.Read(block)))
                        {
                            var doc = r.ReadDocument(fields);

                            yield return(doc);
                        }
                    }

                    next = page.NextPageID;
                }
            }
        }
Example #6
0
        /// <summary>
        /// Create a new index (or do nothing if already exists) to a collection/field
        /// </summary>
        public bool EnsureIndex(string collection, string name, BsonExpression expression, bool unique)
        {
            if (collection.IsNullOrWhiteSpace())
            {
                throw new ArgumentNullException(nameof(collection));
            }
            if (name.IsNullOrWhiteSpace())
            {
                throw new ArgumentNullException(nameof(name));
            }
            if (expression == null)
            {
                throw new ArgumentNullException(nameof(expression));
            }
            if (expression.IsIndexable == false)
            {
                throw new ArgumentException("Index expressions must contains at least one document field. Used methods must be immutable. Parameters are not supported.", nameof(expression));
            }

            if (name.Length > INDEX_NAME_MAX_LENGTH)
            {
                throw LiteException.InvalidIndexName(name, collection, "MaxLength = " + INDEX_NAME_MAX_LENGTH);
            }
            if (!name.IsWord())
            {
                throw LiteException.InvalidIndexName(name, collection, "Use only [a-Z$_]");
            }
            if (name.StartsWith("$"))
            {
                throw LiteException.InvalidIndexName(name, collection, "Index name can't starts with `$`");
            }

            if (name == "_id")
            {
                return(false);               // always exists
            }
            return(this.AutoTransaction(transaction =>
            {
                var snapshot = transaction.CreateSnapshot(LockMode.Write, collection, true);
                var col = snapshot.CollectionPage;
                var indexer = new IndexService(snapshot);
                var data = new DataService(snapshot);

                // check if index already exists
                var current = col.GetCollectionIndex(name);

                // if already exists, just exit
                if (current != null)
                {
                    // but if expression are different, throw error
                    if (current.Expression != expression.Source)
                    {
                        throw LiteException.IndexAlreadyExist(name);
                    }

                    return false;
                }

                LOG($"create index `{collection}.{name}`", "COMMAND");

                // create index head
                var index = indexer.CreateIndex(name, expression.Source, unique);
                var count = 0u;

                // read all objects (read from PK index)
                foreach (var pkNode in new IndexAll("_id", LiteDB.Query.Ascending).Run(col, indexer))
                {
                    using (var reader = new BufferReader(data.Read(pkNode.DataBlock)))
                    {
                        var doc = reader.ReadDocument(expression.Fields);

                        // first/last node in this document that will be added
                        IndexNode last = null;
                        IndexNode first = null;

                        // get values from expression in document
                        var keys = expression.Execute(doc);

                        // adding index node for each value
                        foreach (var key in keys)
                        {
                            // when index key is an array, get items inside array.
                            // valid only for first level (if this items are another array, this arrays will be indexed as array)
                            if (key.IsArray)
                            {
                                var arr = key.AsArray;

                                foreach (var itemKey in arr)
                                {
                                    // insert new index node
                                    var node = indexer.AddNode(index, itemKey, pkNode.DataBlock, last, _flipCoin);

                                    if (first == null)
                                    {
                                        first = node;
                                    }

                                    last = node;

                                    count++;
                                }
                            }
                            else
                            {
                                // insert new index node
                                var node = indexer.AddNode(index, key, pkNode.DataBlock, last, _flipCoin);

                                if (first == null)
                                {
                                    first = node;
                                }

                                last = node;

                                count++;
                            }
                        }

                        // fix single linked-list in pkNode
                        if (first != null)
                        {
                            last.SetNextNode(pkNode.NextNode);
                            pkNode.SetNextNode(first.Position);
                        }
                    }

                    transaction.Safepoint();
                }

                index.KeyCount = count;

                return true;
            }));
        }