Beispiel #1
0
        public DataNode(string path)
        {
            this.path = path;
            //this.tp_element = tp_element;
            string     dbpath     = path + "DataNodeStorage.bin";
            bool       fob_exists = File.Exists(dbpath);
            FileStream fs         = new FileStream(dbpath, FileMode.OpenOrCreate, FileAccess.ReadWrite);

            fob = new FileOfBlocks(fs);
            Stream first_stream = fob.GetFirstAsStream();

            if (!fob_exists)
            {
                PagedStream.InitPagedStreamHead(first_stream, 8L, 0, PagedStream.HEAD_SIZE);
                fob.Flush();
            }
            main_stream = new PagedStream(fob, fob.GetFirstAsStream(), 8L);

            //long sz = PagedStream.HEAD_SIZE;

            // Если main_stream нулевой длины, надо инициировать конфигурацию стримов
            bool toinit = main_stream.Length == 0;

            if (toinit)
            {
                // инициируем 2 головы для потоков
                PagedStream.InitPagedStreamHead(main_stream, 0L, 0L, -1L);
                PagedStream.InitPagedStreamHead(main_stream, PagedStream.HEAD_SIZE, 0L, -1L);
                //PagedStream.InitPagedStreamHead(main_stream, 2 * sz, 0L, -1L);

                main_stream.Flush(); fob.Flush();
            }
            // создадим 2 потока
            Stream stream_common_params = new FileStream(path + "common.pac", FileMode.OpenOrCreate, FileAccess.ReadWrite); //new PagedStream(fob, main_stream, 0L);
            Stream stream_SP_list       = new FileStream(path + "splist.pac", FileMode.OpenOrCreate, FileAccess.ReadWrite); //new PagedStream(fob, main_stream, 1 * PagedStream.HEAD_SIZE);

            //PagedStream stream_offsets = new PagedStream(fob, main_stream, 2 * sz); // пока не знаю для чего...

            // Создадим ячейки
            tp_common = new PTypeRecord(
                new NamedType("configuration", tp_configuration));
            cell_common = new PaCell(tp_common, stream_common_params, false);
            tp_list     = new PTypeSequence(KVSequencePortion.tp_pobj);
            cell_list   = new PaCell(tp_list, stream_SP_list, false);

            // Инициализируем
            if (toinit)
            {
                cell_common.Fill(new object[] { new object[0] });
                cell_list.Fill(new object[0]);
            }
            common_data = cell_common.Root.Get();
            foreach (object[] p in cell_list.Root.ElementValues())
            {
                KVSequencePortion kvsp = new KVSequencePortion(this, p);
                sportion_list.Add(kvsp);
            }
        }
