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 void Format(DiskDriver disk) { // wipe all sectors of disk and create minimum required DRIVE_INFO, DIR_NODE and DATA_SECTOR //how many sectors int numSectors = disk.SectorCount; FREE_SECTOR freeSector = new FREE_SECTOR(disk.BytesPerSector); for (int lba = 0; lba < numSectors; lba++) { disk.WriteSector(lba, freeSector.RawBytes); } DRIVE_INFO diSector1 = new DRIVE_INFO(disk.BytesPerSector, ROOT_DIR_SECTOR); disk.WriteSector(0, diSector1.RawBytes); DIR_NODE rootDirSector = new DIR_NODE(disk.BytesPerSector, ROOT_DATA_SECTOR, FSConstants.ROOT_DIR_NAME, 0); disk.WriteSector(ROOT_DIR_SECTOR, rootDirSector.RawBytes); DATA_SECTOR rootDataSector = new DATA_SECTOR(disk.BytesPerSector, 0, new byte[DATA_SECTOR.MaxDataLength(disk.BytesPerSector)]); disk.WriteSector(ROOT_DATA_SECTOR, rootDataSector.RawBytes); }
public VirtualNode CreateFileNode(string name) { LoadChildren(); //insure child cached is full if (children.ContainsKey(name)) { throw new Exception("Another child with that name already exists"); } //where do we store new file? which sector? //find 2 free sectors int[] sectors = drive.GetNextFreeSectors(2); int newFileNodeSectorAt = sectors[0]; int newFileDataSectorAt = sectors[1]; //creat new on disk FILE_NODE newFileNodeSector = new FILE_NODE(drive.Disk.BytesPerSector, newFileDataSectorAt, name, 0); drive.Disk.WriteSector(newFileNodeSectorAt, newFileNodeSector.RawBytes); //creat a data sector for dir DATA_SECTOR newFileDataSector = new DATA_SECTOR(drive.Disk.BytesPerSector, 0, null); drive.Disk.WriteSector(newFileDataSectorAt, newFileDataSector.RawBytes); //creat virtual node VirtualNode newFile = new VirtualNode(drive, newFileNodeSectorAt, newFileNodeSector, this); //add dir to parent children.Add(name, newFile); CommitChildren(); return(newFile); }
private void CommitChildren() { //write list of this dir's children back to disk //check if cache has data if no data return if (children == null) { return; } //allocate list of children sector addresses byte[] childAddresses = GetChildAddresses(); //write the sector addesses list to directory's data sector DATA_SECTOR dataSector = DATA_SECTOR.CreateFromBytes(drive.Disk.ReadSector(DataSectorAt)); dataSector.DataBytes = childAddresses; drive.Disk.WriteSector(DataSectorAt, dataSector.RawBytes); byte[] dataBytes = new byte[dataSector.DataBytes.Length]; childAddresses.CopyTo(dataBytes, 0); dataSector.DataBytes = dataBytes; drive.Disk.WriteSector(DataSectorAt, dataSector.RawBytes); //update number of children entries for this dir (sector as DIR_NODE).EntryCount = ChildCount; drive.Disk.WriteSector(nodeSector, sector.RawBytes); }
public VirtualBlock(VirtualDrive drive, int sectorAddress, DATA_SECTOR sector, bool dirty = false) { this.drive = drive; this.sector = sector; this.sectorAddress = sectorAddress; this.dirty = dirty; }
public void Format(DiskDriver disk) { // wipe all sectors of disk and create minimum required DRIVE_INFO, DIR_NODE and DATA_SECTOR FREE_SECTOR free = new FREE_SECTOR(disk.BytesPerSector); for (int i = 0; i < disk.SectorCount; i++) { disk.WriteSector(i, free.RawBytes); } // DRIVE_INFO DRIVE_INFO drive = new DRIVE_INFO(disk.BytesPerSector, ROOT_DIR_SECTOR); disk.WriteSector(DRIVE_INFO_SECTOR, drive.RawBytes); // DIR_NODE for root node DIR_NODE rootDir = new DIR_NODE(disk.BytesPerSector, ROOT_DATA_SECTOR, FSConstants.PATH_SEPARATOR.ToString(), 0); disk.WriteSector(ROOT_DIR_SECTOR, rootDir.RawBytes); // DATA_SECTOR for root node DATA_SECTOR data = new DATA_SECTOR(disk.BytesPerSector, 0, new byte[] { 0 }); disk.WriteSector(ROOT_DATA_SECTOR, data.RawBytes); }
private void CommitChildren() { if (children != null) { // Write changes to the in-memory cache to disk // so that what is in the cache and on the disk is the same // Speciffically, write the list of children back to disk dor this directory // in the directory's data sector! // Create a list of children node sectors, in bytes byte[] rawList = new byte[drive.BytesPerDataSector]; int i = 0; foreach (VirtualNode child in children.Values) { int sectorAt = child.nodeSector; BitConverter.GetBytes(sectorAt).CopyTo(rawList, i); i += 4; // 4 byte integers are being copied to the array } // write the bytes to the directory's DATA_SECTOR // by replacing it's data bytes with the new list int dataSectorAt = sector.FirstDataAt; DATA_SECTOR dataSector = DATA_SECTOR.CreateFromBytes(drive.Disk.ReadSector(dataSectorAt)); dataSector.DataBytes = rawList; drive.Disk.WriteSector(dataSectorAt, dataSector.RawBytes); // Update the number of children in the dir's node on disk (sector as DIR_NODE).EntryCount = children.Count; drive.Disk.WriteSector(nodeSector, sector.RawBytes); } }
public void Format(DiskDriver disk) { // wipe all sectors of disk and create minimum required DRIVE_INFO, DIR_NODE and DATA_SECTOR // Wipe all sectors (replace with "zeroes" are FREE_SECTOR) int bps = disk.BytesPerSector; FREE_SECTOR free = new FREE_SECTOR(bps); for (int i = 0; i < disk.SectorCount; i++) { disk.WriteSector(i, free.RawBytes); } // Create DRIVE_INFO DRIVE_INFO di = new DRIVE_INFO(bps, ROOT_DIR_SECTOR); disk.WriteSector(DRIVE_INFO_SECTOR, di.RawBytes); // Create and write the DIR_NODE for the root node... DIR_NODE dn = new DIR_NODE(bps, ROOT_DATA_SECTOR, FSConstants.ROOT_DIR_NAME, 0); disk.WriteSector(ROOT_DIR_SECTOR, dn.RawBytes); // ... and an empty DATA_SECTOR DATA_SECTOR ds = new DATA_SECTOR(bps, 0, null); // 0 = no next data sector, nul = empty set disk.WriteSector(ROOT_DATA_SECTOR, ds.RawBytes); }
public void Delete() { if (IsDirectory) { //nuke children LoadChildren(); foreach (VirtualNode child in children.Values.ToArray()) { child.Delete(); } CommitChildren(); } // make sectors free! //overwirte node sector FREE_SECTOR freeSector = new FREE_SECTOR(drive.Disk.BytesPerSector); drive.Disk.WriteSector(nodeSector, freeSector.RawBytes); //overwrite data sectors int lba = DataSectorAt; while (lba != 0) { DATA_SECTOR dataSector = DATA_SECTOR.CreateFromBytes(drive.Disk.ReadSector(lba)); drive.Disk.WriteSector(lba, freeSector.RawBytes); lba = dataSector.NextSectorAt; } // remove this node from it's parent node parent.LoadChildren(); parent.children.Remove(Name); parent.CommitChildren(); }
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; } } }
private DRIVE_INFO sector; // caching entire sector for now public VirtualDrive(DiskDriver disk, int driveInfoSector, DRIVE_INFO sector) { this.disk = disk; this.driveInfoSector = driveInfoSector; this.bytesPerDataSector = DATA_SECTOR.MaxDataLength(disk.BytesPerSector); this.sector = sector; }
private void LoadChildren() { //test if we already have everything in cache? if (children != null) { return; } //create empty cache children = new Dictionary <string, VirtualNode>(); //read this dir's data sector DATA_SECTOR dataSector = DATA_SECTOR.CreateFromBytes(drive.Disk.ReadSector(DataSectorAt)); //create virtual nodes for each child and add to children dictionary byte[] data = dataSector.DataBytes; for (int i = 0; i < ChildCount; i++) { int childAt = BitConverter.ToInt32(data, i * 4); NODE childNodeSector = NODE.CreateFromBytes(drive.Disk.ReadSector(childAt)); VirtualNode childNode = new VirtualNode(drive, childAt, childNodeSector, this); children.Add(childNode.Name, childNode); } }
public VirtualNode CreateFileNode(string name) { if (!IsDirectory) { throw new Exception("Must be a directory to create children!"); } // read current list of children LoadChildren(); // Find the first two FREE_SECTORs on the disk int[] freeSectors = drive.GetNextFreeSectors(2); // allocate a new FILE_NODE and DATA_SECTOR on the disk //FILE_NODE FILE_NODE fileSector = new FILE_NODE(drive.Disk.BytesPerSector, freeSectors[1], name, 0); drive.Disk.WriteSector(freeSectors[0], fileSector.RawBytes); //DATA_SECTOR DATA_SECTOR dataSector = new DATA_SECTOR(drive.Disk.BytesPerSector, 0, new byte[] { 0 }); drive.Disk.WriteSector(freeSectors[1], dataSector.RawBytes); // Create a new virtual node VirtualNode newNode = new VirtualNode(drive, freeSectors[0], fileSector, this); // Add it to its parent children.Add(name, newNode); CommitChildren(); return(newNode); }
private void CommitChildren() { if (children != null) { // Create empty byte array byte[] childListBytes = new byte[DATA_SECTOR.MaxDataLength(drive.Disk.BytesPerSector)]; int i = 0; foreach (VirtualNode childNode in children.Values) { int childAddress = childNode.nodeSector; BitConverter.GetBytes(childAddress).CopyTo(childListBytes, i * 4); i++; } DATA_SECTOR data = new DATA_SECTOR(drive.Disk.BytesPerSector, 0, childListBytes); drive.Disk.WriteSector(sector.FirstDataAt, data.RawBytes); // Update entry count (sector as DIR_NODE).EntryCount = children.Count; // save the entry count drive.Disk.WriteSector(nodeSector, sector.RawBytes); } }
public void Delete() { /* make sectors free! * - wipe data for this node from the disk * - wipe this node from parent directory from the disk * - remove this node from it's parent node */ // Don't try to nuke the root! if (parent == null) { throw new Exception("Can't delete the root!"); } // Recurse into directory contents and delete children if (IsDirectory) { LoadChildren(); // Loop throught a copy of the children cahce and delete each foreach (VirtualNode child in children.Values.ToArray()) { child.Delete(); } // NOTE: do not need to call CommitChildren(); } // Replace data sector(s) with free sector(s) FREE_SECTOR free = new FREE_SECTOR(drive.Disk.BytesPerSector); int dataSectorAt = sector.FirstDataAt; while (dataSectorAt != 0) { // Read the data sector om and save nextSectorAt DATA_SECTOR dataSector = DATA_SECTOR.CreateFromBytes(drive.Disk.ReadSector(dataSectorAt)); int nextDataSectorAt = dataSector.NextSectorAt; // Replace it drive.Disk.WriteSector(dataSectorAt, free.RawBytes); // Next one dataSectorAt = nextDataSectorAt; } // Replace node sector with free sector drive.Disk.WriteSector(nodeSector, free.RawBytes); // Remove ourself from our parent and commit paren'ts list of children parent.LoadChildren(); parent.children.Remove(Name); parent.CommitChildren(); }
private void LoadChildren() { // Ensure that the children cache is correctly put in memory (i.e. reflects what's on the disk) // Assume if the cache exsists, it is correct at the moment // So, we need to call CommitChildren() if (children == null) { // Create the cache itself children = new Dictionary <string, VirtualNode>(); // Read the list of children for this directory from disk // Instantiate a VirtualNode for each [child?] and add them to the children cache. // Read the data sector for this directory DATA_SECTOR dataSector = DATA_SECTOR.CreateFromBytes(drive.Disk.ReadSector(sector.FirstDataAt)); // Extract the list of children from the sata sector byte[] rawList = dataSector.DataBytes; // Foreach child in the list... for (int i = 0; i < ChildCount; i++) { // Getthe child's sector address int childSectorAt = BitConverter.ToInt32(rawList, i * 4); // Read its sector from disk // Check if it's a file or directory byte[] childNodeBytes = drive.Disk.ReadSector(childSectorAt); NODE childSector; if (SECTOR.GetTypeFromBytes(childNodeBytes) == SECTOR.SectorType.DIR_NODE) { childSector = DIR_NODE.CreateFromBytes(drive.Disk.ReadSector(childSectorAt)); } else if (SECTOR.GetTypeFromBytes(childNodeBytes) == SECTOR.SectorType.FILE_NODE) { childSector = FILE_NODE.CreateFromBytes(drive.Disk.ReadSector(childSectorAt)); } else { throw new Exception("Unexpected sector type whe reading directory's children!"); } // Construct a VirtualNode VirtualNode childNode = new VirtualNode(drive, childSectorAt, childSector, this); // Add the VirtualNode to the children cache children.Add(childNode.Name, childNode); } } }
private VirtualNode CreateNode(string name, SECTOR.SectorType type) { // Create a new file, both on disk and in memory // type may be DIR_NODE or FILE_NODE if (type != SECTOR.SectorType.DIR_NODE && type != SECTOR.SectorType.FILE_NODE) { throw new Exception("Illegal type, CreateNode only take DIR_NODE and FILE_NODE types!"); } // Get 2 free sectors // First Sector: NODE, containing metadata // Second Sector: DATA_SECTOR, containing the new node's data int[] freeSectors = drive.GetNextFreeSectors(2); if (freeSectors == null || freeSectors.Length != 2) { throw new Exception("Can't find 2 free sectors for a new " + (type == SECTOR.SectorType.DIR_NODE ? "directory" : "file") + "!"); } int newNodeAt = freeSectors[0]; int newDataSectorAt = freeSectors[1]; // Create the node sector on disk, initially empty int bps = drive.Disk.BytesPerSector; NODE newNode = (type == SECTOR.SectorType.DIR_NODE ? new DIR_NODE(bps, newDataSectorAt, name, 0) as NODE : new FILE_NODE(bps, newDataSectorAt, name, 0) as NODE); //Create the DATA_SECTOR sector on disk for the new directory // initially empty data sector for this new directory DATA_SECTOR dataSector = new DATA_SECTOR(bps, 0, null); // Write sectors to disk drive.Disk.WriteSector(newNodeAt, newNode.RawBytes); drive.Disk.WriteSector(newDataSectorAt, dataSector.RawBytes); // Create a new VirtualNode instance VirtualNode newVirtualNode = new VirtualNode(drive, newNodeAt, newNode, this); // Add this to the in-memory cache of this directory's children LoadChildren(); children.Add(name, newVirtualNode); CommitChildren(); // Return the new VirtualNode instace return(newVirtualNode); }
private void LoadChildren() { if (children == null) { children = new Dictionary <string, VirtualNode>(); DATA_SECTOR data = DATA_SECTOR.CreateFromBytes(drive.Disk.ReadSector(sector.FirstDataAt)); for (int i = 0; i < ChildCount; i++) { int childAddress = BitConverter.ToInt32(data.DataBytes, i * 4); NODE childSector = NODE.CreateFromBytes(drive.Disk.ReadSector(childAddress)); VirtualNode vn = new VirtualNode(drive, childAddress, childSector, this); children.Add(childSector.Name, vn); } } }
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 void Mount(DiskDriver disk, string mountPoint) { // read drive info from disk, load root node and connect to mountPoint // for the first mounted drive, expect mountPoint to be named "/", FSConstants.ROOT_DIR_NAME, as the root try { // Step 1: Read infor from the disk to understand it's directory structure // Read DRIVE_INFO from FRIVE_INFO_SECTOR DRIVE_INFO di = DRIVE_INFO.CreateFromBytes(disk.ReadSector(DRIVE_INFO_SECTOR)); DIR_NODE dn = DIR_NODE.CreateFromBytes(disk.ReadSector(di.RootNodeAt)); DATA_SECTOR ds = DATA_SECTOR.CreateFromBytes(disk.ReadSector(dn.FirstDataAt)); // Step 2: Join th new disk into the virtual file system structure, at the mount point. // Create a VistualDrive for the disk VirtualDrive vd = new VirtualDrive(disk, DRIVE_INFO_SECTOR, di); if (rootNode == null) { // Create a VirtualNode to represent the root dictionaru, at the mount point. // Set the VFS's root node, if this is the first disk to be mounted. rootNode = new VirtualNode(vd, di.RootNodeAt, dn, null); } else { // TODO: Extra Credit: Handle 2nd dick mounted to exsisting VFS // Create a virtual node for this new disk's root // "join" the new node to the exsisting node structure at the mount point } // Add a new VirtualDrive to drives dictionary, using te mountPoint as the key drives.Add(mountPoint, vd); } catch (Exception ex) { throw new Exception("Failed to mount disk"); } }
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; } } }
public static void ExtendBlocks(VirtualDrive drive, List <VirtualBlock> blocks, int initialFileLength, int finalFileLength) { //given initial list of blocks in memory add more block if necessary to grow file from initial to final length //determine # of blocks eeded for the file int currentBlockCount = blocks.Count; int finalBlockCount = BlocksNeeded(drive, finalFileLength); if (finalBlockCount <= currentBlockCount) { return; } //get sector addresses for new blocks int additionalBlocks = finalBlockCount - currentBlockCount; int[] additionalBlockAddresses = drive.GetNextFreeSectors(additionalBlocks); //update the last current block to point to the first new block blocks[currentBlockCount - 1].sector.NextSectorAt = additionalBlockAddresses[0]; blocks[currentBlockCount - 1].dirty = true; //Allocate each block as a sector for (int i = 0; i < additionalBlocks; i++) { //wcreate new data sectorin memory DATA_SECTOR dataSector = new DATA_SECTOR(drive.Disk.BytesPerSector, 0, null); //set this sector's link to the data sector, if there is a next sector if (i < additionalBlocks - 1) { dataSector.NextSectorAt = additionalBlockAddresses[i + 1]; } //add new virtualblock to list which is drity so it will be writen to disk when commited blocks.Add(new VirtualBlock(drive, additionalBlockAddresses[i], dataSector, true)); } }