Пример #1
0
        EmptyClass()
        {
            PType tp = new PType(PTypeEnumeration.integer);

            Polar.Cells.PaCell              cell = null;
            Polar.CellIndexes.TableView     table;
            Polar.PagedStreams.FileOfBlocks fob;
        }
Пример #2
0
        internal long AppendPObj(PType tp, object valu)
        {
            //long off = this.freespace;
            //this.SetOffset(off);
            //this.Append(tp, valu);
            //if (tp.HasNoTail)
            //{
            //    this.freespace += tp.HeadSize;
            //}
            //else
            //{
            //    this.freespace = this.fs.Position;
            //}
            long off = this.fs.Position;

            PaCell.SetPO(tp, bw, valu);
            this.nElements += 1;
            this.freespace  = tp.HasNoTail ? freespace + tp.HeadSize : fs.Position;
            return(off);
        }
Пример #3
0
 public PaEntry(PType tp, long offset, PaCell cell)
 {
     this.tp     = tp;
     this.offset = offset;
     this.cell   = cell;
 }
Пример #4
0
        private void MergeUp(long start, long number1, long number2, KeyString keyfunction)
        {
            if (number1 == 0 || number2 == 0)
            {
                return;
            }
            PTypeSequence pts  = (PTypeSequence)typ;
            int           size = pts.ElementType.HeadSize;
            // Заведем файл для верхнего массива
            string tmp_name = "../../../Databases/temp.bin";

            System.IO.FileStream tmp = new System.IO.FileStream(tmp_name, System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite, System.IO.FileShare.None, 10000);
            // Cкопируем нужное число байтов
            int buff_size = 8192;

            byte[]  buffer  = new byte[buff_size];
            PxEntry entry1  = this.Element(start);
            long    pointer = entry1.offset;

            this.fis.SetOffset(pointer);
            long bytestocopy = number1 * size;

            while (bytestocopy > 0)
            {
                int nb = this.fis.fs.Read(buffer, 0, bytestocopy < buff_size ? (int)bytestocopy : buff_size);
                tmp.Write(buffer, 0, nb);
                bytestocopy -= nb;
            }
            // Вычислим и запомним во временной ячейке ключи массива 1.
            // сначала тип ячейки и ячейка:
            PType  tp_tmp        = new PType(PTypeEnumeration.sstring);
            string tmp_cell_name = "../../../Databases/tmp.pac";
            PaCell tmp_cell      = new PaCell(tp_tmp, tmp_cell_name, false);

            // теперь заполним ее значениями
            //tmp_cell.StartSerialFlow();
            //tmp_cell.S();
            //for (long ii=0; ii<number1; ii++)
            //{
            //    string key = keyfunction(entry1);
            //    tmp_cell.V(key);
            //    entry1.offset += size;
            //}
            //tmp_cell.Se();
            //tmp_cell.EndSerialFlow();
            tmp_cell.Fill(new object[0]);
            for (long ii = 0; ii < number1; ii++)
            {
                string key = keyfunction(entry1);
                tmp_cell.Root.AppendElement(key);
                entry1.offset += size;
            }
            tmp_cell.Flush();
            // теперь будем сливать массивы
            tmp.Position = 0L; // в файле tmp
            long pointer2   = pointer + number1 * size;
            long tmp_offset = tmp_cell.Root.Element(0).offset;

            tmp_cell.SetOffset(tmp_offset);
            PType   tp_sstring = new PType(PTypeEnumeration.sstring);
            string  key1       = (string)tmp_cell.ScanObject(tp_sstring);
            long    cnt1       = 1; // число прочитанных элементов первой подпоследовательности
            PxEntry entry2     = this.Element(start + number1);
            string  key2       = keyfunction(entry2);
            long    cnt2       = 1; // число прочитанных элементов второй подпоследовательности

            byte[] buff_el  = new byte[size * 8192];
            int    buff_pos = 0;

            while (cnt1 > number1 || cnt2 > number2)
            {
                if (key1.CompareTo(key2) < 0)
                { // Продвигаем первую подпоследовательность
                    tmp.Read(buff_el, buff_pos, size); buff_pos += size;
                    key1 = (string)tmp_cell.ScanObject(tp_sstring);
                    cnt1++;
                }
                else
                { // Продвигаем вторую последовательность
                    entry2.fis.SetOffset(entry2.offset);
                    entry2.fis.fs.Read(buff_el, buff_pos, size); buff_pos += size;
                    entry2.offset += size;
                    key2           = keyfunction(entry2);
                    cnt2++;
                }
            }
            // Теперь надо переписать остатки
        }
