TaxonomyWriter which uses a Directory to store the taxonomy information on disk, and keeps an additional in-memory cache of some or all categories.

In addition to the permanently-stored information in the Directory, efficiency dictates that we also keep an in-memory cache of recently seen or all categories, so that we do not need to go back to disk for every category addition to see which ordinal this category already has, if any. A TaxonomyWriterCache object determines the specific caching algorithm used.

This class offers some hooks for extending classes to control the IndexWriter instance that is used. See #openIndexWriter. @lucene.experimental

상속: TaxonomyWriter
예제 #1
0
 public ThreadAnonymousInnerClassHelper(TestAddTaxonomy outerInstance, int range, AtomicInteger numCats, DirectoryTaxonomyWriter tw)
 {
     this.outerInstance = outerInstance;
     this.range = range;
     this.numCats = numCats;
     this.tw = tw;
 }
예제 #2
0
        private void Dotest(int ncats, int range)
        {
            AtomicInteger numCats = new AtomicInteger(ncats);
            Directory[] dirs = new Directory[2];
            for (int i = 0; i < dirs.Length; i++)
            {
                dirs[i] = NewDirectory();
                var tw = new DirectoryTaxonomyWriter(dirs[i]);
                ThreadClass[] addThreads = new ThreadClass[4];
                for (int j = 0; j < addThreads.Length; j++)
                {
                    addThreads[j] = new ThreadAnonymousInnerClassHelper(this, range, numCats, tw);
                }

                foreach (ThreadClass t in addThreads)
                {
                    t.Start();
                }
                foreach (ThreadClass t in addThreads)
                {
                    t.Join();
                }

                tw.Dispose();
            }

            var tw1 = new DirectoryTaxonomyWriter(dirs[0]);
            IOrdinalMap map = randomOrdinalMap();
            tw1.AddTaxonomy(dirs[1], map);
            tw1.Dispose();

            validate(dirs[0], dirs[1], map);

            IOUtils.Close(dirs);
        }
        /// <summary>
        /// Called only from <seealso cref="#doOpenIfChanged()"/>. If the taxonomy has been
        /// recreated, you should pass {@code null} as the caches and parent/children
        /// arrays.
        /// </summary>
        internal DirectoryTaxonomyReader(DirectoryReader indexReader, DirectoryTaxonomyWriter taxoWriter, LRUHashMap<FacetLabel, IntClass> ordinalCache, LRUHashMap<int, FacetLabel> categoryCache, TaxonomyIndexArrays taxoArrays)
        {
            this.indexReader = indexReader;
            this.taxoWriter = taxoWriter;
            this.taxoEpoch = taxoWriter == null ? -1 : taxoWriter.TaxonomyEpoch;

            // use the same instance of the cache, note the protective code in getOrdinal and getPath
            this.ordinalCache = ordinalCache == null ? new LRUHashMap<FacetLabel, IntClass>(DEFAULT_CACHE_VALUE) : ordinalCache;
            this.categoryCache = categoryCache == null ? new LRUHashMap<int, FacetLabel>(DEFAULT_CACHE_VALUE) : categoryCache;

            this.taxoArrays = taxoArrays != null ? new TaxonomyIndexArrays(indexReader, taxoArrays) : null;
        }
        public virtual void TestCloseAfterIncRef()
        {
            Directory dir = NewDirectory();
            var ltw = new DirectoryTaxonomyWriter(dir);
            ltw.AddCategory(new FacetLabel("a"));
            ltw.Dispose();

            DirectoryTaxonomyReader ltr = new DirectoryTaxonomyReader(dir);
            ltr.IncRef();
            ltr.Dispose();

            // should not fail as we IncRef() before close
            var tmpSie = ltr.Size;
            ltr.DecRef();

            dir.Dispose();
        }
        public virtual void TestCloseNoEmptyCommits()
        {
            // LUCENE-4972: DTW used to create empty commits even if no changes were made
            Directory dir = NewDirectory();
            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(dir);

            taxoWriter.AddCategory(new FacetLabel("a"));
            taxoWriter.Commit();

            long gen1 = SegmentInfos.GetLastCommitGeneration(dir);

            taxoWriter.Dispose();
            long gen2 = SegmentInfos.GetLastCommitGeneration(dir);

            Assert.AreEqual(gen1, gen2, "empty commit should not have changed the index");

            taxoWriter.Dispose();
            dir.Dispose();
        }
예제 #6
0
        public virtual void TestAddToEmpty()
        {
            Directory dest = NewDirectory();

            Directory src = NewDirectory();
            DirectoryTaxonomyWriter srcTW = new DirectoryTaxonomyWriter(src);
            srcTW.AddCategory(new FacetLabel("Author", "Rob Pike"));
            srcTW.AddCategory(new FacetLabel("Aardvarks", "Bob"));
            srcTW.Dispose();

            DirectoryTaxonomyWriter destTW = new DirectoryTaxonomyWriter(dest);
            OrdinalMap map = randomOrdinalMap();
            destTW.AddTaxonomy(src, map);
            destTW.Dispose();

            validate(dest, src, map);

            IOUtils.Close(dest, src);
        }
        public virtual void TestBackwardsCompatibility()
        {
            // tests that if the taxonomy index doesn't have the INDEX_EPOCH
            // property (supports pre-3.6 indexes), all still works.
            Directory dir = NewDirectory();

            // create an empty index first, so that DirTaxoWriter initializes indexEpoch to 1.
            (new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, null))).Dispose();

            var taxoWriter = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE_OR_APPEND, NO_OP_CACHE);
            taxoWriter.Dispose();

            var taxoReader = new DirectoryTaxonomyReader(dir);
            Assert.AreEqual(1, Convert.ToInt32(taxoReader.CommitUserData[DirectoryTaxonomyWriter.INDEX_EPOCH]));
            Assert.Null(TaxonomyReader.OpenIfChanged(taxoReader));
            (taxoReader).Dispose();

            dir.Dispose();
        }
예제 #8
0
        public virtual void TestOpenIfChangedReuseAfterRecreate()
        {
            // tests that if the taxonomy is recreated, no data is reused from the previous taxonomy
            Directory dir = NewDirectory();
            DirectoryTaxonomyWriter writer = new DirectoryTaxonomyWriter(dir);
            FacetLabel cp_a = new FacetLabel("a");

            writer.AddCategory(cp_a);
            writer.Dispose();

            DirectoryTaxonomyReader r1 = new DirectoryTaxonomyReader(dir);

            // fill r1's caches
            Assert.AreEqual(1, r1.GetOrdinal(cp_a));
            Assert.AreEqual(cp_a, r1.GetPath(1));

            // now recreate, add a different category
            writer = new DirectoryTaxonomyWriter(dir, IndexWriterConfig.OpenMode_e.CREATE);
            FacetLabel cp_b = new FacetLabel("b");

            writer.AddCategory(cp_b);
            writer.Dispose();

            DirectoryTaxonomyReader r2 = TaxonomyReader.OpenIfChanged(r1);

            Assert.NotNull(r2);

            // fill r2's caches
            Assert.AreEqual(1, r2.GetOrdinal(cp_b));
            Assert.AreEqual(cp_b, r2.GetPath(1));

            // check that r1 doesn't see cp_b
            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, r1.GetOrdinal(cp_b));
            Assert.AreEqual(cp_a, r1.GetPath(1));

            // check that r2 doesn't see cp_a
            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, r2.GetOrdinal(cp_a));
            Assert.AreEqual(cp_b, r2.GetPath(1));

            (r2).Dispose();
            (r1).Dispose();
            dir.Dispose();
        }
