public void Write(int index, byte[] data) { if (!IsFile) { throw new Exception("Must be a file to write bytes!"); } // Make sure the cache is filled! LoadBlocks(); // Extend the blocks if necessarry int initialFileLength = FileLength; int finalFileLength = Math.Max(index + data.Length, initialFileLength); VirtualBlock.ExtendBlocks(drive, blocks, initialFileLength, finalFileLength); // Write the data to the blocks VirtualBlock.WriteBlockData(drive, blocks, index, data); //Write the blocks CommitBlocks(); // Update file length in file node sector // Make sure to incease the file length as needed if (finalFileLength > initialFileLength) { (sector as FILE_NODE).FileSize = finalFileLength; drive.Disk.WriteSector(nodeSector, sector.RawBytes); } }
public void Write(int index, byte[] data) { // Make sure this is a file if (!IsFile) { throw new Exception("Must write to a file!"); } // Load the cache of blocks for the file LoadBlocks(); // Grow the cached blocks if needed int finalLength = Math.Max(FileLength, index + data.Length); VirtualBlock.ExtendBlocks(drive, blocks, FileLength, finalLength); // Write the bytes to the cache VirtualBlock.WriteBlockData(drive, blocks, index, data); // Flush the cache of blocks CommitBlocks(); // Adjust file size as needed if (finalLength > FileLength) { (sector as FILE_NODE).FileSize = index + data.Length; drive.Disk.WriteSector(nodeSector, sector.RawBytes); } }
public static void ExtendBlocks(VirtualDrive drive, List <VirtualBlock> blocks, int initialFileLength, int finalFileLength) { // if current number of blocks is too small, then append more blocks as needed // allocate free sectors for each new block int finalBlockCount = BlocksNeeded(drive, finalFileLength); int additionalBlocks = finalBlockCount - blocks.Count; if (additionalBlocks > 0) { int[] freeSectorAddresses = drive.GetNextFreeSectors(additionalBlocks); VirtualBlock prevBlock = blocks.Last(); foreach (int i in freeSectorAddresses) { // connect sectors prevBlock.sector.NextSectorAt = i; prevBlock.dirty = true; // create new block DATA_SECTOR dataSector = new DATA_SECTOR(drive.Disk.BytesPerSector, 0, new byte[] { 0 }); VirtualBlock newBlock = new VirtualBlock(drive, i, dataSector, true); // add to the end of block list blocks.Add(newBlock); // prepare next block prevBlock = newBlock; } } }
public void Write(int index, byte[] data) { //writes data bytes to the file starting at the index byte //fill cache by read current data from disk for this file LoadBlocks(); //if data to be writen is beyond the end of the current number of blocks, extend blocks int currentFileLength = FileLength; int newFileLength = Math.Max(currentFileLength, index + data.Length); VirtualBlock.ExtendBlocks(drive, blocks, currentFileLength, newFileLength); //copy data from cache to blocks VirtualBlock.WriteBlockData(drive, blocks, index, data); //commit cache back to disk CommitBlocks(); if (newFileLength > currentFileLength) { (sector as FILE_NODE).FileSize = newFileLength; drive.Disk.WriteSector(nodeSector, sector.RawBytes); } }
private void LoadBlocks() { // read data secvtors from disk and create virtual blocks in memory //check if cahce is up to date if (blocks != null) { return; } //instantiate an empty cache blocks = new List <VirtualBlock>(); //loop through data sectors for this file int nextDataSectorAt = DataSectorAt; while (nextDataSectorAt != 0) { //read sector DATA_SECTOR dataSector = DATA_SECTOR.CreateFromBytes(drive.Disk.ReadSector(nextDataSectorAt)); //create virtual block to cache VirtualBlock block = new VirtualBlock(drive, nextDataSectorAt, dataSector); //add block to cache blocks.Add(block); //get the address of the next daa scetor nextDataSectorAt = dataSector.NextSectorAt; } }
public static void WriteBlockData(VirtualDrive drive, List <VirtualBlock> blocks, int startIndex, byte[] data) { int bdps = drive.BytesPerDataSector; int totalBytesToCopy = data.Length; // Part 1: Find the first block to be written and write the first chunk to the end of it int blockIndex = (startIndex / bdps); // Index of the first block to be written VirtualBlock block = blocks[blockIndex]; // Copy the first chunk into the first block int toStart = startIndex % bdps; // Where to start in the first block int bytesToCopy = Math.Min(totalBytesToCopy, bdps - toStart); // How many bytes to copy into the first block int fromStart = 0; byte[] db = block.sector.DataBytes; CopyBytes(bytesToCopy, data, fromStart, db, toStart); block.sector.DataBytes = db; block.dirty = true; // Move on to the next chunk of data fromStart += bytesToCopy; // Part 2: Loop hoguh the middle blokcj and overwrite them completly with full chunks of data while (fromStart < (totalBytesToCopy - bdps)) { // Next block block = blocks[++blockIndex]; // Copy next chunk bytesToCopy = bdps; // Full block toStart = 0; // Overwrite starting at beginning of block db = block.sector.DataBytes; CopyBytes(bytesToCopy, data, fromStart, db, toStart); block.sector.DataBytes = db; block.dirty = true; // Move on to the next chunk of data fromStart += bytesToCopy; } // Part 3: Write the first part of the last block with the final chunk if (fromStart < totalBytesToCopy) { // Next block block = blocks[++blockIndex]; // Copy last chunk bytesToCopy = totalBytesToCopy - fromStart; toStart = 0; // Overwrite starting at beginning of block db = block.sector.DataBytes; CopyBytes(bytesToCopy, data, fromStart, db, toStart); block.sector.DataBytes = db; block.dirty = true; } }
public byte[] Read(int index, int length) { //reads length data bytes from file starting at index byte //fill cache by read current data from disk for this file LoadBlocks(); //copy data from blocks return(VirtualBlock.ReadBlockData(drive, blocks, index, length)); }
public static byte[] ReadBlockData(VirtualDrive drive, List <VirtualBlock> blocks, int startIndex, int length) { //given list of blocks in memory copy length bytes from blocks, starting at start index //allocate resulting data array byte[] data = new byte[length]; //case 1: initial bytes from middle of block to end of block //copy from block, starting somewhere to begining of data array int fromIndex = startIndex % drive.BytesPerDataSector; //where we start copying from the block? int copyCount = Math.Min(data.Length, drive.BytesPerDataSector - fromIndex); //min of data length and the # of bytes left int firstBlocktoRead = startIndex / drive.BytesPerDataSector; //the first block to be writen? VirtualBlock block = blocks[firstBlocktoRead]; int toStart = 0; //index in data to start at CopyBytes(copyCount, block.Data, fromIndex, data, toStart); //change clone toStart += copyCount; //update to where to copy to next //case 2: read all bytes in block int nextBlocktoRead = firstBlocktoRead + 1; //the next block to be writen? copyCount = drive.BytesPerDataSector; while (toStart + copyCount < data.Length) { block = blocks[nextBlocktoRead]; nextBlocktoRead++; fromIndex = 0; CopyBytes(copyCount, block.Data, fromIndex, data, toStart); //change clone toStart += copyCount; //update to where to copy to next } //there is still data left to copy if (toStart < data.Length) { //case 3: final bytes from beginning of block to middle of that block int finalIndex = (startIndex + data.Length); int finalBlockToRead = finalIndex / drive.BytesPerDataSector; block = blocks[finalBlockToRead]; copyCount = finalIndex % drive.BytesPerDataSector; //where to stop reading fromIndex = 0; CopyBytes(copyCount, block.Data, fromIndex, data, toStart); } return(data); }
public static void WriteBlockData(VirtualDrive drive, List <VirtualBlock> blocks, int startIndex, byte[] data) { //given list of blocks in memory copy data bytes starting at start index //case 1: initial bytes from middle of block to end of block int toStart = startIndex % drive.BytesPerDataSector; //where we start copying in the block? int copyCount = Math.Min(data.Length, drive.BytesPerDataSector - toStart); //min of data length and the # of bytes left int firstBlocktoWrite = startIndex / drive.BytesPerDataSector; //the first block to be writen? VirtualBlock block = blocks[firstBlocktoWrite]; int fromIndex = 0; //index in data to start at byte[] to = block.Data; //data clones CopyBytes(copyCount, data, fromIndex, to, toStart); //change clone block.Data = to; //write back changed data set dirty fromIndex += copyCount; //update to where to copy to next //case 2: overwrite all bytes in block int nextBlocktoWrite = firstBlocktoWrite + 1; //the next block to be writen? copyCount = drive.BytesPerDataSector; toStart = 0; while (fromIndex + copyCount < data.Length) { block = blocks[nextBlocktoWrite]; nextBlocktoWrite++; to = block.Data; CopyBytes(copyCount, data, fromIndex, to, toStart); //change clone block.Data = to; //write back changed data set dirty fromIndex += copyCount; //update to where to copy to next } //there is still data left to copy if (fromIndex < data.Length) { //case 3: final bytes from beginning of block to middle of that block int finalIndex = (startIndex + data.Length); block = blocks[nextBlocktoWrite]; copyCount = finalIndex % drive.BytesPerDataSector; to = block.Data; //data clones toStart = 0; CopyBytes(copyCount, data, fromIndex, to, toStart); //change clone block.Data = to; //write back changed data set dirty } }
public static byte[] ReadBlockData(VirtualDrive drive, List <VirtualBlock> blocks, int startIndex, int length) { int bdps = drive.BytesPerDataSector; int totalBytesToCopy = length; // Create the result byte[] to return at the end byte[] result = new byte[length]; // Part 1: Find the first block to be read and read the first chunk to the end of it int blockIndex = startIndex / bdps; // Index of the first block to be read VirtualBlock block = blocks[blockIndex]; // Copy the first chunk into the first block int fromStart = startIndex % bdps; // Where to start in the first block int bytesToCopy = Math.Min(totalBytesToCopy, bdps - fromStart); // How many bytes to copy into the first block int toStart = 0; CopyBytes(bytesToCopy, block.Data, fromStart, result, toStart); // Move on to the next chunk of data toStart += bytesToCopy; // Part 2: Loop hoguh the middle blokcj and overwrite them completly with full chunks of data while (toStart < (totalBytesToCopy - bdps)) { // Next block block = blocks[++blockIndex]; // Copy next chunk bytesToCopy = bdps; // Full block fromStart = 0; // Overwrite starting at beginning of block CopyBytes(bytesToCopy, block.Data, fromStart, result, toStart); // Move on to the next chunk of data toStart += bytesToCopy; } // Part 3: Read the first part of the last block with the final chunk if (toStart < totalBytesToCopy) { // Next block block = blocks[++blockIndex]; // Copy last chunk bytesToCopy = totalBytesToCopy - toStart; fromStart = 0; // Overwrite starting at beginning of block CopyBytes(bytesToCopy, block.Data, fromStart, result, toStart); } return(result); }
public byte[] Read(int index, int length) { if (!IsFile) { throw new Exception("Must be a file to read bytes!"); } // Make sure the cache is filled LoadBlocks(); // Copy the data from the blocks byte[] result = VirtualBlock.ReadBlockData(drive, blocks, index, length); // Return the data return(result); }
public static void WriteBlockData(VirtualDrive drive, List <VirtualBlock> blocks, int startIndex, byte[] data) { // Write data into the list of blocks, starting at index // calculate starting block and ending block int blockSize = drive.BytesPerDataSector; int startBlock = startIndex / blockSize; int endBlock = (startIndex + data.Length) / blockSize; // Write data to first block int fromStart = 0; VirtualBlock vb = blocks[startBlock]; byte[] blockData = vb.Data; // Overwrite old data int toStart = startIndex % blockSize; int copyCount = Math.Min(data.Length, blockSize - toStart); CopyBytes(copyCount, data, fromStart, blockData, toStart); // Put new data in vb.Data = blockData; fromStart += copyCount; // Write data to each affected block for (int i = startBlock + 1; i <= endBlock; i++) { vb = blocks[i]; blockData = vb.Data; // Overwrite old data toStart = 0; copyCount = Math.Min((data.Length - fromStart), blockSize - toStart); CopyBytes(copyCount, data, fromStart, blockData, toStart); // Put new data in vb.Data = blockData; fromStart += copyCount; } }
public byte[] Read(int index, int length) { // Make sure this is a file if (!IsFile) { throw new Exception("Must read from a file!"); } // Check for reading past end if ((index + length) > FileLength) { throw new Exception("Can't read beyond end of file! /n"); } // Load the cache of blocks for the file LoadBlocks(); // Write the bytes to the cache return(VirtualBlock.ReadBlockData(drive, blocks, index, length)); }
private void LoadBlocks() { if (blocks == null) { blocks = new List <VirtualBlock>(); // find data sectors int dataSectorAddr = sector.FirstDataAt; while (dataSectorAddr != 0) { DATA_SECTOR dataSector = DATA_SECTOR.CreateFromBytes(drive.Disk.ReadSector(dataSectorAddr)); VirtualBlock block = new VirtualBlock(drive, dataSectorAddr, dataSector); blocks.Add(block); // Go on to next data sector dataSectorAddr = dataSector.NextSectorAt; } } }
public static byte[] ReadBlockData(VirtualDrive drive, List <VirtualBlock> blocks, int startIndex, int length) { // Read data from list of blocks // Assumes block list contains all data // Assumes list of blcoks is long enough byte[] result = new byte[length]; int blockSize = drive.BytesPerDataSector; int startBlock = startIndex / blockSize; int endBlock = (startIndex + length) / blockSize; int toStart = 0; // Read data from first block VirtualBlock vb = blocks[startBlock]; byte[] blockData = vb.Data; // Copy data from here int fromStart = startIndex % blockSize; int copyCount = Math.Min(length, blockSize - fromStart); CopyBytes(copyCount, blockData, fromStart, result, toStart); toStart += copyCount; // read data from rest of blocks for (int i = startBlock + 1; i <= endBlock; i++) { vb = blocks[i]; blockData = vb.Data; // Overwrite result data with this block's data fromStart = 0; copyCount = Math.Min((length - toStart), blockSize); CopyBytes(copyCount, blockData, fromStart, result, toStart); toStart += copyCount; } return(result); }
public static void ExtendBlocks(VirtualDrive drive, List <VirtualBlock> blocks, int initialFileLength, int finalFileLength) { // If the file length has grown... if (finalFileLength > initialFileLength) { // ...and if we need ore blocks... int finalBlockCount = BlocksNeeded(drive, finalFileLength); if (finalBlockCount > blocks.Count) { // how many new blocks to do what we need to do? int neededNewBlocks = finalBlockCount - blocks.Count; // Get needed number of free sectors int[] freeSectors = drive.GetNextFreeSectors(neededNewBlocks); // Allocate and connect them up VirtualBlock previousBlock = blocks.Last(); for (int i = 0; i < neededNewBlocks; i++) { // write out the previousBlock to connect it to this new block previousBlock.sector.NextSectorAt = freeSectors[i]; previousBlock.dirty = true; // instantiate new DATA_SECTOR DATA_SECTOR newDataSector = new DATA_SECTOR(drive.Disk.BytesPerSector, 0, null); // instantiate new VirtualBlock VirtualBlock newBlock = new VirtualBlock(drive, freeSectors[i], newDataSector, true); // Add new VirtualBlocks to the list of blocks blocks.Add(newBlock); // Update prev block previousBlock = newBlock; } } } }
private void LoadBlocks() { // Read each block if not alread in cache if (blocks == null) { // The cache is currently empty, so create and fill it! blocks = new List <VirtualBlock>(); // Read the data sectors off the disk for this file and... int dataSectorAt = sector.FirstDataAt; while (dataSectorAt != 0) { // ...create VirtualBlocks for them and add to the cache DATA_SECTOR dataSector = DATA_SECTOR.CreateFromBytes(drive.Disk.ReadSector(dataSectorAt)); VirtualBlock vb = new VirtualBlock(drive, dataSectorAt, dataSector); blocks.Add(vb); // Go on to the next data sector dataSectorAt = dataSector.NextSectorAt; } } }