/// <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("");
        }