Ejemplo n.º 1
0
        /// <summary>
        /// Формирует значение кеша местоположения
        /// </summary>
        /// <param name="i">Идентификатор местоположения</param>
        /// <param name="buffer">Буфер</param>
        /// <returns></returns>
        private unsafe byte[] GetLocationJson(int i, JsonSerializer.Buffer buffer)
        {
            buffer.Reset();
            LocationRecord rec = _db.GetLocationRecordById(i);

            JsonSerializer.WriteLocationRecord(buffer, rec);
            return(buffer.GetByteArray());
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Собирает кеш городов
        /// </summary>
        private unsafe void AcquireCityCache()
        {
            // Сначала проходим по индексу городов и собираем интервалы, соответствующие одному городу
            List <IndexCacheItem> indexCache = new List <IndexCacheItem>(_db.RecordCount / 10);

            byte[] baCurrentCity = new byte[24];
            fixed(byte *bpCurrentCity = &baCurrentCity[0])
            {
                sbyte *currentCity = (sbyte *)bpCurrentCity;
                int    startIndex  = 0;

                for (int i = 0; i < _db.RecordCount; i++)
                {
                    LocationRecord rec = _db.GetLocationRecordByNameIndex(i);
                    if (i == 0 || Utils.CompareSbpCity(currentCity, rec.city, 24) != 0)
                    {
                        if (i > 0)
                        {
                            indexCache.Add(new IndexCacheItem(startIndex, i - 1));
                            startIndex = i;
                        }
                        Utils.CopyMemory(currentCity, rec.city, 24);
                    }
                }

                indexCache.Add(new IndexCacheItem(startIndex, _db.RecordCount - 1));
            }

            // Затем в параллельном режиме формируем записи в кеше для городов
            int indexCacheLength = indexCache.Count;
            int currentItemIndex = -1;

            Task[] tasks = new Task[_cacheLoadOperationsDop];
            for (int i = 0; i < _cacheLoadOperationsDop; i++)
            {
                Task task = Task.Run(() =>
                {
                    while (true)
                    {
                        int cacheIndex = Interlocked.Increment(ref currentItemIndex);
                        if (cacheIndex >= indexCacheLength)
                        {
                            return;
                        }

                        IndexCacheItem cacheItem = indexCache[cacheIndex];
                        LocationRecord rec       = _db.GetLocationRecordByNameIndex(cacheItem.StartIndex);
                        AddCityCacheEntry(new string(rec.city), cacheItem.StartIndex, cacheItem.EndIndex);
                    }
                });
                tasks[i] = task;
            }

            Task.WaitAll(tasks);
        }
Ejemplo n.º 3
0
 internal static unsafe void WriteLocationRecord(Buffer buffer, LocationRecord rec)
 {
     buffer.Write(LocationCountryProperty);
     buffer.Write(_utf8.GetBytes(new string(rec.country)));
     buffer.Write(LocationRegionProperty);
     buffer.Write(_utf8.GetBytes(new string(rec.region)));
     buffer.Write(LocationPostalProperty);
     buffer.Write(_utf8.GetBytes(new string(rec.postal)));
     buffer.Write(LocationCityProperty);
     buffer.Write(_utf8.GetBytes(new string(rec.city)));
     buffer.Write(LocationOrganizationProperty);
     buffer.Write(_utf8.GetBytes(new string(rec.organization)));
     buffer.Write(LocationLatitudeProperty);
     buffer.Write(_utf8.GetBytes(rec.latitude.ToString(CultureInfo.InvariantCulture)));
     buffer.Write(LocationLongitudeProperty);
     buffer.Write(_utf8.GetBytes(rec.longitude.ToString(CultureInfo.InvariantCulture)));
     buffer.Write(_objectEnd);
 }
Ejemplo n.º 4
0
        /// <summary>
        /// Осуществляет двоичный поиск города по сортированному индексу.
        /// Возвращает идентификатор первого найденного соответствия.
        /// </summary>
        /// <param name="city">Название города</param>
        /// <param name="rangeStart">
        /// Принимает на вход идентификатор первого элемента интервала, в котором нужно осуществлять поиск.
        /// Возвращает идентификатор первого элемента интервала, в котором найден город
        /// </param>
        /// <param name="rangeEnd">
        /// Принимает на вход идентификатор последнего элемента интервала, в котором нужно осуществлять поиск.
        /// Возвращает идентификатор последнего элемента интервала, в котором найден город
        /// </param>
        /// <returns>true, если город найден. Иначе false</returns>
        private unsafe int BinarySearchByCityName(sbyte *city, ref int rangeStart, ref int rangeEnd)
        {
            if (rangeStart > rangeEnd)
            {
                return(-1);
            }

            int  rangeMiddle  = (rangeStart + rangeEnd) / 2;
            bool elementFound = false;

            while (true)
            {
                LocationRecord rec = GetLocationRecordByNameIndex(rangeMiddle);
                int            comparisonResult = Utils.CompareSbpCity(rec.city, city, 24);
                if (comparisonResult == 0)
                {
                    elementFound = true;
                    break;
                }

                if (rangeStart == rangeEnd)
                {
                    break;
                }

                if (comparisonResult == 1)
                {
                    rangeEnd = rangeMiddle - 1;
                }
                else
                {
                    rangeStart = rangeMiddle + 1;
                }

                if (rangeEnd < rangeStart)
                {
                    break;
                }

                rangeMiddle = (rangeStart + rangeEnd) / 2;
            }

            return(elementFound ? rangeMiddle : -1);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Диагностический метод
        /// </summary>
        internal static unsafe void WriteDbFiles(DataHolder holder, int ipTableSize)
        {
            using (StreamWriter sw = new StreamWriter("ip.txt", false, Encoding.UTF8))
            {
                for (int i = 0; i < ipTableSize; i++)
                {
                    IpRecord       rec  = holder.IpTable[i];
                    LocationRecord lrec = holder.GetLocationRecordById((int)rec.location_index);
                    string         str  =
                        Utils.ConvertUintToIp(rec.ip_from).PadRight(20) +
                        Utils.ConvertUintToIp(rec.ip_to).PadRight(20) +
                        new string(lrec.city).PadRight(24);
                    sw.WriteLine(str);
                }
            }

            using (StreamWriter sw = new StreamWriter("location.txt", false, Encoding.UTF8))
            {
                for (int i = 0; i < holder.RecordCount; i++)
                {
                    LocationRecord rec          = holder.GetLocationRecordByNameIndex(i);
                    string         city         = new string(rec.city);
                    string         country      = new string(rec.country);
                    string         region       = new string(rec.region);
                    string         postal       = new string(rec.postal);
                    string         organization = new string(rec.organization);
                    if (city.Length > 23 || country.Length > 7 || region.Length > 11 || postal.Length > 23 || organization.Length > 31)
                    {
                        throw new Exception();
                    }

                    string str = city.PadRight(24) +
                                 country.PadRight(8) +
                                 region.PadRight(12) +
                                 postal.PadRight(12) +
                                 organization.PadRight(32) +
                                 rec.latitude.ToString().PadRight(20) +
                                 rec.longitude.ToString().PadRight(20);
                    sw.WriteLine(str);
                }
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Служебный метод
        /// </summary>
        internal unsafe string[] GetAllCities()
        {
            if (_isCacheAvailable)
            {
                return(new List <string>(_cityCache.Keys).ToArray());
            }
            else
            {
                HashSet <string> set = new HashSet <string>(StringComparer.Ordinal);
                for (int i = 0; i < _db.RecordCount; i++)
                {
                    LocationRecord rec  = _db.GetLocationRecordById(i);
                    string         city = new string(rec.city);
                    if (!set.Contains(city))
                    {
                        set.Add(city);
                    }
                }

                return(set.ToArray());
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Диагностический метод
        /// </summary>
        internal static unsafe void ReadCities(Database db)
        {
            int max = 0;
            Dictionary <string, int> dict = new Dictionary <string, int>();

            for (int i = 0; i < db.RecordCount; i++)
            {
                LocationRecord rec     = db.GetLocationRecordById(i);
                string         strCity = new string(rec.city);
                int            count;
                if (!dict.TryGetValue(strCity, out count))
                {
                    dict.Add(strCity, 1);
                    max = Math.Max(1, max);
                }
                else
                {
                    dict[strCity] = count + 1;
                    max           = Math.Max(count + 1, max);
                }
            }
        }