<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>mr795 new document title</title>
</head>
<body>
<p>// -*- java -*-</p>
<div></div>
<div>import java.io.*;</div>
<div></div>
<div>/**</div>
<div>&nbsp;*</div>
<div>&nbsp;* An implementation of BlockDevice that uses a file to store data</div>
<div>&nbsp;* Also, point this at /dev/fd0 on a linux system and you can use it&nbsp;</div>
<div>&nbsp;* to read/write from disks!</div>
<div>&nbsp;*</div>
<div>&nbsp;* Comments: sdh300@ecs.soton.ac.uk</div>
<div>&nbsp;*</div>
<div>&nbsp;* @author Simon Howard</div>
<div>&nbsp;*/</div>
<div></div>
<div>public class FileBlockDevice implements BlockDevice {</div>
<div><span style="white-space: pre;"> </span></div>
<div>&nbsp;// default size for a new file</div>
<div></div>
<div>&nbsp;private static final int DEFAULT_FILE_SIZE = 1423 * 1024; // 1.44 megs</div>
<div></div>
<div>&nbsp;// for accessing file</div>
<div></div>
<div>&nbsp;private RandomAccessFile r;</div>
<div>&nbsp;private int numBlocks, blockSize;</div>
<div></div>
<div>&nbsp;/**&nbsp;</div>
<div>&nbsp; * Creates a new FileBlockDevice. The filename is the path to the</div>
<div>&nbsp; * file used to store the data. A blocksize can be specified to</div>
<div>&nbsp; * use (seeing as there is no real block size on arbitrary files)</div>
<div>&nbsp; * If the file does not exist then a new file is created of</div>
<div>&nbsp; * size 1.44 megs</div>
<div>&nbsp; *</div>
<div>&nbsp; * @param        filename   the file to use to store data&nbsp;</div>
<div>&nbsp; * @param        blockSize  the size of the blocks to use</div>
<div>&nbsp; */</div>
<div></div>
<div>&nbsp;public FileBlockDevice(String filename, int blockSize) {</div>
<div></div>
<div>&nbsp; this.blockSize = blockSize;</div>
<div>&nbsp;&nbsp;</div>
<div>&nbsp; File f = new File(filename);</div>
<div>&nbsp; boolean newfile = !f.exists();</div>
<div></div>
<div>&nbsp; // open file</div>
<div></div>
<div>&nbsp; try {</div>
<div>&nbsp; &nbsp;r = new RandomAccessFile(f, "rw");</div>
<div>&nbsp; } catch(IOException e) {</div>
<div>&nbsp; &nbsp;System.err.println("FileBlockDevice: error opening "&nbsp;</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; + filename);</div>
<div>&nbsp; &nbsp;e.printStackTrace();</div>
<div>&nbsp; }</div>
<div></div>
<div>&nbsp; // if this is a new file, give a warning message and make</div>
<div>&nbsp; // sure we extend the file size&nbsp;</div>
<div>&nbsp;&nbsp;</div>
<div>&nbsp; if (newfile) {</div>
<div>&nbsp; &nbsp;System.err.println("FileBlockDevice: Creating new file "&nbsp;</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; + filename);</div>
<div></div>
<div>&nbsp; &nbsp;numBlocks = DEFAULT_FILE_SIZE / blockSize;</div>
<div>&nbsp; &nbsp;try {</div>
<div>&nbsp; &nbsp; r.setLength(DEFAULT_FILE_SIZE);</div>
<div>&nbsp; &nbsp;} catch(IOException e) {</div>
<div>&nbsp; &nbsp; System.err.println("FileBlockDevice: " +</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;"error creating new file");</div>
<div>&nbsp; &nbsp; e.printStackTrace();</div>
<div>&nbsp; &nbsp;}</div>
<div>&nbsp; } else {</div>
<div>&nbsp; &nbsp;// cheap hack</div>
<div></div>
<div>&nbsp; &nbsp;if (filename.equals("/dev/fd0")) {</div>
<div>&nbsp; &nbsp; numBlocks = (int) (DEFAULT_FILE_SIZE / blockSize);</div>
<div>&nbsp; &nbsp;} else {</div>
<div>&nbsp; &nbsp; numBlocks = (int) (f.length() / blockSize);</div>
<div>&nbsp; &nbsp;}</div>
<div>&nbsp; &nbsp;if (f.length() % blockSize != 0) {</div>
<div>&nbsp; &nbsp; System.err.println("Warning: length of "&nbsp;</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;+ filename&nbsp;</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;+ " is not a multiple of "&nbsp;</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;+ blockSize);</div>
<div>&nbsp; &nbsp;}</div>
<div>&nbsp; }</div>
<div>&nbsp;}</div>
<div></div>
<div>&nbsp;/**&nbsp;</div>
<div>&nbsp; * Default of 1024 byte blocks</div>
<div>&nbsp; *</div>
<div>&nbsp; * @param        filename   the file to use to store data&nbsp;</div>
<div>&nbsp; */</div>
<div></div>
<div>&nbsp;public FileBlockDevice(String filename) {</div>
<div>&nbsp; this(filename, 1024);</div>
<div>&nbsp;}</div>
<div></div>
<div>&nbsp;/**</div>
<div>&nbsp; * Read a block into memory.&nbsp;</div>
<div>&nbsp; *</div>
<div>&nbsp; * @param        b          A buffer into which the block data is read.</div>
<div>&nbsp; *                          The buffer should be large enough to hold&nbsp;</div>
<div>&nbsp; *                          a block.</div>
<div>&nbsp; * @param        block      The block number of the block to read in</div>
<div>&nbsp; */</div>
<div><span style="white-space: pre;"> </span></div>
<div>&nbsp;public void readBlock(byte[] b, int block) {</div>
<div>&nbsp;&nbsp;</div>
<div>&nbsp; // sanity check</div>
<div></div>
<div>&nbsp; if (block &lt; 0 || block &gt;= numBlocks) {</div>
<div>&nbsp; &nbsp;System.err.println("FileBlockDevice: Attempt to access "&nbsp;</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; + "block " + block);</div>
<div>&nbsp; &nbsp;return;</div>
<div>&nbsp; }</div>
<div></div>
<div>&nbsp; try {</div>
<div>&nbsp; &nbsp;r.seek(block * blockSize);</div>
<div>&nbsp; &nbsp;r.read(b);</div>
<div>&nbsp; } catch(IOException e) {</div>
<div>&nbsp; &nbsp;System.err.println("FileBlockDevice: " +&nbsp;</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; "Error reading from file");</div>
<div>&nbsp; &nbsp;e.printStackTrace();</div>
<div>&nbsp; }</div>
<div>&nbsp;}</div>
<div></div>
<div>&nbsp;/**</div>
<div>&nbsp; * Write a block to disk</div>
<div>&nbsp; *</div>
<div>&nbsp; * @param        b          A buffer storing the data to be written.</div>
<div>&nbsp; *                          The buffer should be large enough to hold&nbsp;</div>
<div>&nbsp; *                          a block.</div>
<div>&nbsp; * @param        block      The block number of the block to read in.</div>
<div>&nbsp; */</div>
<div></div>
<div>&nbsp;public void writeBlock(byte[] b, int block) {</div>
<div></div>
<div>&nbsp; // sanity check</div>
<div></div>
<div>&nbsp; if (block &lt; 0 || block &gt;= numBlocks) {</div>
<div>&nbsp; &nbsp;System.err.println("FileBlockDevice: Attempt to access "&nbsp;</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; + "block " + block);</div>
<div>&nbsp; &nbsp;return;</div>
<div>&nbsp; }</div>
<div></div>
<div>&nbsp; try {</div>
<div>&nbsp; &nbsp;r.seek(block * blockSize);</div>
<div>&nbsp; &nbsp;r.write(b);</div>
<div>&nbsp; } catch(IOException e) {</div>
<div>&nbsp; &nbsp;System.err.println("FileBlockDevice: " +&nbsp;</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; "Error writing to file");</div>
<div>&nbsp; &nbsp;e.printStackTrace();</div>
<div>&nbsp; }</div>
<div>&nbsp;}</div>
<div></div>
<div>&nbsp;/**</div>
<div>&nbsp; * Get the number of blocks in the file</div>
<div>&nbsp; *</div>
<div>&nbsp; * @return        The number of blocks in the device</div>
<div>&nbsp; */</div>
<div></div>
<div>&nbsp;public int getNumberOfBlocks() {</div>
<div>&nbsp; return numBlocks;</div>
<div>&nbsp;}</div>
<div></div>
<div>&nbsp;/**&nbsp;</div>
<div>&nbsp; * Get the block size</div>
<div>&nbsp; *</div>
<div>&nbsp; * @return        The size of each block in bytes</div>
<div>&nbsp; */</div>
<div></div>
<div>&nbsp;public int getBlockSize() {</div>
<div>&nbsp; return blockSize;</div>
<div>&nbsp;}</div>
<div></div>
<div>&nbsp;public static void main(String[] args) {</div>
<div>&nbsp; FileBlockDevice f = new FileBlockDevice("blockfile.bin");</div>
<div>&nbsp; byte[] b = new byte[f.getBlockSize()];</div>
<div></div>
<div>&nbsp; for (int i=0; i&lt;f.getBlockSize(); ++i)</div>
<div>&nbsp; &nbsp;b[i] = (byte) (i % 256);</div>
<div>&nbsp;&nbsp;</div>
<div>&nbsp; f.writeBlock(b, 1);</div>
<div>&nbsp;}</div>
<div>}</div>
</body>
</html>