示例#1
0
        /// <summary>
        /// Serialize all fields to object fields space
        /// Free excessive chunks if needed
        /// </summary>
        private void serialize()
        {
            // If no fields
            if (FCache.Count == 0)
            {
                set_alloc(ALLOC_RESET);
                FIELDS_SIZE = 0;
                FreeSpace   = -1;
                FCache      = null;
                return;
            }

            byte[] b        = null;
            int    old_size = (int)(FIELDS_SIZE);                  // Current used size (number of fields + all fields size)

            // 1. Calculate new size
            int new_size = FIRST_FIELD_OFFSET_REL;

            for (int i = 0; i < FCache.Count; i++)
            {
                new_size += FCache[i].FULL_LENGTH;
            }

            // 2. Check if space is availabe, extend if required
            if (new_size > (old_size + FreeSpace))
            {
                sp.Extend(this, (new_size - old_size));
            }

            // 3. Check if only value update is required

            List <FieldCache> afc = FCache;

            FCache = new List <FieldCache>(32);

            int array_size = (new_size > old_size) ? new_size : old_size;

            byte[] data = new byte[array_size];


            int data_pos = FIRST_FIELD_OFFSET_REL;

            VSLib.CopyBytes(data, VSLib.ConvertIntToByte(new_size), FIELDS_SIZE_POS, FIELDS_SIZE_LEN);                          // Size
            VSLib.CopyBytes(data, VSLib.ConvertShortToByte((short)afc.Count), FIELDS_NUMBER_POS, FIELDS_NUMBER_LEN);            // Fields number

            FCache.Clear();
            for (int i = 0; i < afc.Count; i++)
            {
                FieldCache fc_element = afc[i];
                if (!fc_element.DELETED)
                {
                    fc_element.OFFSET = data_pos;

                    // Type
                    data[data_pos] = fc_element.TYPE;
                    data_pos++;

                    // Name length
                    data[data_pos] = (byte)(fc_element.NAME.Length);
                    data_pos++;

                    // Name
                    b = VSLib.ConvertStringToByte(fc_element.NAME);
                    VSLib.CopyBytes(data, b, data_pos, b.Length);
                    data_pos += b.Length;

                    // Value
                    if (FIELD_COMPRESS[fc_element.TYPE])                                                              // int/long/decimal
                    {
                        data[data_pos] = (byte)(fc_element.LENGTH);
                        data_pos++;
                    }
                    else if ((fc_element.TYPE == FIELD_TYPE_BYTES) | (fc_element.TYPE == FIELD_TYPE_STRING))
                    {
                        b = compress(VSLib.ConvertLongToByte(fc_element.LENGTH), FIELD_TYPE_LONG);
                        data[data_pos] = (byte)b.Length;
                        data_pos++;

                        if (b.Length > 0)
                        {
                            VSLib.CopyBytes(data, b, data_pos, b.Length);
                            data_pos += b.Length;
                        }
                    }

                    // Write value
                    if (fc_element.VALUE.Length > 0)
                    {
                        VSLib.CopyBytes(data, fc_element.VALUE, data_pos, fc_element.VALUE.Length);
                        data_pos += afc[i].LENGTH;
                    }

                    // Shift offset and add to cache
                    fc_element.OLDLENGTH = afc[i].LENGTH;
                    fc_element.STATE     = STATE_LOADED;

                    FCacheTree.Insert(fc_element.NAME, FCache.Count);
                    FCache.Add(fc_element);
                }
            }

            base.Write(base.FIXED, data, data.Length);

            set_alloc(ALLOC_RENEW);

            // Fill the rest by zeros if le length < old length
            if (new_size < old_size)
            {
                long full_used_size = base.FIXED + new_size;
                b = new byte[old_size - new_size];
                base.Write(full_used_size, b, b.Length);                              // Fill be zeros unused space

                // Multiple chunks, chech if there are exessive
                if (base.Chunk > 0)
                {
                    sp.ShrinkObject(this, full_used_size);
                }
            }

            FreeSpace = (int)(this.Size - base.FIXED - new_size);
        }
示例#2
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);
        }