⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 edsimulator.java

📁 peersim最新版1.0.4
💻 JAVA
字号:
/* * Copyright (c) 2003-2005 The BISON Project * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2 as * published by the Free Software Foundation. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */package peersim.edsim;import java.util.*;import peersim.config.*;import peersim.core.*;/*** Event-driven simulator engine.* It is a fully static singleton class.* For an event driven simulation * the configuration has to describe a set of {@link Protocol}s,* a set of {@link Control}s and their ordering and a set of* initializers and their ordering. See parameters {@value #PAR_INIT},* {@value #PAR_CTRL}.* <p>* One experiment run by {@link #nextExperiment} works as follows.* First the initializers are run in the specified order. Then the first* execution of all specified controls is scheduled in the event queue.* This scheduling is defined by the {@link Scheduler} parameters of each* control component.* After this, the first event is taken from the event queue. If the event* wraps a control, the control is executed, otherwise the event is* delivered to the destination protocol, that must implement* {@link EDProtocol}. This* is iterated while the current time is less than {@value #PAR_ENDTIME} or* the queue becomes empty.* If more control events fall at the same time point, then the order given* in the configuration is respected. If more non-control events fall at the same* time point, they are processed in a random order.* <p>* The engine also provides the interface to add events to the queue.* Note that this engine does not explicitly run the protocols.* In all cases at least one control or initializer has to be defined that* sends event(s) to protocols.* <p>* Controls can be scheduled (using the {@link Scheduler}* parameters in the configuration) to run after the experiment* has finished.* That is, each experiment is finished by running the controls that are* scheduled to be run after the experiment.* <p>* Any control can interrupt an experiment at any time it is* executed by returning true in method {@link Control#execute}.* However, the controls scheduled to run after the experiment are still* executed completely, irrespective of their return value and even if* the experiment was interrupted.* <p>* {@link CDScheduler} has to be mentioned that is a control that* can bridge the gap between {@link peersim.cdsim} and the event driven* engine. It can wrap {@link peersim.cdsim.CDProtocol} appropriately so that the* execution of the cycles are scheduled in configurable ways for each node* individually. In some cases this can add a more fine-grained control* and more realism to {@link peersim.cdsim.CDProtocol} simulations,* at the cost of some* loss in performance.* <p>* When protocols at different nodes send messages to each other, they might* want to use a model of the transport layer so that in the simulation* message delay and message omissions can be modeled in a modular way.* This functionality is implemented in package {@link peersim.transport}.* @see Configuration */public class EDSimulator{//---------------------------------------------------------------------// Parameters//---------------------------------------------------------------------	/** * The ending time for simulation. Only events that have a strictly smaller * value are executed. It must be positive. Although in principle * negative timestamps could be allowed, we assume time will be positive. * @config */public static final String PAR_ENDTIME = "simulation.endtime";	/** * This parameter specifies * how often the simulator should log the current time on the * standard error. The time is logged only if there were events in the * respective interval, and only the time of some actual event is printed. * That is, the actual log is not guaranteed to happen * in identical intervals of time. It is merely a way of seeing whether the * simulation progresses and how fast... * @config */private static final String PAR_LOGTIME = "simulation.logtime";	/**  * This parameter specifies the event queue to be used. It must be an * implementation of interface {@link PriorityQ}. If it is not defined, * the internal implementation is used. * @config  */	private static final String PAR_PQ = "simulation.eventqueue";/** * This is the prefix for initializers. * These have to be of type * {@link Control}. They are run at the beginning of each experiment, in the * order specified by the configuration. * @see Configuration * @config * @config */private static final String PAR_INIT = "init";/** * This is the prefix for {@link Control} components. * They are run at the time points defined by the * {@link Scheduler} associated to them. If some controls have to be * executed at the same time point, they are executed in the order * specified in the configuration. * @see Configuration * @config */private static final String PAR_CTRL = "control";//---------------------------------------------------------------------//Fields//---------------------------------------------------------------------/** Maximum time for simulation */private static long endtime;/** Log time */private static long logtime;/** holds the modifiers of this simulation */private static Control[] controls=null;/** Holds the control schedulers of this simulation */private static Scheduler[] ctrlSchedules = null;/** Ordered list of events (heap) */private static PriorityQ heap = null;private static long nextlog = 0;// =============== initialization ======================================// =====================================================================/** to prevent construction */private EDSimulator() {}//---------------------------------------------------------------------//Private methods//---------------------------------------------------------------------/** * Load and run initializers. */private static void runInitializers() {		Object[] inits = Configuration.getInstanceArray(PAR_INIT);	String names[] = Configuration.getNames(PAR_INIT);		for(int i=0; i<inits.length; ++i)	{		System.err.println(		"- Running initializer " +names[i]+ ": " + inits[i].getClass());		((Control)inits[i]).execute();	}}// --------------------------------------------------------------------private static void scheduleControls(){	// load controls	String[] names = Configuration.getNames(PAR_CTRL);	controls = new Control[names.length];	ctrlSchedules = new Scheduler[names.length];	for(int i=0; i<names.length; ++i)	{		controls[i]=(Control)Configuration.getInstance(names[i]);		ctrlSchedules[i] = new Scheduler(names[i], false);	}	System.err.println("EDSimulator: loaded controls "+		Arrays.asList(names));	// Schedule controls execution	if (controls.length > heap.maxPriority()+1)		throw new IllegalArgumentException(		"Too many control objects");	for (int i=0; i < controls.length; i++) {		new ControlEvent(controls[i], ctrlSchedules[i], i);	}}//---------------------------------------------------------------------/** * Adds a new event to be scheduled, specifying the number of time units * of delay, and the execution order parameter. *  * @param time  *   The actual time at which the next event should be scheduled. * @param order *   The index used to specify the order in which control events *   should be executed, if they happen to be at the same time, which is *   typically the case. * @param event  *   The control event */static void addControlEvent(long time, int order, ControlEvent event){// we don't check whether time is negative or in the past: we trust// the caller, which must be from this package	if (time >= endtime) return;	heap.add(time, event, null, (byte)0, order);}//---------------------------------------------------------------------/** * This method is used to check whether the current configuration can * be used for event driven simulations. It checks for the existence of * config parameter {@value #PAR_ENDTIME}. */public static final boolean isConfigurationEventDriven(){	return Configuration.contains(PAR_ENDTIME);}//---------------------------------------------------------------------/** * Execute and remove the next event from the ordered event list. * @return true if the execution should be stopped. */private static boolean executeNext() {	PriorityQ.Event ev = heap.removeFirst();	if( ev == null )	{		System.err.println("EDSimulator: queue is empty, quitting"+		" at time "+CommonState.getTime());		return true;	}		long time = ev.time;	if (time >= nextlog)	{		System.err.println("Current time: " + time);		// seemingly complicated: to prevent overflow		while( time-nextlog >= logtime ) nextlog+=logtime;		if( endtime-nextlog >= logtime ) nextlog+=logtime;		else nextlog=endtime;	}	if (time >= endtime)	{		System.err.println("EDSimulator: reached end time, quitting,"+		" leaving "+heap.size()+" unprocessed events in the queue");		return true;	}		CommonState.setTime(time);	int pid = ev.pid;	if (ev.node == null)	{		// might be control event; handled through a special method		try {			ControlEvent ctrl = (ControlEvent) ev.event;			return ctrl.execute();		} catch (ClassCastException e) {			throw new RuntimeException(				"No destination specified (null) for event "+				ev);		}	}	else if (ev.node != Network.prototype && ev.node.isUp() )	{		CommonState.setPid(pid);		CommonState.setNode(ev.node);		if( ev.event instanceof NextCycleEvent )		{			NextCycleEvent nce = (NextCycleEvent) ev.event;			nce.execute();		}		else		{			EDProtocol prot = null;			try {				prot = (EDProtocol) ev.node.getProtocol(pid);			} catch (ClassCastException e) {				e.printStackTrace();				throw new IllegalArgumentException("Protocol " +					Configuration.lookupPid(pid) + 					" does not implement EDProtocol; " + ev.event.getClass()  );			}			prot.processEvent(ev.node, pid, ev.event);		}	}		return false;}//---------------------------------------------------------------------//Public methods//---------------------------------------------------------------------/** * Runs an experiment, resetting everything except the random seed. */public static void nextExperiment() {	// Reading parameter	if( Configuration.contains(PAR_PQ) ) 		heap = (PriorityQ) Configuration.getInstance(PAR_PQ);	else 		heap = new Heap();	endtime = Configuration.getLong(PAR_ENDTIME);	if( CommonState.getEndTime() < 0 ) // not initialized yet		CommonState.setEndTime(endtime);	if( heap.maxTime() < endtime )		throw new IllegalParameterException(PAR_ENDTIME,			"End time is too large: configured event queue only"+			" supports "+heap.maxTime());	logtime = Configuration.getLong(PAR_LOGTIME, Long.MAX_VALUE);	// initialization	System.err.println("EDSimulator: resetting");	CommonState.setPhase(CommonState.PHASE_UNKNOWN);	CommonState.setTime(0); // needed here	controls = null;	ctrlSchedules = null;	nextlog = 0;	Network.reset();	System.err.println("EDSimulator: running initializers");	runInitializers();	scheduleControls();	// Perform the actual simulation; executeNext() will tell when to	// stop.	boolean exit = false;	while (!exit) {		exit = executeNext();	}	// analysis after the simulation	CommonState.setPhase(CommonState.POST_SIMULATION);	for(int j=0; j<controls.length; ++j)	{		if( ctrlSchedules[j].fin ) controls[j].execute();	}}//---------------------------------------------------------------------/** * Adds a new event to be scheduled, specifying the number of time units * of delay, and the node and the protocol identifier to which the event * will be delivered. *  * @param delay  *   The number of time units before the event is scheduled. *   Has to be non-negative. * @param event  *   The object associated to this event * @param node  *   The node associated to the event. * @param pid  *   The identifier of the protocol to which the event will be delivered */public static void add(long delay, Object event, Node node, int pid){	if (delay < 0)		throw new IllegalArgumentException("Protocol "+			node.getProtocol(pid)+" is trying to add event "+			event+" with a negative delay: "+delay);	if (pid > Byte.MAX_VALUE) 		throw new IllegalArgumentException(				"This version does not support more than " 				+ Byte.MAX_VALUE + " protocols");		long time = CommonState.getTime();	if( endtime - time > delay ) // check like this to deal with overflow 		heap.add(time+delay, event, node, (byte) pid);}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -