Package org.nebulaframework.grid.cluster.manager.services.jobs.splitaggregate

Source Code of org.nebulaframework.grid.cluster.manager.services.jobs.splitaggregate.AggregatorServiceImpl

/*
* Copyright (C) 2008 Yohan Liyanage.
*
* 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.nebulaframework.grid.cluster.manager.services.jobs.splitaggregate;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.jms.ConnectionFactory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nebulaframework.core.job.GridJobState;
import org.nebulaframework.core.job.exceptions.AggregateException;
import org.nebulaframework.core.job.splitaggregate.SplitAggregateGridJob;
import org.nebulaframework.core.task.GridTaskResult;
import org.nebulaframework.grid.cluster.manager.ClusterManager;
import org.nebulaframework.grid.cluster.manager.services.jobs.ClusterJobService;
import org.nebulaframework.grid.cluster.manager.services.jobs.GridJobProfile;
import org.nebulaframework.grid.cluster.manager.services.jobs.InternalClusterJobService;
import org.nebulaframework.util.jms.JMSNamingSupport;
import org.springframework.jms.listener.DefaultMessageListenerContainer;
import org.springframework.jms.listener.adapter.MessageListenerAdapter;

/**
* Implementation of {@code AggregatorService}.
* <p>
* {@code AggregatorService} collects results of {@code GridTask}s from
* participating {@code GridNode}s and aggregates results to calculate
* the final result for the {@code GridJob}.
* <p>
* <i>Spring Managed</i>
*
* @author Yohan Liyanage
* @version 1.0
*
* @see AggregatorService
* @see ClusterJobService
*/
public class AggregatorServiceImpl implements AggregatorService {

  private static Log log = LogFactory.getLog(AggregatorServiceImpl.class);
 
  private ConnectionFactory connectionFactory;
  private InternalClusterJobService jobService;
  private boolean initialized = false;
 
  /**
   * Constructs an AggregatorServiceImpl instance.
   */
  public AggregatorServiceImpl() {
    super();

  }
 
  private synchronized void initialize() {
    if (!initialized) {
      ClusterManager manager = ClusterManager.getInstance();
      this.jobService = manager.getJobService();     
      this.connectionFactory = ClusterManager.getInstance().getConnectionFactory();
      initialized = true;
    }
  }
 
  /**
   * {@inheritDoc}
   * <p>
   * This method simply delegates to {@code #doStartAggregator(GridJobProfile)} method,
   * invoked on a separate {@code Thread}.
   */
  public synchronized void startAggregator(final GridJobProfile profile, final SplitAggregateJobManager manager) {
   
    initialize();
   
    //Start Aggregator, on a new Thread
    new Thread(new Runnable() {
      public void run() {
        try {
          doStartAggregator(profile, manager);
        } catch (Exception e) {
          log.error("[Aggregator] Exception while starting ", e);
        }
      }
    }, "Aggregator[ResultCollector]-" + profile.getJobId()).start();
  }

  /**
   * Internal method which handles the aggregator start-up for
   * a given {@code GridJobProfile}.
   * <p>
   * Creates and starts a {@code ResultCollector} instance for
   * the given {@code GridJob}, and also creates necessary JMS message
   * handling infrastructure.
   *
   * @param profile {@code GridJobProfile} jobProfile
   */
  protected void doStartAggregator(GridJobProfile profile, SplitAggregateJobManager manager) {
   
    // Create Message Listener Adapter and Result Collector for Job
    MessageListenerAdapter adapter = new MessageListenerAdapter();
    adapter.setDefaultListenerMethod("onResult");

    // Create JMS Message Listener Container
    DefaultMessageListenerContainer container = new DefaultMessageListenerContainer();
    container.setConnectionFactory(connectionFactory);
    container.setDestinationName(JMSNamingSupport
        .getResultQueueName(profile.getJobId()));
    container.setMessageListener(adapter);
   
    //Create results collector and set it as Execution Manager
    ResultCollector collector = new ResultCollector(profile, manager, container);
    profile.setExecutionManager(manager);
    manager.addResultCollector(profile.getJobId(), collector);
   
    // Initialize Adapter and Container
    adapter.setDelegate(collector);
    container.afterPropertiesSet();
  }

  /**
   * {@inheritDoc}
   * <p>
   * This method simply delegates to {@code #doAggregateResults(GridJobProfile)} method,
   * invoked on a separate {@code Thread}.
   */
  public void aggregateResults(final GridJobProfile profile) {

    // Aggregate results, on a separate Thread
    new Thread(new Runnable() {
      public void run() {
        try {
          doAggregateResults(profile);
        } catch (Exception e) {
          log.error("[Aggregator] Exception while starting ", e);
        }
      }
    }, "Aggregator[Aggregate]-" + profile.getJobId()).start();

  }

  /**
   * Internal method which does the aggregation of {@code GridTaskResult}s for a
   * given {@code GridJob}, denoted by corresponding {@code GridJobProfile}.
   * <p>
   * Furthermore, this method invokes necessary methods of {@code ClusterJobServiceImpl}
   * to notify workers about events such as End of Job Execution.<p>
   *
   * @param profile {@code GridJobProfile} of {@code GridJob}
   */
  protected void doAggregateResults(GridJobProfile profile) {
   
    Serializable jobResult = null;
   
    // Get GridTaskResults
    Collection<GridTaskResult> taskResults = profile.getResults();
    List<Serializable> results = new ArrayList<Serializable>();
   
    try {
      log.info("[Aggregator] Aggregating Results for Job : {" + profile.getJobId() + "}");
     
      // Fetch the result from GridTaskResults
      for (GridTaskResult result : taskResults) {
        results.add(result.getResult());
      }
     
      // Do Aggregation
      jobResult = ((SplitAggregateGridJob<?, ?>)profile.getJob()).aggregate(results);
     
    } catch (SecurityException e) {
     
      log.error("[Aggregator] Security Violation while aggregating final result of "
          + profile.getJobId(), e);
     
      // Update Future
      profile.getFuture().setException(e);
      profile.getFuture().setState(GridJobState.FAILED);
     
      // Notify Workers that Job is canceled
      jobService.notifyJobCancel(profile.getJobId());
     
      return;
    } catch (Exception e) {
     
     
      log.warn("[Aggregator] Exception while aggregating final result of "
          + profile.getJobId(), e);
     
      // Wait if execution completed before minimum duration
      waitIfNeeded(profile);
     
      // Update Future
      profile.getFuture().setException(new AggregateException(e));
      profile.getFuture().setState(GridJobState.FAILED);
     
      // Notify Workers that Job is canceled
      jobService.notifyJobCancel(profile.getJobId());
     
      return;
    }
   
    // Wait if execution completed before minimum duration
    waitIfNeeded(profile);
   
    /*  -- Aggregation Complete : Job Complete -- */
   
    // Notify Workers
    jobService.notifyJobEnd(profile.getJobId());
   
    // Update Future and return Result
    profile.getFuture().setResult(jobResult);
    profile.getFuture().setState(GridJobState.COMPLETE);
  }

  /**
   * Withholds results if execution finished before minimum execution
   * duration, to avoid thread synchronization issues.
   *
   * @param profile Job Profile
   */
  private void waitIfNeeded(GridJobProfile profile) {
    if (System.currentTimeMillis() - profile.getStartTime() < GridJobProfile.MINIMUM_EXEUCTION_TIME) {
      try {
        long duration = GridJobProfile.MINIMUM_EXEUCTION_TIME
                  - (System.currentTimeMillis()
                  - profile.getStartTime())
                  + 1000;
       
        if (duration < 0) return;
       
        Thread.sleep(duration);
      } catch (InterruptedException e) {
        log.warn("Interrupted",e);
      }
    }
  }

}
TOP

Related Classes of org.nebulaframework.grid.cluster.manager.services.jobs.splitaggregate.AggregatorServiceImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.