Пример #1
0
        /// <summary>
        /// Set use dedicated space {index_space_name} for indexes of the {space_name} objects
        /// Empty 'index_space_name' means stop using index space. Indexes will not be removed automatically.
        ///
        /// </summary>
        /// <param name="space_name"></param>
        /// <param name="index_space_name"></param>
        /// <returns></returns>
        public string UseIndexSpace(string space_name, string index_space_name)
        {
            string s = "";
            VSCatalogDescriptor d_desc = this.CATALOG.Get(space_name);
            VSCatalogDescriptor x_desc = null;

            if (d_desc == null)
            {
                s = "Space '" + space_name + "' is not found";
            }
            else
            {
                if (index_space_name.Trim() != "")
                {
                    x_desc = this.CATALOG.Get(index_space_name);
                    if (x_desc == null)
                    {
                        s = "Space '" + index_space_name + "' is not found";
                    }
                    else if (x_desc.IndexSpace != "")
                    {
                        s = "The specified index space cannot refer to anothe index space ('" + index_space_name + "' refers to '" + x_desc.IndexSpace + "'";
                    }
                }
            }

            if (s == "")
            {
                if (x_desc == null)
                {
                    if (d_desc.indexspace == "")
                    {
                        return("");
                    }
                    else
                    {
                        d_desc.indexspace = "";
                    }
                }
                else
                {
                    if (d_desc.indexspace == index_space_name.Trim().ToLower())
                    {
                        return("");
                    }
                    else
                    {
                        d_desc.indexspace = index_space_name;
                    }
                }

                if (!IMO)
                {
                    this.CATALOG.Save();
                }
            }
            return(s);
        }
Пример #2
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();
        }
Пример #3
0
        ////////////////////////////////////////////////////////////////////////////
        //////////////////////  COMMON METHODS   ///////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Attach new address space. Return 0 - successful; -1 - error
        /// </summary>
        /// <param name="_path"></param>
        /// <param name="_cat_file"></param>
        /// <param name="idx"></param>
        /// <returns></returns>
        internal string Attach(VSCatalogDescriptor desc, VSVirtualMemoryManager vmm, VSTransaction ta, bool imo)
        {
            DESCRIPTOR = desc;
            vm         = vmm;
            vs_imo     = imo;

            // Check if restore is not completed
            long l = vm.ReadLong(DEFS.SYSTEM_STATUS_ADDRESS);

            if (l != 0)
            {
                return(VSException.GetMessage(DEFS.E0009_RESTORE_NOT_COMPLETED_CODE) + " Space: " + Name);
            }


            // Build index list
            index_list      = new List <VSIndex>();
            index_list_full = new List <VSIndex>();
            long addr = GetRootAddress(DEFS.POOL_INDEX);            // Get 1st ADSC addredd

            while (addr > 0)
            {
                VSIndex xd = new VSIndex(this, addr);
                index_list_full.Add(xd);
                if (xd.Name.IndexOf(DEFS.INDEX_CROSS_REFERENCES) < 0)
                {
                    index_list.Add(xd);
                }

                addr = xd.NEXT;
            }

            // Set ref indexes
            for (int i = 0; i < index_list.Count; i++)
            {
                set_ref_index(index_list[i]);
            }

            return("");
        }
Пример #4
0
        /// <summary>
        /// Get information about space
        /// </summary>
        /// <param name="name"></param>
        private string[] GetSpaceHeaderInfo(string name)
        {
            string[] hdr = new string[8];
            for (int i = 0; i < hdr.Length; i++)
            {
                hdr[i] = "";
            }

            VSCatalogDescriptor desc = CATALOG.Get(name);

            if (desc != null)
            {
                hdr[0] = "Id:             " + desc.Id.ToString();
                hdr[1] = "Name:           " + desc.Name;
                hdr[2] = "Path:           " + desc.Path;
                hdr[3] = "Page size:      " + desc.PageSize.ToString("#,#;(#,#)") + " bytes";
                hdr[4] = "Partitions:     " + desc.Partitions.ToString();
                hdr[5] = "Size:           " + desc.SpaceSize.ToString("#,#;(#,#)") + " bytes (" + desc.SpaceSizeMb.ToString("#,#;(#,#)") + " Mb)";
                hdr[6] = "Pages:          " + desc.space_size_pg.ToString();
                hdr[7] = "Auto extension: " + ((desc.Extension == 0) ? "No" : (desc.extension_pg.ToString("#,0;(#,0)") + " pages (" + desc.ExtensionMb.ToString("#,0;(#,0)") + " Mb)"));
            }
            return(hdr);
        }