Пример #5
0
        private void MergeUp <T>(long start, long number1, long number2, Func <PxEntry, T> keyfunction)
        {
            if (number1 == 0 || number2 == 0)
            {
                return;
            }
            PTypeSequence pts      = (PTypeSequence)typ;
            int           size     = pts.ElementType.HeadSize;
            string        tmp_name = "../../../Databases/temp.bin";

            System.IO.FileStream tmp = new System.IO.FileStream(tmp_name, System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite, System.IO.FileShare.None, 10000);
            // Cкопируем нужное число байтов
            int buff_size = 8192;

            byte[]  buffer  = new byte[buff_size];
            PxEntry entry1  = this.Element(start);
            long    pointer = entry1.offset;

            this.fis.SetOffset(pointer);
            long bytestocopy = number1 * size;

            while (bytestocopy > 0)
            {
                int nb = this.fis.fs.Read(buffer, 0, bytestocopy < buff_size ? (int)bytestocopy : buff_size);
                tmp.Write(buffer, 0, nb);
                bytestocopy -= nb;
            }
            // Вычислим и запомним во временной ячейке ключи массива 1.
            // сначала тип ячейки и ячейка:
            PxEntry     entry2 = this.Element(start + number1); // Это понадобится в будущем, а пока используем для определения типа ключа
            IComparable key2   = (IComparable)keyfunction(entry2);
            PType       tp_key = key2 is string?new PType(PTypeEnumeration.sstring) :
                                     (key2 is int?new PType(PTypeEnumeration.integer) :
                                          (key2 is long?new PType(PTypeEnumeration.longinteger) :
                                               (key2 is byte?new PType(PTypeEnumeration.@byte) :
                                                    (key2 is double?new PType(PTypeEnumeration.real) : null))));

            PType  tp_tmp        = new PTypeSequence(tp_key);
            string tmp_cell_name = "../../../Databases/tmp.pac"; //TODO: Надо имя файла генерировать, а то могут быть коллизии
            PaCell tmp_cell      = new PaCell(tp_tmp, tmp_cell_name, false);

            // теперь заполним ее значениями
            //tmp_cell.StartSerialFlow();
            //tmp_cell.S();
            //for (long ii = 0; ii < number1; ii++)
            //{
            //    var key = keyfunction(entry1);
            //    tmp_cell.V(key);
            //    entry1.offset += size;
            //}
            //tmp_cell.Se();
            //tmp_cell.EndSerialFlow();
            tmp_cell.Fill(new object[0]);
            for (long ii = 0; ii < number1; ii++)
            {
                var key = keyfunction(entry1);
                tmp_cell.Root.AppendElement(key);
                entry1.offset += size;
            }
            tmp_cell.Flush();
            // теперь будем сливать массивы
            tmp.Position = 0L; // в файле tmp
            long pointer2   = pointer + number1 * size;
            long tmp_offset = tmp_cell.Root.Element(0).offset;

            tmp_cell.SetOffset(tmp_offset);
            //PType tp_sstring = new PType(PTypeEnumeration.sstring);
            IComparable key1 = (IComparable)tmp_cell.ScanObject(tp_key);
            long        cnt1 = 0; // число переписанных элементов первой подпоследовательности
            //PxEntry entry2 = this.Element(start + number1);
            //var key2 = keyfunction(entry2); // Уже прочитан
            long cnt2 = 0; // число переписанных элементов второй подпоследовательности

            byte[] buff     = new byte[size * 8192];
            int    buff_pos = 0;

            while (cnt1 == number1 || cnt2 == number2)
            {
                if (key1.CompareTo(key2) < 0)
                { // Продвигаем первую подпоследовательность
                    tmp.Read(buff, buff_pos, size); buff_pos += size;
                    cnt1++;
                    if (cnt1 < number1)
                    {
                        key1 = (IComparable)tmp_cell.ScanObject(tp_key);                 // Возможен конец
                    }
                }
                else
                { // Продвигаем вторую последовательность
                    entry2.fis.SetOffset(pointer2);
                    pointer2 += size;
                    entry2.fis.fs.Read(buff, buff_pos, size); buff_pos += size;
                    cnt2++;
                    if (cnt2 < number2)
                    {
                        key2 = (IComparable)keyfunction(entry2);                 // Возможен конец
                    }
                }
                // Если буфер заполнился, его надо сбросить
                if (buff_pos == buff.Length)
                {
                    this.fis.SetOffset(pointer);
                    this.fis.fs.Write(buff, 0, buff_pos);
                    pointer += buff_pos;
                    buff_pos = 0;
                }
            }
            // Теперь надо переписать остатки
            if (cnt1 < number1)
            {
                this.fis.SetOffset(pointer); // Здесь запись ведется подряд, без перемещений головки чтения/записи
                bytestocopy = (number1 - cnt1) * size;
                while (bytestocopy > 0)
                {
                    int nbytes = buff.Length - buff_pos;
                    if (bytestocopy < nbytes)
                    {
                        nbytes = (int)bytestocopy;
                    }
                    tmp.Read(buff, buff_pos, nbytes); buff_pos += nbytes;
                    this.fis.fs.Write(buff, 0, buff_pos);
                    buff_pos = 0;
                }
            }
            else if (cnt2 < number2)
            {
                bytestocopy = (number2 - cnt2) * size;
                while (bytestocopy > 0)
                {
                    int nbytes = buff.Length - buff_pos;
                    if (bytestocopy < nbytes)
                    {
                        nbytes = (int)bytestocopy;
                    }
                    this.fis.SetOffset(pointer2); //TODO: Здесь вроде я не то беру, надо разобраться (2 строчки ниже!)
                    pointer2 += nbytes;
                    tmp.Read(buff, buff_pos, nbytes); buff_pos += nbytes;
                    this.fis.SetOffset(pointer);
                    this.fis.fs.Write(buff, 0, buff_pos);
                    pointer += buff_pos;
                    buff_pos = 0;
                }
            }
        }
