Beispiel #1
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++;
                }
            }
            // Теперь надо переписать остатки
        }
Beispiel #2
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;
                }
            }
        }