예제 #9
0
        public virtual void TestCloseAfterIncRef()
        {
            Directory dir = NewDirectory();
            var       ltw = new DirectoryTaxonomyWriter(dir);

            ltw.AddCategory(new FacetLabel("a"));
            ltw.Dispose();

            DirectoryTaxonomyReader ltr = new DirectoryTaxonomyReader(dir);

            ltr.IncRef();
            ltr.Dispose();

            // should not fail as we IncRef() before close
            var _ = ltr.Count;

            ltr.DecRef();

            dir.Dispose();
        }
        public virtual void TestRollback()
        {
            // Verifies that if rollback is called, DTW is closed.
            Directory dir = NewDirectory();
            var       dtw = new DirectoryTaxonomyWriter(dir);

            dtw.AddCategory(new FacetLabel("a"));
            dtw.Rollback();
            try
            {
                dtw.AddCategory(new FacetLabel("a"));
                Fail("should not have succeeded to add a category following rollback.");
            }
            catch (AlreadyClosedException)
            {
                // expected
            }

            dir.Dispose();
        }
        public virtual void TestAlreadyClosed()
        {
            Directory dir = NewDirectory();
            var ltw = new DirectoryTaxonomyWriter(dir);
            ltw.AddCategory(new FacetLabel("a"));
            ltw.Dispose();

            var ltr = new DirectoryTaxonomyReader(dir);
            ltr.Dispose();
            try
            {
                var tmpSize = ltr.Size;
                Fail("An AlreadyClosedException should have been thrown here");
            }
            catch (AlreadyClosedException)
            {
                // good!
            }
            dir.Dispose();
        }
        public virtual void TestReplaceTaxonomy()
        {
            Directory input      = NewDirectory();
            var       taxoWriter = new DirectoryTaxonomyWriter(input);
            int       ordA       = taxoWriter.AddCategory(new FacetLabel("a"));

            taxoWriter.Dispose();

            Directory dir = NewDirectory();

            taxoWriter = new DirectoryTaxonomyWriter(dir);
            int ordB = taxoWriter.AddCategory(new FacetLabel("b"));

            taxoWriter.AddCategory(new FacetLabel("c"));
            taxoWriter.Commit();

            long origEpoch = getEpoch(dir);

            // replace the taxonomy with the input one
            taxoWriter.ReplaceTaxonomy(input);

            // LUCENE-4633: make sure that category "a" is not added again in any case
            taxoWriter.AddTaxonomy(input, new MemoryOrdinalMap());
            Assert.AreEqual(2, taxoWriter.Size, "no categories should have been added"); // root + 'a'
            Assert.AreEqual(ordA, taxoWriter.AddCategory(new FacetLabel("a")), "category 'a' received new ordinal?");

            // add the same category again -- it should not receive the same ordinal !
            int newOrdB = taxoWriter.AddCategory(new FacetLabel("b"));

            Assert.AreNotSame(ordB, newOrdB, "new ordinal cannot be the original ordinal");
            Assert.AreEqual(2, newOrdB, "ordinal should have been 2 since only one category was added by replaceTaxonomy");

            taxoWriter.Dispose();

            long newEpoch = getEpoch(dir);

            Assert.True(origEpoch < newEpoch, "index epoch should have been updated after replaceTaxonomy");

            dir.Dispose();
            input.Dispose();
        }
        public virtual void TestBackwardsCompatibility()
        {
            // tests that if the taxonomy index doesn't have the INDEX_EPOCH
            // property (supports pre-3.6 indexes), all still works.
            Directory dir = NewDirectory();

            // create an empty index first, so that DirTaxoWriter initializes indexEpoch to 1.
            (new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, null))).Dispose();

            var taxoWriter = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE_OR_APPEND, NO_OP_CACHE);

            taxoWriter.Dispose();

            var taxoReader = new DirectoryTaxonomyReader(dir);

            Assert.AreEqual(1, Convert.ToInt32(taxoReader.CommitUserData[DirectoryTaxonomyWriter.INDEX_EPOCH]));
            Assert.Null(TaxonomyReader.OpenIfChanged(taxoReader));
            (taxoReader).Dispose();

            dir.Dispose();
        }
예제 #14
0
        public virtual void TestAddToEmpty()
        {
            Directory dest = NewDirectory();

            Directory src = NewDirectory();
            DirectoryTaxonomyWriter srcTW = new DirectoryTaxonomyWriter(src);

            srcTW.AddCategory(new FacetLabel("Author", "Rob Pike"));
            srcTW.AddCategory(new FacetLabel("Aardvarks", "Bob"));
            srcTW.Dispose();

            DirectoryTaxonomyWriter destTW = new DirectoryTaxonomyWriter(dest);
            IOrdinalMap             map    = randomOrdinalMap();

            destTW.AddTaxonomy(src, map);
            destTW.Dispose();

            validate(dest, src, map);

            IOUtils.Dispose(dest, src);
        }
        public virtual void TestRecreateAndRefresh()
        {
            // DirTaxoWriter lost the INDEX_EPOCH property if it was opened in
            // CREATE_OR_APPEND (or commit(userData) called twice), which could lead to
            // DirTaxoReader succeeding to refresh().
            Directory dir = NewDirectory();

            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE_OR_APPEND, NO_OP_CACHE);

            TouchTaxo(taxoWriter, new FacetLabel("a"));

            var taxoReader = new DirectoryTaxonomyReader(dir);

            TouchTaxo(taxoWriter, new FacetLabel("b"));

            var newtr = TaxonomyReader.OpenIfChanged(taxoReader);

            taxoReader.Dispose();
            taxoReader = newtr;
            Assert.AreEqual(1, Convert.ToInt32(taxoReader.CommitUserData[DirectoryTaxonomyWriter.INDEX_EPOCH]));

            // now recreate the taxonomy, and check that the epoch is preserved after opening DirTW again.
            taxoWriter.Dispose();
            taxoWriter = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE, NO_OP_CACHE);
            TouchTaxo(taxoWriter, new FacetLabel("c"));
            taxoWriter.Dispose();

            taxoWriter = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE_OR_APPEND, NO_OP_CACHE);
            TouchTaxo(taxoWriter, new FacetLabel("d"));
            taxoWriter.Dispose();

            newtr = TaxonomyReader.OpenIfChanged(taxoReader);
            taxoReader.Dispose();
            taxoReader = newtr;
            Assert.AreEqual(2, Convert.ToInt32(taxoReader.CommitUserData[DirectoryTaxonomyWriter.INDEX_EPOCH]));

            taxoReader.Dispose();
            dir.Dispose();
        }
