Package jmt.engine.NodeSections

Source Code of jmt.engine.NodeSections.BlockingQueue

/**   
  * Copyright (C) 2006, Laboratorio di Valutazione delle Prestazioni - Politecnico di Milano

  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.

  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.

  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */

package jmt.engine.NodeSections;

import java.util.List;
import java.util.ListIterator;

import jmt.common.exception.NetException;
import jmt.engine.QueueNet.BlockingRegion;
import jmt.engine.QueueNet.Job;
import jmt.engine.QueueNet.JobClass;
import jmt.engine.QueueNet.JobInfo;
import jmt.engine.QueueNet.JobInfoList;
import jmt.engine.QueueNet.LinkedJobInfoList;
import jmt.engine.QueueNet.NetEvent;
import jmt.engine.QueueNet.NetMessage;
import jmt.engine.QueueNet.NetNode;

/**
* This class implements the queue of a region input station, that is
* the node which controls the access to a blocking region.
*
* @author Stefano Omini
*
* Modifief by Bertoli Marco 31-03-2006 (my birthday!!!)
*
* Modified by Ashanka (Oct 2009):
* Desc: FCR(Finite Capacity Region) is a blocking region and it was measuring wrong
*      values for the Performance Indices. This was because the Jobs in FCR were not
*      considering the time spent in the Queuing Stations in the FCR and simply reporting
*       time spent in Queuing in FCR. This behavior is incorrect as Performance Indices for
*       FCR should also contain the time spent in the FCR and not only the time spent queuing.
*      
*       Approach taken presently to rectify is to delay the capture of the performance indices
*       untill the job is out of the FCR. So the job dropping are manually handled for Blocking region
*       at Node level.
*/
public class BlockingQueue extends InputSection {

  public static final boolean DEBUG = false;

  /** Property Identifier: infinite. */
  public static final int PROPERTY_ID_INFINITE = 0x0101;
  /** Property Identifier: drop.*/
  public static final int PROPERTY_ID_DROP = 0x0102;
  /** Property Identifier: size.*/
  public static final int PROPERTY_ID_SIZE = 0x0103;
  /** Property Identifier: Waiting request.*/
  public static final int PROPERTY_ID_WAITING_REQUESTS = 0x0104;
  /** Property Identifier: Queue get strategy.*/
  public static final int PROPERTY_ID_GET_STRATEGY = 0x0105;
  /** Property Identifier: Queue put strategy.*/
  public static final int PROPERTY_ID_PUT_STRATEGY = 0x0106;

  //coolStart is true if there are no waiting jobs when the queue is started
  private boolean coolStart;

  private int size;

  private BlockingRegion blockingRegion;

  /** For each class, true if jobs in excess must be dropped */
  protected boolean[] classDrop;

  /** For each class, true if jobs in excess must be dropped */
  protected double[] classWeights = null;

  private int droppedJobs;
  private int[] droppedJobsPerClass;

  //job info list of the owner node: used to remove job after drop
  private JobInfoList jobsList_node;

  /**
   * Creates a new instance of infinite BlockingQueue.
   */
  public BlockingQueue(BlockingRegion myRegion) {

    super(true);

    coolStart = true;
    //infinite queue
    this.size = -1;
    //sets the blocking region owner of this blocking queue
    this.blockingRegion = myRegion;

  }

  @Override
  protected void nodeLinked(NetNode node) {
    // Sets netnode dependent properties

    //if (jobsList == null)
    jobsList = new LinkedJobInfoList(getJobClasses().size(), true);

    jobsList_node = this.getOwnerNode().getJobInfoList();

    //copies drop properties from blocking region
    //and initializes dropped jobs
    droppedJobs = 0;
    droppedJobsPerClass = new int[node.getJobClasses().size()];
    this.classDrop = new boolean[node.getJobClasses().size()];

    for (int i = 0; i < droppedJobsPerClass.length; i++) {
      //copies drop properties from blocking region
      this.classDrop[i] = blockingRegion.getClassDrop(i);
      //initializes dropped jobs
      droppedJobsPerClass[i] = 0;
    }

    return;
  }

