/// <summary> /// Set use dedicated space {index_space_name} for indexes of the {space_name} objects /// Empty 'index_space_name' means stop using index space. Indexes will not be removed automatically. /// /// </summary> /// <param name="space_name"></param> /// <param name="index_space_name"></param> /// <returns></returns> public string UseIndexSpace(string space_name, string index_space_name) { string s = ""; VSCatalogDescriptor d_desc = this.CATALOG.Get(space_name); VSCatalogDescriptor x_desc = null; if (d_desc == null) { s = "Space '" + space_name + "' is not found"; } else { if (index_space_name.Trim() != "") { x_desc = this.CATALOG.Get(index_space_name); if (x_desc == null) { s = "Space '" + index_space_name + "' is not found"; } else if (x_desc.IndexSpace != "") { s = "The specified index space cannot refer to anothe index space ('" + index_space_name + "' refers to '" + x_desc.IndexSpace + "'"; } } } if (s == "") { if (x_desc == null) { if (d_desc.indexspace == "") { return(""); } else { d_desc.indexspace = ""; } } else { if (d_desc.indexspace == index_space_name.Trim().ToLower()) { return(""); } else { d_desc.indexspace = index_space_name; } } if (!IMO) { this.CATALOG.Save(); } } return(s); }
/// <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(); }
//////////////////////////////////////////////////////////////////////////// ////////////////////// COMMON METHODS /////////////////////////////////// //////////////////////////////////////////////////////////////////////////// /// <summary> /// Attach new address space. Return 0 - successful; -1 - error /// </summary> /// <param name="_path"></param> /// <param name="_cat_file"></param> /// <param name="idx"></param> /// <returns></returns> internal string Attach(VSCatalogDescriptor desc, VSVirtualMemoryManager vmm, VSTransaction ta, bool imo) { DESCRIPTOR = desc; vm = vmm; vs_imo = imo; // Check if restore is not completed long l = vm.ReadLong(DEFS.SYSTEM_STATUS_ADDRESS); if (l != 0) { return(VSException.GetMessage(DEFS.E0009_RESTORE_NOT_COMPLETED_CODE) + " Space: " + Name); } // Build index list index_list = new List <VSIndex>(); index_list_full = new List <VSIndex>(); long addr = GetRootAddress(DEFS.POOL_INDEX); // Get 1st ADSC addredd while (addr > 0) { VSIndex xd = new VSIndex(this, addr); index_list_full.Add(xd); if (xd.Name.IndexOf(DEFS.INDEX_CROSS_REFERENCES) < 0) { index_list.Add(xd); } addr = xd.NEXT; } // Set ref indexes for (int i = 0; i < index_list.Count; i++) { set_ref_index(index_list[i]); } return(""); }
/// <summary> /// Get information about space /// </summary> /// <param name="name"></param> private string[] GetSpaceHeaderInfo(string name) { string[] hdr = new string[8]; for (int i = 0; i < hdr.Length; i++) { hdr[i] = ""; } VSCatalogDescriptor desc = CATALOG.Get(name); if (desc != null) { hdr[0] = "Id: " + desc.Id.ToString(); hdr[1] = "Name: " + desc.Name; hdr[2] = "Path: " + desc.Path; hdr[3] = "Page size: " + desc.PageSize.ToString("#,#;(#,#)") + " bytes"; hdr[4] = "Partitions: " + desc.Partitions.ToString(); hdr[5] = "Size: " + desc.SpaceSize.ToString("#,#;(#,#)") + " bytes (" + desc.SpaceSizeMb.ToString("#,#;(#,#)") + " Mb)"; hdr[6] = "Pages: " + desc.space_size_pg.ToString(); hdr[7] = "Auto extension: " + ((desc.Extension == 0) ? "No" : (desc.extension_pg.ToString("#,0;(#,0)") + " pages (" + desc.ExtensionMb.ToString("#,0;(#,0)") + " Mb)")); } return(hdr); }
/// <summary> /// Open new address space: _path - root folder path; _cat_file - catalog file name; idx - index in the catalog. Return: space id or -1(if error) /// </summary> /// <param name="_path"></param> /// <param name="_cat_file"></param> /// <param name="idx"></param> /// <returns></returns> public string Open(VSCatalogDescriptor desc, VSTransaction ta) { this.DESCRIPTOR = desc; this.page_size = DESCRIPTOR.PageSize; this.imo = DESCRIPTOR.IMO; e_key = VSLib.ConvertStringToByte(DEFS.ENCRYPT_SPACE); e_buf = new byte[page_size]; _ta = ta; ////////////////////////////////////////////// ///////////// Initiate partitions //////////// ////////////////////////////////////////////// this.pd = new partition_descriptor[DESCRIPTOR.Partitions]; //Check if all partitions exists if (imo) { pd[0].start_page = 0; //Start Page pd[0].end_page = DESCRIPTOR.space_size_pg - 1; //End Page } else { for (int i = 0; i < DESCRIPTOR.Partitions; i++) { short j = (short)(i + 1); pd[i].file_name = DESCRIPTOR.Path + "\\" + DEFS.SPACE_FILE_NAME(DESCRIPTOR.Name, i); if (!System.IO.File.Exists(pd[i].file_name)) { return("Error: space file is not found - " + pd[i].file_name); } //FileStream f = null; //f = File.Open(pd[i].file_name, FileMode.Open, FileAccess.ReadWrite, FileShare.None); pd[i].fs = new VSIO(pd[i].file_name, VSIO.FILE_MODE_OPEN, DEFS.ENCRYPT_SPACE); pd[i].fs.SetEncryption(false); pd[i].start_page = (i == 0) ? 0 : pd[i - 1].end_page + 1; //Start Page pd[i].end_page = pd[i].start_page + ((pd[i].fs.GetLength()) / page_size) - 1; //End Page } } ////////////////////////////////////////////// ///////////// Initiate cache ///////////////// ////////////////////////////////////////////// // Create segment table segment_table = new page_segment_descriptor[DEFS.PAGE_SEGMENTS_NUMBER]; // Create page table for 1st segment segment_table[0] = new page_segment_descriptor(); segment_table[0].start_page = 0; segment_table[0].end_page = DESCRIPTOR.space_size_pg - 1; // Set initial number of segments used segments_used = 1; // Calculate cache size in pages if (imo) { cache_size_pages = DESCRIPTOR.space_size_pg; cache_size_bytes = DESCRIPTOR.SpaceSize; } else { string confs = VSLib.VSGetKey(DEFS.VM_CACHE_SIZE_KEY); if (confs == "") { confs = DEFS.VM_CACHE_SIZE_DEFAULT; VSLib.VSSetKey(DEFS.VM_CACHE_SIZE_KEY, confs); } int csize = VSLib.ConvertStringToInt(confs); cache_size_bytes = ((csize < 2) ? 2 : csize) * 1048576; if (cache_size_bytes < (page_size * 10)) { cache_size_bytes = page_size * 10; } cache_size_pages = (cache_size_bytes / page_size) + 1; } // Initialize cache segment_table[0].cache = new page_buffer[cache_size_pages]; for (int i = 0; i < cache_size_pages; i++) { segment_table[0].cache[i].buf = new byte[page_size]; segment_table[0].cache[i].tbuf = null; segment_table[0].cache[i].last_access = 0; segment_table[0].cache[i].access_count = 0; if (imo) { segment_table[0].cache[i].page_no = i; // Page no = Buf no segment_table[0].cache[i].prev = -1; segment_table[0].cache[i].next = -1; } else { segment_table[0].cache[i].page_no = -1; segment_table[0].cache[i].prev = i - 1; segment_table[0].cache[i].next = ((i + 1) == cache_size_pages) ? -1 : i + 1; } } // Initialize queues (not IMO) if (!imo) { q_read = new int[3]; q_read[number] = 0; q_read[first] = -1; q_read[last] = -1; q_write = new int[3]; q_write[number] = 0; q_write[first] = -1; q_write[last] = -1; q_free = new int[3]; q_free[number] = (int)cache_size_pages; q_free[first] = 0; q_free[last] = (int)cache_size_pages - 1; } ////////////////////////////////////////////// ///////////// Initiate page table //////////// ////////////////////////////////////////////// segment_table[0].page_table = new page_descriptor[DESCRIPTOR.space_size_pg]; for (int i = 0; i < segment_table[0].page_table.Length; i++) { if (imo) { segment_table[0].page_table[i].page_state = DEFS.PAGE_READ; segment_table[0].page_table[i].page_lock = DEFS.PAGE_LOCKED; segment_table[0].page_table[i].bufno = i; // For IMO bufno = page table element } else { segment_table[0].page_table[i].page_state = DEFS.PAGE_FREE; segment_table[0].page_table[i].page_lock = DEFS.PAGE_UNLOCKED; segment_table[0].page_table[i].bufno = -1; } } // Set state 'Opened' this.state = DEFS.SPACE_OPENED; // For IMO: write owner 'undefined'; otherwise: load and lock page 0. if (imo) { this.Write(DEFS.SYSTEM_OWNER_ADDRESS, DEFS.SYSTEM_OWNER_UNDEFINED.PadRight((int)DEFS.SYSTEM_OWNER_LENGTH)); } else { fetch(0, 0, 0, DEFS.PAGE_READ); this.lock_page(0); // lock 1st page } return(""); }
/// <summary> /// Load catalog content /// </summary> public void Load() { int pos = 0; string s = ""; err_line = -1; if (!File.Exists(catalog_file_name)) { File.WriteAllBytes(catalog_file_name, VSLib.ConvertStringToByte(sg_ok + DEFS.VSTORAGE_VERSION + "$" + "U" + "$" + DEFS.DELIM_NEWLINE)); // 'U' dont encrypt (+19) } s = VSLib.ConvertByteToString(File.ReadAllBytes(catalog_file_name)); // Parse file pos = s.IndexOf(DEFS.DELIM_NEWLINE); if (pos < 0) { return; } // Get encryption status string sth = s.Substring(0, pos); if (sth.Length < 21) { err_line = 1; } else { // Encryption ste = sth.Substring(19, 1).ToUpper(); ENCRYPT = (sth.Substring(19, 1) == "E"); pos += DEFS.DELIM_NEWLINE.Length; line = 1; VSCatalogDescriptor desc = null; while ((pos < s.Length) & (err_line < 0)) { string par = ""; int ln = 0; int new_pos = s.IndexOf(DEFS.DELIM_NEWLINE, pos); if (new_pos < 0) { ln = s.Length - pos; } else { ln = new_pos - pos; } if (ln > 0) { par = s.Substring(pos, ln).Trim(); } line++; pos += (ln + DEFS.DELIM_NEWLINE.Length); if (par != "") { if (par.Substring(0, 1) == "[") { // Parse new descriptor desc = null; string sname = ""; int eb = par.IndexOf("]", 1); if (eb < 0) { err_line = line; } else { if (eb > 1) { sname = par.Substring(1, eb - 1); } if (sname != "") { sname = sname.Trim().ToLower(); for (int i = 0; i < dl.Count; i++) { if (dl[i].Name == sname) { desc = dl[i]; break; } } if (desc == null) { desc = new VSCatalogDescriptor(this); desc.name = sname; dl.Add(desc); } } else { err_line = line; } } } else { // Parse parameters string s_val = ""; long n_val = 0; if (desc == null) { err_line = line; } else { par += " "; if (parse_long(ref par, DEF_ID, out n_val)) { if (n_val >= 0) { desc.id = (short)n_val; } } else if (parse_long(ref par, DEF_SIZE, out n_val)) { if (n_val >= 0) { desc.space_size_pg = n_val; } } else if (parse_long(ref par, DEF_EXTENSION, out n_val)) { if (n_val >= 0) { desc.extension_pg = n_val; } } else if (parse_long(ref par, DEF_PAGESIZE, out n_val)) { if (n_val >= 0) { desc.page_size_kb = n_val; } } else if (parse_long(ref par, DEF_PARTITIONS, out n_val)) { if (n_val >= 0) { desc.partitions = n_val; } } else if (parse_string(ref par, DEF_PATH, out s_val)) { if (s_val != DEF_ERROR) { desc.path = s_val; } } else if (parse_string(ref par, DEF_INDEXSPACE, out s_val)) { if (s_val != DEF_ERROR) { desc.indexspace = s_val; } } else if (parse_string(ref par, DEF_TIMESTAMP, out s_val)) { if (s_val != DEF_ERROR) { desc.creation_timestamp = s_val; } } else if (parse_string(ref par, DEF_SIGNATURE, out s_val)) { if (s_val != DEF_ERROR) { desc.signature = s_val; } } else { err_line = line; } } } } } } if (err_line >= 0) { throw new VSException(DEFS.E0016_OPEN_STORAGE_ERROR_CODE, "- invalid catalog entry at line " + err_line.ToString()); } for (int i = 0; i < dl.Count; i++) { string sg = dl[i].Signature; dl[i].CalculateSignature(); if (dl[i].Signature != sg) { throw new VSException(DEFS.E0016_OPEN_STORAGE_ERROR_CODE, "- missing or invalid space signature for '" + dl[i].Name); } } }
/// <summary> /// Update or create catalog descriptor /// Size - Mb /// Extension - Mb /// pagesize - Kb /// </summary> /// <param name="desc"></param> public VSCatalogDescriptor Create(string name, long size, long extension = 0, long pagesize = 0, string path = "") { for (int i = 0; i < dl.Count; i++) { if (dl[i].Name == name.Trim().ToLower()) { return(null); } } VSCatalogDescriptor d = new VSCatalogDescriptor(this); // Name d.name = name.Trim().ToLower(); // Page size (Kb) long p = pagesize; if (p <= 0) { p = 16; } else if (p < 4) { p = 4; } else if (p > 64) { p = 64; } d.page_size_kb = p; // Space size (pages) p = size; if (p <= 0) { p = 5; } d.space_size_pg = (p * 1048576) / d.PageSize; // Extension (pages) p = extension; if (p <= 0) { p = 0; } d.extension_pg = (p * 1048576) / d.PageSize; // Path d.path = path.Trim(); // Timestamp d.creation_timestamp = DateTime.Now.ToString("u"); // Calculate new id short new_id = 1; bool ready = false; while (!ready) { ready = true; for (int i = 0; i < dl.Count; i++) { if (new_id == dl[i].Id) { ready = false; new_id++; break; } } } d.id = new_id; dl.Add(d); return(d); }
/// <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(); }