예제 #16
0
        public virtual void TestAlreadyClosed()
        {
            Directory dir = NewDirectory();
            var       ltw = new DirectoryTaxonomyWriter(dir);

            ltw.AddCategory(new FacetLabel("a"));
            ltw.Dispose();

            var ltr = new DirectoryTaxonomyReader(dir);

            ltr.Dispose();
            try
            {
                var _ = ltr.Count;
                fail("An ObjectDisposedException should have been thrown here");
            }
            catch (ObjectDisposedException)
            {
                // good!
            }
            dir.Dispose();
        }
예제 #17
0
        private void Dotest(int ncats, int range)
        {
            AtomicInt32 numCats = new AtomicInt32(ncats);

            Directory[] dirs = new Directory[2];
            for (int i = 0; i < dirs.Length; i++)
            {
                dirs[i] = NewDirectory();
                var         tw         = new DirectoryTaxonomyWriter(dirs[i]);
                ThreadJob[] addThreads = new ThreadJob[4];
                for (int j = 0; j < addThreads.Length; j++)
                {
                    addThreads[j] = new ThreadAnonymousInnerClassHelper(this, range, numCats, tw);
                }

                foreach (ThreadJob t in addThreads)
                {
                    t.Start();
                }
                foreach (ThreadJob t in addThreads)
                {
                    t.Join();
                }

                tw.Dispose();
            }

            var         tw1 = new DirectoryTaxonomyWriter(dirs[0]);
            IOrdinalMap map = randomOrdinalMap();

            tw1.AddTaxonomy(dirs[1], map);
            tw1.Dispose();

            validate(dirs[0], dirs[1], map);

            IOUtils.Dispose(dirs);
        }
        public virtual void TestReplaceTaxoWithLargeTaxonomy()
        {
            var srcTaxoDir    = NewDirectory();
            var targetTaxoDir = NewDirectory();

            // build source, large, taxonomy
            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(srcTaxoDir);
            int ord = taxoWriter.AddCategory(new FacetLabel("A", "1", "1", "1", "1", "1", "1"));

            taxoWriter.Dispose();

            taxoWriter = new DirectoryTaxonomyWriter(targetTaxoDir);
            int ordinal = taxoWriter.AddCategory(new FacetLabel("B", "1"));

            Assert.AreEqual(1, taxoWriter.GetParent(ordinal)); // call getParent to initialize taxoArrays
            taxoWriter.Commit();

            taxoWriter.ReplaceTaxonomy(srcTaxoDir);
            Assert.AreEqual(ord - 1, taxoWriter.GetParent(ord));
            taxoWriter.Dispose();

            srcTaxoDir.Dispose();
            targetTaxoDir.Dispose();
        }
        public virtual void TestOpenIfChangedReuseAfterRecreate()
        {
            // tests that if the taxonomy is recreated, no data is reused from the previous taxonomy
            Directory dir = NewDirectory();
            DirectoryTaxonomyWriter writer = new DirectoryTaxonomyWriter(dir);
            FacetLabel cp_a = new FacetLabel("a");
            writer.AddCategory(cp_a);
            writer.Dispose();

            DirectoryTaxonomyReader r1 = new DirectoryTaxonomyReader(dir);
            // fill r1's caches
            Assert.AreEqual(1, r1.GetOrdinal(cp_a));
            Assert.AreEqual(cp_a, r1.GetPath(1));

            // now recreate, add a different category
            writer = new DirectoryTaxonomyWriter(dir, IndexWriterConfig.OpenMode_e.CREATE);
            FacetLabel cp_b = new FacetLabel("b");
            writer.AddCategory(cp_b);
            writer.Dispose();

            DirectoryTaxonomyReader r2 = TaxonomyReader.OpenIfChanged(r1);
            Assert.NotNull(r2);

            // fill r2's caches
            Assert.AreEqual(1, r2.GetOrdinal(cp_b));
            Assert.AreEqual(cp_b, r2.GetPath(1));

            // check that r1 doesn't see cp_b
            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, r1.GetOrdinal(cp_b));
            Assert.AreEqual(cp_a, r1.GetPath(1));

            // check that r2 doesn't see cp_a
            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, r2.GetOrdinal(cp_a));
            Assert.AreEqual(cp_b, r2.GetPath(1));

            (r2).Dispose();
            (r1).Dispose();
            dir.Dispose();
        }
예제 #20
0
        public virtual void TestConcurrency()
        {
            // tests that addTaxonomy and addCategory work in parallel
            int numCategories = AtLeast(10000);

            // build an input taxonomy index
            Directory src = NewDirectory();
            var tw = new DirectoryTaxonomyWriter(src);
            for (int i = 0; i < numCategories; i++)
            {
                tw.AddCategory(new FacetLabel("a", Convert.ToString(i)));
            }
            tw.Dispose();

            // now add the taxonomy to an empty taxonomy, while adding the categories
            // again, in parallel -- in the end, no duplicate categories should exist.
            Directory dest = NewDirectory();
            var destTw = new DirectoryTaxonomyWriter(dest);
            ThreadClass t = new ThreadAnonymousInnerClassHelper2(this, numCategories, destTw);
            t.Start();

            OrdinalMap map = new MemoryOrdinalMap();
            destTw.AddTaxonomy(src, map);
            t.Join();
            destTw.Dispose();

            // now validate

            var dtr = new DirectoryTaxonomyReader(dest);
            // +2 to account for the root category + "a"
            Assert.AreEqual(numCategories + 2, dtr.Size);
            var categories = new HashSet<FacetLabel>();
            for (int i = 1; i < dtr.Size; i++)
            {
                FacetLabel cat = dtr.GetPath(i);
                Assert.True(categories.Add(cat), "category " + cat + " already existed");
            }
            dtr.Dispose();

            IOUtils.Close(src, dest);
        }
예제 #21
0
        public virtual void TestSimple()
        {
            Directory dest = NewDirectory();
            var tw1 = new DirectoryTaxonomyWriter(dest);
            tw1.AddCategory(new FacetLabel("Author", "Mark Twain"));
            tw1.AddCategory(new FacetLabel("Animals", "Dog"));
            tw1.AddCategory(new FacetLabel("Author", "Rob Pike"));

            Directory src = NewDirectory();
            var tw2 = new DirectoryTaxonomyWriter(src);
            tw2.AddCategory(new FacetLabel("Author", "Rob Pike"));
            tw2.AddCategory(new FacetLabel("Aardvarks", "Bob"));
            tw2.Dispose();

            OrdinalMap map = randomOrdinalMap();

            tw1.AddTaxonomy(src, map);
            tw1.Dispose();

            validate(dest, src, map);

            IOUtils.Close(dest, src);
        }
