Beispiel #1
0
        /// <summary>
        /// Save storage to file
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public void Dump(string path, string name, bool encrypt = false)
        {
            string d_path = path;

            if (d_path != "")
            {
                if (!System.IO.Directory.Exists(d_path))
                {
                    throw new VSException(DEFS.E0025_STORAGE_UNABLE_TO_COMPLETE_CODE, "Dump, path is not found: '" + d_path + "'");
                }
            }
            else
            {
                d_path = System.IO.Directory.GetCurrentDirectory();
            }

            string fname = GenerateDumpFileName(d_path);

            if (File.Exists(fname))
            {
                File.Delete(fname);
            }

            VSIO IO = new VSIO(fname, VSIO.FILE_MODE_CREATE, DEFS.ENCRYPT_DUMP);

            IO.SetEncryption(encrypt);

            dump(IO, name);

            IO.Close();
        }
Beispiel #2
0
 /// <summary>
 /// Close file and set to null (private)
 /// </summary>
 private void CloseTAFile()
 {
     if (IO != null)
     {
         IO.Close();
         IO = null;
     }
 }
Beispiel #3
0
        /// <summary>
        /// Add partition to space: name - space name; size - size(Mb)
        /// </summary>
        /// <param name="name"></param>
        /// <param name="size">Mb</param>
        /// <returns></returns>
        public void AddPartition(string name, int size)
        {
            if (state != DEFS.STATE_DEFINED)
            {
                throw new VSException(DEFS.E0025_STORAGE_UNABLE_TO_COMPLETE_CODE, "- 'AddPartition' (storage is opened or undefined)");
            }

            VSCatalogDescriptor desc = CATALOG.Get(name);

            if (desc == null)
            {
                throw new VSException(DEFS.E0002_SPACE_NOT_FOUND_CODE, "(" + name + ")");
            }

            if (!this.Lock())
            {
                throw new VSException(DEFS.E0001_UNABLE_TO_LOCK_CODE, "(Add partition)");
            }

            long old_size = desc.SpaceSize;

            //Calculate space size (in pages)
            long add_pages = (long)(((size < 1) ? 1 : size) * 1048576) / desc.PageSize;

            desc.space_size_pg += add_pages;

            if (!IMO)
            {
                // Append pages
                byte[] dataArray = new byte[desc.PageSize];

                VSIO IO = new VSIO(GetSpaceFileName(name, desc.Path, (int)desc.Partitions), VSIO.FILE_MODE_CREATE, "");

                byte[] resv = new byte[8];

                for (long i = 0; i < add_pages; i++)
                {
                    IO.Write(-1, DEFS.DATA_NOT_ENCRYPTED);                // + 0 (4) Encryption indicator

                    IO.Write(-1, (uint)0);                                // + 4 (4) CRC32 placeholder

                    IO.Write(-1, ref resv);                               // +8 (8) reserve

                    IO.Write(-1, ref dataArray);
                }

                IO.Close();

                desc.partitions++;

                AddNewAllocation(desc.Path, name, old_size, add_pages * desc.PageSize);

                CATALOG.Save();
            }
            Release();
        }
Beispiel #4
0
        /// <summary>
        /// Restore storage from byte array
        /// </summary>
        public void RestoreFromArray(byte[] array, string name = "*")
        {
            if (state != DEFS.STATE_DEFINED)
            {
                throw new VSException(DEFS.E0025_STORAGE_UNABLE_TO_COMPLETE_CODE, "- 'Restore' - storage is opened or undefined");
            }

            VSIO IO = new VSIO(array, DEFS.ENCRYPT_DUMP);

            this.restore(IO, name);

            IO.Close();
        }
Beispiel #5
0
        /// <summary>
        /// Open for Rollback/rollforward transaction (NOT USED for IMO!)
        /// </summary>
        public void Open()
        {
            CURRENT_POS = -1;
            EOF         = false;

            IO = new VSIO(_path, VSIO.FILE_MODE_OPEN, "");

            if (IO.GetLength() == 0)
            {
                EOF = true;
            }
            else
            {
                CURRENT_POS = IO.GetLength();
            }
            roll_mode = true;
        }
