TEST_F(SegmentTermEnumTest, testPrevTermAtEnd) { DirectoryPtr dir = newLucene<MockRAMDirectory>(); IndexWriterPtr writer = newLucene<IndexWriter>(dir, newLucene<WhitespaceAnalyzer>(), true, IndexWriter::MaxFieldLengthLIMITED); addDoc(writer, L"aaa bbb"); writer->close(); SegmentReaderPtr reader = SegmentReader::getOnlySegmentReader(dir); SegmentTermEnumPtr termEnum = boost::dynamic_pointer_cast<SegmentTermEnum>(reader->terms()); EXPECT_TRUE(termEnum->next()); EXPECT_EQ(L"aaa", termEnum->term()->text()); EXPECT_TRUE(termEnum->next()); EXPECT_EQ(L"aaa", termEnum->prev()->text()); EXPECT_EQ(L"bbb", termEnum->term()->text()); EXPECT_TRUE(!termEnum->next()); EXPECT_EQ(L"bbb", termEnum->prev()->text()); }
TermInfoPtr TermInfosReader::get(TermPtr term, bool useCache) { if (_size == 0) return TermInfoPtr(); ensureIndexIsRead(); TermInfoPtr ti; TermInfosReaderThreadResourcesPtr resources(getThreadResources()); TermInfoCachePtr cache; if (useCache) { cache = resources->termInfoCache; // check the cache first if the term was recently looked up ti = cache->get(term); if (ti) return ti; } // optimize sequential access: first try scanning cached enum without seeking SegmentTermEnumPtr enumerator = resources->termEnum; if (enumerator->term() && // term is at or past current ((enumerator->prev() && term->compareTo(enumerator->prev()) > 0) || term->compareTo(enumerator->term()) >= 0)) { int32_t enumOffset = (int32_t)(enumerator->position / totalIndexInterval ) + 1; if (indexTerms.size() == enumOffset || // but before end of block term->compareTo(indexTerms[enumOffset]) < 0) { // no need to seek int32_t numScans = enumerator->scanTo(term); if (enumerator->term() && term->compareTo(enumerator->term()) == 0) { ti = enumerator->termInfo(); if (cache && numScans > 1) { // we only want to put this TermInfo into the cache if scanEnum skipped more // than one dictionary entry. This prevents RangeQueries or WildcardQueries to // wipe out the cache when they iterate over a large numbers of terms in order. cache->put(term, ti); } } else ti.reset(); return ti; } } // random-access: must seek seekEnum(enumerator, getIndexOffset(term)); enumerator->scanTo(term); if (enumerator->term() && term->compareTo(enumerator->term()) == 0) { ti = enumerator->termInfo(); if (cache) cache->put(term, ti); } else ti.reset(); return ti; }
void TermInfosReader::seekEnum(SegmentTermEnumPtr enumerator, int32_t indexOffset) { enumerator->seek(indexPointers[indexOffset], ((int64_t)indexOffset * (int64_t)totalIndexInterval) - 1, indexTerms[indexOffset], indexInfos[indexOffset]); }