Пример #5
0
        /// <summary>
        /// Open new address space: _path - root folder path; _cat_file - catalog file name; idx - index in the catalog. Return: space id or -1(if error)
        /// </summary>
        /// <param name="_path"></param>
        /// <param name="_cat_file"></param>
        /// <param name="idx"></param>
        /// <returns></returns>
        public string Open(VSCatalogDescriptor desc, VSTransaction ta)
        {
            this.DESCRIPTOR = desc;
            this.page_size  = DESCRIPTOR.PageSize;
            this.imo        = DESCRIPTOR.IMO;

            e_key = VSLib.ConvertStringToByte(DEFS.ENCRYPT_SPACE);

            e_buf = new byte[page_size];

            _ta = ta;

            //////////////////////////////////////////////
            ///////////// Initiate partitions ////////////
            //////////////////////////////////////////////
            this.pd = new partition_descriptor[DESCRIPTOR.Partitions];


            //Check if all partitions exists
            if (imo)
            {
                pd[0].start_page = 0;                                           //Start Page
                pd[0].end_page   = DESCRIPTOR.space_size_pg - 1;                //End Page
            }
            else
            {
                for (int i = 0; i < DESCRIPTOR.Partitions; i++)
                {
                    short j = (short)(i + 1);
                    pd[i].file_name = DESCRIPTOR.Path + "\\" + DEFS.SPACE_FILE_NAME(DESCRIPTOR.Name, i);

                    if (!System.IO.File.Exists(pd[i].file_name))
                    {
                        return("Error: space file is not found - " + pd[i].file_name);
                    }

                    //FileStream f = null;

                    //f = File.Open(pd[i].file_name, FileMode.Open, FileAccess.ReadWrite, FileShare.None);


                    pd[i].fs = new VSIO(pd[i].file_name, VSIO.FILE_MODE_OPEN, DEFS.ENCRYPT_SPACE);
                    pd[i].fs.SetEncryption(false);

                    pd[i].start_page = (i == 0) ? 0 : pd[i - 1].end_page + 1;                         //Start Page
                    pd[i].end_page   = pd[i].start_page + ((pd[i].fs.GetLength()) / page_size) - 1;   //End Page
                }
            }

            //////////////////////////////////////////////
            ///////////// Initiate cache /////////////////
            //////////////////////////////////////////////

            // Create segment table
            segment_table = new page_segment_descriptor[DEFS.PAGE_SEGMENTS_NUMBER];

            // Create page table for 1st segment
            segment_table[0]            = new page_segment_descriptor();
            segment_table[0].start_page = 0;
            segment_table[0].end_page   = DESCRIPTOR.space_size_pg - 1;

            // Set initial number of segments used
            segments_used = 1;

            // Calculate cache size in pages
            if (imo)
            {
                cache_size_pages = DESCRIPTOR.space_size_pg;
                cache_size_bytes = DESCRIPTOR.SpaceSize;
            }
            else
            {
                string confs = VSLib.VSGetKey(DEFS.VM_CACHE_SIZE_KEY);
                if (confs == "")
                {
                    confs = DEFS.VM_CACHE_SIZE_DEFAULT;
                    VSLib.VSSetKey(DEFS.VM_CACHE_SIZE_KEY, confs);
                }
                int csize = VSLib.ConvertStringToInt(confs);

                cache_size_bytes = ((csize < 2) ? 2 : csize) * 1048576;

                if (cache_size_bytes < (page_size * 10))
                {
                    cache_size_bytes = page_size * 10;
                }

                cache_size_pages = (cache_size_bytes / page_size) + 1;
            }

            // Initialize cache
            segment_table[0].cache = new page_buffer[cache_size_pages];
            for (int i = 0; i < cache_size_pages; i++)
            {
                segment_table[0].cache[i].buf          = new byte[page_size];
                segment_table[0].cache[i].tbuf         = null;
                segment_table[0].cache[i].last_access  = 0;
                segment_table[0].cache[i].access_count = 0;
                if (imo)
                {
                    segment_table[0].cache[i].page_no = i;                  // Page no = Buf no
                    segment_table[0].cache[i].prev    = -1;
                    segment_table[0].cache[i].next    = -1;
                }
                else
                {
                    segment_table[0].cache[i].page_no = -1;
                    segment_table[0].cache[i].prev    = i - 1;
                    segment_table[0].cache[i].next    = ((i + 1) == cache_size_pages) ? -1 : i + 1;
                }
            }

            // Initialize queues (not IMO)
            if (!imo)
            {
                q_read         = new int[3];
                q_read[number] = 0;
                q_read[first]  = -1;
                q_read[last]   = -1;

                q_write         = new int[3];
                q_write[number] = 0;
                q_write[first]  = -1;
                q_write[last]   = -1;

                q_free         = new int[3];
                q_free[number] = (int)cache_size_pages;
                q_free[first]  = 0;
                q_free[last]   = (int)cache_size_pages - 1;
            }

            //////////////////////////////////////////////
            ///////////// Initiate page table ////////////
            //////////////////////////////////////////////
            segment_table[0].page_table = new page_descriptor[DESCRIPTOR.space_size_pg];
            for (int i = 0; i < segment_table[0].page_table.Length; i++)
            {
                if (imo)
                {
                    segment_table[0].page_table[i].page_state = DEFS.PAGE_READ;
                    segment_table[0].page_table[i].page_lock  = DEFS.PAGE_LOCKED;
                    segment_table[0].page_table[i].bufno      = i;                  // For IMO bufno = page table element
                }
                else
                {
                    segment_table[0].page_table[i].page_state = DEFS.PAGE_FREE;
                    segment_table[0].page_table[i].page_lock  = DEFS.PAGE_UNLOCKED;
                    segment_table[0].page_table[i].bufno      = -1;
                }
            }

            // Set state 'Opened'
            this.state = DEFS.SPACE_OPENED;

            // For IMO: write owner 'undefined'; otherwise: load and lock page 0.
            if (imo)
            {
                this.Write(DEFS.SYSTEM_OWNER_ADDRESS, DEFS.SYSTEM_OWNER_UNDEFINED.PadRight((int)DEFS.SYSTEM_OWNER_LENGTH));
            }
            else
            {
                fetch(0, 0, 0, DEFS.PAGE_READ);
                this.lock_page(0);                                                            // lock 1st page
            }

            return("");
        }
