All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jppf.server.protocol.ServerTaskBundleNode Maven / Gradle / Ivy

There is a newer version: 6.3-alpha
Show newest version
/*
 * JPPF.
 * Copyright (C) 2005-2015 JPPF Team.
 * http://www.jppf.org
 *
 * 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 org.jppf.server.protocol;

import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicLong;

import org.jppf.execute.ExecutorChannel;
import org.jppf.io.DataLocation;
import org.jppf.job.JobReturnReason;
import org.jppf.node.protocol.TaskBundle;
import org.jppf.utils.*;
import org.slf4j.*;

/**
 * Instances of this class group tasks for the same node channel together.
 * @author Martin JANDA
 * @exclude
 */
public class ServerTaskBundleNode {
  /**
   * Logger for this class.
   */
  private static final Logger log = LoggerFactory.getLogger(ServerTaskBundleNode.class);
  /**
   * Determines whether debug-level logging is enabled.
   */
  private static boolean debugEnabled = LoggingUtils.isDebugEnabled(log);
  /**
   * Flag indicating whether collection of debug information is available via JMX.
   */
  private static final boolean JPPF_DEBUG = JPPFConfiguration.getProperties().getBoolean("jppf.debug.enabled", false);
  /**
   * Count of instances of this class.
   */
  private static final AtomicLong INSTANCE_COUNT = new AtomicLong(0L);
  /**
   * A unique id for this node bundle.
   */
  private final long id = INSTANCE_COUNT.incrementAndGet();
  /**
   * The job to execute.
   */
  private final ServerJob job;
  /**
   * The shared data provider for this task bundle.
   */
  private transient final DataLocation dataProvider;
  /**
   * The tasks to be executed by the node.
   */
  private transient final List taskList;
  /**
   * Job requeue indicator.
   */
  private boolean requeued = false;
  /**
   * Job cancel indicator.
   */
  private boolean cancelled  = false;
  /**
   * Job dispatch expiration indicator.
   */
  private boolean expired  = false;
  /**
   * The job this submission is for.
   */
  private TaskBundle taskBundle;
  /**
   * Channel to which is this bundle dispatched.
   */
  private ExecutorChannel channel = null;
  /**
   * The future from channel dispatch.
   */
  private Future future = null;
  /**
   * The number of tasks in this node bundle.
   */
  private final int taskCount;
  /**
   * The reason why the task results are reeived.
   */
  private JobReturnReason jobReturnReason = null;

  /**
   * Initialize this task bundle and set its build number.
   * @param job   the job to execute.
   * @param taskBundle the job.
   * @param taskList the tasks to execute.
   */
  public ServerTaskBundleNode(final ServerJob job, final TaskBundle taskBundle, final List taskList) {
    if (job == null) throw new IllegalArgumentException("job is null");
    if (taskBundle == null) throw new IllegalArgumentException("taskBundle is null");
    if (taskList == null) throw new IllegalArgumentException("taskList is null");

    this.job = job;
    this.taskBundle = taskBundle;
    this.taskList = new ArrayList<>(taskList);
    int size = this.taskList.size();
    this.taskBundle.setTaskCount(size);
    this.taskBundle.setCurrentTaskCount(size);
    this.dataProvider = job.getDataProvider();
    this.taskCount = size;
    if (JPPF_DEBUG) this.taskBundle.setParameter("node.bundle.id", this.id);
    checkTaskCount();
  }

  /**
   * Get the job this submission is for.
   * @return a {@link TaskBundle} instance.
   */
  public TaskBundle getJob() {
    return taskBundle;
  }

  /**
   * Get the client job this submission is for
   * @return a {@link ServerJob} instance.
   */
  public ServerJob getClientJob() {
    return job;
  }

  /**
   * Get shared data provider for this task.
   * @return a DataProvider instance.
   */
  public DataLocation getDataProvider() {
    return dataProvider;
  }

  /**
   * Get the tasks to be executed by the node.
   * @return the tasks as a List of arrays of bytes.
   */
  public List getTaskList() {
    return taskList;
  }

  /**
   * Set the node channel onto this job dispatch.
   * @param channel the node to which the job is dispatched.
   */
  public void setChannel(final ExecutorChannel channel) {
    if (channel == null) throw new IllegalArgumentException("channel is null for " + this);
    this.channel = channel;
  }

  /**
   * Called when all or part of a job is dispatched to a node.
   * @param channel the node to which the job is dispatched.
   * @param future  future assigned to bundle execution.
   */
  public void jobDispatched(final ExecutorChannel channel, final Future future) {
    if (channel == null) throw new IllegalArgumentException("channel is null for " + this);
    if (future == null) throw new IllegalArgumentException("future is null for " + this);
    this.channel = channel;
    this.future  = future;
    job.jobDispatched(this);
  }

  /**
   * Called to notify that the results of a number of tasks have been received from the server.
   * @param results the list of tasks whose results have been received from the server.
   */
  public void resultsReceived(final List results) {
    job.resultsReceived(this, results);
    taskCompleted(null);
  }

  /**
   * Called to notify that throwable eventually raised while receiving the results.
   * @param throwable the throwable that was raised while receiving the results.
   */
  public void resultsReceived(final Throwable throwable) {
    job.resultsReceived(this, throwable);
    taskCompleted(throwable);
  }

