public static FullRouteIPInfoEntry SearchWithoutHitCache(uint ip32)
        {
            try
            {
                checkUpdate();
            }
            catch
            {
            }


            try
            {
                FullRouteIPInfoCache current_cache = cache;

                if (current_cache != null)
                {
                    foreach (FullRouteIPInfoEntry e in current_cache.EntryList)
                    {
                        if (ip32 >= e.From && ip32 <= e.To)
                        {
                            return(e);
                        }
                    }
                }
            }
            catch
            {
            }

            return(null);
        }
        static void checkUpdate()
        {
            lock (lockObj)
            {
                if (cache != null && (cache.TimeStamp + LifeTime) >= DateTime.Now)
                {
                    return;
                }

                using (cache_file_global_lock.Lock())
                {
                    if (cache == null)
                    {
                        try
                        {
                            cache = FullRouteIPInfoCache.LoadFromFile(CacheFileName);
                        }
                        catch
                        {
                        }
                    }

                    if (cache != null && (cache.TimeStamp + LifeTime) >= DateTime.Now)
                    {
                        return;
                    }

                    try
                    {
                        if (nextDownloadRetry == 0 || (nextDownloadRetry <= Time.Tick64))
                        {
                            FullRouteIPInfoCache c2 = FullRouteIPInfoCache.CreateFromDownload(Url);
                            c2.SaveToFile(CacheFileName);
                            cache = c2;
                        }
                    }
                    catch
                    {
                        nextDownloadRetry = Time.Tick64 + DownloadRetryMSecs;
                    }
                }
            }
        }
        public static FullRouteIPInfoCache LoadFromBuf(Buf b)
        {
            b.Seek(b.Size - 20, SeekOrigin.Begin);
            byte[] hash = b.Read(20);
            b.SeekToBegin();
            byte[] hash2 = Secure.HashSHA1(Util.CopyByte(b.ByteData, 0, (int)b.Size - 20));

            if (Util.CompareByte(hash, hash2) == false)
            {
                throw new ApplicationException("Invalid Hash");
            }

            FullRouteIPInfoCache ret = new FullRouteIPInfoCache();

            ret.TimeStamp = new DateTime((long)b.ReadInt64());
            int num = (int)b.ReadInt();

            int i;

            for (i = 0; i < num; i++)
            {
                FullRouteIPInfoEntry e = new FullRouteIPInfoEntry();
                e.From        = b.ReadInt();
                e.To          = b.ReadInt();
                e.Registry    = b.ReadStr();
                e.Assigned    = b.ReadInt();
                e.Country2    = b.ReadStr();
                e.Country3    = b.ReadStr();
                e.CountryFull = DeleteSemi(b.ReadStr());
                ret.EntryList.Add(e);
            }

            ret.EntryList.Sort();

            ret.build_country_code_to_name_db();

            return(ret);
        }
        public static FullRouteIPInfoCache CreateFromDownload(string url)
        {
            FullRouteIPInfoCache ret = new FullRouteIPInfoCache();

            ret.TimeStamp = DateTime.Now;

            // Download CSV
            WebRequest  req = HttpWebRequest.Create(url);
            WebResponse res = req.GetResponse();

            try
            {
                Stream stream = res.GetResponseStream();
                try
                {
                    byte[] rawData = Util.ReadAllFromStream(stream);
                    byte[] data    = GZipUtil.Decompress(rawData);

                    Csv csv = new Csv(new Buf(data));
                    foreach (CsvEntry ce in csv.Items)
                    {
                        if (ce.Count >= 7)
                        {
                            FullRouteIPInfoEntry e = new FullRouteIPInfoEntry();

                            e.From = Str.StrToUInt(ce[2]);
                            e.To   = Str.StrToUInt(ce[3]);
                            //e.Registry = ce[2];
                            //e.Assigned = Str.StrToUInt(ce[3]);
                            e.Country2 = ce[5];
                            //e.Country3 = ce[5];
                            e.CountryFull = DeleteSemi(ce[6]);

                            if (e.From != 0 && e.To != 0)
                            {
                                ret.EntryList.Add(e);
                            }
                        }
                    }

                    ret.EntryList.Sort();

                    if (ret.EntryList.Count <= 70000)
                    {
                        throw new ApplicationException("ret.EntryList.Count <= 70000");
                    }
                }
                finally
                {
                    stream.Close();
                }
            }
            finally
            {
                res.Close();
            }

            ret.build_country_code_to_name_db();

            return(ret);
        }
        public static FullRouteIPInfoEntry SearchFast(uint ip32)
        {
            try
            {
                checkUpdate();
            }
            catch
            {
            }
            try
            {
                FullRouteIPInfoCache c = cache;

                if (c != null)
                {
                    int low, high, middle, pos;

                    low  = 0;
                    high = c.EntryList.Count - 1;
                    pos  = int.MaxValue;

                    while (low <= high)
                    {
                        middle = (low + high) / 2;

                        uint target_from = c.EntryList[middle].From;

                        if (target_from == ip32)
                        {
                            pos = middle;
                            break;
                        }
                        else if (ip32 < target_from)
                        {
                            high = middle - 1;
                        }
                        else
                        {
                            low = middle + 1;
                        }
                    }

                    if (pos == int.MaxValue)
                    {
                        pos = low;
                    }

                    int pos_start = Math.Max(0, pos - 3);
                    int pos_end   = Math.Min(pos + 3, c.EntryList.Count);

                    int i;
                    for (i = pos_start; i < pos_end; i++)
                    {
                        FullRouteIPInfoEntry e = c.EntryList[i];
                        if (ip32 >= e.From && ip32 <= e.To)
                        {
                            return(e);
                        }
                    }
                }
            }
            catch
            {
            }

            return(null);
        }