예제 #22
0
 public ThreadAnonymousInnerClassHelper(TestConcurrentFacetedIndexing outerInstance, AtomicInt32 numDocs, ConcurrentDictionary <string, string> values, IndexWriter iw, DirectoryTaxonomyWriter tw, FacetsConfig config)
 {
     this.outerInstance = outerInstance;
     this.numDocs       = numDocs;
     this.values        = values;
     this.iw            = iw;
     this.tw            = tw;
     this.config        = config;
 }
예제 #23
0
        /// <summary>
        /// Open for reading a taxonomy stored in a given <seealso cref="Directory"/>.
        /// </summary>
        /// <param name="directory">
        ///          The <seealso cref="Directory"/> in which the taxonomy resides. </param>
        /// <exception cref="CorruptIndexException">
        ///           if the Taxonomy is corrupt. </exception>
        /// <exception cref="IOException">
        ///           if another error occurred. </exception>
        public DirectoryTaxonomyReader(Directory directory)
        {
            indexReader = OpenIndexReader(directory);
            taxoWriter = null;
            taxoEpoch = -1;

            // These are the default cache sizes; they can be configured after
            // construction with the cache's setMaxSize() method

            ordinalCache = new LRUHashMap<FacetLabel, IntClass>(DEFAULT_CACHE_VALUE);
            categoryCache = new LRUHashMap<int, FacetLabel>(DEFAULT_CACHE_VALUE);
        }