Beispiel #6
0
        /// <summary>
        /// Save storage to byte arrray
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public byte[] DumpToArray(string name, bool encrypt = false)
        {
            long sz = (this.GetStorageSize() / 4);

            if (sz > int.MaxValue)
            {
                throw new VSException(DEFS.E0025_STORAGE_UNABLE_TO_COMPLETE_CODE, "Storage size is too big for in-memory backup)");
            }

            VSIO IO = new VSIO(null, DEFS.ENCRYPT_DUMP);

            IO.SetEncryption(encrypt);

            dump(IO, name);

            return(IO.GetBytes());
        }
Beispiel #7
0
        /// <summary>
        /// Restore storage from file
        /// </summary>
        public void Restore(string filename = "", string name = "*")
        {
            if (state != DEFS.STATE_DEFINED)
            {
                throw new VSException(DEFS.E0025_STORAGE_UNABLE_TO_COMPLETE_CODE, "- 'Restore' - storage is opened or undefined");
            }

            if (!System.IO.File.Exists(filename))
            {
                throw new VSException(DEFS.E0025_STORAGE_UNABLE_TO_COMPLETE_CODE, "- 'Restore' - file is not found: '" + filename + "'");
            }

            VSIO IO = new VSIO(filename, VSIO.FILE_MODE_OPEN, DEFS.ENCRYPT_DUMP);

            this.restore(IO, name);

            IO.Close();
        }
Beispiel #8
0
        /*************************************************************************************/
        /*************************  PRIVATE METHODS ******************************************/
        /*************************************************************************************/
        /// <summary>
        /// Update FSAT by adding new element (Extend, AddPartition) or in Create
        /// </summary>
        /// <param name="name"></param>
        /// <param name="address"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        private void AddNewAllocation(string space_path, string name, long address, long length)
        {
            VSIO IO = new VSIO(GetSpaceFileName(name, space_path), VSIO.FILE_MODE_OPEN, "");

            long  h_addr = DEFS.SYSTEM_ALLOCATION_ADDRESS;
            short n      = IO.ReadShort(h_addr);  //The number of pending updates

            long e_addr = h_addr + 2 + (n * 16);

            IO.Write(e_addr, address);

            IO.Write(e_addr + 8, address + length);

            n++;

            IO.Write(h_addr, n);

            IO.Close();
        }
Beispiel #9
0
        /// <summary>
        /// Begin transaction
        /// </summary>
        public void Begin()
        {
            if (!Started)
            {
                if (!imo)
                {
                    CURRENT_POS = 0;
                    CloseTAFile();

                    IO = new VSIO(_path, VSIO.FILE_MODE_CREATE, "");

                    if (IO.GetLength() > 0)
                    {
                        CloseTAFile();
                        throw new VSException(DEFS.E0018_TRANSACTION_ERROR_CODE, "- Begin transaction - previous transaction is not completed or rolled back");
                    }
                }
                started = true;
            }
        }
