现在的位置: 首页 > 综合 > 正文

云计算仿真工具中文注释SimEntity.java

2013年09月03日 ⁄ 综合 ⁄ 共 18007字 ⁄ 字号 评论关闭
/*
 * Title:        CloudSim Toolkit
 * Description:  CloudSim (Cloud Simulation) Toolkit for Modeling and Simulation of Clouds
 * Licence:      GPL - http://www.gnu.org/copyleft/gpl.html
 *
 * Copyright (c) 2009-2010, The University of Melbourne, Australia
 */

package org.cloudbus.cloudsim.core;

import org.cloudbus.cloudsim.Log;
import org.cloudbus.cloudsim.NetworkTopology;
import org.cloudbus.cloudsim.core.predicates.Predicate;

/**
 * simEntity类继承Cloneable接口,必须实现clone()方法,可以使此类按字段复制,产生一
 * 个对象副本
 * 这个类代表仿真实体,一个实体可以处理事件,也可以发送事件到其他实体。当这个类被继承,
 * 有一些方法需要实现
 * startEntity()方法被请求,当仿真开始的时候,这个方法负责启动实体。
 * processEvent()被请求,当defered队列中还有事件时。
 *  当仿真结束前,需要关闭实体.
 *  方法总结:
 *  1、发送事件,有cloudsim组建成simevent,调用futureQueue方法加入future queue队列中
 *  2、队列中发往本实体满足谓词p的事件个数,谓词p用来对事件限制
 *  3、队列中等待发往本实体的事件个数
 *  4、选择第一个满足src(此目的地为实体本身)和谓词p条件的事件,并把它从队列中移走
 *  5、在future队列中寻找第一个满足条件的事件,从中移走即取消此事件
 *  6、选择下一个事件
 *  7、三个核心方法,分别是实体开始,处理事件,实体销毁
 *  8、实体线程,一直查找事件并处理事件
 *  9、clone对象
 *  10、向目标实体发送事件delay差brite矩阵获得。
 *  11、获得两实体之间传送事件延迟,从birte矩阵中获得
 *  可认为包括三种方法:发送事件,查找事件,处理事件
 * This class represents a simulation entity. An entity handles events and can
 * send events to other entities. When this class is extended, there are a few
 * methods that need to be implemented:
 * <ul>
 * <li> {@link #startEntity()} is invoked by the {@link Simulation} class when
 * the simulation is started. This method should be responsible for starting the
 * entity up.
 * <li> {@link #processEvent(SimEvent)} is invoked by the {@link Simulation}
 * class whenever there is an event in the deferred queue, which needs to be
 * processed by the entity.
 * <li> {@link #shutdownEntity()} is invoked by the {@link Simulation} before the
 * simulation finishes. If you want to save data in log files this is the method
 * in which the corresponding code would be placed.
 * </ul>
 * @author		Marcos Dias de Assuncao
 * @since		CloudSim Toolkit 1.0
 */
public abstract class SimEntity implements Cloneable {

	/**
	 * 实体字段:
	 * 1、名字name
	 * 2、实体的id
	 * 3、从defer Queue中的事件evbuf
	 * 4、实体现在的状态state:RUNNABLE,WAITING,HOLDING,FINISHED
	 */
	/** The name. */
	private String name;

	/** The id. */
	private int id;

	/** The buffer for selected incoming events. */
	private SimEvent evbuf;

	/** The entity's current state. */
	private int state;

	/**
	 * Creates a new entity.
	 *
	 * @param name the name to be associated with this entity
	 */
	public SimEntity(String name) {
		//名字不可以包含空格
		if (name.indexOf(" ") != -1) {
			throw new IllegalArgumentException(
					"Entity names can't contain spaces.");
		}
		this.name = name;
		id = -1;                             //默认id为-1
		state = RUNNABLE; 					//实体创建后的状态为运行状态
		CloudSim.addEntity(this);           //实体添加到cloudsim的实体列表中
	}

	/**
	 * Get the name of this entity.
	 *
	 * @return The entity's name
	 */
	public String getName() {
		return name;
	}

	/**
	 * Get the unique id number assigned to this entity.
	 *
	 * @return The id number
	 */
	public int getId() {
		return id;
	}

	// The schedule functions

	/**
	 * 发送事件,有cloudsim组建成simevent,调用futureQueue方法加入future queue队列中
	 * Send an event to another entity by id number, with data. Note that the
	 * tag <code>9999</code> is reserved.
	 * @param dest The unique id number of the destination entity
	 * @param delay How long from the current simulation time the event
	 * should be sent
	 * @param tag An user-defined number representing the type of event.
	 * @param data The data to be sent with the event.
	 */
	public void schedule(int dest, double delay, int tag, Object data) {
		if (!CloudSim.running()) {
			return;
		}
		CloudSim.send(id, dest, delay, tag, data);
	}

	/**
	 * Send an event to another entity by id number and with <b>no</b> data.
	 * Note that the tag <code>9999</code> is reserved.
	 *
	 * @param dest The unique id number of the destination entity
	 * @param delay How long from the current simulation time the event
	 * should be sent
	 * @param tag An user-defined number representing the type of event.
	 */
	public void schedule(int dest, double delay, int tag) {
		schedule(dest, delay, tag, null);
	}

	/**
	 * Send an event to another entity through a port with a given name, with
	 * data. Note that the tag <code>9999</code> is reserved.
	 *
	 * @param dest The name of the port to send the event through
	 * @param delay How long from the current simulation time the event
	 * should be sent
	 * @param tag An user-defined number representing the type of event.
	 * @param data The data to be sent with the event.
	 */
	public void schedule(String dest, double delay, int tag, Object data) {
		schedule(CloudSim.getEntityId(dest), delay, tag, data);
	}

	/**
	 * Send an event to another entity through a port with a given name, with
	 * <b>no</b> data. Note that the tag <code>9999</code> is reserved.
	 *
	 * @param dest The name of the port to send the event through
	 * @param delay How long from the current simulation time the event should be
	 * sent
	 * @param tag An user-defined number representing the type of event.
	 */
	public void schedule(String dest, double delay, int tag) {
		schedule(dest, delay, tag, null);
	}

	/**
	 * Send an event to another entity by id number, with data. Note that the
	 * tag <code>9999</code> is reserved.
	 *
	 * @param dest The unique id number of the destination entity
	 * @param tag An user-defined number representing the type of event.
	 * @param data The data to be sent with the event.
	 */
	public void scheduleNow(int dest, int tag, Object data) {
		schedule(dest, 0, tag, data);
	}

	/**
	 * Send an event to another entity by id number and with <b>no</b> data.
	 * Note that the tag <code>9999</code> is reserved.
	 *
	 * @param dest The unique id number of the destination entity
	 * @param tag An user-defined number representing the type of event.
	 */
	public void scheduleNow(int dest, int tag) {
		schedule(dest, 0, tag, null);
	}

	/**
	 * Send an event to another entity through a port with a given name, with
	 * data. Note that the tag <code>9999</code> is reserved.
	 *
	 * @param dest The name of the port to send the event through
	 * @param tag An user-defined number representing the type of event.
	 * @param data The data to be sent with the event.
	 */
	public void scheduleNow(String dest, int tag, Object data) {
		schedule(CloudSim.getEntityId(dest), 0, tag, data);
	}

	/**
	 * Send an event to another entity through a port with a given name, with
	 * <b>no</b> data. Note that the tag <code>9999</code> is reserved.
	 *
	 * @param dest The name of the port to send the event through
	 * @param tag An user-defined number representing the type of event.
	 */
	public void scheduleNow(String dest, int tag) {
		schedule(dest, 0, tag, null);
	}
	
	/**
	 * 设置高优先及加入future Queue队列中,调用cloudsim.sendfirst方法会设置event中
	 * 的serial字段更低,优先级更高
	 * Send a high priority event to another entity by id number, with data. Note that the
	 * tag <code>9999</code> is reserved.
	 *
	 * @param dest The unique id number of the destination entity
	 * @param delay How long from the current simulation time the event
	 * should be sent
	 * @param tag An user-defined number representing the type of event.
	 * @param data The data to be sent with the event.
	 */
	public void scheduleFirst(int dest, double delay, int tag, Object data) {
		if (!CloudSim.running()) {
			return;
		}
		CloudSim.sendFirst(id, dest, delay, tag, data);
	}