예제 #24
0
        /// <summary>
        /// Opens a <seealso cref="DirectoryTaxonomyReader"/> over the given
        /// <seealso cref="DirectoryTaxonomyWriter"/> (for NRT).
        /// </summary>
        /// <param name="taxoWriter">
        ///          The <seealso cref="DirectoryTaxonomyWriter"/> from which to obtain newly
        ///          added categories, in real-time. </param>
        public DirectoryTaxonomyReader(DirectoryTaxonomyWriter taxoWriter)
        {
            this.taxoWriter = taxoWriter;
            taxoEpoch = taxoWriter.TaxonomyEpoch;
            indexReader = OpenIndexReader(taxoWriter.InternalIndexWriter);

            // These are the default cache sizes; they can be configured after
            // construction with the cache's setMaxSize() method

            ordinalCache = new LRUHashMap<FacetLabel, IntClass>(DEFAULT_CACHE_VALUE);
            categoryCache = new LRUHashMap<int, FacetLabel>(DEFAULT_CACHE_VALUE);
        }
        public virtual void TestOpenIfChangedAndRefCount()
        {
            Directory dir = new RAMDirectory(); // no need for random directories here

            var taxoWriter = new DirectoryTaxonomyWriter(dir);
            taxoWriter.AddCategory(new FacetLabel("a"));
            taxoWriter.Commit();

            var taxoReader = new DirectoryTaxonomyReader(dir);
            Assert.AreEqual(1, taxoReader.RefCount, "wrong refCount");

            taxoReader.IncRef();
            Assert.AreEqual(2, taxoReader.RefCount, "wrong refCount");

            taxoWriter.AddCategory(new FacetLabel("a", "b"));
            taxoWriter.Commit();
            var newtr = TaxonomyReader.OpenIfChanged(taxoReader);
            Assert.NotNull(newtr);
            taxoReader.Dispose();
            taxoReader = newtr;
            Assert.AreEqual(1, taxoReader.RefCount, "wrong refCount");

            taxoWriter.Dispose();
            taxoReader.Dispose();
            dir.Dispose();
        }
        public virtual void TestCloseTwice()
        {
            Directory dir = NewDirectory();
            var ltw = new DirectoryTaxonomyWriter(dir);
            ltw.AddCategory(new FacetLabel("a"));
            ltw.Dispose();

            var ltr = new DirectoryTaxonomyReader(dir);
            (ltr).Dispose();
            (ltr).Dispose(); // no exception should be thrown

            dir.Dispose();
        }
        public virtual void TestRollback()
        {
            // Verifies that if rollback is called, DTW is closed.
            Directory dir = NewDirectory();
            var dtw = new DirectoryTaxonomyWriter(dir);
            dtw.AddCategory(new FacetLabel("a"));
            dtw.Rollback();
            try
            {
                dtw.AddCategory(new FacetLabel("a"));
                Fail("should not have succeeded to add a category following rollback.");
            }
            catch (AlreadyClosedException)
            {
                // expected
            }

            dir.Dispose();
        }
        public virtual void TestOpenIfChangedReplaceTaxonomy()
        {
            // test openIfChanged when replaceTaxonomy is called, which is equivalent to recreate
            // only can work with NRT as well
            Directory src = NewDirectory();
            DirectoryTaxonomyWriter w = new DirectoryTaxonomyWriter(src);
            FacetLabel cp_b = new FacetLabel("b");
            w.AddCategory(cp_b);
            w.Dispose();

            foreach (bool nrt in new bool[] { false, true })
            {
                Directory dir = NewDirectory();
                var writer = new DirectoryTaxonomyWriter(dir);

                FacetLabel cp_a = new FacetLabel("a");
                writer.AddCategory(cp_a);
                if (!nrt)
                {
                    writer.Commit();
                }

                DirectoryTaxonomyReader r1 = nrt ? new DirectoryTaxonomyReader(writer) : new DirectoryTaxonomyReader(dir);
                // fill r1's caches
                Assert.AreEqual(1, r1.GetOrdinal(cp_a));
                Assert.AreEqual(cp_a, r1.GetPath(1));

                // now replace taxonomy
                writer.ReplaceTaxonomy(src);
                if (!nrt)
                {
                    writer.Commit();
                }

                DirectoryTaxonomyReader r2 = TaxonomyReader.OpenIfChanged(r1);
                Assert.NotNull(r2);

                // fill r2's caches
                Assert.AreEqual(1, r2.GetOrdinal(cp_b));
                Assert.AreEqual(cp_b, r2.GetPath(1));

                // check that r1 doesn't see cp_b
                Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, r1.GetOrdinal(cp_b));
                Assert.AreEqual(cp_a, r1.GetPath(1));

                // check that r2 doesn't see cp_a
                Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, r2.GetOrdinal(cp_a));
                Assert.AreEqual(cp_b, r2.GetPath(1));

                (r2).Dispose();
                (r1).Dispose();
                writer.Dispose();
                dir.Dispose();
            }

            src.Dispose();
        }
        public virtual void TestOpenIfChangedResult()
        {
            Directory dir = null;
            DirectoryTaxonomyWriter ltw = null;
            DirectoryTaxonomyReader ltr = null;

            try
            {
                dir = NewDirectory();
                ltw = new DirectoryTaxonomyWriter(dir);

                ltw.AddCategory(new FacetLabel("a"));
                ltw.Commit();

                ltr = new DirectoryTaxonomyReader(dir);
                Assert.Null(TaxonomyReader.OpenIfChanged(ltr), "Nothing has changed");

                ltw.AddCategory(new FacetLabel("b"));
                ltw.Commit();

                DirectoryTaxonomyReader newtr = TaxonomyReader.OpenIfChanged(ltr);
                Assert.NotNull(newtr, "changes were committed");
                Assert.Null(TaxonomyReader.OpenIfChanged(newtr), "Nothing has changed");
                (newtr).Dispose();
            }
            finally
            {
                IOUtils.Close(ltw, ltr, dir);
            }
        }
        private void doTestReadRecreatedTaxonomy(Random random, bool closeReader)
        {
            Directory dir = null;
            TaxonomyWriter tw = null;
            TaxonomyReader tr = null;

            // prepare a few categories
            int n = 10;
            FacetLabel[] cp = new FacetLabel[n];
            for (int i = 0; i < n; i++)
            {
                cp[i] = new FacetLabel("a", Convert.ToString(i));
            }

            try
            {
                dir = NewDirectory();

                tw = new DirectoryTaxonomyWriter(dir);
                tw.AddCategory(new FacetLabel("a"));
                tw.Dispose();

                tr = new DirectoryTaxonomyReader(dir);
                int baseNumCategories = tr.Size;

                for (int i = 0; i < n; i++)
                {
                    int k = random.Next(n);
                    tw = new DirectoryTaxonomyWriter(dir, IndexWriterConfig.OpenMode_e.CREATE);
                    for (int j = 0; j <= k; j++)
                    {
                        tw.AddCategory(cp[j]);
                    }
                    tw.Dispose();
                    if (closeReader)
                    {
                        tr.Dispose(true);
                        tr = new DirectoryTaxonomyReader(dir);
                    }
                    else
                    {
                        var newtr = TaxonomyReader.OpenIfChanged(tr);
                        Assert.NotNull(newtr);
                        tr.Dispose(true);
                        tr = newtr;
                    }
                    Assert.AreEqual(baseNumCategories + 1 + k, tr.Size, "Wrong #categories in taxonomy (i=" + i + ", k=" + k + ")");
                }
            }
            finally
            {
                IOUtils.Close(tr as DirectoryTaxonomyReader, tw, dir);
            }
        }
        public virtual void TestCommit()
        {
            // Verifies that nothing is committed to the underlying Directory, if
            // commit() wasn't called.
            Directory dir = NewDirectory();
            var ltw = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE_OR_APPEND, NO_OP_CACHE);
            Assert.False(DirectoryReader.IndexExists(dir));
            ltw.Commit(); // first commit, so that an index will be created
            ltw.AddCategory(new FacetLabel("a"));

            IndexReader r = DirectoryReader.Open(dir);
            Assert.AreEqual(1, r.NumDocs, "No categories should have been committed to the underlying directory");
            r.Dispose();
            ltw.Dispose();
            dir.Dispose();
        }
        public virtual void TestRecreateAndRefresh()
        {
            // DirTaxoWriter lost the INDEX_EPOCH property if it was opened in
            // CREATE_OR_APPEND (or commit(userData) called twice), which could lead to
            // DirTaxoReader succeeding to refresh().
            Directory dir = NewDirectory();

            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE_OR_APPEND, NO_OP_CACHE);
            TouchTaxo(taxoWriter, new FacetLabel("a"));

            var taxoReader = new DirectoryTaxonomyReader(dir);

            TouchTaxo(taxoWriter, new FacetLabel("b"));

            var newtr = TaxonomyReader.OpenIfChanged(taxoReader);
            taxoReader.Dispose();
            taxoReader = newtr;
            Assert.AreEqual(1, Convert.ToInt32(taxoReader.CommitUserData[DirectoryTaxonomyWriter.INDEX_EPOCH]));

            // now recreate the taxonomy, and check that the epoch is preserved after opening DirTW again.
            taxoWriter.Dispose();
            taxoWriter = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE, NO_OP_CACHE);
            TouchTaxo(taxoWriter, new FacetLabel("c"));
            taxoWriter.Dispose();

            taxoWriter = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE_OR_APPEND, NO_OP_CACHE);
            TouchTaxo(taxoWriter, new FacetLabel("d"));
            taxoWriter.Dispose();

            newtr = TaxonomyReader.OpenIfChanged(taxoReader);
            taxoReader.Dispose();
            taxoReader = newtr;
            Assert.AreEqual(2, Convert.ToInt32(taxoReader.CommitUserData[DirectoryTaxonomyWriter.INDEX_EPOCH]));

            taxoReader.Dispose();
            dir.Dispose();
        }
        public virtual void TestCommitUserData()
        {
            // Verifies taxonomy commit data
            Directory dir = NewDirectory();
            var taxoWriter = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE_OR_APPEND, NO_OP_CACHE);
            taxoWriter.AddCategory(new FacetLabel("a"));
            taxoWriter.AddCategory(new FacetLabel("b"));
            IDictionary<string, string> userCommitData = new Dictionary<string, string>();
            userCommitData["testing"] = "1 2 3";
            taxoWriter.CommitData = userCommitData;
            taxoWriter.Dispose();
            var r = DirectoryReader.Open(dir);
            Assert.AreEqual(3, r.NumDocs, "2 categories plus root should have been committed to the underlying directory");
            var readUserCommitData = r.IndexCommit.UserData;
            Assert.True("1 2 3".Equals(readUserCommitData["testing"]), "wrong value extracted from commit data");
            Assert.NotNull(DirectoryTaxonomyWriter.INDEX_EPOCH + " not found in commitData", readUserCommitData[DirectoryTaxonomyWriter.INDEX_EPOCH]);
            r.Dispose();

            // open DirTaxoWriter again and commit, INDEX_EPOCH should still exist
            // in the commit data, otherwise DirTaxoReader.refresh() might not detect
            // that the taxonomy index has been recreated.
            taxoWriter = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE_OR_APPEND, NO_OP_CACHE);
            taxoWriter.AddCategory(new FacetLabel("c")); // add a category so that commit will happen


            taxoWriter.CommitData = new Dictionary<string, string>()
		    {
			    {"just", "data"}
		    };
            taxoWriter.Commit();

            // verify taxoWriter.getCommitData()
            Assert.NotNull(DirectoryTaxonomyWriter.INDEX_EPOCH + " not found in taoxWriter.commitData", taxoWriter.CommitData[DirectoryTaxonomyWriter.INDEX_EPOCH]);
            taxoWriter.Dispose();

            r = DirectoryReader.Open(dir);
            readUserCommitData = r.IndexCommit.UserData;
            Assert.NotNull(DirectoryTaxonomyWriter.INDEX_EPOCH + " not found in commitData", readUserCommitData[DirectoryTaxonomyWriter.INDEX_EPOCH]);
            r.Dispose();

            dir.Dispose();
        }
        public virtual void TestConcurrency()
        {
            int ncats = AtLeast(100000); // add many categories
            int range = ncats * 3; // affects the categories selection
            AtomicInteger numCats = new AtomicInteger(ncats);
            Directory dir = NewDirectory();
            var values = new ConcurrentDictionary<string, string>();
            double d = Random().NextDouble();
            ITaxonomyWriterCache cache;
            if (d < 0.7)
            {
                // this is the fastest, yet most memory consuming
                cache = new Cl2oTaxonomyWriterCache(1024, 0.15f, 3);
            }
            else if (TEST_NIGHTLY && d > 0.98)
            {
                // this is the slowest, but tests the writer concurrency when no caching is done.
                // only pick it during NIGHTLY tests, and even then, with very low chances.
                cache = NO_OP_CACHE;
            }
            else
            {
                // this is slower than CL2O, but less memory consuming, and exercises finding categories on disk too.
                cache = new LruTaxonomyWriterCache(ncats / 10);
            }
            if (VERBOSE)
            {
                Console.WriteLine("TEST: use cache=" + cache);
            }
            var tw = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE, cache);
            ThreadClass[] addThreads = new ThreadClass[AtLeast(4)];
            for (int z = 0; z < addThreads.Length; z++)
            {
                addThreads[z] = new ThreadAnonymousInnerClassHelper(this, range, numCats, values, tw);
            }

            foreach (var t in addThreads)
            {
                t.Start();
            }
            foreach (var t in addThreads)
            {
                t.Join();
            }
            tw.Dispose();

            DirectoryTaxonomyReader dtr = new DirectoryTaxonomyReader(dir);
            // +1 for root category
            if (values.Count + 1 != dtr.Count)
            {
                foreach (string value in values.Keys)
                {
                    FacetLabel label = new FacetLabel(FacetsConfig.StringToPath(value));
                    if (dtr.GetOrdinal(label) == -1)
                    {
                        Console.WriteLine("FAIL: path=" + label + " not recognized");
                    }
                }
                Fail("mismatch number of categories");
            }

            int[] parents = dtr.ParallelTaxonomyArrays.Parents;
            foreach (string cat in values.Keys)
            {
                FacetLabel cp = new FacetLabel(FacetsConfig.StringToPath(cat));
                Assert.True(dtr.GetOrdinal(cp) > 0, "category not found " + cp);
                int level = cp.Length;
                int parentOrd = 0; // for root, parent is always virtual ROOT (ord=0)
                FacetLabel path = new FacetLabel();
                for (int i = 0; i < level; i++)
                {
                    path = cp.Subpath(i + 1);
                    int ord = dtr.GetOrdinal(path);
                    Assert.AreEqual(parentOrd, parents[ord], "invalid parent for cp=" + path);
                    parentOrd = ord; // next level should have this parent
                }
            }

            IOUtils.Close(dtr, dir);
        }
        public virtual void TestConcurrency()
        {
            int                 ncats   = AtLeast(100000); // add many categories
            int                 range   = ncats * 3;       // affects the categories selection
            AtomicInteger       numCats = new AtomicInteger(ncats);
            Directory           dir     = NewDirectory();
            var                 values  = new ConcurrentDictionary <string, string>();
            double              d       = Random().NextDouble();
            TaxonomyWriterCache cache;

            if (d < 0.7)
            {
                // this is the fastest, yet most memory consuming
                cache = new Cl2oTaxonomyWriterCache(1024, 0.15f, 3);
            }
            else if (TEST_NIGHTLY && d > 0.98)
            {
                // this is the slowest, but tests the writer concurrency when no caching is done.
                // only pick it during NIGHTLY tests, and even then, with very low chances.
                cache = NO_OP_CACHE;
            }
            else
            {
                // this is slower than CL2O, but less memory consuming, and exercises finding categories on disk too.
                cache = new LruTaxonomyWriterCache(ncats / 10);
            }
            if (VERBOSE)
            {
                Console.WriteLine("TEST: use cache=" + cache);
            }
            var tw = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE, cache);

            ThreadClass[] addThreads = new ThreadClass[AtLeast(4)];
            for (int z = 0; z < addThreads.Length; z++)
            {
                addThreads[z] = new ThreadAnonymousInnerClassHelper(this, range, numCats, values, tw);
            }

            foreach (var t in addThreads)
            {
                t.Start();
            }
            foreach (var t in addThreads)
            {
                t.Join();
            }
            tw.Dispose();

            DirectoryTaxonomyReader dtr = new DirectoryTaxonomyReader(dir);

            // +1 for root category
            if (values.Count + 1 != dtr.Size)
            {
                foreach (string value in values.Keys)
                {
                    FacetLabel label = new FacetLabel(FacetsConfig.StringToPath(value));
                    if (dtr.GetOrdinal(label) == -1)
                    {
                        Console.WriteLine("FAIL: path=" + label + " not recognized");
                    }
                }
                Fail("mismatch number of categories");
            }

            int[] parents = dtr.ParallelTaxonomyArrays.Parents();
            foreach (string cat in values.Keys)
            {
                FacetLabel cp = new FacetLabel(FacetsConfig.StringToPath(cat));
                Assert.True(dtr.GetOrdinal(cp) > 0, "category not found " + cp);
                int        level     = cp.Length;
                int        parentOrd = 0; // for root, parent is always virtual ROOT (ord=0)
                FacetLabel path      = new FacetLabel();
                for (int i = 0; i < level; i++)
                {
                    path = cp.Subpath(i + 1);
                    int ord = dtr.GetOrdinal(path);
                    Assert.AreEqual(parentOrd, parents[ord], "invalid parent for cp=" + path);
                    parentOrd = ord; // next level should have this parent
                }
            }

            IOUtils.Close(dtr, dir);
        }
        public virtual void TestReplaceTaxonomy()
        {
            Directory input = NewDirectory();
            var taxoWriter = new DirectoryTaxonomyWriter(input);
            int ordA = taxoWriter.AddCategory(new FacetLabel("a"));
            taxoWriter.Dispose();

            Directory dir = NewDirectory();
            taxoWriter = new DirectoryTaxonomyWriter(dir);
            int ordB = taxoWriter.AddCategory(new FacetLabel("b"));
            taxoWriter.AddCategory(new FacetLabel("c"));
            taxoWriter.Commit();

            long origEpoch = getEpoch(dir);

            // replace the taxonomy with the input one
            taxoWriter.ReplaceTaxonomy(input);

            // LUCENE-4633: make sure that category "a" is not added again in any case
            taxoWriter.AddTaxonomy(input, new MemoryOrdinalMap());
            Assert.AreEqual(2, taxoWriter.Count, "no categories should have been added"); // root + 'a'
            Assert.AreEqual(ordA, taxoWriter.AddCategory(new FacetLabel("a")), "category 'a' received new ordinal?");

            // add the same category again -- it should not receive the same ordinal !
            int newOrdB = taxoWriter.AddCategory(new FacetLabel("b"));
            Assert.AreNotSame(ordB, newOrdB, "new ordinal cannot be the original ordinal");
            Assert.AreEqual(2, newOrdB, "ordinal should have been 2 since only one category was added by replaceTaxonomy");

            taxoWriter.Dispose();

            long newEpoch = getEpoch(dir);
            Assert.True(origEpoch < newEpoch, "index epoch should have been updated after replaceTaxonomy");

            dir.Dispose();
            input.Dispose();
        }
