/// <summary> /// Save storage to file /// </summary> /// <param name="name"></param> /// <returns></returns> public void Dump(string path, string name, bool encrypt = false) { string d_path = path; if (d_path != "") { if (!System.IO.Directory.Exists(d_path)) { throw new VSException(DEFS.E0025_STORAGE_UNABLE_TO_COMPLETE_CODE, "Dump, path is not found: '" + d_path + "'"); } } else { d_path = System.IO.Directory.GetCurrentDirectory(); } string fname = GenerateDumpFileName(d_path); if (File.Exists(fname)) { File.Delete(fname); } VSIO IO = new VSIO(fname, VSIO.FILE_MODE_CREATE, DEFS.ENCRYPT_DUMP); IO.SetEncryption(encrypt); dump(IO, name); IO.Close(); }
/// <summary> /// Close file and set to null (private) /// </summary> private void CloseTAFile() { if (IO != null) { IO.Close(); IO = null; } }
/// <summary> /// Add partition to space: name - space name; size - size(Mb) /// </summary> /// <param name="name"></param> /// <param name="size">Mb</param> /// <returns></returns> public void AddPartition(string name, int size) { if (state != DEFS.STATE_DEFINED) { throw new VSException(DEFS.E0025_STORAGE_UNABLE_TO_COMPLETE_CODE, "- 'AddPartition' (storage is opened or undefined)"); } VSCatalogDescriptor desc = CATALOG.Get(name); if (desc == null) { throw new VSException(DEFS.E0002_SPACE_NOT_FOUND_CODE, "(" + name + ")"); } if (!this.Lock()) { throw new VSException(DEFS.E0001_UNABLE_TO_LOCK_CODE, "(Add partition)"); } long old_size = desc.SpaceSize; //Calculate space size (in pages) long add_pages = (long)(((size < 1) ? 1 : size) * 1048576) / desc.PageSize; desc.space_size_pg += add_pages; if (!IMO) { // Append pages byte[] dataArray = new byte[desc.PageSize]; VSIO IO = new VSIO(GetSpaceFileName(name, desc.Path, (int)desc.Partitions), VSIO.FILE_MODE_CREATE, ""); byte[] resv = new byte[8]; for (long i = 0; i < add_pages; i++) { IO.Write(-1, DEFS.DATA_NOT_ENCRYPTED); // + 0 (4) Encryption indicator IO.Write(-1, (uint)0); // + 4 (4) CRC32 placeholder IO.Write(-1, ref resv); // +8 (8) reserve IO.Write(-1, ref dataArray); } IO.Close(); desc.partitions++; AddNewAllocation(desc.Path, name, old_size, add_pages * desc.PageSize); CATALOG.Save(); } Release(); }
/// <summary> /// Restore storage from byte array /// </summary> public void RestoreFromArray(byte[] array, string name = "*") { if (state != DEFS.STATE_DEFINED) { throw new VSException(DEFS.E0025_STORAGE_UNABLE_TO_COMPLETE_CODE, "- 'Restore' - storage is opened or undefined"); } VSIO IO = new VSIO(array, DEFS.ENCRYPT_DUMP); this.restore(IO, name); IO.Close(); }
/// <summary> /// Restore storage from file /// </summary> public void Restore(string filename = "", string name = "*") { if (state != DEFS.STATE_DEFINED) { throw new VSException(DEFS.E0025_STORAGE_UNABLE_TO_COMPLETE_CODE, "- 'Restore' - storage is opened or undefined"); } if (!System.IO.File.Exists(filename)) { throw new VSException(DEFS.E0025_STORAGE_UNABLE_TO_COMPLETE_CODE, "- 'Restore' - file is not found: '" + filename + "'"); } VSIO IO = new VSIO(filename, VSIO.FILE_MODE_OPEN, DEFS.ENCRYPT_DUMP); this.restore(IO, name); IO.Close(); }
/*************************************************************************************/ /************************* PRIVATE METHODS ******************************************/ /*************************************************************************************/ /// <summary> /// Update FSAT by adding new element (Extend, AddPartition) or in Create /// </summary> /// <param name="name"></param> /// <param name="address"></param> /// <param name="length"></param> /// <returns></returns> private void AddNewAllocation(string space_path, string name, long address, long length) { VSIO IO = new VSIO(GetSpaceFileName(name, space_path), VSIO.FILE_MODE_OPEN, ""); long h_addr = DEFS.SYSTEM_ALLOCATION_ADDRESS; short n = IO.ReadShort(h_addr); //The number of pending updates long e_addr = h_addr + 2 + (n * 16); IO.Write(e_addr, address); IO.Write(e_addr + 8, address + length); n++; IO.Write(h_addr, n); IO.Close(); }
/// <summary> /// Extend space size: name - space name; size - extension(Mb) /// </summary> /// <param name="name"></param> /// <param name="size (Mb)"></param> /// <returns></returns> public void Extend(string name, int size) { if (state != DEFS.STATE_DEFINED) { throw new VSException(DEFS.E0025_STORAGE_UNABLE_TO_COMPLETE_CODE, "- 'Extend' (storage is opened or undefined)"); } VSCatalogDescriptor desc = CATALOG.Get(name); if (desc == null) { throw new VSException(DEFS.E0002_SPACE_NOT_FOUND_CODE, "(" + name + ")"); } if (!IMO) { if (desc.Partitions > 1) // Check if more than 1 partition exists. If so - add partition instead of extending { this.AddPartition(name, size); return; } } if (!this.Lock()) { throw new VSException(DEFS.E0001_UNABLE_TO_LOCK_CODE, "(Extend space)"); } long start_pos = desc.SpaceSize; //Address of the 1st byte out of space //Calculate new allocation size in pages long add_pages = (long)(((size < 1) ? 1 : size) * 1048576) / (long)(desc.PageSize); // Increase space size in descriptor desc.space_size_pg += add_pages; if (!IMO) { //Initialize page buffer byte[] dataArray = new byte[desc.PageSize]; //Append pages VSIO IO = new VSIO(GetSpaceFileName(name, desc.Path), VSIO.FILE_MODE_APPEND, ""); byte[] resv = new byte[8]; for (long i = 0; i < add_pages; i++) { IO.Write(-1, DEFS.DATA_NOT_ENCRYPTED); // + 0 (4) Encryption indicator IO.Write(-1, (uint)0); // + 4 (4) CRC32 placeholder IO.Write(-1, ref resv); // +8 (8) reserve IO.Write(-1, ref dataArray); } IO.Close(); AddNewAllocation(desc.Path, name, start_pos, add_pages * desc.PageSize); CATALOG.Save(); } Release(); }
//==========================================================================================================// //=========================================== Manager ======================================================// //==========================================================================================================// /// <summary> /// Create new address space. Return 0 - successful; -1 - error /// dir - directory /// name - space name /// page size - in Kb /// size - size of the space in Mb. Default - 5 /// extension - size for dynamic extension in MB. Default - 5 /// </summary> /// <param name="name"></param> /// <param name="pagesize"></param> /// <param name="size"></param> /// <returns></returns> public void Create(string name, int pagesize = DEFS.DEFAULT_PAGE_SIZE, int size = DEFS.DEFAULT_SPACE_SIZE, int extension = DEFS.DEFAULT_EXT_SIZE, string path = "") { if (state != DEFS.STATE_DEFINED) { throw new VSException(DEFS.E0025_STORAGE_UNABLE_TO_COMPLETE_CODE, "- 'Create' (storage is opened or undefined)"); } VSCatalogDescriptor desc = CATALOG.Get(name); if (desc != null) { throw new VSException(DEFS.E0024_CREATE_SPACE_ERROR_CODE, "- space already exists(" + name + ")"); } string space_path = path.Trim(); string sname = ""; if (IMO) { space_path = ""; } else { if (space_path == "") { space_path = root_path; } if (!System.IO.Directory.Exists(space_path)) { throw new VSException(DEFS.E0004_STORAGE_NOT_FOUND_CODE, "(" + space_path + ")"); } // Check if directory exists if (!System.IO.Directory.Exists(root_path)) { throw new VSException(DEFS.E0004_STORAGE_NOT_FOUND_CODE, "(" + root_path + ")"); } if (!this.Lock()) { throw new VSException(DEFS.E0001_UNABLE_TO_LOCK_CODE, "(Create space)"); } // Check if file exists, if no - create new space. sname = GetSpaceFileName(name, space_path); if (System.IO.File.Exists(sname)) { throw new VSException(DEFS.E0005_FILE_ALREADY_EXISTS_CODE, "(" + sname + ")"); } } // Add descriptor desc = CATALOG.Create(name, (long)size, (long)extension, (long)pagesize, space_path); desc.IMO = IMO; if (!desc.IMO) { //Create file byte[] dataArray = new byte[desc.PageSize]; VSIO IO = new VSIO(sname, VSIO.FILE_MODE_CREATE, ""); byte[] resv = new byte[8]; for (long i = 0; i < desc.space_size_pg; i++) { IO.Write(-1, DEFS.DATA_NOT_ENCRYPTED); // + 0 (4) Encryption indicator IO.Write(-1, (uint)0); // + 4 (4) CRC32 placeholder IO.Write(-1, ref resv); // +8 (8) reserve IO.Write(-1, ref dataArray); } IO.Write(DEFS.SYSTEM_OWNER_ADDRESS + 16, DEFS.SYSTEM_OWNER_UNDEFINED.PadRight((int)DEFS.SYSTEM_OWNER_LENGTH)); IO.Close(); CATALOG.Save(); } Release(); }