Пример #6
0
        /// <summary>
        /// Load catalog content
        /// </summary>
        public void Load()
        {
            int    pos = 0;
            string s   = "";


            err_line = -1;

            if (!File.Exists(catalog_file_name))
            {
                File.WriteAllBytes(catalog_file_name, VSLib.ConvertStringToByte(sg_ok + DEFS.VSTORAGE_VERSION + "$" + "U" + "$" + DEFS.DELIM_NEWLINE));         // 'U'  dont encrypt (+19)
            }
            s = VSLib.ConvertByteToString(File.ReadAllBytes(catalog_file_name));
            // Parse file
            pos = s.IndexOf(DEFS.DELIM_NEWLINE);
            if (pos < 0)
            {
                return;
            }
            // Get encryption status
            string sth = s.Substring(0, pos);

            if (sth.Length < 21)
            {
                err_line = 1;
            }
            else
            {
                // Encryption
                ste     = sth.Substring(19, 1).ToUpper();
                ENCRYPT = (sth.Substring(19, 1) == "E");

                pos += DEFS.DELIM_NEWLINE.Length;
                line = 1;
                VSCatalogDescriptor desc = null;

                while ((pos < s.Length) & (err_line < 0))
                {
                    string par     = "";
                    int    ln      = 0;
                    int    new_pos = s.IndexOf(DEFS.DELIM_NEWLINE, pos);
                    if (new_pos < 0)
                    {
                        ln = s.Length - pos;
                    }
                    else
                    {
                        ln = new_pos - pos;
                    }

                    if (ln > 0)
                    {
                        par = s.Substring(pos, ln).Trim();
                    }
                    line++;
                    pos += (ln + DEFS.DELIM_NEWLINE.Length);

                    if (par != "")
                    {
                        if (par.Substring(0, 1) == "[")
                        { // Parse new descriptor
                            desc = null;
                            string sname = "";
                            int    eb    = par.IndexOf("]", 1);
                            if (eb < 0)
                            {
                                err_line = line;
                            }
                            else
                            {
                                if (eb > 1)
                                {
                                    sname = par.Substring(1, eb - 1);
                                }
                                if (sname != "")
                                {
                                    sname = sname.Trim().ToLower();
                                    for (int i = 0; i < dl.Count; i++)
                                    {
                                        if (dl[i].Name == sname)
                                        {
                                            desc = dl[i];
                                            break;
                                        }
                                    }
                                    if (desc == null)
                                    {
                                        desc      = new VSCatalogDescriptor(this);
                                        desc.name = sname;
                                        dl.Add(desc);
                                    }
                                }
                                else
                                {
                                    err_line = line;
                                }
                            }
                        }
                        else
                        { // Parse parameters
                            string s_val = "";
                            long   n_val = 0;
                            if (desc == null)
                            {
                                err_line = line;
                            }
                            else
                            {
                                par += "                            ";

                                if (parse_long(ref par, DEF_ID, out n_val))
                                {
                                    if (n_val >= 0)
                                    {
                                        desc.id = (short)n_val;
                                    }
                                }
                                else if (parse_long(ref par, DEF_SIZE, out n_val))
                                {
                                    if (n_val >= 0)
                                    {
                                        desc.space_size_pg = n_val;
                                    }
                                }
                                else if (parse_long(ref par, DEF_EXTENSION, out n_val))
                                {
                                    if (n_val >= 0)
                                    {
                                        desc.extension_pg = n_val;
                                    }
                                }
                                else if (parse_long(ref par, DEF_PAGESIZE, out n_val))
                                {
                                    if (n_val >= 0)
                                    {
                                        desc.page_size_kb = n_val;
                                    }
                                }
                                else if (parse_long(ref par, DEF_PARTITIONS, out n_val))
                                {
                                    if (n_val >= 0)
                                    {
                                        desc.partitions = n_val;
                                    }
                                }
                                else if (parse_string(ref par, DEF_PATH, out s_val))
                                {
                                    if (s_val != DEF_ERROR)
                                    {
                                        desc.path = s_val;
                                    }
                                }
                                else if (parse_string(ref par, DEF_INDEXSPACE, out s_val))
                                {
                                    if (s_val != DEF_ERROR)
                                    {
                                        desc.indexspace = s_val;
                                    }
                                }
                                else if (parse_string(ref par, DEF_TIMESTAMP, out s_val))
                                {
                                    if (s_val != DEF_ERROR)
                                    {
                                        desc.creation_timestamp = s_val;
                                    }
                                }
                                else if (parse_string(ref par, DEF_SIGNATURE, out s_val))
                                {
                                    if (s_val != DEF_ERROR)
                                    {
                                        desc.signature = s_val;
                                    }
                                }
                                else
                                {
                                    err_line = line;
                                }
                            }
                        }
                    }
                }
            }
            if (err_line >= 0)
            {
                throw new VSException(DEFS.E0016_OPEN_STORAGE_ERROR_CODE, "- invalid catalog entry at line " + err_line.ToString());
            }

            for (int i = 0; i < dl.Count; i++)
            {
                string sg = dl[i].Signature;
                dl[i].CalculateSignature();
                if (dl[i].Signature != sg)
                {
                    throw new VSException(DEFS.E0016_OPEN_STORAGE_ERROR_CODE, "- missing or invalid space signature for '" + dl[i].Name);
                }
            }
        }