예제 #37
0
        public virtual void TestConcurrency()
        {
            AtomicInt32 numDocs  = new AtomicInt32(AtLeast(10000));
            Directory   indexDir = NewDirectory();
            Directory   taxoDir  = NewDirectory();
            ConcurrentDictionary <string, string> values = new ConcurrentDictionary <string, string>();
            IndexWriter iw = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, null));
            var         tw = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE, NewTaxoWriterCache(numDocs));

            ThreadJob[]  indexThreads = new ThreadJob[AtLeast(4)];
            FacetsConfig config       = new FacetsConfig();

            for (int i = 0; i < 10; i++)
            {
                config.SetHierarchical("l1." + i, true);
                config.SetMultiValued("l1." + i, true);
            }

            for (int i = 0; i < indexThreads.Length; i++)
            {
                indexThreads[i] = new ThreadAnonymousInnerClassHelper(this, numDocs, values, iw, tw, config);
            }

            foreach (ThreadJob t in indexThreads)
            {
                t.Start();
            }
            foreach (ThreadJob t in indexThreads)
            {
                t.Join();
            }

            var tr = new DirectoryTaxonomyReader(tw);

            // +1 for root category
            if (values.Count + 1 != tr.Count)
            {
                foreach (string value in values.Keys)
                {
                    FacetLabel label = new FacetLabel(FacetsConfig.StringToPath(value));
                    if (tr.GetOrdinal(label) == -1)
                    {
                        Console.WriteLine("FAIL: path=" + label + " not recognized");
                    }
                }
                fail("mismatch number of categories");
            }
            int[] parents = tr.ParallelTaxonomyArrays.Parents;
            foreach (string cat in values.Keys)
            {
                FacetLabel cp = new FacetLabel(FacetsConfig.StringToPath(cat));
                Assert.IsTrue(tr.GetOrdinal(cp) > 0, "category not found " + cp);
                int        level     = cp.Length;
                int        parentOrd = 0; // for root, parent is always virtual ROOT (ord=0)
                FacetLabel path      = null;
                for (int i = 0; i < level; i++)
                {
                    path = cp.Subpath(i + 1);
                    int ord = tr.GetOrdinal(path);
                    Assert.AreEqual(parentOrd, parents[ord], "invalid parent for cp=" + path);
                    parentOrd = ord; // next level should have this parent
                }
            }

            IOUtils.Dispose(tw, iw, tr, taxoDir, indexDir);
        }
 public virtual void TestReaderFreshness()
 {
     // ensures that the internal index reader is always kept fresh. Previously,
     // this simple scenario failed, if the cache just evicted the category that
     // is being added.
     Directory dir = NewDirectory();
     DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE, NO_OP_CACHE);
     int o1 = taxoWriter.AddCategory(new FacetLabel("a"));
     int o2 = taxoWriter.AddCategory(new FacetLabel("a"));
     Assert.True(o1 == o2, "ordinal for same category that is added twice should be the same !");
     taxoWriter.Dispose();
     dir.Dispose();
 }