Пример #6
0
        //================== Сортировки ====================
        /// <summary>
        /// Слияние двух участков одной ячейки первого (он в младшей индексной части) и второго, следующего за ним.
        /// Результирующий массив начинается с начала первого участка. Слияние производится сравнением объектных значений
        /// элементов посредством функции сравнения ComparePO
        /// </summary>
        /// <param name="tel">Тип элемента последовательности</param>
        /// <param name="off1">offset начала первого участка</param>
        /// <param name="number1">длина первого участка</param>
        /// <param name="off2">offset начала второго участка</param>
        /// <param name="number2">длина второго участка</param>
        /// <param name="comparePO">Функция сравнения объектных представлений элементов</param>
        internal void CombineParts(PType tel, long off1, long number1, long off2, long number2, Func <object, object, int> comparePO)
        {
            long pointer_out = off1;
            long pointer_in  = off2;
            int  size        = tel.HeadSize;

            // Используем временный файл
            string tmp_fname = "tmp_merge.pac";

            System.IO.FileStream   tmp_fs = new System.IO.FileStream(tmp_fname, System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite);
            System.IO.BinaryReader tmp_br = new System.IO.BinaryReader(tmp_fs);

            // Перепишем number1 * size байтов от начальной точки во временный файл (Первую часть)
            this.SetOffset(pointer_out);
            long bytestocopy = number1 * size;
            int  buffLen     = 8192;

            byte[] buff = new byte[buffLen * size];
            while (bytestocopy > 0)
            {
                int nb = bytestocopy < buff.Length ? (int)bytestocopy : buff.Length;
                this.fs.Read(buff, 0, nb);
                tmp_fs.Write(buff, 0, nb);
                bytestocopy -= nb;
            }
            tmp_fs.Flush();

            // теперь будем сливать массивы
            long cnt1 = 0;                  // число переписанных элементов первой подпоследовательности
            long cnt2 = 0;                  // число переписанных элементов второй подпоследовательности

            tmp_fs.Position = 0L;           // Установка начальной позиции в файле
            this.SetOffset(pointer_in);     // Установка на начало второй части последовательности в ячейке

            System.IO.Stream fs1 = tmp_fs;  // Первый поток
            System.IO.Stream fs2 = this.fs; // Второй поток

            // Микробуфера для элементов
            byte[] m_buf1 = new byte[size];
            byte[] m_buf2 = new byte[size];

            // Заполнение микробуферов
            fs1.Read(m_buf1, 0, size);
            fs2.Read(m_buf2, 0, size);
            pointer_in += size;
            // Это чтобы читать P-значения
            System.IO.BinaryReader m_reader1 = new System.IO.BinaryReader(new System.IO.MemoryStream(m_buf1));
            System.IO.BinaryReader m_reader2 = new System.IO.BinaryReader(new System.IO.MemoryStream(m_buf2));
            // Текущие объекты
            object val1 = PaCell.GetPO(tel, m_reader1);
            object val2 = PaCell.GetPO(tel, m_reader2);
            // Писать будем в тот же буффер buff, текущее место записи:
            int ind_buff = 0;

            // Слияние!!!
            while (cnt1 < number1 && cnt2 < number2)
            {
                if (comparePO(val1, val2) < 0)
                { // Продвигаем первую подпоследовательность
                    Buffer.BlockCopy(m_buf1, 0, buff, ind_buff, size);
                    cnt1++;
                    if (cnt1 < number1) // Возможен конец
                    {
                        fs1.Read(m_buf1, 0, size);
                        m_reader1.BaseStream.Position = 0;
                        val1 = PaCell.GetPO(tel, m_reader1);
                    }
                }
                else
                { // Продвигаем вторую последовательность
                    Buffer.BlockCopy(m_buf2, 0, buff, ind_buff, size);
                    cnt2++;
                    if (cnt2 < number2)             // Возможен конец
                    {
                        this.SetOffset(pointer_in); // Установка на текущее место чтения !!!!!!!!!
                        fs2.Read(m_buf2, 0, size);
                        pointer_in += size;
                        m_reader2.BaseStream.Position = 0;
                        val2 = PaCell.GetPO(tel, m_reader2);
                    }
                }
                ind_buff += size;
                // Если буфер заполнился, его надо сбросить
                if (ind_buff == buff.Length)
                {
                    this.SetOffset(pointer_out);
                    int volume = ind_buff;
                    this.fs.Write(buff, 0, volume);
                    pointer_out += volume;
                    ind_buff     = 0;
                }
            }
            // Если в буфере остались данные, их надо сбросить
            if (ind_buff > 0)
            {
                this.SetOffset(pointer_out);
                int volume = ind_buff;
                this.fs.Write(buff, 0, volume);
                pointer_out += volume;
            }
            // Теперь надо переписать остатки
            if (cnt1 < number1)
            {
                this.SetOffset(pointer_out); // Здесь запись ведется подряд, без перемещений головки чтения/записи
                // Сначала запишем уже прочитанную запись
                this.fs.Write(m_buf1, 0, size);
                // а теперь - остальное
                bytestocopy = (number1 - cnt1 - 1) * size;
                while (bytestocopy > 0)
                {
                    int nbytes = buff.Length;
                    if (bytestocopy < nbytes)
                    {
                        nbytes = (int)bytestocopy;
                    }
                    fs1.Read(buff, 0, nbytes);
                    this.fs.Write(buff, 0, nbytes);
                    bytestocopy -= nbytes;
                }
            }
            else if (cnt2 < number2)
            { // Поскольку в тот же массив, то надо переписать только прочитанный, а остатки массива уже на своем месте
              //this.cell.SetOffset(pointer_out);
              //this.cell.fs.Write(m_buf2, 0, size);
            }
            this.fs.Flush();
            // Закрываем временный файл
            tmp_fs.Flush();
            tmp_fs.Dispose();
            // Убираем временный файл
            System.IO.File.Delete(tmp_fname); // не убираем, а то он помещается в мусорную корзину, а так - будет переиспользоваться
        }