Exemple #1
0
        /************************************************************************************/
        /************************   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);
        }
Exemple #2
0
        /// <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;
        }