Beispiel #10
0
        /// <summary>
        /// Dump storage
        /// Space name - 32
        /// System area - 1024
        /// Pool area - 4096
        /// </summary>
        private void dump(VSIO IO, string name)
        {
            bool was_opened = false;

            uint e_code = IO.GetEncryption() ? e_code = DEFS.DATA_ENCRYPTED : e_code = DEFS.DATA_NOT_ENCRYPTED;

            if (state == DEFS.STATE_OPENED)
            {
                if (TA.Started)
                {
                    throw new VSException(DEFS.E0025_STORAGE_UNABLE_TO_COMPLETE_CODE, "- Dump (transaction is in progress)");
                }
                was_opened = true;
            }
            else
            {
                Open(null);
            }

            string[] spaces = this.GetSpaceList();
            bool     encr   = IO.GetEncryption();

            IO.SetEncryption(false);

            IO.Write(0, e_code);                                                     // + 0 (4)Encryption indicator

            IO.SetEncryption(encr);

            IO.Write(-1, DEFS.DUMP_SIGNATURE_INCOMPLETE);                            // + 4 (4) Signature 'incomplete'
            IO.Write(-1, (int)0);                                                    // + 8 (4) CRC placeholder
            IO.Write(-1, (long)0);                                                   // +12 (8)Total length


            for (int sp_index = 0; sp_index < spaces.Length; sp_index++)
            {
                VSpace sp = GetSpace(spaces[sp_index]);
                VSVirtualMemoryManager vm = GetVM(spaces[sp_index]);

                if ((name == "") | (VSLib.Compare(name, sp.Name)))
                {
                    long sp_hdr_pos = IO.GetPosition();                          // Position for header(number of bytes)

                    IO.Write(-1, (long)0);

                    // Save space header
                    IO.Write(-1, (short)sp.Name.Length);                             // Space neme length (short)
                    IO.Write(-1, sp.Name);                                           // Space name

                    IO.Write(-1, (short)sp.Owner.Length);                            // Space owner length (short)
                    IO.Write(-1, sp.Owner);                                          // Space owner

                    //////////////////////////////////////////////////////////////
                    // Save keys
                    //////////////////////////////////////////////////////////////
                    IO.Write(-1, DEFS.DUMP_KEYS_SIGNATURE);                                // Start keys
                    VSKeyManager kh = sp.KeyManager;
                    kh.Reset();

                    while (kh.Next())
                    {
                        long k = kh.Current;
                        IO.Write(-1, k);
                    }

                    IO.Write(-1, (long)-1);                                   // End keys

                    // Save pool ares (starting from 2)

                    short[] pools = sp.GetPoolsForDump();                           // Create list of pools

                    for (int i = 0; i < pools.Length; i++)
                    {
                        long a_desc = sp.GetFirstAddress(pools[i]);
                        while (a_desc > 0)
                        {
                            VSAllocation a = sp.GetAllocationByDescriptor(a_desc);

                            //////////// Save ADSC fields ///////////
                            IO.Write(-1, a.Id);
                            IO.Write(-1, a.Pool);

                            IO.Write(-1, (a.Chunk == 0) ? a.Length : a.Size);    // Memory size
                            IO.Write(-1, a.ChunkSize);                           // Chunk sizeMemory size

                            IO.Write(-1, a.ALLOC);                               // Alloc version (object)
                            IO.Write(-1, a.FIXED);                               // Fixed part (object)

                            //////////// Save data //////////////////
                            byte[] b = vm.ReadBytes(a.Address, a.Length);
                            IO.Write(-1, ref b);
                            a_desc = a.NEXT;
                            if (a.Chunk != 0)
                            {
                                while (a_desc != 0)
                                {
                                    a = sp.GetAllocationByDescriptor(a_desc);
                                    if ((a.Chunk == 0) | (a.Chunk == 1))
                                    {
                                        break;
                                    }
                                    b = vm.ReadBytes(a.Address, a.Length);
                                    IO.Write(-1, ref b);
                                    a_desc = a.NEXT;
                                }
                            }
                        }
                    }
                    long sp_count    = IO.GetPosition() - sp_hdr_pos;           // Calculate count
                    long current_pos = IO.GetPosition();                        // Save current position
                    IO.Write(sp_hdr_pos, sp_count);                             // Write count to the header (incl hdr)
                    IO.SetPosition(current_pos);                                // Restore position
                }
            }

            IO.Write(-1, (long)-1);                                      // Write eof indicator

            IO.Write(12, (long)IO.GetLength());                          // + 8 (8) - Total length

            IO.Flush();

            uint c = IO.GetCRC32(12, -1);                                // calculate CRC32

            IO.Write(8, c);                                              // + 4 (4) - CRC32

            IO.Write(4, DEFS.DUMP_SIGNATURE);                            // Signature 'complete'

            IO.Flush();

            if (!was_opened)
            {
                Close();
            }
        }
Beispiel #11
0
        /// <summary>
        /// Extend space size: name - space name; size - extension(Mb)
        /// </summary>
        /// <param name="name"></param>
        /// <param name="size (Mb)"></param>
        /// <returns></returns>
        public void Extend(string name, int size)
        {
            if (state != DEFS.STATE_DEFINED)
            {
                throw new VSException(DEFS.E0025_STORAGE_UNABLE_TO_COMPLETE_CODE, "- 'Extend' (storage is opened or undefined)");
            }

            VSCatalogDescriptor desc = CATALOG.Get(name);

            if (desc == null)
            {
                throw new VSException(DEFS.E0002_SPACE_NOT_FOUND_CODE, "(" + name + ")");
            }

            if (!IMO)
            {
                if (desc.Partitions > 1)        // Check if more than 1 partition exists. If so - add partition instead of extending
                {
                    this.AddPartition(name, size);
                    return;
                }
            }

            if (!this.Lock())
            {
                throw new VSException(DEFS.E0001_UNABLE_TO_LOCK_CODE, "(Extend space)");
            }


            long start_pos = desc.SpaceSize;                                                  //Address of the 1st byte out of space

            //Calculate new allocation size in pages
            long add_pages = (long)(((size < 1) ? 1 : size) * 1048576) / (long)(desc.PageSize);

            // Increase space size in descriptor
            desc.space_size_pg += add_pages;

            if (!IMO)
            {
                //Initialize page buffer
                byte[] dataArray = new byte[desc.PageSize];

                //Append pages
                VSIO IO = new VSIO(GetSpaceFileName(name, desc.Path), VSIO.FILE_MODE_APPEND, "");

                byte[] resv = new byte[8];

                for (long i = 0; i < add_pages; i++)
                {
                    IO.Write(-1, DEFS.DATA_NOT_ENCRYPTED);                // + 0 (4) Encryption indicator

                    IO.Write(-1, (uint)0);                                // + 4 (4) CRC32 placeholder

                    IO.Write(-1, ref resv);                               // +8 (8) reserve

                    IO.Write(-1, ref dataArray);
                }
                IO.Close();

                AddNewAllocation(desc.Path, name, start_pos, add_pages * desc.PageSize);

                CATALOG.Save();
            }

            Release();
        }
