/** This DocIdSet implementation is cacheable if the inner set is cacheable. */ @Override public boolean isCacheable() { return _innerSet.isCacheable(); }
/** This DocIdSet implementation is cacheable if the inner set is cacheable. */ @Override public boolean isCacheable() { return _innerSet.isCacheable(); }
@Override public boolean isCacheable() { return in.isCacheable(); }
@Override public boolean isCacheable() { return in.isCacheable(); }
static boolean isCheapToCache(DocIdSet set) { // the produced doc set is already cacheable, so caching has no // overhead at all. TODO: extend this to sets whose iterators have a low // cost? return set == null || set.isCacheable(); }
static boolean isCheapToCache(DocIdSet set) { // the produced doc set is already cacheable, so caching has no // overhead at all. TODO: extend this to sets whose iterators have a low // cost? return set == null || set.isCacheable(); }
/** * Provide the DocIdSet to be cached, using the DocIdSet provided * by the wrapped Filter. <p>This implementation returns the given {@link DocIdSet}, * if {@link DocIdSet#isCacheable} returns <code>true</code>, else it calls * {@link #cacheImpl(DocIdSetIterator, org.apache.lucene.index.LeafReader)} * <p>Note: This method returns {@linkplain DocIdSet#EMPTY} if the given docIdSet * is <code>null</code> or if {@link DocIdSet#iterator()} return <code>null</code>. The empty * instance is use as a placeholder in the cache instead of the <code>null</code> value. */ protected DocIdSet docIdSetToCache(DocIdSet docIdSet, LeafReader reader) throws IOException { if (docIdSet == null || docIdSet.isCacheable()) { return docIdSet; } else { final DocIdSetIterator it = docIdSet.iterator(); if (it == null) { return null; } else { return cacheImpl(it, reader); } } }
/** * Provide the DocIdSet to be cached, using the DocIdSet provided * by the wrapped Filter. <p>This implementation returns the given {@link DocIdSet}, * if {@link DocIdSet#isCacheable} returns <code>true</code>, else it calls * {@link #cacheImpl(DocIdSetIterator, org.apache.lucene.index.LeafReader)} * <p>Note: This method returns {@linkplain DocIdSet#EMPTY} if the given docIdSet * is <code>null</code> or if {@link DocIdSet#iterator()} return <code>null</code>. The empty * instance is use as a placeholder in the cache instead of the <code>null</code> value. */ protected DocIdSet docIdSetToCache(DocIdSet docIdSet, LeafReader reader) throws IOException { if (docIdSet == null || docIdSet.isCacheable()) { return docIdSet; } else { final DocIdSetIterator it = docIdSet.iterator(); if (it == null) { return null; } else { return cacheImpl(it, reader); } } }
/** * Provide the DocIdSet to be cached, using the DocIdSet provided * by the wrapped Filter. <p>This implementation returns the given {@link DocIdSet}, * if {@link DocIdSet#isCacheable} returns <code>true</code>, else it calls * {@link #cacheImpl(DocIdSetIterator, org.apache.lucene.index.LeafReader)} * <p>Note: This method returns {@linkplain DocIdSet#EMPTY} if the given docIdSet * is <code>null</code> or if {@link DocIdSet#iterator()} return <code>null</code>. The empty * instance is use as a placeholder in the cache instead of the <code>null</code> value. */ protected DocIdSet docIdSetToCache(DocIdSet docIdSet, LeafReader reader) throws IOException { if (docIdSet == null || docIdSet.isCacheable()) { return docIdSet; } else { final DocIdSetIterator it = docIdSet.iterator(); if (it == null) { return null; } else { return cacheImpl(it, reader); } } }
/** * Provide the DocIdSet to be cached, using the DocIdSet provided * by the wrapped Filter. <p>This implementation returns the given {@link DocIdSet}, * if {@link DocIdSet#isCacheable} returns <code>true</code>, else it calls * {@link #cacheImpl(DocIdSetIterator, org.apache.lucene.index.LeafReader)} * <p>Note: This method returns {@linkplain DocIdSet#EMPTY} if the given docIdSet * is <code>null</code> or if {@link DocIdSet#iterator()} return <code>null</code>. The empty * instance is use as a placeholder in the cache instead of the <code>null</code> value. */ protected DocIdSet docIdSetToCache(DocIdSet docIdSet, LeafReader reader) throws IOException { if (docIdSet == null || docIdSet.isCacheable()) { return docIdSet; } else { final DocIdSetIterator it = docIdSet.iterator(); if (it == null) { return null; } else { return cacheImpl(it, reader); } } }
/** * Returns a cacheable version of the given set of document ids. May * just return the given set if it was already cacheable. * @param docIdSet the set to make cacheable. * @param reader the index reader the docIdSet references. * @return the cacheable version. * @throws IOException if IO errors occur. */ public static DocIdSet cacheable(@Nullable final DocIdSet docIdSet, final IndexReader reader) throws IOException { if (docIdSet == null) { return DocIdSet.EMPTY_DOCIDSET; } else if (docIdSet.isCacheable()) { return docIdSet; } else { DocIdSetIterator it = docIdSet.iterator(); if (it == null) { return DocIdSet.EMPTY_DOCIDSET; } else { FixedBitSet bits = new FixedBitSet(reader.maxDoc()); bits.or(it); return bits; } } }
@Override public DocIdSet getDocIdSet(LeafReaderContext context, final Bits acceptDocs) throws IOException { final LeafReader reader = context.reader(); final Object key = reader.getCoreCacheKey(); DocIdSet docIdSet = cache.get(key); if (docIdSet != null) { hitCount++; } else { docIdSet = filter.getDocIdSet(context, null); if (policy.shouldCache(filter, context, docIdSet)) { missCount++; docIdSet = docIdSetToCache(docIdSet, reader); if (docIdSet == null) { // We use EMPTY as a sentinel for the empty set, which is cacheable docIdSet = EMPTY; } assert docIdSet.isCacheable(); cache.put(key, docIdSet); } } return docIdSet == EMPTY ? null : BitsFilteredDocIdSet.wrap(docIdSet, acceptDocs); }
@Override public DocIdSet getDocIdSet(LeafReaderContext context, final Bits acceptDocs) throws IOException { final LeafReader reader = context.reader(); final Object key = reader.getCoreCacheKey(); DocIdSet docIdSet = cache.get(key); if (docIdSet != null) { hitCount++; } else { docIdSet = filter.getDocIdSet(context, null); if (policy.shouldCache(filter, context, docIdSet)) { missCount++; docIdSet = docIdSetToCache(docIdSet, reader); if (docIdSet == null) { // We use EMPTY as a sentinel for the empty set, which is cacheable docIdSet = EMPTY; } assert docIdSet.isCacheable(); cache.put(key, docIdSet); } } return docIdSet == EMPTY ? null : BitsFilteredDocIdSet.wrap(docIdSet, acceptDocs); }
/** * Provide the DocIdSet to be cached, using the DocIdSet provided by the wrapped Filter. * <p> * This implementation returns the given {@link DocIdSet}, if {@link DocIdSet#isCacheable} * returns <code>true</code>, else it copies the {@link DocIdSetIterator} into an * {@link FixedBitSet}. */ private DocIdSet docIdSetToCache(DocIdSet docIdSet) throws IOException { if (docIdSet == null) { // this is better than returning null, as the nonnull result can be cached return DocIdSet.EMPTY_DOCIDSET; } else if (docIdSet.isCacheable()) { return docIdSet; } else { final DocIdSetIterator it = docIdSet.iterator(); // null is allowed to be returned by iterator(), // in this case we wrap with the empty set, // which is cacheable. if (it == null) { return DocIdSet.EMPTY_DOCIDSET; } else { final FixedBitSet bits = new FixedBitSet(reader.maxDoc()); bits.or(it); return bits; } } } }
synchronized void putIfAbsent(Filter filter, LeafReaderContext context, DocIdSet set) { // under a lock to make sure that mostRecentlyUsedFilters and cache remain sync'ed assert set.isCacheable(); Filter singleton = uniqueFilters.get(filter); if (singleton == null) { uniqueFilters.put(filter, filter); onFilterCache(singleton, LINKED_HASHTABLE_RAM_BYTES_PER_ENTRY + ramBytesUsed(filter)); } else { filter = singleton; } final Object key = context.reader().getCoreCacheKey(); LeafCache leafCache = cache.get(key); if (leafCache == null) { leafCache = new LeafCache(key); final LeafCache previous = cache.put(context.reader().getCoreCacheKey(), leafCache); ramBytesUsed += HASHTABLE_RAM_BYTES_PER_ENTRY; assert previous == null; // we just created a new leaf cache, need to register a close listener context.reader().addCoreClosedListener(new CoreClosedListener() { @Override public void onClose(Object ownerCoreCacheKey) { clearCoreCacheKey(ownerCoreCacheKey); } }); } leafCache.putIfAbsent(filter, set); evictIfNecessary(); }
synchronized void putIfAbsent(Filter filter, LeafReaderContext context, DocIdSet set) { // under a lock to make sure that mostRecentlyUsedFilters and cache remain sync'ed assert set.isCacheable(); Filter singleton = uniqueFilters.get(filter); if (singleton == null) { uniqueFilters.put(filter, filter); onFilterCache(singleton, LINKED_HASHTABLE_RAM_BYTES_PER_ENTRY + ramBytesUsed(filter)); } else { filter = singleton; } final Object key = context.reader().getCoreCacheKey(); LeafCache leafCache = cache.get(key); if (leafCache == null) { leafCache = new LeafCache(key); final LeafCache previous = cache.put(context.reader().getCoreCacheKey(), leafCache); ramBytesUsed += HASHTABLE_RAM_BYTES_PER_ENTRY; assert previous == null; // we just created a new leaf cache, need to register a close listener context.reader().addCoreClosedListener(new CoreClosedListener() { @Override public void onClose(Object ownerCoreCacheKey) { clearCoreCacheKey(ownerCoreCacheKey); } }); } leafCache.putIfAbsent(filter, set); evictIfNecessary(); }
/** * Returns a cacheable version of the given set of document ids. Optimized * for cases where the target doc id set is sparse, specifically when less * than 1/32 of the documents match the input. * @param docIdSet the set to make cacheable. * @return the cacheable version. * @throws IOException if IO errors occur. */ public static DocIdSet cacheableSparse(@Nullable final DocIdSet docIdSet) throws IOException { if (docIdSet == null) { return DocIdSet.EMPTY_DOCIDSET; } else if (docIdSet.isCacheable()) { return docIdSet; } else { DocIdSetIterator it = docIdSet.iterator(); IntList docIds = new ArrayIntList(); // null is allowed to be returned by iterator(), // in this case we wrap with the empty set, // which is cacheable. if (it == null) { return DocIdSet.EMPTY_DOCIDSET; } else { while (it.nextDoc() != DocIdSetIterator.NO_MORE_DOCS) { docIds.add(it.docID()); } return new IntListDocIdSet(docIds); } } }
@Override public Bits get(final IndexReader reader) throws IOException { DocIdSet docIdSet = this.filter.getDocIdSet(reader); if (docIdSet == null) { return new Bits.MatchNoBits(reader.maxDoc()); } else if (docIdSet instanceof Bits && docIdSet.isCacheable()) { return (Bits) docIdSet; } else { FixedBitSet result = new FixedBitSet(reader.maxDoc()); DocIdSetIterator iterator = docIdSet.iterator(); if (iterator != null) { result.or(iterator); } return result; } }