예제 #1
0
        public override void LoadXFlow(IEnumerable <XElement> xflow, Dictionary <string, string> orig_ids)
        {
            IEnumerable <object> flow = xflow.Select(record =>
            {
                string id = record.Attribute(ONames.rdfabout).Value;
                // Корректируем идентификатор
                if (orig_ids.TryGetValue(id, out string idd))
                {
                    id = idd;
                }
                int rec_type     = store.CodeEntity(ONames.fog + record.Name.LocalName);
                int id_ent       = store.CodeEntity(id);
                object[] orecord = new object[] {
                    id_ent,
                    (new object[] { new object[] { store.cod_rdftype, rec_type } }).Concat(
                        record.Elements().Where(el => el.Attribute(ONames.rdfresource) != null)
                        .Select(subel =>
                    {
                        int prop        = store.CodeEntity(subel.Name.NamespaceName + subel.Name.LocalName);
                        string resource = subel.Attribute(ONames.rdfresource).Value;
                        if (orig_ids.TryGetValue(resource, out string res))
                        {
                            if (res != null)
                            {
                                resource = res;
                            }
                        }
                        return(new object[] { prop, store.CodeEntity(resource) });
                    })).ToArray()
                    ,
                    record.Elements().Where(el => el.Attribute(ONames.rdfresource) == null)
                    .Select(subel =>
                    {
                        int prop    = store.CodeEntity(subel.Name.NamespaceName + subel.Name.LocalName);
                        var xlang   = subel.Attribute("{http://www.w3.org/XML/1998/namespace}lang");
                        string lang = xlang == null ? "" : xlang.Value;
                        return(new object[] { prop, subel.Value, lang });
                    })
                    .ToArray()
                };
                return(orecord);
            });

            store.Load(flow);
        }