예제 #39
0
 public ThreadAnonymousClass2(TestAddTaxonomy outerInstance, int numCategories, DirectoryTaxonomyWriter destTW)
 {
     this.outerInstance = outerInstance;
     this.numCategories = numCategories;
     this.destTW        = destTW;
 }
        public virtual void TestPrepareCommitNoEmptyCommits()
        {
            // LUCENE-4972: DTW used to create empty commits even if no changes were made
            Directory dir = NewDirectory();
            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(dir);
            taxoWriter.AddCategory(new FacetLabel("a"));
            taxoWriter.PrepareCommit();
            taxoWriter.Commit();

            long gen1 = SegmentInfos.GetLastCommitGeneration(dir);
            taxoWriter.PrepareCommit();
            taxoWriter.Commit();
            long gen2 = SegmentInfos.GetLastCommitGeneration(dir);
            Assert.AreEqual(gen1, gen2, "empty commit should not have changed the index");

            taxoWriter.Dispose();
            dir.Dispose();
        }
예제 #41
0
 public ThreadAnonymousInnerClassHelper(TestAddTaxonomy outerInstance, int range, AtomicInt32 numCats, DirectoryTaxonomyWriter tw)
 {
     this.outerInstance = outerInstance;
     this.range         = range;
     this.numCats       = numCats;
     this.tw            = tw;
 }
        public virtual void TestHugeLabel()
        {
            Directory indexDir = NewDirectory(), taxoDir = NewDirectory();
            IndexWriter indexWriter = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE, new Cl2oTaxonomyWriterCache(2, 1f, 1));
            FacetsConfig config = new FacetsConfig();

            // Add one huge label:
            string bigs = null;
            int ordinal = -1;

            int len = FacetLabel.MAX_CATEGORY_PATH_LENGTH - 4; // for the dimension and separator
            bigs = TestUtil.RandomSimpleString(Random(), len, len);
            FacetField ff = new FacetField("dim", bigs);
            FacetLabel cp = new FacetLabel("dim", bigs);
            ordinal = taxoWriter.AddCategory(cp);
            Document doc = new Document();
            doc.Add(ff);
            indexWriter.AddDocument(config.Build(taxoWriter, doc));

            // Add tiny ones to cause a re-hash
            for (int i = 0; i < 3; i++)
            {
                string s = TestUtil.RandomSimpleString(Random(), 1, 10);
                taxoWriter.AddCategory(new FacetLabel("dim", s));
                doc = new Document();
                doc.Add(new FacetField("dim", s));
                indexWriter.AddDocument(config.Build(taxoWriter, doc));
            }

            // when too large components were allowed to be added, this resulted in a new added category
            Assert.AreEqual(ordinal, taxoWriter.AddCategory(cp));

            IOUtils.Close(indexWriter, taxoWriter);

            DirectoryReader indexReader = DirectoryReader.Open(indexDir);
            var taxoReader = new DirectoryTaxonomyReader(taxoDir);
            IndexSearcher searcher = new IndexSearcher(indexReader);
            DrillDownQuery ddq = new DrillDownQuery(new FacetsConfig());
            ddq.Add("dim", bigs);
            Assert.AreEqual(1, searcher.Search(ddq, 10).TotalHits);

            IOUtils.Close(indexReader, taxoReader, indexDir, taxoDir);
        }