	/**
	 * Send a high priority event to another entity by id number and with <b>no</b> data.
	 * Note that the tag <code>9999</code> is reserved.
	 *
	 * @param dest The unique id number of the destination entity
	 * @param delay How long from the current simulation time the event
	 * should be sent
	 * @param tag An user-defined number representing the type of event.
	 */
	public void scheduleFirst(int dest, double delay, int tag) {
		scheduleFirst(dest, delay, tag, null);
	}

	/**
	 * Send a high priority event to another entity through a port with a given name, with
	 * data. Note that the tag <code>9999</code> is reserved.
	 *
	 * @param dest The name of the port to send the event through
	 * @param delay How long from the current simulation time the event
	 * should be sent
	 * @param tag An user-defined number representing the type of event.
	 * @param data The data to be sent with the event.
	 */
	public void scheduleFirst(String dest, double delay, int tag, Object data) {
		scheduleFirst(CloudSim.getEntityId(dest), delay, tag, data);
	}

	/**
	 * Send a high priority event to another entity through a port with a given name, with
	 * <b>no</b> data. Note that the tag <code>9999</code> is reserved.
	 *
	 * @param dest The name of the port to send the event through
	 * @param delay How long from the current simulation time the event should be
	 * sent
	 * @param tag An user-defined number representing the type of event.
	 */
	public void scheduleFirst(String dest, double delay, int tag) {
		scheduleFirst(dest, delay, tag, null);
	}

	/**
	 * Send a high priority event to another entity by id number, with data. Note that the
	 * tag <code>9999</code> is reserved.
	 *
	 * @param dest The unique id number of the destination entity
	 * @param tag An user-defined number representing the type of event.
	 * @param data The data to be sent with the event.
	 */
	public void scheduleFirstNow(int dest, int tag, Object data) {
		scheduleFirst(dest, 0, tag, data);
	}

	/**
	 * Send a high priority event to another entity by id number and with <b>no</b> data.
	 * Note that the tag <code>9999</code> is reserved.
	 *
	 * @param dest The unique id number of the destination entity
	 * @param tag An user-defined number representing the type of event.
	 */
	public void scheduleFirstNow(int dest, int tag) {
		scheduleFirst(dest, 0, tag, null);
	}

	/**
	 * Send a high priority event to another entity through a port with a given name, with
	 * data. Note that the tag <code>9999</code> is reserved.
	 *
	 * @param dest The name of the port to send the event through
	 * @param tag An user-defined number representing the type of event.
	 * @param data The data to be sent with the event.
	 */
	public void scheduleFirstNow(String dest, int tag, Object data) {
		scheduleFirst(CloudSim.getEntityId(dest), 0, tag, data);
	}

	/**
	 * Send a high priority event to another entity through a port with a given name, with
	 * <b>no</b> data. Note that the tag <code>9999</code> is reserved.
	 *
	 * @param dest The name of the port to send the event through
	 * @param tag An user-defined number representing the type of event.
	 */
	public void scheduleFirstNow(String dest, int tag) {
		scheduleFirst(dest, 0, tag, null);
	}

	/**
	 * Set the entity to be inactive for a time period.
	 * 实体挂起一段时间
	 * @param delay the time period for which the entity will be inactive
	 */
	public void pause(double delay) {
		if (delay < 0) {
			throw new IllegalArgumentException("Negative delay supplied.");
		}
		//仿真不在运行
		if (!CloudSim.running()) {
			return;
		}
		CloudSim.pause(id, delay);
	}

	/**
	 * 队列中发往本实体满足谓词p的事件个数,谓词p用来对事件限制
	 * p:实体要选择的事件谓词。
	 * Count how many events matching a predicate are waiting in the entity's
	 * deferred queue.
	 *
	 * @param p The event selection predicate
	 *
	 * @return The count of matching events
	 */
	public int numEventsWaiting(Predicate p) {
		return CloudSim.waiting(id, p);
	}

