/************************************************************************************/ /************************ Memory management (system methods)***********************/ /************************************************************************************/ /// <summary> /// Allocate space (system method) /// </summary> /// <param name="size">Allocation size</param> /// <param name="pool">Allocation pool. 0 if base_address != 0</param> /// <param name="generateID">True id ID is required. false if base_address != 0</param> /// <param name="base_address"> 1st allocated address (extend)</param> /// <returns> /// 0 - address /// 1 - ID (or 0) /// </returns> internal VSAllocation AllocateSpaceSegment(long size, short pool, bool generateID = true, VSAllocation base_alloc = null) { #if (DEBUG) __TIMER.START("alloc:main"); #endif if ((base_alloc != null) & ((pool != 0) | (generateID == true))) { throw new VSException(DEFS.E0020_INVALID_EXTENSION_PARAMETERS_ERROR_CODE); } //VSFreeSpaceManager.FBQE f; long alloc_addr = 0; long length_desc = (base_alloc == null)? DEFS.BaseDescriptorLength: DEFS.ExpansionDescriptorLength; // Descriptor length // Calculate allocation size) long length = size / DEFS.MIN_SPACE_ALLOCATION_CHUNK; if (length == 0) { length++; } else if ((length * DEFS.MIN_SPACE_ALLOCATION_CHUNK) < size) { length++; } long length_use = (length * DEFS.MIN_SPACE_ALLOCATION_CHUNK); length = length_use + length_desc; // Acquire free space location alloc_addr = FreeSpaceMgr.AcquireSpace(length); while (alloc_addr == 0) { if (vm.Extend() != 0) { throw new VSException(DEFS.E0013_SPACE_NOT_AVAILABLE_CODE, "Requested size: " + length.ToString()); } else { this.VerifySpaceChanges(); //Process new if space is successfully extended } alloc_addr = FreeSpaceMgr.AcquireSpace(length); } short new_pool = pool; // If base_address != 0 - take pool# from the root descriptor if (base_alloc != null) { new_pool = base_alloc.Pool; } // Create allocated space descriptor VSAllocation new_obj = new VSAllocation(vm, alloc_addr, length, new_pool); long last_obj = GetLastAddress(new_pool); VSAllocation prev_obj; if (base_alloc == null) { // Initial allocation #if (DEBUG) __TIMER.START("alloc:new_alloc"); #endif #if (DEBUG) __TIMER.START("alloc:gen_id"); #endif if (generateID) { new_obj.Id = key_manager.Add(new_obj); // Generate ID if required } #if (DEBUG) __TIMER.END("alloc:gen_id"); #endif if (last_obj == 0) { // First allocation for pool SetFirstAddress(new_pool, alloc_addr); SetLastAddress(new_pool, alloc_addr); } else { prev_obj = GetAllocationByDescriptor(last_obj); prev_obj.NEXT = new_obj.DescriptorAddress; new_obj.PREV = prev_obj.DescriptorAddress; SetLastAddress(new_pool, new_obj.DescriptorAddress); // New Last } #if (DEBUG) __TIMER.END("alloc:new_alloc"); #endif } else { //Extend #if (DEBUG) __TIMER.START("alloc:extend_obj"); #endif prev_obj = base_alloc; if (base_alloc.Chunk == 0) { base_alloc.Chunk = 1; new_obj.Chunk = -2; } else { prev_obj = GetAllocationByDescriptor(base_alloc.LAST); short ch = (short)(prev_obj.Chunk * -1); if (ch == DEFS.MAX_SPACE_ALLOCATION_CHUNKS) { throw new VSException(DEFS.E0021_MAX_ALLOCATION_CHUNKS_REACHED_CODE, "- " + DEFS.MAX_SPACE_ALLOCATION_CHUNKS.ToString()); } prev_obj.Chunk = ch; new_obj.Chunk = (short)((ch + 1) * -1); } base_alloc.LAST = new_obj.DescriptorAddress; // New pointer to last if (prev_obj.NEXT == 0) { prev_obj.NEXT = new_obj.DescriptorAddress; new_obj.PREV = prev_obj.DescriptorAddress; SetLastAddress(new_pool, new_obj.DescriptorAddress); // New last } else { VSAllocation next_obj = GetAllocationByDescriptor(prev_obj.NEXT); prev_obj.NEXT = new_obj.DescriptorAddress; new_obj.NEXT = next_obj.DescriptorAddress; new_obj.PREV = prev_obj.DescriptorAddress; next_obj.PREV = new_obj.DescriptorAddress; } #if (DEBUG) __TIMER.END("alloc:extend_obj"); #endif } if (base_alloc == null) { new_obj.SetSize(length_use); } else { base_alloc.SetSize(base_alloc.Size + length_use); } #if (DEBUG) __TIMER.END("alloc:main"); #endif return(new_obj); }
/// <summary> /// Restore storage /// </summary> public void restore(VSIO IO, string name = "*") { byte[] buf; // Buffer // Check database state if (state != DEFS.STATE_DEFINED) { throw new VSException(DEFS.E0025_STORAGE_UNABLE_TO_COMPLETE_CODE, "- 'Restore' (storage is opened or undefined)"); } // Check if length not less than 16 if (IO.GetLength() < 32) { throw new VSException(DEFS.E0025_STORAGE_UNABLE_TO_COMPLETE_CODE, "Restore - invalid source stream (wrong source length)"); } // Check encryption IO.SetEncryption(false); uint encr = IO.ReadUInt(0); IO.SetEncryption(encr == DEFS.DATA_ENCRYPTED); // Check signature string sig = IO.ReadString(-1, DEFS.DUMP_SIGNATURE.Length); if (sig != DEFS.DUMP_SIGNATURE) { throw new VSException(DEFS.E0025_STORAGE_UNABLE_TO_COMPLETE_CODE, "Restore - invalid source stream (wrong signature)"); } // Check CRC uint old_crc = IO.ReadUInt(-1); uint new_crc = IO.GetCRC32(12, -1); // calculate CRC32 if (old_crc != new_crc) { throw new VSException(DEFS.E0025_STORAGE_UNABLE_TO_COMPLETE_CODE, "Restore - invalid source stream (wrong CRC)"); } // Check source length vs saved long slen = IO.ReadLong(-1); if (IO.GetLength() != slen) { throw new VSException(DEFS.E0025_STORAGE_UNABLE_TO_COMPLETE_CODE, "Restore - invalid source stream (wrong source length)"); } long save_pos = IO.GetPosition(); // +16 long cpos = save_pos; TRANSACTIONS_ON = false; Open(); TA.RollMode = true; long splen = IO.ReadLong(cpos); // Space length // Validate list of spaces while (splen > 0) { // Read space name length int n_len = IO.ReadShort(cpos + 8); // Read space name string sname = IO.ReadString(cpos + 10, n_len); VSpace sp = GetSpace(sname); if (sp == null) { this.Close(); this.Create(sname); this.Open(); } cpos += splen; splen = IO.ReadLong(cpos); } // Restore position IO.SetPosition(save_pos); // Proceed with restore splen = IO.ReadLong(-1); long spcnt = 8; while (splen != -1) { // Read space name length int n_len = IO.ReadShort(-1); // Read space name string sname = IO.ReadString(-1, n_len); spcnt += (n_len + 2); // Read owner length int o_len = IO.ReadShort(-1); // Read Owner string sowner = IO.ReadString(-1, o_len); spcnt += (o_len + 2); VSpace sp = GetSpace(sname); VSVirtualMemoryManager vm = GetVM(sname); sp.Owner = sowner; vm.Write(DEFS.SYSTEM_STATUS_ADDRESS, DateTime.Now.ToBinary()); // Write timestamp - restore started if (!IMO) { vm.flush(); } // Restore keys if (IO.GetPosition() < IO.GetLength()) { sig = IO.ReadString(-1, DEFS.DUMP_KEYS_SIGNATURE.Length); spcnt += DEFS.DUMP_KEYS_SIGNATURE.Length; if (sig != DEFS.DUMP_KEYS_SIGNATURE) { throw new VSException(DEFS.E0006_INVALID_SIGNATURE_CODE, "(Restore missing start key signature)"); } VSKeyManager kh = sp.KeyManager; if (!kh.IsEmpty) { throw new VSException(DEFS.E0025_STORAGE_UNABLE_TO_COMPLETE_CODE, "Space '" + sname + "' is not empty. Restore terminated."); } long id = IO.ReadLong(-1); spcnt += 8; while (id >= 0) { //VSDebug.StopPoint(id, 23884); //VSDebug.StopPoint(id, 24033); kh.Add(null, id); id = IO.ReadLong(-1); spcnt += 8; } } // Restore data pools long size = 0; int chunk_size = 0; ushort alloc = 0; ushort fix = 0; while (spcnt < splen) { VSAllocation new_a; //Read ADSC fields long oldid = IO.ReadLong(-1); short pool = IO.ReadShort(-1); spcnt += 10; size = IO.ReadLong(-1); // Total size spcnt += 8; chunk_size = IO.ReadInt(-1); // Chunk size spcnt += 4; alloc = IO.ReadUShort(-1); // Alloc spcnt += 2; fix = IO.ReadUShort(-1); // Fixed part length spcnt += 2; buf = IO.ReadBytes(-1, (int)size); spcnt += size; // Allocate space new_a = sp.ALLOCATE_SPACE(size, pool, false, (long)chunk_size, (short)fix); new_a.ALLOC = (ushort)((alloc == 0) ? 0 : 1); // Set allocation 0 - RAW; 1 - FIELD if (oldid > 0) { new_a.Id = oldid; sp.KeyManager.Update(oldid, new_a); } new_a.Write(0, buf, buf.Length); //Save data } vm.Write(DEFS.SYSTEM_STATUS_ADDRESS, (long)0); // Write 0 - restore ended for space splen = IO.ReadLong(-1); spcnt = 8; } if (!IMO) { Close(); } TRANSACTIONS_ON = true; }