예제 #43
0
 public ThreadAnonymousInnerClassHelper(int range, AtomicInt32 numCats, ConcurrentDictionary <string, string> values, DirectoryTaxonomyWriter tw)
 {
     this.range   = range;
     this.numCats = numCats;
     this.values  = values;
     this.tw      = tw;
 }
        public virtual void TestReplaceTaxoWithLargeTaxonomy()
        {
            var srcTaxoDir = NewDirectory();
            var targetTaxoDir = NewDirectory();

            // build source, large, taxonomy
            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(srcTaxoDir);
            int ord = taxoWriter.AddCategory(new FacetLabel("A", "1", "1", "1", "1", "1", "1"));
            taxoWriter.Dispose();

            taxoWriter = new DirectoryTaxonomyWriter(targetTaxoDir);
            int ordinal = taxoWriter.AddCategory(new FacetLabel("B", "1"));
            Assert.AreEqual(1, taxoWriter.GetParent(ordinal)); // call getParent to initialize taxoArrays
            taxoWriter.Commit();

            taxoWriter.ReplaceTaxonomy(srcTaxoDir);
            Assert.AreEqual(ord - 1, taxoWriter.GetParent(ord));
            taxoWriter.Dispose();

            srcTaxoDir.Dispose();
            targetTaxoDir.Dispose();
        }
 public virtual void TestEnsureOpen()
 {
     // verifies that an exception is thrown if DTW was closed
     Directory dir = NewDirectory();
     DirectoryTaxonomyWriter dtw = new DirectoryTaxonomyWriter(dir);
     dtw.Dispose();
     try
     {
         dtw.AddCategory(new FacetLabel("a"));
         Fail("should not have succeeded to add a category following close.");
     }
     catch (AlreadyClosedException)
     {
         // expected
     }
     dir.Dispose();
 }
        public virtual void TestOpenIfChangedReuse()
        {
            // test the reuse of data from the old DTR instance
            foreach (bool nrt in new bool[] { false, true })
            {
                Directory dir = NewDirectory();
                DirectoryTaxonomyWriter writer = new DirectoryTaxonomyWriter(dir);

                FacetLabel cp_a = new FacetLabel("a");
                writer.AddCategory(cp_a);
                if (!nrt)
                {
                    writer.Commit();
                }

                DirectoryTaxonomyReader r1 = nrt ? new DirectoryTaxonomyReader(writer) : new DirectoryTaxonomyReader(dir);
                // fill r1's caches
                Assert.AreEqual(1, r1.GetOrdinal(cp_a));
                Assert.AreEqual(cp_a, r1.GetPath(1));

                FacetLabel cp_b = new FacetLabel("b");
                writer.AddCategory(cp_b);
                if (!nrt)
                {
                    writer.Commit();
                }

                DirectoryTaxonomyReader r2 = TaxonomyReader.OpenIfChanged(r1);
                Assert.NotNull(r2);

                // add r2's categories to the caches
                Assert.AreEqual(2, r2.GetOrdinal(cp_b));
                Assert.AreEqual(cp_b, r2.GetPath(2));

                // check that r1 doesn't see cp_b
                Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, r1.GetOrdinal(cp_b));
                Assert.Null(r1.GetPath(2));

                (r1).Dispose();
                (r2).Dispose();
                writer.Dispose();
                dir.Dispose();
            }
        }
예제 #47
0
        public virtual void TestGetChildren()
        {
            Directory dir = NewDirectory();
            var       taxoWriter = new DirectoryTaxonomyWriter(dir);
            int       numCategories = AtLeast(10);
            int       numA = 0, numB = 0;
            Random    random = Random;

            // add the two categories for which we'll also add children (so asserts are simpler)
            taxoWriter.AddCategory(new FacetLabel("a"));
            taxoWriter.AddCategory(new FacetLabel("b"));
            for (int i = 0; i < numCategories; i++)
            {
                if (random.NextBoolean())
                {
                    taxoWriter.AddCategory(new FacetLabel("a", Convert.ToString(i, CultureInfo.InvariantCulture)));
                    ++numA;
                }
                else
                {
                    taxoWriter.AddCategory(new FacetLabel("b", Convert.ToString(i, CultureInfo.InvariantCulture)));
                    ++numB;
                }
            }
            // add category with no children
            taxoWriter.AddCategory(new FacetLabel("c"));
            taxoWriter.Dispose();

            var taxoReader = new DirectoryTaxonomyReader(dir);

            // non existing category
            TaxonomyReader.ChildrenEnumerator it = taxoReader.GetChildren(taxoReader.GetOrdinal(new FacetLabel("invalid")));

            Assert.AreEqual(false, it.MoveNext());

            // a category with no children
            it = taxoReader.GetChildren(taxoReader.GetOrdinal(new FacetLabel("c")));
            Assert.AreEqual(false, it.MoveNext());

            // arbitrary negative ordinal
            it = taxoReader.GetChildren(-2);
            Assert.AreEqual(false, it.MoveNext());

            // root's children
            var roots = new JCG.HashSet <string> {
                "a", "b", "c"
            };

            it = taxoReader.GetChildren(TaxonomyReader.ROOT_ORDINAL);
            while (roots.Count > 0)
            {
                it.MoveNext();
                FacetLabel root = taxoReader.GetPath(it.Current);
                Assert.AreEqual(1, root.Length);
                Assert.IsTrue(roots.Remove(root.Components[0]));
            }
            Assert.AreEqual(false, it.MoveNext());

            for (int i = 0; i < 2; i++)
            {
                FacetLabel cp      = i == 0 ? new FacetLabel("a") : new FacetLabel("b");
                int        ordinal = taxoReader.GetOrdinal(cp);
                it = taxoReader.GetChildren(ordinal);
                int numChildren = 0;
                int child;
                while (it.MoveNext())
                {
                    child = it.Current;
                    FacetLabel path = taxoReader.GetPath(child);
                    Assert.AreEqual(2, path.Length);
                    Assert.AreEqual(path.Components[0], i == 0 ? "a" : "b");
                    ++numChildren;
                }
                int expected = i == 0 ? numA : numB;
                Assert.AreEqual(expected, numChildren, "invalid num children");
            }
            taxoReader.Dispose();

            dir.Dispose();
        }
        private void TouchTaxo(DirectoryTaxonomyWriter taxoWriter, FacetLabel cp)
        {
            taxoWriter.AddCategory(cp);
            taxoWriter.CommitData = new Dictionary<string, string>()
		{
			{"just", "data"}
		};
            taxoWriter.Commit();
        }