use of org.apache.ignite.internal.GridTopic.TOPIC_EVENT in project ignite by apache.
the class GridEventStorageManager method query.
/**
* @param p Grid event predicate.
* @param nodes Collection of nodes.
* @param timeout Maximum time to wait for result, if {@code 0}, then wait until result is received.
* @return Collection of events.
* @throws IgniteCheckedException Thrown in case of any errors.
*/
@SuppressWarnings({ "SynchronizationOnLocalVariableOrMethodParameter", "deprecation" })
private <T extends Event> List<T> query(IgnitePredicate<T> p, Collection<? extends ClusterNode> nodes, long timeout) throws IgniteCheckedException {
assert p != null;
assert nodes != null;
if (nodes.isEmpty()) {
U.warn(log, "Failed to query events for empty nodes collection.");
return Collections.emptyList();
}
GridIoManager ioMgr = ctx.io();
final List<T> evts = new ArrayList<>();
final AtomicReference<Throwable> err = new AtomicReference<>();
final Set<UUID> uids = new HashSet<>();
final Object qryMux = new Object();
for (ClusterNode node : nodes) uids.add(node.id());
GridLocalEventListener evtLsnr = new GridLocalEventListener() {
@Override
public void onEvent(Event evt) {
assert evt instanceof DiscoveryEvent;
synchronized (qryMux) {
uids.remove(((DiscoveryEvent) evt).eventNode().id());
if (uids.isEmpty())
qryMux.notifyAll();
}
}
};
GridMessageListener resLsnr = new GridMessageListener() {
@SuppressWarnings("deprecation")
@Override
public void onMessage(UUID nodeId, Object msg) {
assert nodeId != null;
assert msg != null;
if (!(msg instanceof GridEventStorageMessage)) {
U.error(log, "Received unknown message: " + msg);
return;
}
GridEventStorageMessage res = (GridEventStorageMessage) msg;
try {
if (res.eventsBytes() != null)
res.events(U.<Collection<Event>>unmarshal(marsh, res.eventsBytes(), U.resolveClassLoader(ctx.config())));
if (res.exceptionBytes() != null)
res.exception(U.<Throwable>unmarshal(marsh, res.exceptionBytes(), U.resolveClassLoader(ctx.config())));
} catch (IgniteCheckedException e) {
U.error(log, "Failed to unmarshal events query response: " + msg, e);
return;
}
synchronized (qryMux) {
if (uids.remove(nodeId)) {
if (res.events() != null)
evts.addAll((Collection<T>) res.events());
} else
U.warn(log, "Received duplicate response (ignoring) [nodeId=" + nodeId + ", msg=" + res + ']');
if (res.exception() != null)
err.set(res.exception());
if (uids.isEmpty() || err.get() != null)
qryMux.notifyAll();
}
}
};
Object resTopic = TOPIC_EVENT.topic(IgniteUuid.fromUuid(ctx.localNodeId()));
try {
addLocalEventListener(evtLsnr, new int[] { EVT_NODE_LEFT, EVT_NODE_FAILED });
ioMgr.addMessageListener(resTopic, resLsnr);
byte[] serFilter = U.marshal(marsh, p);
GridDeployment dep = ctx.deploy().deploy(p.getClass(), U.detectClassLoader(p.getClass()));
if (dep == null)
throw new IgniteDeploymentCheckedException("Failed to deploy event filter: " + p);
GridEventStorageMessage msg = new GridEventStorageMessage(resTopic, serFilter, p.getClass().getName(), dep.classLoaderId(), dep.deployMode(), dep.userVersion(), dep.participants());
sendMessage(nodes, TOPIC_EVENT, msg, PUBLIC_POOL);
if (timeout == 0)
timeout = Long.MAX_VALUE;
long now = U.currentTimeMillis();
// Account for overflow of long value.
long endTime = now + timeout <= 0 ? Long.MAX_VALUE : now + timeout;
long delta = timeout;
Collection<UUID> uidsCp = null;
synchronized (qryMux) {
try {
while (!uids.isEmpty() && err.get() == null && delta > 0) {
qryMux.wait(delta);
delta = endTime - U.currentTimeMillis();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IgniteCheckedException("Got interrupted while waiting for event query responses.", e);
}
if (err.get() != null)
throw new IgniteCheckedException("Failed to query events due to exception on remote node.", err.get());
if (!uids.isEmpty())
uidsCp = new LinkedList<>(uids);
}
// Outside of synchronization.
if (uidsCp != null) {
for (Iterator<UUID> iter = uidsCp.iterator(); iter.hasNext(); ) // Ignore nodes that have left the grid.
if (ctx.discovery().node(iter.next()) == null)
iter.remove();
if (!uidsCp.isEmpty())
throw new IgniteCheckedException("Failed to receive event query response from following nodes: " + uidsCp);
}
} finally {
ioMgr.removeMessageListener(resTopic, resLsnr);
removeLocalEventListener(evtLsnr);
}
return evts;
}
Aggregations