CS644 Qualifying/Diagnostic Exam, due Thurs, Jan. 28, at start of class.

(Just write it out on notebook paper, or use a word processor.)

Layering Concepts and Management of State Information

A primitive operating system allows only one file open at a time, and files must be opened to be read or written.  It offers the following system calls under that restriction:

int openf(const char *name, int startpos) -- open file of given name, set file pointer at byte startpos, so that next read or write accesses that byte.

int readf() -- read one byte and return it in an int, step file pointer one byte. Return -1 for error or EOF.

int writef(char ch) -- write char (one byte in C) ch to file, step file pointer one byte

int closef(void) -- close currently-open file.

Note: All return success=0 (>= 0 for readf), failure=-1 as functional value.  Note that -1 as an int does not match any single-byte data value (0x00-0xff).

1.     Write a package in C (or Java, see below)  to allow applications programmers to use the following calls that support the notion of one read-file and one write-file in the usual sequential access manner, without the users (applications programmers) having to worry about the one-file-open rule:

 

int openread(const char *name) -- open, at byte position 0, a file for reading

int openwrite(const char *name) -- open, at byte position 0, a file for writing

int char read() -- read one byte from the read-file at the current read-file position, return the byte in an int, step that position.

int write(char ch) -- write one byte to the write-file at the current write-file position, step that position.

int closeread(void) -- close current read-file

int closewrite(void) -- close current write-file

 

The first read after an openread reads in byte 0, the second reads in byte 1, and so on, so that each read steps the current read-file position.  For example, the sequence (in an application program) “openrd(foo”); ch1 = read(); openwr(“bar”); write(‘a’); ch2 = read()” should read byte 0 of foo into ch1 and byte 1 of foo into ch2, as well as writing the ‘a’ into bar at position 0 in that file.

Assume all file access for the applications program pass through your package.  You may require a int fileinit(void) call to precede all other calls to your package if you desire.  You don’t have to write out repetitious code, just show enough to make clear you know how to do it.

a.     First implement the trivial solution that keeps the files OS-closed between calls to your package and opens the appropriate one for each byte of i/o.  What is wrong with this approach?

b.     Second implement the more complicated solution that allows files to stay OS-open until the file-in-use changes.  Don’t go to the extreme of buffering data in your package!  Also be content to support  only one read-file and one write-file, no more.

 

2.     Analysis of state information, system of 1b.

a.     What variables in your implementation hold state of the package between calls from the applications program?  These should be static external variables so that the applications code can’t access them, yet they can hold data from one call from the application  to be used in another call.

b.     Concentrating on the variables that summarize state information, determine less than 10 distinct states of the system (that hold for periods of time, i.e., not transient states) and make a state transition diagram between these states, with the arrows between states labeled with openread, openwrite, read, etc.  For example, one of these states is the idle state, with no files open to the application or in the OS.  Another state is a readfile open for the app but no writefile, with the readfile open in the OS.  And so on.

 

Java setup—use only if you feel your C is too weak to do it right!

public interface PrimitiveFile {

   // open file of given name, set file pointer at byte startpos, so that next

   // read or write accesses that byte.

   int openf(String name, int startpos);

   // read one byte, step file pointer one byte, return byte >= 0 or -1 for error or EOF

   int readf(String buff);

   //-- write pointed-to char in memory to file, step file pointer one byte

   int writef(String buff);

   // close currently-open file.

   int closef();

}

public class PrimitiveOS implements PrimitiveFile {

   // create exactly one OS object (assume this class is all implemented)

   static private PrimitiveOS theOSobject = new PrimitiveOS();

   private PrimitiveOS() {}

   public static PrimitiveOS getOS() {return theOSobject;}

   public int openf(String name, int startpos) {System.out.println("openf"); return 1;}

   // read one byte, step file pointer one byte, return byte >= 0 or -1 for error or EOF

   public int readf(String buff){return 0;}

   //-- write pointed-to char in memory to file, step file pointer one byte

   public int writef(String buff){return 6;}

   // close currently-open file.

   public int closef(){return 1;}

   public static void main(String [] args)

   {

      PrimitiveOS os = getOS();

      os.openf("foo", 0);

   }

}

public interface AppFileAPI {

   // open file of given name, set file pointer at byte 0, for reading

   int openread(String name);

   //  open, at byte position 0, a file for writing

   int openwrite(String name);

   // read one byte from the read-file, step read-file pos

   int read();

   // write one byte from the write-file, step write-file pos

   int write(byte ch);

   // close current read-file

   int closeread();

   // close current write-file

   int closewrite();

}

// You fill out this one--

public class AppFileService implements AppFileAPI {

   // create exactly one AFS object, at initialization time

   static private AppFileService theAFS = new AppFileService();

   // get reference for primitive OS service, for private use

   static private PrimitiveOS os = PrimitiveOS.getOS();

       // you add more fields here

   private AppFileService() {}

 

   // provide a reference to the one AFS object to anyone--

   public static AppFileService getAFS() { return theAFS;}

   // open read file

   public int openread(String name)

     {return os.openf(name, 0);}  // fake implementation, showing call to os

 

   public int openwrite(String name) {return 1;}

   // read one byte, step file pointer one byte, return byte >= 0 or -1 for error or EOF

   public int read(){return 0;}

   //-- write pointed-to char in memory to file, step file pointer one byte

   public int write(byte ch){return 6;}

 

   // close currently-open file.

   public int closewrite(){return 1;}

   public int closeread(){return 1;}

 

   public static void main(String [] args)

   {

      AppFileService afs = AppFileService.getAFS();

      afs.openread("foo");

   }

}