云计算仿真工具中文注释CloudSim.java
/** Title:CloudSim Toolkit* Description:CloudSim (Cloud Simulation) Toolkit for Modeling and Simulation of Clouds* Licence:GPL - http://www.gnu.org/copyleft/gpl.html** C
·
/*
* 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 java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.cloudbus.cloudsim.Log;
import org.cloudbus.cloudsim.core.predicates.Predicate;
import org.cloudbus.cloudsim.core.predicates.PredicateAny;
import org.cloudbus.cloudsim.core.predicates.PredicateNone;
/**
* 这个类主要作用是把几个核心类组成系统(CIS,QUEUE,CLOUDSIMSHUTDOWN)
* 主要包括CIS
* cloudsim中所有的字段和方法都是static
* This class extends the CloudSimCore to enable network simulation in CloudSim.
* Also, it disables all the network models from CloudSim, to provide a simpler
* simulation of networking. In the network model used by CloudSim, a topology
* file written in BRITE format is used to describe the network. Later, nodes in
* such file are mapped to CloudSim entities. Delay calculated from the BRITE
* model are added to the messages send through CloudSim. Messages using the old
* model are converted to the apropriate methods with the correct parameters.
*
* @author Rodrigo N. Calheiros
* @author Anton Beloglazov
* @since CloudSim Toolkit 1.0
*/
public class CloudSim {
/** The Constant CLOUDSIM_VERSION_STRING. */
private static final String CLOUDSIM_VERSION_STRING = "2.0";
/** The id of CIS entity. */
private static int cisId = -1;
/** The id of CloudSimShutdown entity. */
@SuppressWarnings("unused")
private static int shutdownId = -1;
/** The CIS object. */
private static CloudInformationService cis = null;
/** The Constant NOT_FOUND. */
private static final int NOT_FOUND = -1;
/** The trace flag. */
@SuppressWarnings("unused")
private static boolean traceFlag = false;
/** The calendar. */
private static Calendar calendar = null;
/**
* 初始化实体列表,实体hash,future,defered,calendar,traceflag,cloudsimshutdown
* Initialises all the common attributes.
*
* @param _calendar the _calendar
* @param _traceFlag the _trace flag
* @param numUser number of users
* @throws Exception This happens when creating this entity before initialising
* CloudSim package or this entity name is <tt>null</tt> or empty
* @pre $none
* @post $none
*/
private static void initCommonVariable(Calendar _calendar, boolean _traceFlag, int numUser) throws Exception {
//初始化实体列表,实体hash,future,defered,等
initialize();
// NOTE: the order for the below 3 lines are important
traceFlag = _traceFlag;
// Set the current Wall clock time as the starting time of
// simulation
if (_calendar == null) {
calendar = Calendar.getInstance();
} else {
calendar = _calendar;
}
// creates a CloudSimShutdown object
CloudSimShutdown shutdown = new CloudSimShutdown("CloudSimShutdown", numUser);
shutdownId = shutdown.getId(); //id默认为-1
}
/**
* Initialises CloudSim parameters. This method should be called before
* creating any entities.
* <p>
* Inside this method, it will create the following CloudSim entities:
* <ul>
* <li>CloudInformationService.
* <li>CloudSimShutdown
* </ul>
* <p>
*
* @param numUser the number of User Entities created. This parameters indicates
* that {@link gridsim.CloudSimShutdown} first waits for all user
* entities's END_OF_SIMULATION signal before issuing terminate
* signal to other entities
* @param cal starting time for this simulation. If it is <tt>null</tt>,
* then the time will be taken from
* <tt>Calendar.getInstance()</tt>
* @param traceFlag <tt>true</tt> if CloudSim trace need to be written
*
* @see gridsim.CloudSimShutdown
* @see CloudInformationService.CloudInformationService
* @pre numUser >= 0
* @post $none
*/
public static void init(int numUser, Calendar cal, boolean traceFlag) {
try {
initCommonVariable(cal, traceFlag, numUser);
// create a GIS object
cis = new CloudInformationService("CloudInformationService");
// set all the above entity IDs
cisId = cis.getId();
} catch (IllegalArgumentException s) {
Log.printLine("CloudSim.init(): Unwanted errors happen");
Log.printLine(s.getMessage());
} catch (Exception e) {
Log.printLine("CloudSim.init(): Unwanted errors happen");
Log.printLine(e.getMessage());
}
}
/**
* Starts the execution of CloudSim simulation. It waits for complete
* execution of all entities, i.e. until all entities threads reach
* non-RUNNABLE state or there are no more events in the future event queue.
* <p>
* <b>Note</b>: This method should be called after all the entities have
* been setup and added.
*
* @return the double
* @throws NullPointerException This happens when creating this entity before initialising
* CloudSim package or this entity name is <tt>null</tt> or
* empty.
* @see gridsim.CloudSim#init(int, Calendar, boolean)
* @pre $none
* @post $none
*/
public static double startSimulation() throws NullPointerException {
Log.printLine("Starting CloudSim version " + CLOUDSIM_VERSION_STRING);
try {
double clock = run();
// reset all static variables
cisId = -1;
shutdownId = -1;
cis = null;
calendar = null;
traceFlag = false;
return clock;
} catch (IllegalArgumentException e) {
e.printStackTrace();
throw new NullPointerException("CloudSim.startCloudSimulation() :"
+ " Error - you haven't initialized CloudSim.");
}
}
/**
*仿真停止。
* Stops Cloud Simulation (based on {@link Simulation#runStop()}). This
* should be only called if any of the user defined entities
* <b>explicitly</b> want to terminate simulation during execution.
*
* @throws NullPointerException This happens when creating this entity before initialising
* CloudSim package or this entity name is <tt>null</tt> or empty
*
* @see gridsim.CloudSim#init(int, Calendar, boolean)
* @see Simulation#runStop()
* @pre $none
* @post $none
*/
public static void stopSimulation() throws NullPointerException {
try {
runStop();
} catch (IllegalArgumentException e) {
throw new NullPointerException("CloudSim.stopCloudSimulation() : "
+ "Error - can't stop Cloud Simulation.");
}
}
/**
* 复制日历
* Gets a new copy of initial simulation Calendar.
*
* @return a new copy of Calendar object or if CloudSim hasn't
* been initialized
* @see gridsim.CloudSim#init(int, Calendar, boolean, String[], String[],
* String)
* @see gridsim.CloudSim#init(int, Calendar, boolean)
* @pre $none
* @post $none
*/
public static Calendar getSimulationCalendar() {
// make a new copy
Calendar clone = calendar;
if (calendar != null) {
clone = (Calendar) calendar.clone();
}
return clone;
}
/**
* 获得CIS的id
* Gets the entity ID of <tt>CloudInformationService</tt>.
*
* @return the Entity ID or if it is not found
* @pre $none
* @post $result >= -1
*/
public static int getCloudInfoServiceEntityId() {
return cisId;
}
/**
* 所得CIS中所有实体列表
* Sends a request to Cloud Information Service (GIS) entity to get the list
* of all Cloud hostList.
*
* @return A List containing CloudResource ID (as an Integer object)
* or if a CIS entity hasn't been created before
* @pre $none
* @post $none
*/
public static List<Integer> getCloudResourceList() {
if (cis == null) {
return null;
}
return cis.getList();
}
// ======== SIMULATION METHODS ===============//
// Private data members
/** The entities. */
private static List<SimEntity> entities;
/** The future event queue. */
private static FutureQueue future;
/** The deferred event queue. */
private static DeferredQueue deferred;
/** The simulation clock. */
private static double clock;
/** Flag for checking if the simulation is running. */
private static boolean running;
/*
* (non-javadoc)
*/
/** The entities by name. */
private static Map<String, SimEntity> entitiesByName;
// The predicates used in entity wait methods
/** The wait predicates. */
private static Map<Integer, Predicate> waitPredicates;
/** The paused. */
private static boolean paused = false;
/** The pause at. */
private static long pauseAt = -1;
/** The abrupt terminate. */
private static boolean abruptTerminate = false;
/**
* 初始化实体列表,实体hash,future,defered,等
* Initialise the simulation for stand alone simulations. This function
* should be called at the start of the simulation.
*/
protected static void initialize() {
Log.printLine("Initialising...");
entities = new ArrayList<SimEntity>();
entitiesByName = new LinkedHashMap<String, SimEntity>();
future = new FutureQueue();
deferred = new DeferredQueue();
waitPredicates = new HashMap<Integer, Predicate>();
clock = 0;
running = false;
}
// The two standard predicates
/** A standard predicate that matches any event. */
public final static PredicateAny SIM_ANY = new PredicateAny();
/** A standard predicate that does not match any events. */
public final static PredicateNone SIM_NONE = new PredicateNone();
// Public access methods
/**
* 返回时钟
* Get the current simulation time.
*
* @return the simulation time
*/
public static double clock() {
return clock;
}
/**
* 返回仿真实体数量
* Get the current number of entities in the simulation.
*
* @return The number of entities
*/
public static int getNumEntities() {
return entities.size();
}
/**
* Get the entity with a given id.
*
* @param id the entity's unique id number
* @return The entity, or if it could not be found
*/
public static SimEntity getEntity(int id) {
return entities.get(id);
}
/**
* Get the entity with a given name.
*
* @param name The entity's name
* @return The entity
*/
public static SimEntity getEntity(String name) {
return entitiesByName.get(name);
}
/**
* Get the id of an entity with a given name.
*
* @param name The entity's name
* @return The entity's unique id number
*/
public static int getEntityId(String name) {
SimEntity obj = entitiesByName.get(name);
if (obj == null) {
return NOT_FOUND;
} else {
return obj.getId();
}
}
/**
* Gets name of the entity given its entity ID.
*
* @param entityID the entity ID
* @return the Entity name or if this object does not have one
* @pre entityID > 0
* @post $none
*/
public static String getEntityName(int entityID) {
try {
return getEntity(entityID).getName();
} catch (IllegalArgumentException e) {
return null;
} catch (Exception e) {
return null;
}
}
/**
* Gets name of the entity given its entity ID.
*
* @param entityID the entity ID
* @return the Entity name or if this object does not have one
* @pre entityID > 0
* @post $none
*/
public static String getEntityName(Integer entityID) {
if (entityID != null) {
return getEntityName(entityID.intValue());
}
return null;
}
/**
* Returns a list of entities created for the simulation.
*
* @return the entity iterator
*/
public static List<SimEntity> getEntityList() {
// create a new list to prevent the user from changing
// the list of entities used by Simulation
List<SimEntity> list = new LinkedList<SimEntity>();
list.addAll(entities);
return list;
}
// Public update methods
/**
* 实体加入仿真中,创建一个crate的事件(其他还有空事件,发送事件,等待事件)加入到future中
* Add a new entity to the simulation. This is present for compatibility
* with existing simulations since entities are automatically added to the
* simulation upon instantiation.
*
* @param e The new entity
*/
public static void addEntity(SimEntity e) {
SimEvent evt;
//??为什么还要发送一个事件??
if (running) {
// Post an event to make this entity
evt = new SimEvent(SimEvent.CREATE, clock, 1, 0, 0, e);
future.addEvent(evt);
}
//实体加入到entities列表中了
if (e.getId() == -1) { // Only add once!
int id = entities.size();
e.setId(id);
entities.add(e);
entitiesByName.put(e.getName(), e);
}
}
/**
* 内部用来添加一个实体,当仿真在运行时候
* ??没有加入队列???
* Internal method used to add a new entity to the simulation when the
* simulation is running. It should <b>not</b> be called from user
* simulations.
*
* @param e The new entity
*/
protected static void addEntityDynamically(SimEntity e) {
if (e == null) {
throw new IllegalArgumentException("Adding null entity.");
} else {
printMessage("Adding: " + e.getName());
}
e.startEntity();
}
/**
* 仿真跑一个时刻,处理defered中所有剩下的事件,处理future中所有和第一个事件
* 发生时间相同的事件
* Internal method used to run one tick of the simulation. This method
* should <b>not</b> be called in simulations.
*
* @return true, if successful
* otherwise
*/
public static boolean runClockTick() {
SimEntity ent;
boolean queue_empty;
int entities_size = entities.size();
//处理所有defered中的事件
for (int i = 0; i < entities_size; i++) {
ent = entities.get(i);
if (ent.getState() == SimEntity.RUNNABLE) {
ent.run();
}
}
// If there are more future events then deal with them
//处理future中所有和第一个事件发生时间相同的事件
if (future.size() > 0) {
List<SimEvent> toRemove = new ArrayList<SimEvent>();
Iterator<SimEvent> it = future.iterator();
queue_empty = false;
SimEvent first = it.next();
processEvent(first);
future.remove(first);
it = future.iterator();
// Check if next events are at same time...
boolean trymore = it.hasNext();
while (trymore) {
SimEvent next = it.next();
if (next.eventTime() == first.eventTime()) {
processEvent(next);
toRemove.add(next);
trymore = it.hasNext();
} else {
trymore = false;
}
}
future.removeAll(toRemove);
} else {
queue_empty = true;
running = false;
printMessage("Simulation: No more future events");
}
return queue_empty;
}
/**
* Internal method used to stop the simulation. This method should
* <b>not</b> be used directly.
*/
public static void runStop() {
printMessage("Simulation completed.");
}
/**
* 同pause相同
* Used to hold an entity for some time.
*
* @param src the src
* @param delay the delay
*/
public static void hold(int src, long delay) {
SimEvent e = new SimEvent(SimEvent.HOLD_DONE, clock + delay, src);
future.addEvent(e);
entities.get(src).setState(SimEntity.HOLDING);
}
/**
* 用于实体挂起,实体中的pause方法会调用此方法
* 该方法建立事件,加入future中,设置实体状体
* ???为什么直接设置实体状态,不是应该是该实体收到该事件之后才挂起吗??
* 回答:事件作用是在延迟时间到达后,从新启动该实体
* Used to pause an entity for some time.
*
* @param src the src
* @param delay the delay
*/
public static void pause(int src, double delay) {
SimEvent e = new SimEvent(SimEvent.HOLD_DONE, clock + delay, src);
future.addEvent(e);
entities.get(src).setState(SimEntity.HOLDING);
}
/**
* send过程:生成event对象,加入future Queue中,event对象中含有源地址,目标地址
* 和事件的其他信息。
* Used to send an event from one entity to another.
*
* @param src the src
* @param dest the dest
* @param delay the delay
* @param tag the tag
* @param data the data
*/
public static void send(int src, int dest, double delay, int tag, Object data) {
if (delay < 0) {
throw new IllegalArgumentException("Send delay can't be negative.");
}
SimEvent e = new SimEvent(SimEvent.SEND, clock + delay, src, dest, tag, data);
future.addEvent(e);
}
/**
* Used to send an event from one entity to another, with priority in the queue.
*
* @param src the src
* @param dest the dest
* @param delay the delay
* @param tag the tag
* @param data the data
*/
public static void sendFirst(int src, int dest, double delay, int tag, Object data) {
if (delay < 0) {
throw new IllegalArgumentException("Send delay can't be negative.");
}
SimEvent e = new SimEvent(SimEvent.SEND, clock + delay, src, dest, tag, data);
future.addEventFirst(e);
}
/**
* Sets an entity's state to be waiting. The predicate used to wait for an event
* is now passed to Sim_system. Only events that satisfy the predicate will be
* passed to the entity. This is done to avoid unnecessary context switches.
*
* @param src the src
* @param p the p
*/
public static void wait(int src, Predicate p) {
entities.get(src).setState(SimEntity.WAITING);
if (p != SIM_ANY) {
// If a predicate has been used store it in order to check it
waitPredicates.put(src, p);
}
}
/**
* 队列中事件满足:目的地=d,谓词满足p的事件个数
* Checks if events for a specific entity are present in the deferred event queue.
*
* @param d the d
* @param p the p
*
* @return the int
*/
public static int waiting(int d, Predicate p) {
int count = 0;
SimEvent event;
Iterator<SimEvent> iterator = deferred.iterator();
while (iterator.hasNext()) {
event = iterator.next();
if ((event.getDestination() == d) && (p.match(event))) {
count++;
}
}
return count;
}
/**
* 选择第一个满足src(目的地)和谓词p条件的事件,并把它从队列中移走
* Selects an event matching a predicate.
*
* @param src the src
* @param p the p
*
* @return the sim event
*/
public static SimEvent select(int src, Predicate p) {
SimEvent ev = null;
Iterator<SimEvent> iterator = deferred.iterator();
while (iterator.hasNext()) {
ev = iterator.next();
if (ev.getDestination() == src && p.match(ev)) {
iterator.remove();
break;
}
}
return ev;
}
/**
* Removes an event from the event queue.
*
* @param src the src
* @param p the p
*
* @return the sim event
*/
public static SimEvent cancel(int src, Predicate p) {
SimEvent ev = null;
Iterator<SimEvent> iter = future.iterator();
while (iter.hasNext()) {
ev = iter.next();
if (ev.getSource() == src && p.match(ev)) {
iter.remove();
break;
}
}
return ev;
}
/**
* Removes all events that match a given predicate from the future event queue
* returns true if at least one event has been cancelled; false otherwise.
*
* @param src the src
* @param p the p
*
* @return true, if successful
*/
public static boolean cancelAll(int src, Predicate p) {
SimEvent ev = null;
int previousSize = future.size();
Iterator<SimEvent> iter = future.iterator();
while (iter.hasNext()) {
ev = iter.next();
if (ev.getSource() == src && p.match(ev)) {
iter.remove();
}
}
return previousSize < future.size();
}
//
// Private internal methods
//
/**
* Processes an event.处理事件
*
* @param e the e
*/
private static void processEvent(SimEvent e) {
int dest, src;
SimEntity dest_ent;
// Update the system's clock
if (e.eventTime() < clock) {
//此时仿真系统的时钟回拨,有可能使事件执行顺序变化
throw new IllegalArgumentException("Past event detected.");
}
clock = e.eventTime();
// Ok now process it
switch (e.getType()) {
case SimEvent.ENULL:
throw new IllegalArgumentException("Event has a null type.");
case SimEvent.CREATE:
SimEntity newe = (SimEntity) e.getData();
addEntityDynamically(newe);
break;
case SimEvent.SEND:
// Check for matching wait
dest = e.getDestination();
if (dest < 0) {
throw new IllegalArgumentException(
"Attempt to send to a null entity detected.");
} else {
int tag = e.getTag();
dest_ent = entities.get(dest);
/**
* 实体处于waiting状态时候,通过event事件可以叫醒
* 处于waiting状态的实体在waitPredicates中可能纯在谓词
* 只有满足此谓词的事件才可以叫醒
* 运行状态的实体没有谓词
*/
if (dest_ent.getState() == SimEntity.WAITING) {
Integer destObj = Integer.valueOf(dest);
Predicate p = waitPredicates.get(destObj);
if ((p == null) || (tag == 9999) || (p.match(e))) {
dest_ent.setEventBuffer((SimEvent) e.clone());
dest_ent.setState(SimEntity.RUNNABLE);
waitPredicates.remove(destObj);
} else {
deferred.addEvent(e);
}
} else {
deferred.addEvent(e);
}
}
break;
case SimEvent.HOLD_DONE:
src = e.getSource();
if (src < 0) {
throw new IllegalArgumentException("Null entity holding.");
} else {
entities.get(src).setState(SimEntity.RUNNABLE);
}
break;
default:
break;
}
}
/**
* 启动entities中所有实体
* Internal method used to start the simulation. This method should
* <b>not</b> be used by user simulations.
*/
public static void runStart() {
running = true;
// Start all the entities
for (SimEntity ent : entities) {
ent.startEntity();
}
printMessage("Entities started.");
}
/**
* Check if the simulation is still running. This method should be used by
* entities to check if they should continue executing.
*
* @return if the simulation is still running,
* otherwise
*/
public static boolean running() {
return running;
}
/**
* This method is called if one wants to pause the simulation.
*
* @return true, if successful
* otherwise.
*/
public static boolean pauseSimulation() {
paused = true;
return paused;
}
/**
* 终止仿真一定时间
* This method is called if one wants to pause the simulation at a given
* time.
*
* @param time the time at which the simulation has to be paused
* @return true, if successful
* otherwise.
*/
public static boolean pauseSimulation(long time) {
if (time <= clock) {
return false;
} else {
pauseAt = time;
}
return true;
}
/**
* 恢复实体
* This method is called if one wants to resume the simulation that has
* previously been paused.
*
* @return if the simulation has been restarted or or
* otherwise.
*/
public static boolean resumeSimulation() {
paused = false;
if (pauseAt <= clock) {
pauseAt = -1;
}
return !paused;
}
/**
* 仿真运行
* Start the simulation running. This should be called after all the
* entities have been setup and added, and their ports linked.
*
* @return the double last clock value
*/
public static double run() {
if (!running) {
//启动entities中所有实体
runStart();
}
while (true) {
//一个一个时刻运行
if (runClockTick() || abruptTerminate) {
break;
}
if (pauseAt != -1 && ((future.size() > 0 && clock <= pauseAt && pauseAt <= future.iterator().next().eventTime()) || future.size() == 0 && pauseAt <= clock)) {
pauseSimulation();
clock = pauseAt;
}
while (paused) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
double clock = clock();
finishSimulation();
runStop();
return clock;
}
/**
* 仿真结束,置对象为空
* Internal method that allows the entities to terminate. This method should
* <b>not</b> be used in user simulations.
*/
public static void finishSimulation() {
// Allow all entities to exit their body method
//非突然中断允许实体处理完剩下的event
if (!abruptTerminate) {
for (SimEntity ent : entities) {
if (ent.getState() != SimEntity.FINISHED) {
ent.run();
}
}
}
for (SimEntity ent : entities) {
ent.shutdownEntity();
}
// reset all static variables
// Private data members
entities = null;
entitiesByName = null;
future = null;
deferred = null;
clock = 0L;
running = false;
waitPredicates = null;
paused = false;
pauseAt = -1;
abruptTerminate = false;
}
/**
* Abruptally terminate.
*/
public static void abruptallyTerminate() {
abruptTerminate = true;
}
/**
* Prints a message about the progress of the simulation.
*
* @param message the message
*/
private static void printMessage(String message) {
Log.printLine(message);
}
/**
* Checks if is paused.
*
* @return true, if is paused
*/
public static boolean isPaused() {
return paused;
}
}
更多推荐
已为社区贡献5条内容
所有评论(0)