package org.apache.blur.server;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.
*/
import java.io.Closeable;
import java.io.IOException;
import java.net.SocketAddress;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.blur.log.Log;
import org.apache.blur.log.LogFactory;
import org.apache.blur.lucene.search.IndexSearcherCloseable;
import org.apache.blur.thirdparty.thrift_0_9_0.server.ServerContext;
/**
* The thrift session that will hold index reader references to maintain across
* query and fetch calls. Since there is a fixed size thread pool issuing calls
* that involve the _threadsToContext map where Thread is the key we don't need
* to clear or reset threads.
*/
public class ShardServerContext extends BlurServerContext implements ServerContext {
private static final Log LOG = LogFactory.getLog(ShardServerContext.class);
private final static Map<Thread, ShardServerContext> _threadsToContext = new ConcurrentHashMap<Thread, ShardServerContext>();
private final Map<String, IndexSearcherCloseable> _indexSearcherMap = new ConcurrentHashMap<String, IndexSearcherCloseable>();
public ShardServerContext(SocketAddress localSocketAddress, SocketAddress remoteSocketAddress) {
super(localSocketAddress, remoteSocketAddress);
}
/**
* Registers the {@link ShardServerContext} for this thread.
*
* @param context
* the {@link ShardServerContext}.
*/
public static void registerContextForCall(ShardServerContext context) {
_threadsToContext.put(Thread.currentThread(), context);
}
/**
* Gets the {@link ShardServerContext} for this {@link Thread}.
*
* @return the {@link ShardServerContext}.
*/
public static ShardServerContext getShardServerContext() {
return _threadsToContext.get(Thread.currentThread());
}
/**
* Resets the context, this closes and releases the index readers.
*/
public static void resetSearchers() {
ShardServerContext shardServerContext = getShardServerContext();
if (shardServerContext != null) {
shardServerContext.reset();
}
}
/**
* Closes this context, this happens when the client closes it's connect to
* the server.
*/
public void close() {
reset();
}
/**
* Resets the {@link ShardServerContext} by closing the searchers.
*/
public void reset() {
Collection<IndexSearcherCloseable> values = _indexSearcherMap.values();
for (IndexSearcherCloseable indexSearcherClosable : values) {
LOG.debug("Closing [{0}]", indexSearcherClosable);
closeQuietly(indexSearcherClosable);
}
_indexSearcherMap.clear();
}
public static void closeQuietly(Closeable closeable) {
try {
if (closeable != null) {
closeable.close();
}
} catch (IOException e) {
LOG.error("Closing [{0}]", closeable);
}
}
/**
* Gets the cached {@link IndexSearcherCloseable} (if any) for the given table
* and shard.
*
* @param table
* the stable name.
* @param shard
* the shard name.
* @return the {@link IndexSearcherCloseable} or null if not present.
*/
public IndexSearcherCloseable getIndexSearcherClosable(String table, String shard) {
IndexSearcherCloseable indexSearcherClosable = _indexSearcherMap.get(getKey(table, shard));
if (indexSearcherClosable != null) {
LOG.debug("Using cached searcher [{0}] for table [{1}] shard [{2}]", indexSearcherClosable, table, shard);
}
return indexSearcherClosable;
}
/**
* Sets the index searcher for this {@link ShardServerContext} for the given
* table and shard.
*
* @param table
* the table name.
* @param shard
* the shard name.
* @param searcher
* the {@link IndexSearcherCloseable}.
* @throws IOException
*/
public void setIndexSearcherClosable(String table, String shard, IndexSearcherCloseable searcher) throws IOException {
IndexSearcherCloseable indexSearcherClosable = _indexSearcherMap.put(getKey(table, shard), searcher);
if (indexSearcherClosable != null && searcher != indexSearcherClosable) {
indexSearcherClosable.close();
}
}
private String getKey(String table, String shard) {
return table + "/" + shard;
}
}