- /*
- * 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
- //注:下面3行的顺序是很重要的
- 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对象
- 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;
- }
- }
云计算仿真工具中文注释CloudSim.java
最新推荐文章于 2015-05-10 21:41:38 发布