Beispiel #2
0
        //static string path = "Databases/";
        public static void Main4()
        {
            Random rnd = new Random();

            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
            Console.WriteLine("Start demo of table and Universal Index with PagedStorage");
            // Тип основной таблицы
            PType tp_person = new PTypeRecord(
                new NamedType("id", new PType(PTypeEnumeration.integer)),
                new NamedType("name", new PType(PTypeEnumeration.sstring)),
                new NamedType("age", new PType(PTypeEnumeration.real)));

            // ======================== Теперь нам понадобится страничное хранилище =========================
            // файл - носитель хранилища
            string filepath   = dbpath + "storage.bin";
            bool   fob_exists = File.Exists(filepath); // этот признак используется при разных процессах инициализации
            // Открываем иили создаем файл-носитель хранилища
            FileStream fs = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
            // Создаем собственно блочное (страничное) хранилище
            FileOfBlocks fob = new FileOfBlocks(fs);
            // Далее идет корявый способ создания трех потоков (Stream), нужных для базы данных
            Stream first_stream = fob.GetFirstAsStream();

            if (!fob_exists)
            {
                PagedStream.InitPagedStreamHead(first_stream, 8L, 0, PagedStream.HEAD_SIZE);
                fob.Flush();
            }
            PagedStream main_stream = new PagedStream(fob, fob.GetFirstAsStream(), 8L);
            long        sz          = PagedStream.HEAD_SIZE;

            // Если main_stream нулевой длины, надо инициировать конфигурацию стримов
            if (main_stream.Length == 0)
            {
                // инициируем 3 головы для потоков
                PagedStream.InitPagedStreamHead(main_stream, 0L, 0L, -1L);
                PagedStream.InitPagedStreamHead(main_stream, sz, 0L, -1L);
                PagedStream.InitPagedStreamHead(main_stream, 2 * sz, 0L, -1L);
                main_stream.Flush(); fob.Flush();
            }
            // создадим 3 потока
            PagedStream stream_person = new PagedStream(fob, main_stream, 0L);
            PagedStream stream_index  = new PagedStream(fob, main_stream, 1 * sz);
            PagedStream stream_scale  = new PagedStream(fob, main_stream, 2 * sz);
            // =========================== OK ==========================

            // База данных такая же, как и в программе 3, только вместо файлов используются потоки
            TableView               tab_person = new TableView(stream_person, tp_person);
            Func <object, int>      person_code_keyproducer = v => (int)((object[])((object[])v)[1])[0];
            IndexKeyImmutable <int> ind_arr_person          = new IndexKeyImmutable <int>(stream_index)
            {
                Table       = tab_person,
                KeyProducer = person_code_keyproducer,
                Scale       = null
            };

            ind_arr_person.Scale = new ScaleCell(stream_scale)
            {
                IndexCell = ind_arr_person.IndexCell
            };
            IndexDynamic <int, IndexKeyImmutable <int> > index_person = new IndexDynamic <int, IndexKeyImmutable <int> >(true)
            {
                Table       = tab_person,
                IndexArray  = ind_arr_person,
                KeyProducer = person_code_keyproducer
            };

            tab_person.RegisterIndex(index_person);

            fob.DeactivateCache();

            int  nelements = 1000000;
            bool toload    = true; // Загружать или нет новую базу данных

            if (toload)
            {
                sw.Restart();
                // Очистим ячейки последовательности и индекса
                tab_person.Clear();

                IEnumerable <object> flow = Enumerable.Range(0, nelements)
                                            .Select(i =>
                {
                    int id      = nelements - i;
                    string name = "=" + id.ToString() + "=";
                    double age  = rnd.NextDouble() * 100.0;
                    return(new object[] { id, name, age });
                });
                tab_person.Fill(flow);

                // Теперь надо отсортировать индексный массив по ключу
                tab_person.BuildIndexes();
                sw.Stop();
                Console.WriteLine("Load ok. duration for {0} elements: {1} ms", nelements, sw.ElapsedMilliseconds);
            }

            sw.Restart();
            // Загрузка кеша ускоряет обработку
            fob.LoadCache();
            sw.Stop();
            Console.WriteLine("Cache load duration={0}", sw.ElapsedMilliseconds);

            // Проверим работу
            int search_key = nelements * 2 / 3;
            var ob         = index_person.GetAllByKey(search_key)
                             .Select(ent => ((object[])ent.Get())[1])
                             .FirstOrDefault();

            if (ob == null)
            {
                throw new Exception("Didn't find person " + search_key);
            }
            Console.WriteLine("Person {0} has name {1}", search_key, ((object[])ob)[1]);

            // Засечем скорость выборок
            int nte = 10000;

            sw.Restart();
            for (int i = 0; i < nte; i++)
            {
                search_key = rnd.Next(nelements) + 1;
                ob         = index_person.GetAllByKey(search_key)
                             .Select(ent => ((object[])ent.Get())[1])
                             .FirstOrDefault();
                if (ob == null)
                {
                    throw new Exception("Didn't find person " + search_key);
                }
                string nam = (string)((object[])ob)[1];
            }
            sw.Stop();
            Console.WriteLine("Duration for {2} search in {0} elements: {1} ms", nelements, sw.ElapsedMilliseconds, nte);
        }
