import java.util.*;
import java.io.*;
/**
* The SystemDriver class reads the data files that describe the processes
* executing on the system and simulate the system-calls and interrupts
* generated by the actions of those processes. The SystemDriver class requires
* three command line arguments:
*
*
* processFilename
* deviceFilename
* schedulerType
*
*
*
* The file indicated by the processFilename must contains a list
* of the data data files for the processes. Each process will contains its own
* data file. The format for a data file describing a process is as follows:
*
*
* <Process Name>
* <start time>
* CPU <time>
* ...
* IO <device ID> <time>
* CPU <time>
* ...
* WAIT <queue ID>
* CPU <time>
* ...
* NOTIFY <queue ID>
* CPU <time>
* ...
* NOTIFY_ALL <queue ID>
* CPU <time>
* ...
* EXIT
*
*
*
* The time for CPU and IO operations are specified in virtual time units. All
* "device ID"s and "queue ID"s must be listed in the file indicated by
* devicesFilename command line argument as described below.
*
*
* The WAIT, NOTIFY and NOTIFY_ALL commands apply to queues. The WAIT operation
* blocks the invoking process on the queue. The NOTIFY operation wakes a single
* process that is waiting on the queue. The NOTIFY_ALL operation wakes all
* processes that are waiting on the queue. The times specified for a CPU and IO
* operations are specified in ms.
*
*
* The file indicated by the devicesFilename command line
* argument must contain a list of the devices in the system. There are only 2
* types of devices supported: I/O Devices and Queues. I/O devices coorespond to
* any device that generates an interrupt when an operation is complete. Thus, a
* process must actively wait on a I/O Device but the device will generate and
* interrupt when the process is to be woken up. A Queue is also a device on
* which a process may wait. However, another process must take an action to
* wake up a process waiting on a Queue.
*
*
* The format of the devicesFilename file is as follows:
*
*
*
*
* <device type> <device ID>
*
*
*
*
*
* A "Device ID" may be any String. The "device type" must be either "I/O" or
* "Queue".
*
*
* In all of these files, lines begining with # as the first character are
* treated as comments and blank lines are ignored.
*/
public class SystemDriver {
public static void main(String[] args) {
if (args.length == 3) {
String processesFilename = args[0];
String devicesFilename = args[1];
String schedulerType = args[2];
Vector ioDevices = new Vector(20, 20);
Vector queueDevices = new Vector(20, 20);
Vector processList = new Vector(20, 20);
Vector processes = new Vector(20, 20);
EventQueue events = new EventQueue();
SystemTimer timer = new SystemTimer(processes, events);
// Dynamically load the correct Kernel class based on the name
// of the class specified in the schedulerType parameter.
ClassLoader cl = ClassLoader.getSystemClassLoader();
Class c = null;
try {
c = cl.loadClass(schedulerType);
}
catch (ClassNotFoundException e) {
System.out.println("The specified kernel " + schedulerType +
" could not be found.");
System.out.println(e);
System.exit(-1);
}
Kernel osKernel = null;
try {
osKernel = (Kernel)c.newInstance();
}
catch (Exception e) {
System.out.println("Unable to instantiate kernel class: " +
schedulerType + ".");
System.out.println(e);
System.exit(-1);
}
timer.setKernel(osKernel);
readDeviceList(devicesFilename, ioDevices, queueDevices);
readProcessList(processesFilename, processList);
readProcessData(processList, processes, ioDevices, queueDevices,
osKernel);
createDevicesAndQueues(ioDevices, queueDevices, osKernel, timer);
scheduleProcessArrivals(processes, events);
timer.processEvents();
}
else {
System.out
.println("Usage: java SystemDriver \n"
+ "\t - Processes data file.\n"
+ "\t - Devices data file.\n"
+ "\t - Scheduler type.");
}
}
/**
* Schedule an event to occurr at the arrival time for each of the
* processes.
*
* @param processes the Vector of all of the Processes.
* @param systemTimer the Timer that controlls the sequence of events in the
* simulation.
*/
public static void scheduleProcessArrivals(Vector processes,
EventQueue events) {
ListIterator procIt = processes.listIterator();
while (procIt.hasNext()) {
Process p = (Process) procIt.next();
Event e = new Event(p.getArrivalTime(), p.getOp());
p.advanceOpCounter();
events.add(e);
}
//events.printEventQueue();
}
/**
* Make the system calls to the kernel to request that the I/O devices and
* the queues be created.
*
* @param ioDevices a Vector of all of the device names.
* @param queueDevices a Vector of all of the queue names.
* @param osKernel a reference to the Kernel object.
*/
public static void createDevicesAndQueues(Vector ioDevices,
Vector queueDevices, Kernel osKernel, SystemTimer timer) {
// Make a system call to the Kernel requesting that each of the
// I/O devices be created.
ListIterator devIt = ioDevices.listIterator();
while (devIt.hasNext()) {
osKernel.systemCall(Kernel.MAKE_DEVICE, (String) devIt.next(), timer);
}
// Make a system call to the Kernel requesting that each of the
// Queues be created.
// ListIterator queueIt = queueDevices.listIterator();
// while (queueIt.hasNext()) {
// osKernel.systemCall(Kernel.MAKE_QUEUE, (String) queueIt.next(), timer);
// }
}
/**
* Read the list of devices from the specified file.
*
* @param devicesFilename the file from which the list of devices is to be
* read.
* @param ioDevices a Vector of all of the device names.
* @param queueDevices a Vector of all of the queue names.
*/
public static void readDeviceList(String devicesFilename, Vector ioDevices,
Vector queueDevices) {
try {
FileInputStream fStream = new FileInputStream(devicesFilename);
InputStreamReader inReader = new InputStreamReader(fStream);
BufferedReader bReader = new BufferedReader(inReader);
while (bReader.ready()) {
String line = bReader.readLine();
if (!line.trim().equals("") && !line.startsWith("#")) {
line = line.toUpperCase();
if (line.startsWith("I/O")) {
ioDevices.add(line.substring(3).trim());
}
else if (line.startsWith("QUEUE")) {
queueDevices.add(line.substring(5).trim());
}
else {
throw new UnsupportedOperationException(
"Undefined device type: " + line);
}
}
}
fStream.close();
inReader.close();
bReader.close();
}
catch (IOException e) {
System.err.println("Error reading devices.dat file.");
System.err.println(e);
System.exit(-1);
}
}
/**
* Read the list of process filenames from the specified file.
*
* @param processesFilename the file from which the list of process
* filenames is to be read.
* @param processList a Vector to be loaded with the list of process
* filenames is to be stored.
*/
public static void readProcessList(String processesFilename,
Vector processList) {
try {
FileInputStream fStream = new FileInputStream(processesFilename);
InputStreamReader inReader = new InputStreamReader(fStream);
BufferedReader bReader = new BufferedReader(inReader);
while (bReader.ready()) {
String line = bReader.readLine();
if (!line.trim().equals("") && !line.startsWith("#")) {
processList.add(line);
}
}
fStream.close();
inReader.close();
bReader.close();
}
catch (IOException e) {
System.err.println("Error reading processes.dat file.");
System.err.println(e);
System.exit(-1);
}
}
/**
* Read the process profile information for each of the processes listed in
* the "processes.dat" file.
*
* @param processList a Vector of the filenames for each of the processes.
* @param processes a Vector to hold the Process objects for each of the
* processes.
* @param ioDevices a Vector of all of the device names.
* @param queueDevices a Vector of all of the queue names.
* @param osKernel the kernel that will be controlling the execution of the
* processes.
*/
public static void readProcessData(Vector processList, Vector processes,
Vector ioDevices, Vector queueDevices, Kernel osKernel) {
ListIterator procIt = processList.listIterator();
while (procIt.hasNext()) {
processes.add(readProcess((String) procIt.next(), ioDevices,
queueDevices, osKernel));
}
}
/**
* Read the information about a particular process.
*
* @param procFilename the file containing the profiling information about
* the process.
* @param ioDeviceList the Vector of valid I/O devices.
* @param queueDeviceList the Vector of valid queue devices.
* @return a Process object containg the profiling information read from the
* data file.
* @param osKernel the kernel that will be controlling the execution of the
* processes.
*/
public static Process readProcess(String procFilename, Vector ioDeviceList,
Vector queueDeviceList, Kernel osKernel) {
try {
FileInputStream fStream = new FileInputStream(procFilename);
InputStreamReader inReader = new InputStreamReader(fStream);
BufferedReader bReader = new BufferedReader(inReader);
// Read the first line of data in the file as the process name.
String procName;
do {
procName = bReader.readLine().trim();
} while (procName.equals("") || procName.startsWith("#"));
// Read the second line of data in the file as the arrival time.
String arrivalTime;
do {
arrivalTime = bReader.readLine().trim();
} while (arrivalTime.equals("") || arrivalTime.startsWith("#"));
Process p = new Process(procName, Integer.parseInt(arrivalTime),
osKernel);
// Read all the rest of the lines of data in the file as operations.
while (bReader.ready()) {
String line = bReader.readLine();
if (!line.trim().equals("") && !line.startsWith("#")) {
line = line.toUpperCase();
ProcessOperation pOp = new ProcessOperation(line, p);
// Make sure that if the operation uses a device it is
// one that was listed in the devices.dat file.
if (pOp.getOpDevice() == null
|| ioDeviceList.contains(pOp.getOpDevice())
|| queueDeviceList.contains(pOp.getOpDevice())) {
p.addOp(pOp);
}
else {
throw new UnsupportedOperationException(
"Unrecognized device in file: " + procFilename);
}
}
}
fStream.close();
inReader.close();
bReader.close();
return p;
}
catch (IOException e) {
System.err.println("Error reading " + procFilename + "file.");
System.err.println(e);
System.exit(-1);
return null; // stupid compiler!
}
}
}