  @Override
  public int getIntSectionProperty(int id) throws NetException {
    switch (id) {
      case PROPERTY_ID_SIZE:
        return size;
      default:
        return super.getIntSectionProperty(id);
    }
  }

  /**
   * Gets, if exists, the first job in queue that is not class blocked and has an higher priority.
   * @return the first job in queue that is not class blocked; null otherwise.
   */
  private Job getNextNotBlockedJob() {

    if (jobsList == null) {
      return null;
    }

    List<JobInfo> jobList = jobsList.getJobList();

    ListIterator<JobInfo> iterator = jobList.listIterator();

    Job nextJob = null;
    int nextJobPriority = 0;
    while (iterator.hasNext()) {
      JobInfo info = iterator.next();
      JobClass jobClass = info.getJob().getJobClass();
      if (nextJob == null || nextJobPriority < jobClass.getPriority()) {
        if (!blockingRegion.isBlocked(jobClass)) {
          nextJob = info.getJob();
          nextJobPriority = jobClass.getPriority();
        }
      }
    }
    return nextJob;
  }

  /** This method implements a blocking queue
   * @param message message to be processed.
   * @throws NetException
   */
  @Override
  protected int process(NetMessage message) throws NetException {
    Job job;
    Job notBlockedJob;

    switch (message.getEvent()) {

      case NetEvent.EVENT_START:

        //the input station receives the "start" event because it has no nodes in input
        //then it's marked as reference node

        //NEW
        //@author Stefano Omini

        //checks whether there are jobs in queue
        if (jobsList.size() == 0) {
          //no jobs in queue
          coolStart = true;
          break;
        }

        //get the first job which is not blocked (if exists)

        notBlockedJob = getNextNotBlockedJob();

        if (notBlockedJob == null) {
          //all jobs in queue are class blocked
          //nothing else to do
          break;
        } else {
          //get class
          JobClass jobClass = notBlockedJob.getJobClass();
          //forward job and increase occupation
          forward(notBlockedJob);
          blockingRegion.increaseOccupation(jobClass);
          break;
        }

        //the BlockingQueue has almost the same behaviour with the events
        //EVENT_JOB_OUT_OF_REGION and EVENT_ACK

      case NetEvent.EVENT_JOB_OUT_OF_REGION:

        //FCR Bug fix:
        //The dropping of the job was post poned as the time
        //spent in the Queuing station was not taken in consideration.
        //Secondly point to be noted is that I am
        //only dropping Jobs at Node level as the node section jobs
        //are automatically dropped but the node level jobs are
        //dropped manually.
        Job localJob = (Job) message.getData();
        JobInfo jobInfo = jobsList_node.lookFor(localJob);
        //remove only when you find a job in the list.
        if (jobInfo != null) {
          jobsList_node.remove(jobInfo);
        }

        //checks whether there are jobs in queue
        if (jobsList.size() == 0) {
          //no jobs in queue
          coolStart = true;
          break;
        }

        //search for the first job which is not blocked (if exists)
        // and forward it

        notBlockedJob = getNextNotBlockedJob();

        if (notBlockedJob != null) {
          JobClass jobClass = notBlockedJob.getJobClass();
          forward(notBlockedJob);
          blockingRegion.increaseOccupation(jobClass);
          break;
        } else {
          //all jobs in queue are blocked
          //nothing else to do
          break;
        }

      case NetEvent.EVENT_ACK:

        //checks whether there are jobs in queue
        if (jobsList.size() == 0) {
          //no jobs in queue
          coolStart = true;
          break;
        }

        //search for the first job which is not blocked (if exists)
        // and forward it

        notBlockedJob = getNextNotBlockedJob();

        if (notBlockedJob != null) {
          JobClass jobClass = notBlockedJob.getJobClass();
          forward(notBlockedJob);
          blockingRegion.increaseOccupation(jobClass);
          break;
        } else {
          //all jobs in queue are blocked
          //nothing else to do
          break;
        }

      case NetEvent.EVENT_JOB:

        //EVENT_JOB

        job = message.getJob();

        //no ack must be sent to the source of message (the redirecting queue of a node
        //inside the region)

        JobClass jobClass = job.getJobClass();

        //this job has been received by an internal node
        //the region input station will have to send it back
        NetNode realDestination = message.getSource();

        //adds a JobInfo object after modifying the job with redirection informations
        job.setOriginalDestinationNode(realDestination);
        jobsList.add(new JobInfo(job));

        //checks whether the region is blocked for this class
        if (blockingRegion.isBlocked(jobClass)) {
          //the region is already blocked

          //the job must be dropped?
          if (classDrop[jobClass.getId()] == true) {
            //drop job
            drop(job);
            break;
          }
          //otherwise the job remains blocked in queue
          break;
        }

        //the region is not blocked for this class
        //checks whether the queue is empty (coolstart = true) or not

        if (coolStart) {
          // If coolStart is true, this job is sent immediately to the next
          // section and coolStart set to false.

          forward(job);
          blockingRegion.increaseOccupation(jobClass);

          coolStart = false;

        } else {
          //coolStart is false: this means that the jobs in queue are class blocked,
          //otherwise they would have been already sent to the region till it would
          //become globally or class blocked

          //the job is sent to service section

          //OLD
          /* Job firstNotBlocked = getFirstNotBlockedJob();
          if (firstNotBlocked != null) {
              forward(firstNotBlocked);
              if (DEBUG) {
                  System.out.println("SendJobIn");
              }

              blockingRegion.increaseOccupation(jobClass);

          }
          */
          forward(job);
          if (DEBUG) {
            System.out.println("SendJobIn");
          }

          blockingRegion.increaseOccupation(jobClass);

        }
        break;

      default:
        return MSG_NOT_PROCESSED;
    }
    return MSG_PROCESSED;
  }