	/**
	 * 队列中等待发往本实体的事件个数
	 * Count how many events are waiting in the entity's deferred queue.
	 *
	 * @return The count of events
	 */
	public int numEventsWaiting() {
		return CloudSim.waiting(id, CloudSim.SIM_ANY);
	}

	/**
	 * 选择第一个满足src(此目的地为实体本身)和谓词p条件的事件,并把它从队列中移走
	 * Extract the first event matching a predicate waiting in the entity's
	 * deferred queue.
	 *
	 * @param p The event selection predicate
	 *
	 * @return the simulation event
	 */
	public SimEvent selectEvent(Predicate p) {
		if (!CloudSim.running()) {
			return null;
		}

		return CloudSim.select(id, p);
	}

	/**
	 * 在future队列中寻找第一个满足条件的事件,从中移走即取消此事件
	 * Cancel the first event matching a predicate waiting in the entity's
	 * future queue.
	 *
	 * @param p The event selection predicate
	 *
	 * @return The number of events cancelled (0 or 1)
	 */
	public SimEvent cancelEvent(Predicate p) {
		//因为cloudsim在任意时刻可能停止,所以所有操作要保证cloudsim正在运行
		if (!CloudSim.running()) {
			return null;
		}

		return CloudSim.cancel(id, p);
	}

	/**
	 * 选择下一个事件
	 * ??同选择selectevent()一样的
	 * Get the first event matching a predicate from the deferred queue, or if
	 * none match, wait for a matching event to arrive.
	 *
	 * @param p The predicate to match
	 *
	 * @return the simulation event
	 */
	public SimEvent getNextEvent(Predicate p) {
		if (!CloudSim.running()) {
			return null;
		}
		if (numEventsWaiting(p) > 0) {
			return selectEvent(p);
		}
		return null;
	}

	/**
	 * Wait for an event matching a specific predicate. This method does not
	 * check the entity's deferred queue.
	 *
	 * @param p The predicate to match
	 */
	public void waitForEvent(Predicate p) {
		if (!CloudSim.running()) {
			return;
		}

		CloudSim.wait(id, p);
		this.state = WAITING;
	}

	/**
	 * Get the first event waiting in the entity's deferred queue, or if there
	 * are none, wait for an event to arrive.
	 *
	 * @return the simulation event
	 */
	public SimEvent getNextEvent() {
		return getNextEvent(CloudSim.SIM_ANY);
	}

	/**
	 * 三个核心方法,分别是实体开始,处理事件,实体销毁
	 * This method is invoked by the {@link Simulation} class when
	 * the simulation is started. This method should be responsible for starting the
	 * entity up.
	 */
	public abstract void startEntity();

	/**
	 * This method is invoked by the {@link Simulation}
	 * class whenever there is an event in the deferred queue, which needs to be
	 * processed by the entity.
	 *
	 * @param ev the event to be processed by the entity
	 */
	public abstract void processEvent(SimEvent ev);

	/**
	 * 一直查找事件并处理事件
	 * This method is invoked by the {@link Simulation} before the
	 * simulation finishes. If you want to save data in log files this is the method
	 * in which the corresponding code would be placed.
	 */
	public abstract void shutdownEntity();

	public void run() {
		SimEvent ev = evbuf != null ? evbuf : getNextEvent();

		while (ev != null) {
			processEvent(ev);
			if (state != RUNNABLE) {
				break;
			}

			ev = getNextEvent();
		}

		evbuf = null;
	}

	/**
	 * clone对象
	 * Get a clone of the entity. This is used when independent replications
	 * have been specified as an output analysis method. Clones or backups of
	 * the entities are made in the beginning of the simulation in order to
	 * reset the entities for each subsequent replication. This method should
	 * not be called by the user.
	 *
	 * @return A clone of the entity
	 *
	 * @throws CloneNotSupportedException the clone not supported exception
	 */
	//方法前面加final表示此方法不可以被覆盖
	@Override
	protected final Object clone() throws CloneNotSupportedException {
		SimEntity copy = (SimEntity) super.clone();
		copy.setName(name);
		copy.setEventBuffer(null);
		return copy;
	}

