/// <summary> /// Update refrence by Key /// </summary> /// <param name="key"></param> /// <returns></returns> public void Update(long key, VSAllocation a) { long[] ret = this.SearchKey(key); if (ret[2] >= 0) { KeyBlockAllocWrite.Write((ret[2] * KeyBlockDef.BLOCK_ITEM_LENGTH) + KeyBlockDef.A_Address, a.DescriptorAddress); } }
/// <summary> /// Write FBQE /// </summary> /// <param name="f"></param> private void SerializeFBQE(FBQE f) { VSLib.CopyBytes(buffer, VSLib.ConvertStringToByte(DEFS.FBQE_SIGNATURE), f.address + SG_POS, SG_LEN); VSLib.CopyBytes(buffer, VSLib.ConvertLongToByte(f.ADDRESS_START), f.address + ADDRESS_START_POS, ADDRESS_START_LEN); VSLib.CopyBytes(buffer, VSLib.ConvertLongToByte(f.ADDRESS_END), f.address + ADDRESS_END_POS, ADDRESS_END_LEN); VSLib.CopyBytes(buffer, VSLib.ConvertLongToByte(f.LENGTH), f.address + LENGTH_POS, LENGTH_LEN); VSLib.CopyBytes(buffer, VSLib.ConvertIntToByte(f.PREV), f.address + PREV_POS, PREV_LEN); VSLib.CopyBytes(buffer, VSLib.ConvertIntToByte(f.NEXT), f.address + NEXT_POS, NEXT_LEN); F_Object.Write(f.address, VSLib.GetByteArray(buffer, f.address, FBQE_LENGTH), FBQE_LENGTH); }
/// <summary> /// Add reference /// </summary> /// <param name="rf"></param> /// <returns></returns> internal bool add_ref(long rf) { long[] refs = REFS; for (int i = 0; i < refs.Length; i++) { if (refs[i] == rf) { return(true); } } if ((ALLOCATION.Size - AVLNODE_SIZE) < 8) { long ext_size = this.UNIQUE ? DEFS.MIN_SPACE_ALLOCATION_CHUNK : (DEFS.MIN_SPACE_ALLOCATION_CHUNK * 3); sp.ExtendSpace(ALLOCATION, ext_size); } ALLOCATION.Write(REF_POS + (REF_COUNT * 8), rf); REF_COUNT++; return(true); }
/// <summary> /// Initialize data structures /// </summary> private void Initialize() { KeyHeader = new KeyHeaderDef(); // Get root allocation KeyHeaderAlloc = sp.GetRootAllocation(DEFS.POOL_KEY); // If ROOT doesn't exist yet - initial allocation if (KeyHeaderAlloc == null) { // Allocate header space KeyHeaderAlloc = sp.AllocateSpace(KeyHeaderDef.KEYROOT_SIZE, DEFS.POOL_KEY, generateID: false); KeyHeaderAlloc.Write(KeyHeaderDef.A_DescriptorLast, -1); // Allocate descriptor space KeyDescriptorAlloc = sp.AllocateSpace(KeyDescriptorDef.DESCRIPTOR_CHUNK_SIZE, DEFS.POOL_KEY, generateID: false); //Set initial values to memory object KeyHeader.DescriptorAddress = KeyDescriptorAlloc.DescriptorAddress; KeyHeader.DescriptorLength = KeyDescriptorDef.DESCRIPTOR_CHUNK_LENGTH; KeyHeader.DescriptorLast = -1; KeyHeader.DescriptorUsed = 0; KeyHeader.LastKey = 0; // Save initial values KeyHeaderAlloc.Write(KeyHeaderDef.A_DescriptorAddress, KeyHeader.DescriptorAddress); KeyHeaderAlloc.Write(KeyHeaderDef.A_DescriptorLength, KeyHeader.DescriptorLength); KeyHeaderAlloc.Write(KeyHeaderDef.A_DescriptorLast, KeyHeader.DescriptorLast); KeyHeaderAlloc.Write(KeyHeaderDef.A_DescriptorUsed, KeyHeader.DescriptorUsed); KeyHeaderAlloc.Write(KeyHeaderDef.A_LastKey, KeyHeader.LastKey); // Create descriptor KeyDescriptor = new KeyDescriptorDef[KeyHeader.DescriptorLength]; } else { // Read header KeyHeader.DescriptorAddress = KeyHeaderAlloc.ReadLong(KeyHeaderDef.A_DescriptorAddress); KeyHeader.DescriptorLength = KeyHeaderAlloc.ReadInt(KeyHeaderDef.A_DescriptorLength); KeyHeader.DescriptorLast = KeyHeaderAlloc.ReadInt(KeyHeaderDef.A_DescriptorLast); KeyHeader.DescriptorUsed = KeyHeaderAlloc.ReadInt(KeyHeaderDef.A_DescriptorUsed); KeyHeader.LastKey = KeyHeaderAlloc.ReadLong(KeyHeaderDef.A_LastKey); // Read descriptor KeyDescriptor = new KeyDescriptorDef[KeyHeader.DescriptorLength]; KeyDescriptorAlloc = sp.GetAllocationByDescriptor(KeyHeader.DescriptorAddress); for (int i = 0; i < KeyHeader.DescriptorLength; i++) { KeyDescriptor[i].Address = KeyDescriptorAlloc.ReadLong((KeyDescriptorDef.DESCRIPTOR_ITEM_LENGTH * i) + KeyDescriptorDef.A_Address); KeyDescriptor[i].FirstKey = KeyDescriptorAlloc.ReadLong((KeyDescriptorDef.DESCRIPTOR_ITEM_LENGTH * i) + KeyDescriptorDef.A_FirstKey); KeyDescriptor[i].Used = KeyDescriptorAlloc.ReadInt((KeyDescriptorDef.DESCRIPTOR_ITEM_LENGTH * i) + KeyDescriptorDef.A_Used); } } }
public VSFreeSpaceManager(VSpace _sp) { Space = _sp; vm = Space.VM; long hdr_address = Space.GetFirstAddress(DEFS.POOL_FREE_SPACE); if (hdr_address == 0) { // Initialization // 1. Create H-block (header) H_Object = new VSAllocation(vm, DEFS.FBQE_HEADER_ADDRESS, DEFS.FBQE_HEADER_LENGTH_FULL, 0); H_Object.Write(0, DEFS.FBQE_HEADER_SIGNATURE); this.MAX = DEFS.FBQE_ALLOCATION_NUMBER; // Max number of FBQE this.FREE = MAX; this.FIRST = -1; this.LAST = -1; this.FIRST_Q = 0; this.LAST_Q = FREE - 1; // 2. Save H-block address (1st object) Space.SetFirstAddress(DEFS.POOL_FREE_SPACE, H_Object.DescriptorAddress); // 1st object // 3. Create 1st FBQE block F_Object = new VSAllocation(vm, H_Object.DescriptorAddress + H_Object.FullLength, (DEFS.FBQE_ALLOCATION_LENGTH + DEFS.BaseDescriptorLength), 0); // 4. Set initial size F_Object.SetSize(DEFS.FBQE_ALLOCATION_LENGTH); buffer = new byte[F_Object.Size]; // Create buffer // 5. Set references F_Object.PREV = H_Object.DescriptorAddress; H_Object.NEXT = F_Object.DescriptorAddress; // Address of the 1st block F-block // 6. Save F-block address (last object) Space.SetLastAddress(DEFS.POOL_FREE_SPACE, F_Object.DescriptorAddress); //last object // 1.3 Initiate Free queue for (int i = 0; i < FREE; i++) { CreateFBQE(i); } BuildBTrees(); // 1.4 Create initial FBQE long fa = F_Object.DescriptorAddress + F_Object.FullLength; // 1st free address AddFBQE(fa, (Space.vm.Size - fa), -1, -1); // Create 1st FBQE } else { H_Object = Space.GetAllocationByDescriptor(hdr_address); F_Object = Space.GetAllocationByDescriptor(H_Object.NEXT); byte[] b = H_Object.ReadBytes(0, FBQE_HEADER_LENGTH); this.v_MAX = VSLib.ConvertByteToInt(VSLib.GetByteArray(b, MAX_POS, MAX_LEN)); this.v_FREE = VSLib.ConvertByteToInt(VSLib.GetByteArray(b, FREE_POS, FREE_LEN)); this.v_FIRST = VSLib.ConvertByteToInt(VSLib.GetByteArray(b, FIRST_POS, FIRST_LEN)); this.v_LAST = VSLib.ConvertByteToInt(VSLib.GetByteArray(b, LAST_POS, LAST_LEN)); this.v_FIRST_Q = VSLib.ConvertByteToInt(VSLib.GetByteArray(b, FIRST_Q_POS, FIRST_Q_LEN)); this.v_LAST_Q = VSLib.ConvertByteToInt(VSLib.GetByteArray(b, LAST_Q_POS, LAST_Q_LEN)); buffer = F_Object.ReadBytes(0, F_Object.Size); // Read buffer BuildBTrees(); } }
/// <summary> /// Get/set pool descriptot address (first or last) /// </summary> /// <param name="pool"></param> /// <param name="op">0 - read; 1 - write</param> /// <param name="n">0 - first; 1 - last</param> /// <param name="value">optional. of op=1 only</param> /// <returns></returns> private long PoolDescriptorAddressIO(int pool, int op, int n, long value = 0) { long offs = (n == 0) ? 0 : 8; // Offset in the descriptor long addr = 0; if (pool < DEFS.POOL_MIN_USER_DEFINED) { // System pool if (Math.Abs(pool) >= DEFS.SYSTEM_POOL_DESCRIPTOR_NUMBER) { throw new VSException(DEFS.E0012_INVALID_POOL_NUMBER_CODE, "- " + pool.ToString()); } addr = DEFS.SYSTEM_POOL_AREA_ADDRESS + (long)(Math.Abs(pool) * DEFS.SYSTEM_POOL_DESCRIPTOR_LENGTH + offs); if (op == 0) { return(vm.ReadLong(addr)); } else { vm.Write(addr, value); return(0); } } else if (pool < DEFS.POOL_MIN_DYNAMIC) { // User-defined addr = (pool - DEFS.POOL_MIN_USER_DEFINED) * DEFS.SYSTEM_POOL_DESCRIPTOR_LENGTH + offs; while (addr >= A_POOL_USER_DEFINED.Size) { ExtendSpace(A_POOL_USER_DEFINED, DEFS.ALLOCATION_USER_DEFINED); // Extend if needed } if (op == 0) { return(A_POOL_USER_DEFINED.ReadLong(addr)); } else { A_POOL_USER_DEFINED.Write(addr, value); return(0); } } else { // Dynamic addr = (pool - DEFS.POOL_MIN_DYNAMIC) * DEFS.SYSTEM_POOL_DESCRIPTOR_LENGTH + offs; while (addr >= A_POOL_DYNAMIC.Size) { ExtendSpace(A_POOL_USER_DEFINED, DEFS.ALLOCATION_DYNAMIC); // Extend if needed } if (op == 0) { return(A_POOL_DYNAMIC.ReadLong(addr)); } else { A_POOL_DYNAMIC.Write(addr, value); return(0); } } }
/// <summary> /// Create new KEY for address /// If use_key > 0 then add specified key (used by restore) /// If alloc=null - add 0 address (restore) /// </summary> /// <returns>new SID</returns> public long Add(VSAllocation alloc, long use_key = 0) { //VSDebug.StopPoint(alloc.Address, 45724); long address = (alloc == null) ? 0 : alloc.DescriptorAddress; long addr = 0; // 1. Generate new key if (use_key > 0) { if (use_key <= KeyHeader.LastKey) { throw new VSException(DEFS.E0023_INVALID_KEY_SEQUENCE_CODE, " Lask key: " + KeyHeader.LastKey.ToString() + " Use key: " + use_key.ToString()); } KeyHeader.LastKey = use_key; } else { KeyHeader.LastKey++; } // Write new key KeyHeaderAlloc.Write(KeyHeaderDef.A_LastKey, KeyHeader.LastKey); // Lookup place to add KeyBlockAllocWrite = null; if (KeyHeader.DescriptorLast >= 0) { if (KeyHeader.LastKey < (KeyDescriptor[KeyHeader.DescriptorLast].FirstKey + KeyBlockDef.BLOCK_LENGTH)) { KeyBlockAllocWrite = sp.GetAllocationByDescriptor(KeyDescriptor[KeyHeader.DescriptorLast].Address); } } // Not found, allocate new block if (KeyBlockAllocWrite == null) { KeyBlockAllocWrite = sp.AllocateSpace(KeyBlockDef.BLOCK_SIZE, DEFS.POOL_KEY, generateID: false); byte[] b = new byte[KeyBlockDef.BLOCK_SIZE]; // Fill all by -1 for (int i = 0; i < KeyBlockDef.BLOCK_SIZE; i++) { b[i] = 255; } KeyBlockAllocWrite.Write(0, b, b.Length); KeyHeader.DescriptorLast++; KeyHeader.DescriptorUsed++; KeyHeaderAlloc.Write(KeyHeaderDef.A_DescriptorLast, KeyHeader.DescriptorLast); KeyHeaderAlloc.Write(KeyHeaderDef.A_DescriptorUsed, KeyHeader.DescriptorUsed); // Extend if required if (KeyHeader.DescriptorLast == KeyHeader.DescriptorLength) { sp.Extend(KeyHeaderAlloc, KeyDescriptorDef.DESCRIPTOR_CHUNK_SIZE); KeyHeader.DescriptorLength += KeyDescriptorDef.DESCRIPTOR_CHUNK_LENGTH; KeyHeaderAlloc.Write(KeyHeaderDef.A_DescriptorLength, KeyHeader.DescriptorLength); } KeyDescriptor[KeyHeader.DescriptorLast].FirstKey = KeyHeader.LastKey; KeyDescriptor[KeyHeader.DescriptorLast].Address = KeyBlockAllocWrite.DescriptorAddress; KeyDescriptor[KeyHeader.DescriptorLast].Used = 0; addr = KeyHeader.DescriptorLast * KeyDescriptorDef.DESCRIPTOR_ITEM_LENGTH; KeyDescriptorAlloc.Write(addr + KeyDescriptorDef.A_Address, KeyDescriptor[KeyHeader.DescriptorLast].Address); KeyDescriptorAlloc.Write(addr + KeyDescriptorDef.A_FirstKey, KeyDescriptor[KeyHeader.DescriptorLast].FirstKey); } // Write to block KeyBlockAllocWrite = sp.GetAllocationByDescriptor(KeyDescriptor[KeyHeader.DescriptorLast].Address); addr = ((KeyHeader.LastKey - KeyDescriptor[KeyHeader.DescriptorLast].FirstKey) * KeyBlockDef.BLOCK_ITEM_LENGTH); KeyBlockAllocWrite.Write(addr + KeyBlockDef.A_Address, address); // Update used KeyDescriptor[KeyHeader.DescriptorLast].Used++; KeyDescriptorAlloc.Write((KeyHeader.DescriptorLast * KeyDescriptorDef.DESCRIPTOR_ITEM_LENGTH) + KeyDescriptorDef.A_Used, KeyDescriptor[KeyHeader.DescriptorLast].Used); // Set read cache KeyBlockAllocRead = KeyBlockAllocWrite; KeyBlockReadIndex = KeyHeader.DescriptorLast; // Return key return(KeyHeader.LastKey); }