Beispiel #12
0
        //==========================================================================================================//
        //=========================================== Manager ======================================================//
        //==========================================================================================================//
        /// <summary>
        /// Create new address space. Return 0 - successful; -1 - error
        /// dir - directory
        /// name - space name
        /// page size -  in Kb
        /// size - size of the space in Mb. Default - 5
        /// extension - size for dynamic extension in MB. Default - 5
        /// </summary>
        /// <param name="name"></param>
        /// <param name="pagesize"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        public void Create(string name, int pagesize = DEFS.DEFAULT_PAGE_SIZE, int size = DEFS.DEFAULT_SPACE_SIZE, int extension = DEFS.DEFAULT_EXT_SIZE, string path = "")
        {
            if (state != DEFS.STATE_DEFINED)
            {
                throw new VSException(DEFS.E0025_STORAGE_UNABLE_TO_COMPLETE_CODE, "- 'Create' (storage is opened or undefined)");
            }

            VSCatalogDescriptor desc = CATALOG.Get(name);

            if (desc != null)
            {
                throw new VSException(DEFS.E0024_CREATE_SPACE_ERROR_CODE, "- space already exists(" + name + ")");
            }

            string space_path = path.Trim();
            string sname      = "";

            if (IMO)
            {
                space_path = "";
            }
            else
            {
                if (space_path == "")
                {
                    space_path = root_path;
                }

                if (!System.IO.Directory.Exists(space_path))
                {
                    throw new VSException(DEFS.E0004_STORAGE_NOT_FOUND_CODE, "(" + space_path + ")");
                }

                // Check if directory exists
                if (!System.IO.Directory.Exists(root_path))
                {
                    throw new VSException(DEFS.E0004_STORAGE_NOT_FOUND_CODE, "(" + root_path + ")");
                }

                if (!this.Lock())
                {
                    throw new VSException(DEFS.E0001_UNABLE_TO_LOCK_CODE, "(Create space)");
                }

                // Check if file exists, if no - create new space.
                sname = GetSpaceFileName(name, space_path);
                if (System.IO.File.Exists(sname))
                {
                    throw new VSException(DEFS.E0005_FILE_ALREADY_EXISTS_CODE, "(" + sname + ")");
                }
            }

            // Add descriptor
            desc = CATALOG.Create(name, (long)size, (long)extension, (long)pagesize, space_path);

            desc.IMO = IMO;

            if (!desc.IMO)
            {
                //Create file
                byte[] dataArray = new byte[desc.PageSize];

                VSIO IO = new VSIO(sname, VSIO.FILE_MODE_CREATE, "");

                byte[] resv = new byte[8];

                for (long i = 0; i < desc.space_size_pg; i++)
                {
                    IO.Write(-1, DEFS.DATA_NOT_ENCRYPTED);                // + 0 (4) Encryption indicator

                    IO.Write(-1, (uint)0);                                // + 4 (4) CRC32 placeholder

                    IO.Write(-1, ref resv);                               // +8 (8) reserve

                    IO.Write(-1, ref dataArray);
                }
                IO.Write(DEFS.SYSTEM_OWNER_ADDRESS + 16, DEFS.SYSTEM_OWNER_UNDEFINED.PadRight((int)DEFS.SYSTEM_OWNER_LENGTH));

                IO.Close();

                CATALOG.Save();
            }

            Release();
        }
Beispiel #13
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;
        }