	// Used to set a cloned entity's name
	/**
	 * Sets the name.
	 *
	 * @param new_name the new name
	 */
	private void setName(String new_name) {
		name = new_name;
	}

	// --------------- PACKAGE LEVEL METHODS ------------------

	/**
	 * Gets the state.
	 *
	 * @return the state
	 */
	protected int getState() {
		return state;
	}

	/**
	 * Gets the event buffer.
	 *
	 * @return the event buffer
	 */
	protected SimEvent getEventBuffer() {
		return evbuf;
	}

	// The entity states
	/** The Constant RUNNABLE. */
	public static final int RUNNABLE = 0;

	/** The Constant WAITING. */
	public static final int WAITING = 1;

	/** The Constant HOLDING. */
	public static final int HOLDING = 2;

	/** The Constant FINISHED. */
	public static final int FINISHED = 3;

	/**
	 * Sets the state.
	 *
	 * @param state the new state
	 */
	protected void setState(int state) {
		this.state = state;
	}

	/**
	 * Sets the id.
	 *
	 * @param id the new id
	 */
	protected void setId(int id) {
		this.id = id;
	}

	/**
	 * Sets the event buffer.
	 *
	 * @param e the new event buffer
	 */
	protected void setEventBuffer(SimEvent e) {
		evbuf = e;
	}

	// --------------- EVENT / MESSAGE SEND WITH NETWORK DELAY METHODS ------------------

	/**
	 * 向目标实体发送事件delay差brite矩阵获得。
	 * Sends an event/message to another entity by <tt>delaying</tt>
	 * the simulation time from the current time, with a tag representing
	 * the event type.
	 *
	 * @param entityId   the id number of the destination entity
	 * @param delay      how long from the current simulation time the event
	 * should be sent.
	 * If delay is a negative number, then it will be
	 * changed to 0
	 * @param cloudSimTag an user-defined number representing the type of
	 * an event/message
	 * @param data       A reference to data to be sent with the event
	 *
	 * @pre entityID > 0
	 * @pre delay >= 0.0
	 * @pre data != null
	 * @post $none
	 */
	protected void send(int entityId, double delay, int cloudSimTag, Object data) {
		if (entityId < 0) {
			return;
		}

		// if delay is -ve, then it doesn't make sense. So resets to 0.0
		if (delay < 0) {
			delay = 0;
		}

		if (Double.isInfinite(delay)) {
			throw new IllegalArgumentException("The specified delay is infinite value");
		}

		if (entityId < 0) {
			Log.printLine(getName() + ".send(): Error - " +
					"invalid entity id " + entityId);
			return;
		}

		int srcId = getId();
		if (entityId != srcId) {// does not delay self messages
			delay += getNetworkDelay(srcId, entityId);
		}

		schedule(entityId, delay, cloudSimTag, data);
	}


	/**
	 * Sends an event/message to another entity by <tt>delaying</tt> the
	 * simulation time from the current time, with a tag representing
	 * the event type.
	 *
	 * @param entityId   the id number of the destination entity
	 * @param delay      how long from the current simulation time the event
	 * should be sent.
	 * If delay is a negative number, then it will be
	 * changed to 0
	 * @param cloudSimTag an user-defined number representing the type of
	 * an event/message
	 *
	 * @pre entityID > 0
	 * @pre delay >= 0.0
	 * @post $none
	 */
	protected void send(int entityId, double delay, int cloudSimTag) {
		send(entityId, delay, cloudSimTag, null);
	}

	/**
	 * Sends an event/message to another entity by <tt>delaying</tt>
	 * the simulation time from the current time, with a tag representing the
	 * event type.
	 *
	 * @param entityName the name of the destination entity
	 * @param delay      how long from the current simulation time the event
	 * should be sent.
	 * If delay is a negative number, then it will be
	 * changed to 0
	 * @param cloudSimTag an user-defined number representing the type of
	 * an event/message
	 * @param data       A reference to data to be sent with the event
	 *
	 * @pre entityName != null
	 * @pre delay >= 0.0
	 * @pre data != null
	 * @post $none
	 */
	protected void send(String entityName, double delay, int cloudSimTag, Object data) {
		send(CloudSim.getEntityId(entityName), delay, cloudSimTag, data);
	}