Пример #7
0
        /// <summary>
        /// Update or create catalog descriptor
        /// Size - Mb
        /// Extension - Mb
        /// pagesize - Kb
        /// </summary>
        /// <param name="desc"></param>
        public VSCatalogDescriptor Create(string name, long size, long extension = 0, long pagesize = 0, string path = "")
        {
            for (int i = 0; i < dl.Count; i++)
            {
                if (dl[i].Name == name.Trim().ToLower())
                {
                    return(null);
                }
            }
            VSCatalogDescriptor d = new VSCatalogDescriptor(this);

            // Name
            d.name = name.Trim().ToLower();

            // Page size (Kb)
            long p = pagesize;

            if (p <= 0)
            {
                p = 16;
            }
            else if (p < 4)
            {
                p = 4;
            }
            else if (p > 64)
            {
                p = 64;
            }
            d.page_size_kb = p;

            // Space size (pages)
            p = size;
            if (p <= 0)
            {
                p = 5;
            }
            d.space_size_pg = (p * 1048576) / d.PageSize;

            // Extension (pages)
            p = extension;
            if (p <= 0)
            {
                p = 0;
            }
            d.extension_pg = (p * 1048576) / d.PageSize;

            // Path
            d.path = path.Trim();

            // Timestamp
            d.creation_timestamp = DateTime.Now.ToString("u");

            // Calculate new id
            short new_id = 1;
            bool  ready  = false;

            while (!ready)
            {
                ready = true;
                for (int i = 0; i < dl.Count; i++)
                {
                    if (new_id == dl[i].Id)
                    {
                        ready = false;
                        new_id++;
                        break;
                    }
                }
            }
            d.id = new_id;
            dl.Add(d);
            return(d);
        }
Пример #8
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();
        }
Пример #9
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();
        }