/* * Licensed to Crate.IO GmbH ("Crate") under one or more contributor * license agreements. See the NOTICE file distributed with this work for * additional information regarding copyright ownership. Crate licenses * this file to you under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. You may * obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * * However, if you have executed another commercial license agreement * with Crate these terms will supersede the license and you may use the * software solely pursuant to the terms of the relevant commercial agreement. */ package io.crate.action.job; import org.apache.logging.log4j.Logger; import org.apache.lucene.index.IndexReader; import org.apache.lucene.search.IndexSearcher; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.index.IndexNotFoundException; import org.elasticsearch.index.IndexService; import org.elasticsearch.index.engine.Engine; import org.elasticsearch.index.shard.IndexShard; import org.elasticsearch.index.shard.ShardId; import org.elasticsearch.indices.IndicesService; import javax.annotation.concurrent.NotThreadSafe; import java.util.concurrent.atomic.AtomicInteger; @NotThreadSafe public class SharedShardContext { private final static Logger LOGGER = Loggers.getLogger(SharedShardContext.class); private final IndicesService indicesService; private final ShardId shardId; private final int readerId; private RefCountSearcher searcher; private IndexService indexService; private IndexShard indexShard; SharedShardContext(IndicesService indicesService, ShardId shardId, int readerId) { this.indicesService = indicesService; this.shardId = shardId; this.readerId = readerId; } public Engine.Searcher acquireSearcher() throws IndexNotFoundException { if (searcher == null) { searcher = new RefCountSearcher(indexShard().acquireSearcher("shared-shard-context")); } searcher.inc(); return searcher; } public IndexShard indexShard() { if (indexShard == null) { indexShard = indexService().getShard(shardId.id()); } return indexShard; } public IndexService indexService() throws IndexNotFoundException { if (indexService == null) { indexService = indicesService.indexServiceSafe(shardId.getIndex()); } return indexService; } public int readerId() { return readerId; } private static class RefCountSearcher extends Engine.Searcher { private final AtomicInteger refs = new AtomicInteger(); private final Engine.Searcher searcher; RefCountSearcher(Engine.Searcher searcher) { super(searcher.source(), searcher.searcher()); this.searcher = searcher; } @Override public String source() { return searcher.source(); } @Override public IndexReader reader() { return searcher.reader(); } @Override public IndexSearcher searcher() { return searcher.searcher(); } @Override public void close() throws ElasticsearchException { int remainingRefs = refs.decrementAndGet(); traceLog(remainingRefs, "Close called on RefCountSearcher; Remaining refs: {}"); if (remainingRefs == 0) { searcher.close(); } } void inc() { int newRefs = refs.incrementAndGet(); traceLog(newRefs, "Searcher refs increased: {}"); } private void traceLog(int remainingRefs, String msg) { if (LOGGER.isTraceEnabled()) { LOGGER.trace(msg, remainingRefs); } } } }