	/**
	 * Sends an event/message to another entity by <tt>delaying</tt>
	 * the simulation time from the current time, with a tag representing
	 * the event type.
	 *
	 * @param entityName the name of the destination entity
	 * @param delay      how long from the current simulation time the event
	 * should be sent.
	 * If delay is a negative number, then it will be
	 * changed to 0
	 * @param cloudSimTag an user-defined number representing the type of
	 * an event/message
	 *
	 * @pre entityName != null
	 * @pre delay >= 0.0
	 * @post $none
	 */
	protected void send(String entityName, double delay, int cloudSimTag) {
		send(entityName, delay, cloudSimTag, null);
	}

    /**
	 * Sends an event/message to another entity by <tt>delaying</tt>
	 * the simulation time from the current time, with a tag representing
	 * the event type.
	 *
	 * @param entityId   the id number of the destination entity
	 * @param delay      how long from the current simulation time the event
	 * should be sent.
	 * If delay is a negative number, then it will be
	 * changed to 0
	 * @param cloudSimTag an user-defined number representing the type of
	 * an event/message
	 * @param data       A reference to data to be sent with the event
	 *
	 * @pre entityID > 0
	 * @pre delay >= 0.0
	 * @pre data != null
	 * @post $none
	 */
    protected void sendNow(int entityId, int cloudSimTag, Object data) {
    	send(entityId, 0, cloudSimTag, data);
    }

    /**
     * Sends an event/message to another entity by <tt>delaying</tt> the
     * simulation time from the current time, with a tag representing
     * the event type.
     *
     * @param entityId   the id number of the destination entity
     * @param delay      how long from the current simulation time the event
     * should be sent.
     * If delay is a negative number, then it will be
     * changed to 0
     * @param cloudSimTag an user-defined number representing the type of
     * an event/message
     *
     * @pre entityID > 0
     * @pre delay >= 0.0
     * @post $none
     */
    protected void sendNow(int entityId, int cloudSimTag) {
    	send(entityId, 0, cloudSimTag, null);
    }

    /**
     * Sends an event/message to another entity by <tt>delaying</tt>
     * the simulation time from the current time, with a tag representing the
     * event type.
     *
     * @param entityName the name of the destination entity
     * @param delay      how long from the current simulation time the event
     * should be sent.
     * If delay is a negative number, then it will be
     * changed to 0
     * @param cloudSimTag an user-defined number representing the type of
     * an event/message
     * @param data       A reference to data to be sent with the event
     *
     * @pre entityName != null
     * @pre delay >= 0.0
     * @pre data != null
     * @post $none
     */
    protected void sendNow(String entityName, int cloudSimTag, Object data) {
    	send(CloudSim.getEntityId(entityName), 0, cloudSimTag, data);
    }

    /**
     * Sends an event/message to another entity by <tt>delaying</tt>
     * the simulation time from the current time, with a tag representing
     * the event type.
     *
     * @param entityName the name of the destination entity
     * @param delay      how long from the current simulation time the event
     * should be sent.
     * If delay is a negative number, then it will be
     * changed to 0
     * @param cloudSimTag an user-defined number representing the type of
     * an event/message
     *
     * @pre entityName != null
     * @pre delay >= 0.0
     * @post $none
     */
    protected void sendNow(String entityName, int cloudSimTag) {
    	send(entityName, 0, cloudSimTag, null);
    }

	/**
	 * 获得两实体之间传送事件延迟,从birte矩阵中获得
	 * Gets the network delay associated to the sent of a message from
	 * a given source to a given destination.
	 *
	 * @param src source of the message
	 * @param dst destination of the message
	 *
	 * @return delay to send a message from src to dst
	 *
	 * @pre src >= 0
	 * @pre dst >= 0
	 */
	private double getNetworkDelay(int src, int dst) {
		//网络拓扑有效情况下
		if (NetworkTopology.isNetworkEnabled()) {
			return NetworkTopology.getDelay(src, dst);
		}
		//无效
		return 0.0;
	}

}

 

抱歉!评论已关闭.