  /**
   * Called to notify that the execution of a task has completed.
   * @param exception the {@link Exception} thrown during job execution or null.
   */
  public void taskCompleted(final Throwable exception) {
    if (debugEnabled && (exception != null))
      log.debug(String.format("received exception for %s : %s%ncall stack:%n%s" , this, ExceptionUtils.getStackTrace(exception), ExceptionUtils.getCallStack()));
    try {
      job.jobReturned(this);
    } finally {
      //job.taskCompleted(this, exception);
      this.channel = null;
      this.future = null;
    }
  }

  /**
   * Called when this task bundle should be resubmitted
   */
  public void resubmit() {
    if (getJob().getSLA().isBroadcastJob()) return; // broadcast jobs cannot be resubmitted.
    synchronized(this) {
      requeued = true;
      for (ServerTask task: taskList) task.resubmit();
    }
  }

  /**
   * Called when this task bundle should be resubmitted
   */
  public void expire() {
    if (getJob().getSLA().isBroadcastJob()) return; // broadcast jobs cannot expire.
    int max = job.getSLA().getMaxDispatchExpirations();
    synchronized(this) {
      for (ServerTask task: taskList) {
        if (task.incExpirationCount() > max) task.cancel();
        else task.resubmit();
      }
      expired = true;
    }
  }

  /**
   * Get the requeued indicator.
   * @return true if job is requeued, false otherwise.
   */
  public synchronized boolean isRequeued() {
    return requeued;
  }

  /**
   * Called when this task bundle is cancelled.
   */
  public synchronized void cancel() {
    this.cancelled = true;
    for (ServerTask task: taskList) task.cancel();
  }

  /**
   * Get the cancelled indicator.
   * @return true if job is cancelled, false otherwise.
   */
  public synchronized boolean isCancelled() {
    return cancelled;
  }

  /**
   * Get the expired indicator.
   * @return true if job dispatch is expired, false otherwise.
   */
  public synchronized boolean isExpired() {
    return expired;
  }

  /**
   * Get the channel to which the job is dispatched.
   * @return an ExecutorChannel instance.
   */
  public ExecutorChannel getChannel() {
    return channel;
  }

  /**
   * Get the future corresponding to the channel dispatch.
   * @return a Future instance.
   */
  public Future getFuture() {
    return future;
  }

  /**
   * Check the task count in this node bundle is equal to the one in its JPPFTaskBundle.
   */
  public void checkTaskCount() {
    if (taskCount != taskBundle.getTaskCount()) throw new IllegalStateException("task counts do not match");
  }

  /**
   * Get the number of tasks in this node bundle.
   * @return the number of tasks as an int.
   */
  public int getTaskCount()
  {
    return taskCount;
  }

  @Override
  public String toString()
  {
    StringBuilder sb = new StringBuilder();
    sb.append(getClass().getSimpleName()).append('[');
    sb.append("id=").append(id);
    sb.append(", name=").append(job.getName());
    sb.append(", uuid=").append(job.getUuid());
    sb.append(", initialTaskCount=").append(job.getInitialTaskCount());
    sb.append(", taskCount=").append(taskCount);
    sb.append(", cancelled=").append(cancelled);
    sb.append(", requeued=").append(requeued);
    sb.append(", channel=").append(channel);
    sb.append(']');
    return sb.toString();
  }

  @Override
  public int hashCode()
  {
    final int prime = 31;
    int result = 1;
    result = prime * result + (int) (id ^ (id >>> 32));
    return result;
  }

  @Override
  public boolean equals(final Object obj)
  {
    if (this == obj) return true;
    if (obj == null) return false;
    if (getClass() != obj.getClass()) return false;
    ServerTaskBundleNode other = (ServerTaskBundleNode) obj;
    return id == other.id;
  }

  /**
   * Get the unique id for this node bundle.
   * @return the id as a long value.
   */
  public long getId()
  {
    return id;
  }

  /**
   * Build a unique key for the specified node task bundle.
   * @param bundle a {@link ServerTaskBundleNode} instance.
   * @return a unique key as a string.
   */
  public static String makeKey(final ServerTaskBundleNode bundle)
  {
    return makeKey(bundle.getJob().getUuid(), bundle.getId());
  }

  /**
   * Build a unique key for a node task bundle with the specified job uuid and node id.
   * @param jobUuid the uuid of the job to which the bundle belongs.
   * @param bundleId the id of the bundle.
   * @return a unique key as a string.
   */
  public static String makeKey(final String jobUuid, final long bundleId)
  {
    return new StringBuilder(jobUuid).append('|').append(bundleId).toString();
  }

  /**
   * Get the reason why the task results are reeived.
   * @return a {@link JobReturnReason} enum value.
   */
  public JobReturnReason getJobReturnReason() {
    return jobReturnReason;
  }

  /**
   * Set the reason why the task results are reeived.
   * @param jobReturnReason a {@link JobReturnReason} enum value.
   */
  public void setJobReturnReason(final JobReturnReason jobReturnReason) {
    this.jobReturnReason = jobReturnReason;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy