예제 #1
0
파일: Analyze.cs 프로젝트: mercan01/LiteDB
        /// <summary>
        /// Analyze collection indexes to update UniqueKey counter. If collections parameter are null, analyze all collections
        /// </summary>
        public int Analyze(string[] collections)
        {
            // collection analyze is possible only in exclusive transaction for this
            if (_locker.IsInTransaction)
            {
                throw LiteException.AlreadyExistsTransaction();
            }

            var cols  = collections == null || collections.Length == 0 ? _header.GetCollections().Select(x => x.Key).ToArray() : collections;
            var count = 0;

            foreach (var collection in cols)
            {
                // counters for indexes
                var keyCount       = new Dictionary <string, uint>();
                var keyUniqueCount = new Dictionary <string, uint>();

                // create one transaction per colection to avoid lock all database
                this.AutoTransaction(transaction =>
                {
                    // first, get read-only snapshot
                    var snapshot = transaction.CreateSnapshot(LockMode.Read, collection, false);

                    // do not use "col" local variable because `WriteMode()` clear _collectionPage instance
                    if (snapshot.CollectionPage == null)
                    {
                        return(0);
                    }

                    var indexer = new IndexService(snapshot);
                    var indexes = snapshot.CollectionPage.GetCollectionIndexes().ToArray();

                    foreach (var index in indexes)
                    {
                        var last          = BsonValue.MinValue;
                        var counter       = 0u;
                        var uniqueCounter = 0u;

                        foreach (var node in indexer.FindAll(index, LiteDB.Query.Ascending))
                        {
                            counter++;
                            uniqueCounter += node.Key == last ? 0u : 1u;
                            last           = node.Key;
                        }

                        keyCount[index.Name]       = counter;
                        keyUniqueCount[index.Name] = uniqueCounter;
                    }

                    // after do all analyze, update snapshot to write mode
                    snapshot = transaction.CreateSnapshot(LockMode.Write, collection, false);

                    foreach (var name in indexes.Select(x => x.Name))
                    {
                        // will get index and set as dirty
                        var index = snapshot.CollectionPage.UpdateCollectionIndex(name);

                        index.KeyCount       = keyCount[index.Name];
                        index.UniqueKeyCount = keyUniqueCount[index.Name];
                    }

                    snapshot.CollectionPage.LastAnalyzed = DateTime.Now;

                    snapshot.CollectionPage.IsDirty = true;

                    return(++count);
                });
            }

            return(count);
        }
예제 #2
0
        /// <summary>
        /// Delete current collection and all pages - this snapshot can't be used after this
        /// </summary>
        public void DropCollection(Action safePoint)
        {
            var indexer = new IndexService(this, _header.Pragmas.Collation);

            // CollectionPage will be last deleted page (there is no NextPageID from CollectionPage)
            _transPages.FirstDeletedPageID = _collectionPage.PageID;
            _transPages.LastDeletedPageID  = _collectionPage.PageID;

            // mark collection page as empty
            _collectionPage.MarkAsEmtpy();

            _transPages.DeletedPages = 1;

            var indexPages = new HashSet <uint>();

            // getting all indexes pages from all indexes
            foreach (var index in _collectionPage.GetCollectionIndexes())
            {
                // add head/tail (same page) to be deleted
                indexPages.Add(index.Head.PageID);

                foreach (var node in indexer.FindAll(index, Query.Ascending))
                {
                    indexPages.Add(node.Page.PageID);

                    safePoint();
                }
            }

            // now, mark all pages as deleted
            foreach (var pageID in indexPages)
            {
                var page = this.GetPage <IndexPage>(pageID);

                // mark page as delete and fix deleted page list
                page.MarkAsEmtpy();

                page.NextPageID = _transPages.FirstDeletedPageID;
                _transPages.FirstDeletedPageID = page.PageID;

                _transPages.DeletedPages++;

                safePoint();
            }

            // adding all data pages
            foreach (var startPageID in _collectionPage.FreeDataPageList)
            {
                var next = startPageID;

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

                    next = page.NextPageID;

                    // mark page as delete and fix deleted page list
                    page.MarkAsEmtpy();

                    page.NextPageID = _transPages.FirstDeletedPageID;
                    _transPages.FirstDeletedPageID = page.PageID;

                    _transPages.DeletedPages++;

                    safePoint();
                }
            }

            // remove collection name (in header) at commit time
            _transPages.Commit += (h) => h.DeleteCollection(_collectionName);
        }
예제 #3
0
 private IEnumerable <IndexNode> ExecuteLike(IndexService indexer, CollectionIndex index)
 {
     return(indexer
            .FindAll(index, this.Order)
            .Where(x => x.Key.IsString && x.Key.AsString.SqlLike(_pattern, indexer.Collation)));
 }