IdentityHashMap<Client, List<Selector>> map = new IdentityHashMap<Client, List<Selector>>();
// Need to maintain original order.
final IdentityHashMap<Selector, Integer> indexMap = new IdentityHashMap<Selector, Integer>();
for (int i = 0; i < results.results.size(); i++) {
final LazyBlurResult result = (LazyBlurResult) results.results.get(i);
Client client = result.getClient();
Selector s = new Selector(selector);
s.setLocationId(result.locationId);
List<Selector> list = map.get(client);
if (list == null) {
list = new ArrayList<Selector>();
map.put(client, list);
}
list.add(s);
indexMap.put(s, i);
}
// Execute batch fetches
List<Future<Boolean>> futures = new ArrayList<Future<Boolean>>();
final AtomicReferenceArray<FetchResult> fetchResults = new AtomicReferenceArray<FetchResult>(
results.results.size());
for (Entry<Client, List<Selector>> entry : map.entrySet()) {
final Client client = entry.getKey();
final List<Selector> list = entry.getValue();
futures.add(executor.submit(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
Tracer trace = Trace.trace("remote call - thrift", Trace.param("node", getNode(client)));
try {
TraceId traceId = Trace.getTraceId();
if (traceId != null) {
client.startTrace(traceId.getRootId(), traceId.getRequestId());
}
List<FetchResult> fetchRowBatch = client.fetchRowBatch(table, list);
for (int i = 0; i < list.size(); i++) {
int index = indexMap.get(list.get(i));
fetchResults.set(index, fetchRowBatch.get(i));
}
return Boolean.TRUE;
} finally {
trace.done();
}
}
private String getNode(Client client) {
TProtocol inputProtocol = client.getInputProtocol();
TTransport transport = inputProtocol.getTransport();
if (transport instanceof TFramedTransport) {
TFramedTransport framedTransport = (TFramedTransport) transport;
transport = framedTransport.getTransport();
}
if (transport instanceof TSocket) {
TSocket tsocket = (TSocket) transport;
Socket socket = tsocket.getSocket();
SocketAddress remoteSocketAddress = socket.getRemoteSocketAddress();
return remoteSocketAddress.toString();
}
return "unknown";
}
}));
}
// Wait for all parallel calls to finish.
for (Future<Boolean> future : futures) {
try {
future.get();
} catch (ExecutionException e) {
Throwable throwable = e.getCause();
if (throwable instanceof BlurException) {
throw (BlurException) throwable;
} else {
throw new BException("Unknown error during fetch", throwable);
}
}
}
// Place fetch results into result object for response.
for (int i = 0; i < fetchResults.length(); i++) {
FetchResult fetchResult = fetchResults.get(i);
BlurResult result = results.results.get(i);
result.setFetchResult(fetchResult);
result.setLocationId(null);
}
trace.done();
}
results.query = query;