/*
* Copyright (C) 2014 Indeed Inc.
*
* Licensed 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.
*/
package com.indeed.imhotep.client;
import com.google.common.collect.Maps;
import com.indeed.util.core.DataLoadingRunnable;
import com.indeed.imhotep.DatasetInfo;
import com.indeed.imhotep.ImhotepRemoteSession;
import org.apache.log4j.Logger;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
/**
* @author jsgroth
*/
class ImhotepClientShardListReloader extends DataLoadingRunnable {
private static final Logger log = Logger.getLogger(ImhotepClientShardListReloader.class);
private final HostsReloader hostsReloader;
private final ExecutorService rpcExecutor;
private final Object shardListRpcLock = new Object();
private volatile Map<Host, List<DatasetInfo>> shardList = Collections.emptyMap();
ImhotepClientShardListReloader(HostsReloader hostsReloader, ExecutorService rpcExecutor) {
super("ImhotepClientShardListReloader");
this.hostsReloader = hostsReloader;
this.rpcExecutor = rpcExecutor;
}
@Override
public boolean load() {
try {
final Map<Host, List<DatasetInfo>> newShardList = shardListRpc();
if (newShardList.isEmpty()) {
log.error("unable to retrieve shard list from any imhotep daemons");
loadFailed();
return false;
}
if (!newShardList.equals(shardList)) {
shardList = newShardList;
}
return true;
} catch (Exception e) {
log.error("Error reloading hosts", e);
loadFailed();
return false;
}
}
public Map<Host, List<DatasetInfo>> getShardList() {
return shardList;
}
private Map<Host, List<DatasetInfo>> shardListRpc() {
synchronized (shardListRpcLock) {
final List<Host> hosts = hostsReloader.getHosts();
final Map<Host, Future<List<DatasetInfo>>> futures = Maps.newHashMap();
for (final Host host : hosts) {
final Future<List<DatasetInfo>> future = rpcExecutor.submit(new Callable<List<DatasetInfo>>() {
@Override
public List<DatasetInfo> call() throws Exception {
return ImhotepRemoteSession.getShardInfoList(host.hostname, host.port);
}
});
futures.put(host, future);
}
final Map<Host, List<DatasetInfo>> ret = Maps.newHashMapWithExpectedSize(hosts.size());
for (final Host host : futures.keySet()) {
try {
final List<DatasetInfo> shardList = futures.get(host).get();
ret.put(host, shardList);
} catch (ExecutionException e) {
log.error("error getting shard list from " + host, e);
} catch (InterruptedException e) {
log.error("error getting shard list from " + host, e);
}
}
return ret;
}
}
}