use of org.apache.ignite.spi.collision.CollisionJobContext in project ignite by apache.
the class FifoQueueCollisionSpi method onCollision.
/** {@inheritDoc} */
@Override
public void onCollision(CollisionContext ctx) {
assert ctx != null;
Collection<CollisionJobContext> activeJobs = ctx.activeJobs();
Collection<CollisionJobContext> waitJobs = ctx.waitingJobs();
// Save initial sizes to limit iteration.
int activeSize = activeJobs.size();
int waitSize = waitJobs.size();
waitingCnt = waitSize;
runningCnt = activeSize;
heldCnt = ctx.heldJobs().size();
int parallelJobsNum0 = parallelJobsNum;
Iterator<CollisionJobContext> it = null;
if (activeSize < parallelJobsNum0) {
it = waitJobs.iterator();
while (it.hasNext()) {
CollisionJobContext waitCtx = it.next();
waitCtx.activate();
if (--waitSize == 0)
// No more waiting jobs to process (to limit iterations).
return;
// Take actual size, since it might have been changed.
if (activeJobs.size() >= parallelJobsNum0)
// Max active jobs threshold reached.
break;
}
}
int waitJobsNum0 = waitJobsNum;
// Take actual size, since it might have been changed.
if (waitJobs.size() > waitJobsNum0) {
if (it == null)
it = waitJobs.iterator();
while (it.hasNext()) {
CollisionJobContext waitCtx = it.next();
waitCtx.cancel();
if (--waitSize == 0)
// No more waiting jobs to process (to limit iterations).
return;
// Take actual size, since it might have been changed.
if (waitJobs.size() <= waitJobsNum0)
// No need to reject more jobs.
return;
}
}
}
use of org.apache.ignite.spi.collision.CollisionJobContext in project ignite by apache.
the class JobStealingCollisionSpi method sortJobs.
/**
* Sort jobs by priority from high to lowest value.
*
* @param waitJobs Waiting jobs.
* @param waitSize Snapshot size.
* @return Sorted waiting jobs by priority.
*/
private Collection<CollisionJobContext> sortJobs(Collection<CollisionJobContext> waitJobs, int waitSize) {
List<CollisionJobContext> passiveList = new ArrayList<>(waitJobs.size());
int i = 0;
for (CollisionJobContext waitJob : waitJobs) {
passiveList.add(waitJob);
if (i++ == waitSize)
break;
}
Collections.sort(passiveList, comparator());
return passiveList;
}
use of org.apache.ignite.spi.collision.CollisionJobContext in project ignite by apache.
the class JobStealingCollisionSpi method checkBusy.
/**
* Check if node is busy and activate/reject proper number of jobs.
*
* @param waitJobs Waiting jobs.
* @param activeJobs Active jobs.
* @return Number of rejected jobs.
*/
private int checkBusy(Collection<CollisionJobContext> waitJobs, Collection<CollisionJobContext> activeJobs) {
int activeSize = activeJobs.size();
int waitSize = waitJobs.size();
waitingNum = waitJobs.size();
runningNum = activeSize;
IgniteSpiContext ctx = getSpiContext();
int activated = 0;
int rejected = 0;
Collection<CollisionJobContext> waitPriJobs = sortJobs(waitJobs, waitSize);
int activeJobsThreshold0 = activeJobsThreshold;
int waitJobsThreshold0 = waitJobsThreshold;
for (CollisionJobContext waitCtx : waitPriJobs) {
if (activeJobs.size() < activeJobsThreshold0) {
activated++;
// We also need to make sure that job is not being rejected by another thread.
synchronized (waitCtx.getJobContext()) {
waitCtx.activate();
}
} else if (stealReqs.get() > 0) {
if (waitCtx.getJob().getClass().isAnnotationPresent(JobStealingDisabled.class))
continue;
// Collision count attribute.
Integer stealingCnt = waitCtx.getJobContext().getAttribute(STEALING_ATTEMPT_COUNT_ATTR);
// has not been exceeded.
if (stealingCnt != null) {
// If job exceeded failover threshold, skip it.
if (stealingCnt >= maxStealingAttempts) {
if (log.isDebugEnabled())
log.debug("Waiting job exceeded stealing attempts and won't be rejected " + "(will try other jobs on waiting list): " + waitCtx);
continue;
}
} else
stealingCnt = 0;
// Check if allowed to reject job.
int jobsToReject = waitPriJobs.size() - activated - rejected - waitJobsThreshold0;
if (log.isDebugEnabled())
log.debug("Jobs to reject count [jobsToReject=" + jobsToReject + ", waitCtx=" + waitCtx + ']');
if (jobsToReject <= 0)
break;
Integer pri = waitCtx.getJobContext().getAttribute(STEALING_PRIORITY_ATTR);
if (pri == null)
pri = DFLT_JOB_PRIORITY;
// counter to prevent excessive iteration over nodes under load.
for (Iterator<Entry<UUID, MessageInfo>> iter = rcvMsgMap.entrySet().iterator(); iter.hasNext() && stealReqs.get() > 0; ) {
Entry<UUID, MessageInfo> entry = iter.next();
UUID nodeId = entry.getKey();
// Node has left topology.
if (ctx.node(nodeId) == null) {
iter.remove();
continue;
}
MessageInfo info = entry.getValue();
synchronized (info) {
int jobsAsked = info.jobsToSteal();
assert jobsAsked >= 0;
// Skip nodes that have not asked for jobs to steal.
if (jobsAsked == 0)
// Move to next node.
continue;
// If message is expired, ignore it.
if (info.expired()) {
// Subtract expired messages.
stealReqs.addAndGet(-info.jobsToSteal());
info.reset(0);
continue;
}
// Check that waiting job has thief node in topology.
boolean found = false;
for (UUID id : waitCtx.getTaskSession().getTopology()) {
if (id.equals(nodeId)) {
found = true;
break;
}
}
if (!found) {
if (log.isDebugEnabled())
log.debug("Thief node does not belong to task topology [thief=" + nodeId + ", task=" + waitCtx.getTaskSession() + ']');
continue;
}
if (stealReqs.get() <= 0)
break;
// rejected by another thread.
synchronized (waitCtx.getJobContext()) {
boolean cancel = waitCtx.getJobContext().getAttribute(THIEF_NODE_ATTR) == null;
if (cancel) {
// Mark job as stolen.
waitCtx.getJobContext().setAttribute(THIEF_NODE_ATTR, nodeId);
waitCtx.getJobContext().setAttribute(STEALING_ATTEMPT_COUNT_ATTR, stealingCnt + 1);
waitCtx.getJobContext().setAttribute(STEALING_PRIORITY_ATTR, pri + 1);
if (log.isDebugEnabled())
log.debug("Will try to reject job due to steal request [ctx=" + waitCtx + ", thief=" + nodeId + ']');
int i = stealReqs.decrementAndGet();
if (i >= 0 && waitCtx.cancel()) {
rejected++;
info.reset(jobsAsked - 1);
if (log.isDebugEnabled())
log.debug("Rejected job due to steal request [ctx=" + waitCtx + ", nodeId=" + nodeId + ']');
} else {
if (log.isDebugEnabled())
log.debug("Failed to reject job [i=" + i + ']');
waitCtx.getJobContext().setAttribute(THIEF_NODE_ATTR, null);
waitCtx.getJobContext().setAttribute(STEALING_ATTEMPT_COUNT_ATTR, stealingCnt);
waitCtx.getJobContext().setAttribute(STEALING_PRIORITY_ATTR, pri);
stealReqs.incrementAndGet();
}
}
}
// Move to next job.
break;
}
}
} else
// No more jobs to steal or activate.
break;
}
return rejected;
}
use of org.apache.ignite.spi.collision.CollisionJobContext in project ignite by apache.
the class GridJobStealingCollisionSpiCustomTopologySelfTest method testThiefNodeNotInTopology.
/**
* @throws Exception If test failed.
*/
public void testThiefNodeNotInTopology() throws Exception {
List<CollisionJobContext> waitCtxs = new ArrayList<>(2);
final ClusterNode node = getSpiContext().nodes().iterator().next();
Collections.addAll(waitCtxs, new GridTestCollisionJobContext(createTaskSession(node), IgniteUuid.randomUuid()), new GridTestCollisionJobContext(createTaskSession(node), IgniteUuid.randomUuid()), new GridTestCollisionJobContext(createTaskSession(node), IgniteUuid.randomUuid()));
Collection<CollisionJobContext> activeCtxs = new ArrayList<>(1);
// Add active.
Collections.addAll(activeCtxs, new GridTestCollisionJobContext(createTaskSession(node), IgniteUuid.randomUuid()));
// Emulate message to steal 2 jobs.
getSpiContext().triggerMessage(rmtNode2, new JobStealingRequest(2));
getSpi().onCollision(new GridCollisionTestContext(activeCtxs, waitCtxs));
// Check no action.
checkNoAction((GridTestCollisionJobContext) waitCtxs.get(0));
checkNoAction((GridTestCollisionJobContext) waitCtxs.get(1));
checkNoAction((GridTestCollisionJobContext) waitCtxs.get(2));
// Make sure that no message was sent.
Serializable msg1 = getSpiContext().removeSentMessage(getSpiContext().localNode());
assert msg1 == null;
Serializable mgs2 = getSpiContext().removeSentMessage(rmtNode1);
assert mgs2 == null;
Serializable msg3 = getSpiContext().removeSentMessage(rmtNode2);
assert msg3 == null;
}
use of org.apache.ignite.spi.collision.CollisionJobContext in project ignite by apache.
the class GridJobStealingCollisionSpiSelfTest method testOnePassiveOneActiveJobs.
/**
* @throws Exception If test failed.
*/
public void testOnePassiveOneActiveJobs() throws Exception {
List<CollisionJobContext> waitCtxs = new ArrayList<>(1);
// Add passive.
Collections.addAll(waitCtxs, new GridTestCollisionJobContext(createTaskSession(), IgniteUuid.randomUuid()));
List<CollisionJobContext> activeCtxs = new ArrayList<>(1);
// Add active.
Collections.addAll(activeCtxs, new GridTestCollisionJobContext(createTaskSession(), IgniteUuid.randomUuid()));
ClusterNode rmtNode = F.first(getSpiContext().remoteNodes());
getSpiContext().triggerMessage(rmtNode, new JobStealingRequest(1));
getSpi().onCollision(new GridCollisionTestContext(activeCtxs, waitCtxs));
// Active job.
checkNoAction((GridTestCollisionJobContext) activeCtxs.get(0));
// Rejected.
checkRejected((GridTestCollisionJobContext) waitCtxs.get(0), rmtNode);
// Make sure that no message was sent.
Serializable msg = getSpiContext().removeSentMessage(rmtNode);
assert msg == null;
}
Aggregations