Beispiel #3
0
        //static string path = "Databases/";
        public static void Main5()
        {
            Random rnd = new Random();

            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
            Console.WriteLine("Start demo of table and Universal Index and PagedFileStore");
            // Тип основной таблицы
            PType tp_person = new PTypeRecord(
                new NamedType("id", new PType(PTypeEnumeration.integer)),
                new NamedType("name", new PType(PTypeEnumeration.sstring)),
                new NamedType("age", new PType(PTypeEnumeration.real)));

            // ======================== Теперь нам понадобится страничное хранилище =========================
            // файл - носитель хранилища
            string       filepath     = dbpath + "storage3seq.bin";
            bool         fob_exists   = File.Exists(filepath);
            FileStream   fs           = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
            FileOfBlocks fob          = new FileOfBlocks(fs);
            Stream       first_stream = fob.GetFirstAsStream();

            if (!fob_exists)
            {
                PagedStream.InitPagedStreamHead(first_stream, 8L, 0, PagedStream.HEAD_SIZE);
                fob.Flush();
            }
            PagedStream main_stream = new PagedStream(fob, fob.GetFirstAsStream(), 8L);

            long sz = PagedStream.HEAD_SIZE;

            // === В main_stream первым объектом поместим тествый поток
            // Если main_stream нулевой длины, надо инициировать конфигурацию стримов
            if (main_stream.Length == 0)
            {
                // инициируем 3 головы для потоков
                PagedStream.InitPagedStreamHead(main_stream, 0L, 0L, -1L);
                PagedStream.InitPagedStreamHead(main_stream, sz, 0L, -1L);
                PagedStream.InitPagedStreamHead(main_stream, 2 * sz, 0L, -1L);
                main_stream.Flush(); fob.Flush();
            }
            // создадим 3 потока
            PagedStream stream_person  = new PagedStream(fob, main_stream, 0L);
            PagedStream stream_keys    = new PagedStream(fob, main_stream, 1 * sz);
            PagedStream stream_offsets = new PagedStream(fob, main_stream, 2 * sz);



            // =========================== OK ==========================

            // Создадим базу данных, состоящую из последовательности, и двух индексных массивов: массива ключей и массива офсетов
            PaCell             person_seq = new PaCell(new PTypeSequence(tp_person), stream_person, false);
            Func <object, int> person_code_keyproducer = v => (int)((object[])v)[0];
            PaCell             pers_ind_key_arr        = new PaCell(new PTypeSequence(new PType(PTypeEnumeration.integer)), stream_keys, false);
            PaCell             pers_ind_off_arr        = new PaCell(new PTypeSequence(new PType(PTypeEnumeration.longinteger)), stream_offsets, false);

            int  nelements = 1000000;
            bool toload    = true; // Загружать или нет новую базу данных

            if (toload)
            {
                sw.Restart();
                // При загрузке кеш будет мешаться, его полезно деактивировать
                fob.DeactivateCache();
                // Очистим ячейку последовательности
                person_seq.Clear();
                person_seq.Fill(new object[0]);

                // Для загрузки нам понадобятся: поток данных, массив ключей и массив офсетов (это всего лишь демонстрация!)
                IEnumerable <object> flow = Enumerable.Range(0, nelements)
                                            .Select(i =>
                {
                    int id      = nelements - i;
                    string name = "=" + id.ToString() + "=";
                    double age  = rnd.NextDouble() * 100.0;
                    return(new object[] { id, name, age });
                });
                int[]  key_arr = new int[nelements];
                long[] off_arr = new long[nelements];

                int ind = 0;
                foreach (object[] orec in flow)
                {
                    long off = person_seq.Root.AppendElement(orec);
                    int  key = (int)(((object[])orec)[0]);
                    key_arr[ind] = key;
                    off_arr[ind] = off;
                    ind++;
                }
                person_seq.Flush();
                Console.WriteLine("Sequence OK.");
                // Параллельная сортировка по значению ключа
                Array.Sort(key_arr, off_arr);

                pers_ind_key_arr.Clear();
                pers_ind_key_arr.Fill(new object[0]);
                for (int i = 0; i < nelements; i++)
                {
                    pers_ind_key_arr.Root.AppendElement(key_arr[i]);
                }
                pers_ind_key_arr.Flush();

                pers_ind_off_arr.Clear();
                pers_ind_off_arr.Fill(new object[0]);
                for (int i = 0; i < nelements; i++)
                {
                    pers_ind_off_arr.Root.AppendElement(off_arr[i]);
                }
                pers_ind_off_arr.Flush();

                fob.Flush();

                sw.Stop();
                Console.WriteLine("Load ok. duration for {0} elements: {1} ms", nelements, sw.ElapsedMilliseconds);
            }

            sw.Restart();
            fob.LoadCache();
            sw.Stop();
            Console.WriteLine("Cache load duration={0}", sw.ElapsedMilliseconds);

            sw.Restart();
            int nkeys = (int)pers_ind_key_arr.Root.Count();

            int[] keys = new int[nkeys];
            int   ii   = 0;

            foreach (int k in pers_ind_key_arr.Root.ElementValues())
            {
                keys[ii] = k; ii++;
            }

            sw.Stop();
            Console.WriteLine("Index preload duration={0}", sw.ElapsedMilliseconds);

            sw.Restart();

            PaEntry entry = person_seq.Root.Element(0);
            int     nte   = 10000;

            for (int i = 0; i < nte; i++)
            {
                int  key    = rnd.Next(nkeys);
                int  ifirst = GetFirstIndexOf(0, nelements, keys, key);
                long offset = (long)pers_ind_off_arr.Root.Element(ifirst).Get();
                entry.offset = offset;
                object[] rec = (object[])entry.Get();
                //Console.WriteLine($"{rec[0]} {rec[1]} {rec[2]}");
            }
            sw.Stop();
            Console.WriteLine("Duration={0} for {1}", sw.ElapsedMilliseconds, nte);

            //// Проверим работу
            //int search_key = nelements * 2 / 3;
            //var ob = index_person.GetAllByKey(search_key)
            //    .Select(ent => ((object[])ent.Get())[1])
            //    .FirstOrDefault();
            //if (ob == null) throw new Exception("Didn't find person " + search_key);
            //Console.WriteLine("Person {0} has name {1}", search_key, ((object[])ob)[1]);

            //// Засечем скорость выборок
            //sw.Restart();
            //for (int i = 0; i < 1000; i++)
            //{
            //    search_key = rnd.Next(nelements);
            //    ob = index_person.GetAllByKey(search_key)
            //        .Select(ent => ((object[])ent.Get())[1])
            //        .FirstOrDefault();
            //    if (ob == null) throw new Exception("Didn't find person " + search_key);
            //    string nam = (string)((object[])ob)[1];
            //}
            //sw.Stop();
            //Console.WriteLine("Duration for 1000 search in {0} elements: {1} ms", nelements, sw.ElapsedMilliseconds);
        }