  private void forward(Job job) throws NetException {
    sendForward(job, 0.0);
  }

  /**
   * Drop the specified job, removing it from the job info lists and increases
   * the counters of dropped jobs
   * @param job the job to be dropped
   * @throws NetException
   */
  private void drop(Job job) throws NetException {

    int c = job.getJobClass().getId();
    droppedJobs++;
    droppedJobsPerClass[c]++;

    JobInfo jobInfo = jobsList.lookFor(job);
    if (jobInfo != null) {
      //removes job from the jobInfoList of the node section
      jobsList.removeAfterDrop(jobInfo);

      //removes job from the jobInfoList of the node
      this.getOwnerNode().getJobInfoList().removeAfterDrop(jobInfo);
    }

    if (jobsList_node == null) {
      jobsList_node = this.getOwnerNode().getJobInfoList();
    }
    JobInfo jobInfo_node = jobsList_node.lookFor(job);
    if (jobInfo_node != null) {
      //removes job from the jobInfoList of the node
      jobsList_node.removeAfterDrop(jobInfo_node);
    }
    // Removes job from global jobInfoList - Bertoli Marco
    getOwnerNode().getQueueNet().getJobInfoList().dropJob(job);
  }

  /**
   * Gets the number of dropped jobs of each class
   * @return the number of dropped jobs of each class
   */
  public int[] getDroppedJobsPerClass() {
    return droppedJobsPerClass;
  }

  /**
   * Gets the number of dropped jobs for the specified class
   * @param jobClassIndex the index of the job class
   * @return the number of dropped jobs for the specified class, -1 otherwise
   */
  public int getDroppedJobPerClass(int jobClassIndex) {
    return droppedJobsPerClass[jobClassIndex];
  }

  /**
   * Gets the number of dropped jobs
   * @return the number of dropped jobs
   */
  public int getDroppedJobs() {
    return droppedJobs;
  }
}
TOP

Related Classes of jmt.engine.NodeSections.BlockingQueue

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.