/// <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); } } }
/// <summary> /// Return unused pool number /// </summary> /// <returns></returns> public short GetFreePoolNumber() { long n = A_POOL_DYNAMIC.Size / DEFS.SYSTEM_POOL_DESCRIPTOR_LENGTH; for (int iteration = 0; iteration < 2; iteration++) { for (long i = 0; i < n; i++) { long a = A_POOL_DYNAMIC.ReadLong(i * DEFS.SYSTEM_POOL_DESCRIPTOR_LENGTH); if (a == 0) { return((short)(i + DEFS.POOL_MIN_DYNAMIC)); } } ExtendSpace(A_POOL_DYNAMIC, DEFS.ALLOCATION_DYNAMIC); } return(-1); }
/// <summary> /// Return index of the descriptor item of -1 - not found /// </summary> /// <param name="key"></param> /// <returns> /// ret[0] - object address (if found); -1 - not found; /// ret[1] - descriptor index (if found) /// ret[2] - block index (if found) /// </returns> private long[] SearchKey(long key) { long[] ret = new long[3]; ret[0] = -1; ret[1] = -1; ret[2] = -1; long lastk = 0; // 1. Check last used block if (KeyBlockReadIndex >= 0) // Not 1st search { lastk = KeyDescriptor[KeyBlockReadIndex].FirstKey + KeyBlockDef.BLOCK_LENGTH - 1; // Last key in block if ((key < KeyDescriptor[KeyBlockReadIndex].FirstKey) | (key > lastk)) { KeyBlockReadIndex = -1; } } // 2. No last used - find descriptor if (KeyBlockReadIndex < 0) { for (int i = KeyHeader.DescriptorLast; i >= 0; i--) { if (KeyDescriptor[i].Used > 0) { lastk = KeyDescriptor[i].FirstKey + KeyBlockDef.BLOCK_LENGTH - 1; // Last key in block if ((key >= KeyDescriptor[i].FirstKey) & (key <= lastk)) { KeyBlockReadIndex = i; break; } } } } // 3. Descriptor found - check if key is allocated if (KeyBlockReadIndex >= 0) { KeyBlockAllocWrite = sp.GetAllocationByDescriptor(KeyDescriptor[KeyBlockReadIndex].Address); long obj_index = key - KeyDescriptor[KeyBlockReadIndex].FirstKey; long addr = (obj_index * KeyBlockDef.BLOCK_ITEM_LENGTH) + KeyBlockDef.A_Address; long obj_addr = KeyBlockAllocWrite.ReadLong(addr); if (obj_addr >= 0) { ret[0] = obj_addr; ret[1] = KeyBlockReadIndex; ret[2] = obj_index; } } // Assuming KeyBlockAlloc is loaded if ret[0] >= 0 return(ret); }
/// <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> /// Next node /// </summary> /// <returns></returns> public bool Next() { if (action == Action.End) { return(false); } current = -1; // Cases - assuming index is not empty (action !- Action.End) // 1. Initial: D_Current < 0 if (D_current < 0) { D_current = 0; // Set 1st desc B_current = -1; KeyBlockAllocWrite = null; n = 0; NUM = (KeyHeader.DescriptorLast + 1) * KeyBlockDef.BLOCK_LENGTH; // Total numeber of items in all blocks (including empty and deleted) } while (n < NUM) { if (KeyDescriptor[D_current].Used == 0) // If empty block { n += KeyBlockDef.BLOCK_LENGTH; D_current++; B_current = -1; } else { B_current++; if (B_current == KeyBlockDef.BLOCK_LENGTH) // Out of block { KeyBlockAllocWrite = null; D_current++; B_current = -1; } else // Within block { if (KeyBlockAllocWrite == null) { KeyBlockAllocWrite = sp.GetAllocationByDescriptor(KeyDescriptor[D_current].Address); } if (KeyBlockAllocWrite.ReadLong(B_current * KeyBlockDef.BLOCK_ITEM_LENGTH + KeyBlockDef.A_Address) > 0) { current = KeyDescriptor[D_current].FirstKey + B_current; n++; break; } else { n++; } } } } if (current < 0) { action = Action.End; return(false); } return(true); }