Beispiel #4
0
        //static string path = "Databases/";
        public static void Main8_()
        {
            Random rnd = new Random(); //new Random(777);

            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
            Console.WriteLine("Start demo key-value storage");
            // Тип основной таблицы
            PType tp_person = new PTypeRecord(
                new NamedType("id", new PType(PTypeEnumeration.integer)),
                new NamedType("name", new PType(PTypeEnumeration.sstring)),
                new NamedType("age", new PType(PTypeEnumeration.real)));
            PType tp_index = new PTypeSequence(new PTypeRecord(
                                                   new NamedType("key", new PType(PTypeEnumeration.integer)),
                                                   new NamedType("offset", new PType(PTypeEnumeration.longinteger))
                                                   ));

            // ======================== Теперь нам понадобится страничное хранилище =========================
            // файл - носитель хранилища
            string       filepath     = dbpath + "storage8.bin";
            bool         fob_exists   = File.Exists(filepath);
            FileStream   fs           = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
            FileOfBlocks fob          = new FileOfBlocks(fs);
            Stream       first_stream = fob.GetFirstAsStream();

            if (!fob_exists)
            {
                PagedStream.InitPagedStreamHead(first_stream, 8L, 0, PagedStream.HEAD_SIZE);
                fob.Flush();
            }
            PagedStream main_stream = new PagedStream(fob, fob.GetFirstAsStream(), 8L);

            long sz = PagedStream.HEAD_SIZE;

            // === В main_stream первым объектом поместим тествый поток
            // Если main_stream нулевой длины, надо инициировать конфигурацию стримов
            if (main_stream.Length == 0)
            {
                // инициируем 3 головы для потоков
                PagedStream.InitPagedStreamHead(main_stream, 0L, 0L, -1L);
                PagedStream.InitPagedStreamHead(main_stream, sz, 0L, -1L);
                PagedStream.InitPagedStreamHead(main_stream, 2 * sz, 0L, -1L);
                //PagedStream.InitPagedStreamHead(main_stream, 3 * sz, 0L, -1L);
                main_stream.Flush(); fob.Flush();
            }
            // создадим 3 потока
            PagedStream stream_person  = new PagedStream(fob, main_stream, 0L);
            PagedStream stream_keys    = new PagedStream(fob, main_stream, 1 * sz);
            PagedStream stream_offsets = new PagedStream(fob, main_stream, 2 * sz);
            //PagedStream stream_index = new PagedStream(fob, main_stream, 3 * sz);



            // =========================== OK ==========================

            // Создадим базу данных, состоящую из последовательности, и двух индексных массивов: массива ключей и массива офсетов
            PaCell             person_seq = new PaCell(new PTypeSequence(tp_person), stream_person, false);
            Func <object, int> person_code_keyproducer = v => (int)((object[])v)[0];
            PaCell             pers_ind_key_arr        = new PaCell(new PTypeSequence(new PType(PTypeEnumeration.integer)), stream_keys, false);
            PaCell             pers_ind_off_arr        = new PaCell(new PTypeSequence(new PType(PTypeEnumeration.longinteger)), stream_offsets, false);

            int  nelements = 10000000;
            bool toload    = false; // Загружать или нет новую базу данных

            if (toload)
            {
                FileStream tmp_file  = new FileStream(dbpath + "tmp.pac", FileMode.CreateNew, FileAccess.ReadWrite);
                PaCell     key_index = new PaCell(tp_index, tmp_file, false);
                sw.Restart();
                // При загрузке кеш будет мешаться, его полезно деактивировать
                fob.DeactivateCache();
                // Очистим ячейку последовательности
                person_seq.Clear();
                person_seq.Fill(new object[0]);

                // Для загрузки нам понадобятся: поток данных, массив ключей и массив офсетов (это всего лишь демонстрация!)
                IEnumerable <object> flow = Enumerable.Range(0, nelements)
                                            .Select(iv =>
                {
                    int id      = nelements - iv;
                    string name = "=" + id.ToString() + "=";
                    double age  = rnd.NextDouble() * 100.0;
                    return(new object[] { id, name, age });
                });
                //int[] key_arr = new int[nelements];
                //long[] off_arr = new long[nelements];

                key_index.Clear();
                key_index.Fill(new object[0]);
                //int ind = 0;
                foreach (object[] orec in flow)
                {
                    long off = person_seq.Root.AppendElement(orec);

                    int key = (int)(((object[])orec)[0]);
                    key_index.Root.AppendElement(new object[] { key, off });
                }
                person_seq.Flush();
                key_index.Flush();

                Console.WriteLine("Sequence OK. duration={0}", sw.ElapsedMilliseconds);

                // Сортировка по значению ключа
                key_index.Root.SortByKey <int>(ob => (int)((object[])ob)[0]);

                //TODO: Надо "сжать" индексный файл, убрав из него дубли по ключам

                pers_ind_key_arr.Clear(); pers_ind_key_arr.Fill(new object[0]);
                foreach (object[] ob in key_index.Root.ElementValues())
                {
                    pers_ind_key_arr.Root.AppendElement(ob[0]);
                }
                pers_ind_key_arr.Flush();

                pers_ind_off_arr.Clear(); pers_ind_off_arr.Fill(new object[0]);
                foreach (object[] ob in key_index.Root.ElementValues())
                {
                    pers_ind_off_arr.Root.AppendElement(ob[1]);
                }
                pers_ind_off_arr.Flush();

                fob.Flush();

                sw.Stop();
                Console.WriteLine("Load ok. duration for {0} elements: {1} ms", nelements, sw.ElapsedMilliseconds);
                key_index.Close();
                tmp_file.Dispose();
                File.Delete(dbpath + "tmp.pac");
            }

            sw.Restart();
            fob.ActivateCache();
            fob.LoadCache();
            sw.Stop();
            Console.WriteLine("Cache load duration={0}", sw.ElapsedMilliseconds);

            sw.Restart();
            //int nkeys = (int)pers_ind_key_arr.Root.Count();
            int[] keys = pers_ind_key_arr.Root.ElementValues().Cast <int>().ToArray();
            //long[] offsets = key_index.Root.ElementValues().Cast<object[]>().Select(ob => (long)ob[1]).ToArray();

            sw.Stop();
            Console.WriteLine("Index preload duration={0}", sw.ElapsedMilliseconds);

            Func <int, Diapason> GetDia = GetDiaFunc2(keys);

            PaEntry entry      = person_seq.Root.Element(0);
            int     search_key = nelements * 2 / 3;

            ComputeEntry(pers_ind_off_arr, keys, GetDia, entry, search_key);

            object[] re = (object[])entry.Get();
            Console.WriteLine($"{re[0]} {re[1]} {re[2]}");

            int nte = 100000;

            rnd = new Random();

            sw.Restart();
            for (int i = 0; i < nte; i++)
            {
                int      key    = rnd.Next(keys.Length) + 1;
                Diapason diap   = GetDia(key);
                int      ifirst = Get8FirstIndexOf((int)diap.start, (int)diap.numb, keys, key);
                if (ifirst == -1)
                {
                    entry = PaEntry.Empty;
                    Console.WriteLine($"index not found for ...");
                    continue;
                }
                entry.offset = (long)pers_ind_off_arr.Root.Element(ifirst).Get();
                object[] rec = (object[])entry.Get();
            }
            sw.Stop();
            Console.WriteLine("request test duration={0} for {1}", sw.ElapsedMilliseconds, nte);
        }