예제 #2
0
        // Новая реализация загрузки базы данных
        private void FillDb(IEnumerable <FogInfo> fogFlow)
        {
            // Пока каждый раз чистим базу данных
            Store.Clear();
            // Вычисление "важных" кодов
            var codRdftype = Store.CodeEntity("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); // Зафиксирован? 0;


            // Готовим битовый массив для отметки того, что хеш id уже "попадал" в этот бит
            int rang     = 24; // пока предполагается, что число записей (много) меньше 16 млн.
            int mask     = ~((-1) << rang);
            int baVolume = mask + 1;

            System.Collections.BitArray bitArr = new System.Collections.BitArray(baVolume);
            // Хеш-функция будет ограничена rang разрядами, массив и функция нужны только временно
            int Hash(string s) => s.GetHashCode() & mask;

            // Словарь, фиксирующий максимальную дату для заданного идентификатора, первая запись не учитывается
            Dictionary <string, DateTime> lastDefs = new Dictionary <string, DateTime>();

            // Первый проход сканирования фог-файлов. В этом проходе определяется набор повторно определенных записей и
            // формируется словарь lastDefs
            foreach (FogInfo fi in fogFlow)
            {
                switch (fi.Vid)
                {
                // Чтение фога
                case ".fog":
                {
                    fi.Fogx = XElement.Load(fi.Pth);
                    foreach (XElement xElement in fi.Fogx.Elements())
                    {
                        XElement record = ConvertXElement(xElement);
                        // Обработаем "странные" delete и replace
                        if (record.Name == ONames.fogi + "delete")
                        {
                            string idd = record.Attribute(ONames.rdfabout)?.Value ?? record.Attribute("id")?.Value;
                            // Если нет атрибута mT, временная отметка устанавливается максимальной, чтобы "забить" другие отметки
                            string mTvalue = record.Attribute("mT") == null
                                    ? DateTime.MaxValue.ToString(CultureInfo.InvariantCulture)
                                    : record.Attribute("mT")?.Value;

                            CheckAndSet(bitArr, Hash, lastDefs, idd, mTvalue);
                            continue;
                        }

                        if (record.Name == ONames.fogi + "substitute")
                        {
                            continue;                                                // пока не обрабатываем
                        }
                        string id = record.Attribute(ONames.rdfabout)?.Value;
                        CheckAndSet(bitArr, Hash, lastDefs, id, record.Attribute("mT")?.Value);
                    }

                    fi.Fogx = null;
                    break;
                }

                case ".fogp":
                    break;
                }
            }

            // Второй проход сканирования фог-файлов. В этом проходе, для каждого фога формируется поток записей в
            // объектном представлении, потом этот поток добавляется в store
            foreach (FogInfo fi in fogFlow)
            {
                switch (fi.Vid)
                {
                // Чтение фога
                case ".fog":
                case ".fogx":
                {
                    fi.Fogx = XElement.Load(fi.Pth);
                    IEnumerable <object> flow = fi.Fogx.Elements()
                                                .Select(xrec => ConvertXElement(xrec))
                                                // Обработаем delete и replace. delete доминирует (по времени), но в выходной поток ничего не попадает
                                                // substitute - не обрабатываем
                                                .Where(record => record.Name != ONames.fogi + "delete" &&
                                                       record.Name != ONames.fogi + "substitute")
                                                // Отфильтруем записи с малыми временами. т.е. если идентификатор есть в словаре, но он меньше.
                                                // Если он больше, то не фильтруем, а словарный вход корректируем
                                                .Where(record =>
                        {
                            var xAbout = record.Attribute(ONames.rdfabout);
                            if (xAbout == null)
                            {
                                return(true);
                            }
                            string id = xAbout.Value;
                            if (!lastDefs.ContainsKey(id))
                            {
                                return(true);
                            }
                            DateTime mT    = DateTime.MinValue;
                            string mTvalue = record.Attribute("mT")?.Value;
                            if (mTvalue != null)
                            {
                                mT = DateTime.Parse(mTvalue);
                            }
                            DateTime last = lastDefs[id];
                            if (mT < last)
                            {
                                return(false);               // пропускаем
                            }
                            if (mT == last)
                            {
                                return(true);                // берем
                            }
                            // if(mT > last) // берем и корректируем last
                            {
                                lastDefs.Remove(id);
                                lastDefs.Add(id, mT);
                                return(true);
                            }
                        })
                                                .Select(record =>
                        {
                            string id        = record.Attribute(ONames.rdfabout).Value;
                            int rec_type     = Store.CodeEntity(ONames.fog + record.Name.LocalName);
                            int id_ent       = Store.CodeEntity(id);
                            object[] orecord = new object[]
                            {
                                id_ent,
                                (new object[] { new object[] { codRdftype, rec_type } }).Concat(
                                    record.Elements().Where(el => el.Attribute(ONames.rdfresource) != null)
                                    .Select(subel =>
                                {
                                    int prop = Store.CodeEntity(
                                        subel.Name.NamespaceName + subel.Name.LocalName);
                                    return(new object[]
                                           { prop, Store.CodeEntity(subel.Attribute(ONames.rdfresource).Value) });
                                })).ToArray(),
                                record.Elements().Where(el => el.Attribute(ONames.rdfresource) == null)
                                .Select(subel =>
                                {
                                    int prop = Store.CodeEntity(subel.Name.NamespaceName + subel.Name.LocalName);
                                    return(new object[] { prop, subel.Value });
                                })
                                .ToArray()
                            };
                            return(orecord);
                        });
                    Store.Load(flow);

                    fi.Fogx = null;
                    break;
                }

                case ".fogp":
                    break;
                }
            }

            Store.Build();
            Store.Flush();
            GC.Collect();
        }
예제 #3
0
        public static void Main20()
        {
            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
            System.Random rnd = new Random();
            //string path = "../../../../data/Databases/";
            string        path      = "C:/Home/data/Databases/";
            int           fnom      = 0;
            Func <Stream> GenStream = () => File.Open(path + (fnom++), FileMode.OpenOrCreate);

            Console.WriteLine("Start TestConsoleApp (Main32)");
            TripleRecordStore store = new TripleRecordStore(GenStream, path, new string[] {
                "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
                , "http://fogid.net/o/name"
                , "http://fogid.net/o/age"
                , "http://fogid.net/o/person"
                , "http://fogid.net/o/photo-doc"
                , "http://fogid.net/o/reflection"
                , "http://fogid.net/o/reflected"
                , "http://fogid.net/o/in-doc"
            });

            int npersons     = 40_000;
            int nphotos      = npersons * 2;
            int nreflections = npersons * 6;

            bool toload = true;
            bool tocode = true;

            if (toload)
            {
                sw.Restart();
                store.Clear();
                var persons = Enumerable.Range(0, npersons).Select(i => npersons - i - 1)
                              .Select(c => new object[] { -c - 1, // Это "прямой" код не требующий кодирования через таблицу
                                                          new object[] { new object[] { 0, 3 } },
                                                          new object[] { new object[] { 1, "p" + c }, new object[] { 2, "" + 33 } } });
                var persons2 = Enumerable.Range(0, npersons).Select(i => npersons - i - 1)
                               .Select(c => store.CodeRecord(new object[] { "" + c,
                                                                            new object[] { new object[] { "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", "http://fogid.net/o/person" } },
                                                                            new object[] { new object[] { "http://fogid.net/o/name", "p" + c }, new object[] { "http://fogid.net/o/age", "" + 33 } } }));
                var persons3 = Enumerable.Range(0, npersons).Select(i => npersons - i - 1)
                               .Select(c => store.CodeRecord(new object[] { "" + c, // Это "прямой" код не требующий кодирования через таблицу
                                                                            new object[] { new object[] { 0, 3 } },
                                                                            new object[] { new object[] { 1, "p" + c }, new object[] { 2, "" + 33 } } }));
                var photos = Enumerable.Range(0, nphotos).Select(i => nphotos - i - 1)
                             .Select(c => new object[] { -(c + npersons) - 1, // Это "прямой" код не требующий кодирования через таблицу
                                                         new object[] { new object[] { 0, 4 } },
                                                         new object[] { new object[] { 1, "f" + c } } });
                var photos2 = Enumerable.Range(0, nphotos).Select(i => nphotos - i - 1)
                              .Select(c => store.CodeRecord(new object[] { "" + (c + npersons),
                                                                           new object[] { new object[] { "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", "http://fogid.net/o/photo-doc" } },
                                                                           new object[] { new object[] { "http://fogid.net/o/name", "f" + c } } }));
                var photos3 = Enumerable.Range(0, nphotos).Select(i => nphotos - i - 1)
                              .Select(c => store.CodeRecord(new object[] { "" + (c + npersons), // Это "прямой" код не требующий кодирования через таблицу
                                                                           new object[] { new object[] { 0, 4 } },
                                                                           new object[] { new object[] { 1, "f" + c } } }));
                var reflections = Enumerable.Range(0, nreflections).Select(i => nreflections - i - 1)
                                  .Select(c => new object[] { -(c + 3 * npersons) - 1, // Это "прямой" код не требующий кодирования через таблицу
                                                              new object[] { new object[] { 0, 5 },
                                                                             new object[] { 6, -1 - (rnd.Next(npersons)) },
                                                                             new object[] { 7, -1 - (rnd.Next(nphotos) + npersons) } },
                                                              new object[] { } });
                var reflections2 = Enumerable.Range(0, nreflections).Select(i => nreflections - i - 1)
                                   .Select(c => store.CodeRecord(new object[] { "" + (c + 3 * npersons),
                                                                                new object[] { new object[] { "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", "http://fogid.net/o/reflection" },
                                                                                               new object[] { "http://fogid.net/o/reflected", "" + rnd.Next(npersons) },
                                                                                               new object[] { "http://fogid.net/o/in-doc", "" + (rnd.Next(nphotos) + npersons) } },
                                                                                new object[] { } }));
                var reflections3 = Enumerable.Range(0, nreflections).Select(i => nreflections - i - 1)
                                   .Select(c => store.CodeRecord(new object[] { "" + (c + 3 * npersons), // Это "прямой" код не требующий кодирования через таблицу
                                                                                new object[] { new object[] { 0, 5 },
                                                                                               new object[] { 6, "" + rnd.Next(npersons) },
                                                                                               new object[] { 7, "" + (rnd.Next(nphotos) + npersons) } },
                                                                                new object[] { } }));
                if (tocode)
                {
                    store.Load(persons2.Concat(photos2).Concat(reflections2));
                    //store.Load(persons3.Concat(photos3).Concat(reflections3));
                }
                else
                {
                    store.Load(persons.Concat(photos).Concat(reflections));
                }
                store.Build();
                sw.Stop();
                Console.WriteLine($"Load ok. duration={sw.ElapsedMilliseconds}");
            }
            //else
            {
                sw.Restart();
                store.Refresh();
                sw.Stop();
                Console.WriteLine($"Refresh for Phototeka {npersons} persons. Duration={sw.ElapsedMilliseconds}");
            }


            // ПОлукодирование иногда кодирование, иногда нет
            Func <int, int> HCode = nom => tocode?store.Code("" + nom) : -1 - nom;

            // Проверка
            int code = HCode(npersons * 2 / 3);

            var query1 = store.GetRecord(code);

            Console.WriteLine(store.ToTT(query1));

            // Скорость выполнения запросов
            int nprobe = 10000;

            sw.Restart();
            for (int i = 0; i < nprobe; i++)
            {
                int c  = HCode(rnd.Next(npersons));
                var ob = store.GetRecord(c);
            }
            sw.Stop();
            Console.WriteLine($"{nprobe} GetRecord() ok. duration={sw.ElapsedMilliseconds}");

            // Надо найти все фотографии, в которых отражается персона с выбранным (случайно) кодом.
            sw.Restart();
            int total = 0;

            nprobe = 1000;
            for (int i = 0; i < nprobe; i++)
            {
                int c      = HCode(rnd.Next(npersons));
                var query2 = store.GetRefers(c).Cast <object[]>().ToArray();
                var q3     = query2
                             .Select(ob => ((object[])ob[1]).Cast <object[]>()
                                     .First(dupl => (int)dupl[0] == 7));
                var q4 = q3
                         .Select(bb => store.GetRecord((int)bb[1])).ToArray();
                total += query2.Count();
            }
            sw.Stop();
            Console.WriteLine($"{nprobe} persons for photos ok. duration={sw.ElapsedMilliseconds} total={total}");

            //var likes = store.Like("p" + 666);
            //foreach (var like in likes)
            //{
            //    Console.WriteLine($"like {store.ToTT(like)}");
            //}

            sw.Restart();
            total = 0;
            for (int i = 0; i < 1000; i++)
            {
                string id = "p" + rnd.Next(npersons / 10 + 1, npersons);
                total += store.Like(id).Count();
            }
            sw.Stop();
            Console.WriteLine($"{nprobe} likes for persons ok. duration={sw.ElapsedMilliseconds} total={total}");
        }