use of org.apache.hyracks.api.job.ActivityCluster in project asterixdb by apache.
the class ActivityClusterGraphRewriter method rewriteIntraActivityCluster.
/**
* rewrite an activity cluster internally
*
* @param ac
* the activity cluster to be rewritten
*/
private void rewriteIntraActivityCluster(ActivityCluster ac, Map<IActivity, SuperActivity> invertedActivitySuperActivityMap) {
Map<ActivityId, IActivity> activities = ac.getActivityMap();
Map<ActivityId, List<IConnectorDescriptor>> activityInputMap = ac.getActivityInputMap();
Map<ActivityId, List<IConnectorDescriptor>> activityOutputMap = ac.getActivityOutputMap();
Map<ConnectorDescriptorId, Pair<Pair<IActivity, Integer>, Pair<IActivity, Integer>>> connectorActivityMap = ac.getConnectorActivityMap();
ActivityClusterGraph acg = ac.getActivityClusterGraph();
Map<ActivityId, IActivity> startActivities = new HashMap<ActivityId, IActivity>();
Map<ActivityId, SuperActivity> superActivities = new HashMap<ActivityId, SuperActivity>();
Map<ActivityId, Queue<IActivity>> toBeExpendedMap = new HashMap<ActivityId, Queue<IActivity>>();
/**
* Build the initial super activities
*/
for (Entry<ActivityId, IActivity> entry : activities.entrySet()) {
ActivityId activityId = entry.getKey();
IActivity activity = entry.getValue();
if (activityInputMap.get(activityId) == null) {
startActivities.put(activityId, activity);
/**
* use the start activity's id as the id of the super activity
*/
createNewSuperActivity(ac, superActivities, toBeExpendedMap, invertedActivitySuperActivityMap, activityId, activity);
}
}
/**
* expand one-to-one connected activity cluster by the BFS order.
* after the while-loop, the original activities are partitioned
* into equivalent classes, one-per-super-activity.
*/
Map<ActivityId, SuperActivity> clonedSuperActivities = new HashMap<ActivityId, SuperActivity>();
while (toBeExpendedMap.size() > 0) {
clonedSuperActivities.clear();
clonedSuperActivities.putAll(superActivities);
for (Entry<ActivityId, SuperActivity> entry : clonedSuperActivities.entrySet()) {
ActivityId superActivityId = entry.getKey();
SuperActivity superActivity = entry.getValue();
/**
* for the case where the super activity has already been swallowed
*/
if (superActivities.get(superActivityId) == null) {
continue;
}
/**
* expend the super activity
*/
Queue<IActivity> toBeExpended = toBeExpendedMap.get(superActivityId);
if (toBeExpended == null) {
/**
* Nothing to expand
*/
continue;
}
IActivity expendingActivity = toBeExpended.poll();
List<IConnectorDescriptor> outputConnectors = activityOutputMap.get(expendingActivity.getActivityId());
if (outputConnectors != null) {
for (IConnectorDescriptor outputConn : outputConnectors) {
Pair<Pair<IActivity, Integer>, Pair<IActivity, Integer>> endPoints = connectorActivityMap.get(outputConn.getConnectorId());
IActivity newActivity = endPoints.getRight().getLeft();
SuperActivity existingSuperActivity = invertedActivitySuperActivityMap.get(newActivity);
if (outputConn.getClass().getName().contains(ONE_TO_ONE_CONNECTOR)) {
/**
* expend the super activity cluster on an one-to-one out-bound connection
*/
if (existingSuperActivity == null) {
superActivity.addActivity(newActivity);
toBeExpended.add(newActivity);
invertedActivitySuperActivityMap.put(newActivity, superActivity);
} else {
/**
* the two activities already in the same super activity
*/
if (existingSuperActivity == superActivity) {
continue;
}
/**
* swallow an existing super activity
*/
swallowExistingSuperActivity(superActivities, toBeExpendedMap, invertedActivitySuperActivityMap, superActivity, superActivityId, existingSuperActivity);
}
} else {
if (existingSuperActivity == null) {
/**
* create new activity
*/
createNewSuperActivity(ac, superActivities, toBeExpendedMap, invertedActivitySuperActivityMap, newActivity.getActivityId(), newActivity);
}
}
}
}
/**
* remove the to-be-expended queue if it is empty
*/
if (toBeExpended.size() == 0) {
toBeExpendedMap.remove(superActivityId);
}
}
}
Map<ConnectorDescriptorId, IConnectorDescriptor> connMap = ac.getConnectorMap();
Map<ConnectorDescriptorId, RecordDescriptor> connRecordDesc = ac.getConnectorRecordDescriptorMap();
Map<SuperActivity, Integer> superActivityProducerPort = new HashMap<SuperActivity, Integer>();
Map<SuperActivity, Integer> superActivityConsumerPort = new HashMap<SuperActivity, Integer>();
for (Entry<ActivityId, SuperActivity> entry : superActivities.entrySet()) {
superActivityProducerPort.put(entry.getValue(), 0);
superActivityConsumerPort.put(entry.getValue(), 0);
}
/**
* create a new activity cluster to replace the old activity cluster
*/
ActivityCluster newActivityCluster = new ActivityCluster(acg, ac.getId());
newActivityCluster.setConnectorPolicyAssignmentPolicy(ac.getConnectorPolicyAssignmentPolicy());
for (Entry<ActivityId, SuperActivity> entry : superActivities.entrySet()) {
newActivityCluster.addActivity(entry.getValue());
acg.getActivityMap().put(entry.getKey(), newActivityCluster);
}
/**
* Setup connectors: either inside a super activity or among super activities
*/
for (Entry<ConnectorDescriptorId, Pair<Pair<IActivity, Integer>, Pair<IActivity, Integer>>> entry : connectorActivityMap.entrySet()) {
ConnectorDescriptorId connectorId = entry.getKey();
Pair<Pair<IActivity, Integer>, Pair<IActivity, Integer>> endPoints = entry.getValue();
IActivity producerActivity = endPoints.getLeft().getLeft();
IActivity consumerActivity = endPoints.getRight().getLeft();
int producerPort = endPoints.getLeft().getRight();
int consumerPort = endPoints.getRight().getRight();
RecordDescriptor recordDescriptor = connRecordDesc.get(connectorId);
IConnectorDescriptor conn = connMap.get(connectorId);
if (conn.getClass().getName().contains(ONE_TO_ONE_CONNECTOR)) {
/**
* connection edge between inner activities
*/
SuperActivity residingSuperActivity = invertedActivitySuperActivityMap.get(producerActivity);
residingSuperActivity.connect(conn, producerActivity, producerPort, consumerActivity, consumerPort, recordDescriptor);
} else {
/**
* connection edge between super activities
*/
SuperActivity producerSuperActivity = invertedActivitySuperActivityMap.get(producerActivity);
SuperActivity consumerSuperActivity = invertedActivitySuperActivityMap.get(consumerActivity);
int producerSAPort = superActivityProducerPort.get(producerSuperActivity);
int consumerSAPort = superActivityConsumerPort.get(consumerSuperActivity);
newActivityCluster.addConnector(conn);
newActivityCluster.connect(conn, producerSuperActivity, producerSAPort, consumerSuperActivity, consumerSAPort, recordDescriptor);
/**
* bridge the port
*/
producerSuperActivity.setClusterOutputIndex(producerSAPort, producerActivity.getActivityId(), producerPort);
consumerSuperActivity.setClusterInputIndex(consumerSAPort, consumerActivity.getActivityId(), consumerPort);
acg.getConnectorMap().put(connectorId, newActivityCluster);
/**
* increasing the port number for the producer and consumer
*/
superActivityProducerPort.put(producerSuperActivity, ++producerSAPort);
superActivityConsumerPort.put(consumerSuperActivity, ++consumerSAPort);
}
}
/**
* Set up the roots of the new activity cluster
*/
for (Entry<ActivityId, SuperActivity> entry : superActivities.entrySet()) {
List<IConnectorDescriptor> connIds = newActivityCluster.getActivityOutputMap().get(entry.getKey());
if (connIds == null || connIds.size() == 0) {
newActivityCluster.addRoot(entry.getValue());
}
}
/**
* set up the blocked2Blocker mapping, which will be updated in the rewriteInterActivityCluster call
*/
newActivityCluster.getBlocked2BlockerMap().putAll(ac.getBlocked2BlockerMap());
/**
* replace the old activity cluster with the new activity cluster
*/
acg.getActivityClusterMap().put(ac.getId(), newActivityCluster);
}
use of org.apache.hyracks.api.job.ActivityCluster in project asterixdb by apache.
the class ActivityClusterGraphRewriter method rewriteInterActivityCluster.
/**
* rewrite the blocking relationship among activity cluster
*
* @param ac
* the activity cluster to be rewritten
*/
private void rewriteInterActivityCluster(ActivityCluster ac, Map<IActivity, SuperActivity> invertedActivitySuperActivityMap) {
Map<ActivityId, Set<ActivityId>> blocked2BlockerMap = ac.getBlocked2BlockerMap();
Map<ActivityId, ActivityId> invertedAid2SuperAidMap = new HashMap<ActivityId, ActivityId>();
for (Entry<IActivity, SuperActivity> entry : invertedActivitySuperActivityMap.entrySet()) {
invertedAid2SuperAidMap.put(entry.getKey().getActivityId(), entry.getValue().getActivityId());
}
Map<ActivityId, Set<ActivityId>> replacedBlocked2BlockerMap = new HashMap<ActivityId, Set<ActivityId>>();
for (Entry<ActivityId, Set<ActivityId>> entry : blocked2BlockerMap.entrySet()) {
ActivityId blocked = entry.getKey();
ActivityId replacedBlocked = invertedAid2SuperAidMap.get(blocked);
Set<ActivityId> blockers = entry.getValue();
Set<ActivityId> replacedBlockers = null;
if (blockers != null) {
replacedBlockers = new HashSet<ActivityId>();
for (ActivityId blocker : blockers) {
replacedBlockers.add(invertedAid2SuperAidMap.get(blocker));
ActivityCluster dependingAc = ac.getActivityClusterGraph().getActivityMap().get(invertedAid2SuperAidMap.get(blocker));
if (!ac.getDependencies().contains(dependingAc)) {
ac.getDependencies().add(dependingAc);
}
}
}
if (replacedBlockers != null) {
Set<ActivityId> existingBlockers = replacedBlocked2BlockerMap.get(replacedBlocked);
if (existingBlockers == null) {
replacedBlocked2BlockerMap.put(replacedBlocked, replacedBlockers);
} else {
existingBlockers.addAll(replacedBlockers);
replacedBlocked2BlockerMap.put(replacedBlocked, existingBlockers);
}
}
}
blocked2BlockerMap.clear();
blocked2BlockerMap.putAll(replacedBlocked2BlockerMap);
}
use of org.apache.hyracks.api.job.ActivityCluster in project asterixdb by apache.
the class ActivityClusterGraphBuilder method inferActivityClusters.
public ActivityClusterGraph inferActivityClusters(JobId jobId, JobActivityGraph jag) {
/*
* Build initial equivalence sets map. We create a map such that for each IOperatorTask, t -> { t }
*/
Map<ActivityId, Set<ActivityId>> stageMap = new HashMap<ActivityId, Set<ActivityId>>();
Set<Set<ActivityId>> stages = new HashSet<Set<ActivityId>>();
for (ActivityId taskId : jag.getActivityMap().keySet()) {
Set<ActivityId> eqSet = new HashSet<ActivityId>();
eqSet.add(taskId);
stageMap.put(taskId, eqSet);
stages.add(eqSet);
}
boolean changed = true;
while (changed) {
changed = false;
Pair<ActivityId, ActivityId> pair = findMergePair(jag, stages);
if (pair != null) {
merge(stageMap, stages, pair.getLeft(), pair.getRight());
changed = true;
}
}
ActivityClusterGraph acg = new ActivityClusterGraph();
Map<ActivityId, ActivityCluster> acMap = new HashMap<ActivityId, ActivityCluster>();
int acCounter = 0;
Map<ActivityId, IActivity> activityNodeMap = jag.getActivityMap();
List<ActivityCluster> acList = new ArrayList<ActivityCluster>();
for (Set<ActivityId> stage : stages) {
ActivityCluster ac = new ActivityCluster(acg, new ActivityClusterId(jobId, acCounter++));
acList.add(ac);
for (ActivityId aid : stage) {
IActivity activity = activityNodeMap.get(aid);
ac.addActivity(activity);
acMap.put(aid, ac);
}
}
for (Set<ActivityId> stage : stages) {
for (ActivityId aid : stage) {
IActivity activity = activityNodeMap.get(aid);
ActivityCluster ac = acMap.get(aid);
List<IConnectorDescriptor> aOutputs = jag.getActivityOutputMap().get(aid);
if (aOutputs == null || aOutputs.isEmpty()) {
ac.addRoot(activity);
} else {
int nActivityOutputs = aOutputs.size();
for (int i = 0; i < nActivityOutputs; ++i) {
IConnectorDescriptor conn = aOutputs.get(i);
ac.addConnector(conn);
Pair<Pair<IActivity, Integer>, Pair<IActivity, Integer>> pcPair = jag.getConnectorActivityMap().get(conn.getConnectorId());
ac.connect(conn, activity, i, pcPair.getRight().getLeft(), pcPair.getRight().getRight(), jag.getConnectorRecordDescriptorMap().get(conn.getConnectorId()));
}
}
}
}
Map<ActivityId, Set<ActivityId>> blocked2BlockerMap = jag.getBlocked2BlockerMap();
for (ActivityCluster s : acList) {
Map<ActivityId, Set<ActivityId>> acBlocked2BlockerMap = s.getBlocked2BlockerMap();
Set<ActivityCluster> blockerStages = new HashSet<ActivityCluster>();
for (ActivityId t : s.getActivityMap().keySet()) {
Set<ActivityId> blockerTasks = blocked2BlockerMap.get(t);
acBlocked2BlockerMap.put(t, blockerTasks);
if (blockerTasks != null) {
for (ActivityId bt : blockerTasks) {
blockerStages.add(acMap.get(bt));
}
}
}
for (ActivityCluster bs : blockerStages) {
s.getDependencies().add(bs);
}
}
acg.addActivityClusters(acList);
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine(acg.toJSON().asText());
}
return acg;
}
use of org.apache.hyracks.api.job.ActivityCluster in project asterixdb by apache.
the class JobExecutor method assignLocation.
private String assignLocation(ActivityClusterGraph acg, Map<TaskId, LValueConstraintExpression> locationMap, TaskId tid, TaskAttempt taskAttempt) throws HyracksException {
ActivityId aid = tid.getActivityId();
ActivityCluster ac = acg.getActivityMap().get(aid);
Set<ActivityId> blockers = ac.getBlocked2BlockerMap().get(aid);
String nodeId = null;
if (blockers != null) {
for (ActivityId blocker : blockers) {
nodeId = findTaskLocation(new TaskId(blocker, tid.getPartition()));
if (nodeId != null) {
break;
}
}
}
INodeManager nodeManager = ccs.getNodeManager();
Collection<String> liveNodes = nodeManager.getAllNodeIds();
if (nodeId == null) {
LValueConstraintExpression pLocationExpr = locationMap.get(tid);
Object location = solver.getValue(pLocationExpr);
if (location == null) {
// pick any
nodeId = liveNodes.toArray(new String[liveNodes.size()])[random.nextInt(1) % liveNodes.size()];
} else if (location instanceof String) {
nodeId = (String) location;
} else if (location instanceof String[]) {
for (String choice : (String[]) location) {
if (liveNodes.contains(choice)) {
nodeId = choice;
break;
}
}
if (nodeId == null) {
throw new HyracksException("No satisfiable location found for " + taskAttempt.getTaskAttemptId());
}
} else {
throw new HyracksException("Unknown type of value for " + pLocationExpr + ": " + location + "(" + location.getClass() + ")");
}
}
if (nodeId == null) {
throw new HyracksException("No satisfiable location found for " + taskAttempt.getTaskAttemptId());
}
if (!liveNodes.contains(nodeId)) {
throw new HyracksException("Node " + nodeId + " not live");
}
return nodeId;
}
use of org.apache.hyracks.api.job.ActivityCluster in project asterixdb by apache.
the class JobExecutor method abortOngoingTaskClusters.
/**
* Aborts ongoing task clusters.
*
* @param taskFilter,
* selects tasks that should be directly marked as failed without doing the aborting RPC.
* @param exceptionGenerator,
* generates an exception for tasks that are directly marked as failed.
*/
private void abortOngoingTaskClusters(ITaskFilter taskFilter, IExceptionGenerator exceptionGenerator) throws HyracksException {
for (ActivityCluster ac : jobRun.getActivityClusterGraph().getActivityClusterMap().values()) {
if (!isPlanned(ac)) {
continue;
}
TaskCluster[] taskClusters = getActivityClusterPlan(ac).getTaskClusters();
if (taskClusters == null) {
continue;
}
for (TaskCluster tc : taskClusters) {
TaskClusterAttempt lastTaskClusterAttempt = findLastTaskClusterAttempt(tc);
if (lastTaskClusterAttempt == null || !(lastTaskClusterAttempt.getStatus() == TaskClusterAttempt.TaskClusterStatus.COMPLETED || lastTaskClusterAttempt.getStatus() == TaskClusterAttempt.TaskClusterStatus.RUNNING)) {
continue;
}
boolean abort = false;
for (TaskAttempt ta : lastTaskClusterAttempt.getTaskAttempts().values()) {
assert ta.getStatus() == TaskAttempt.TaskStatus.COMPLETED || ta.getStatus() == TaskAttempt.TaskStatus.RUNNING;
if (taskFilter.directlyMarkAsFailed(ta)) {
// Directly mark it as fail, without further aborting.
ta.setStatus(TaskAttempt.TaskStatus.FAILED, Collections.singletonList(exceptionGenerator.getException(ta)));
ta.setEndTime(System.currentTimeMillis());
abort = true;
}
}
if (abort) {
abortTaskCluster(lastTaskClusterAttempt, TaskClusterAttempt.TaskClusterStatus.ABORTED);
}
}
abortDoomedTaskClusters();
}
}
Aggregations