/// <summary> /// Fetch all data from db /// </summary> public void Fetch() { using (var fr = new CustomFileReader()) { if (!fr.Open(FilePath)) { Console.WriteLine("Не получилось открыть запрашиваемый файл"); return; } var headerBuffer = new byte[60]; fr.Read(headerBuffer, 0, 60); var recordCount = BitConverter.ToInt32(headerBuffer, 44); ThreadPool.SetMaxThreads(Environment.ProcessorCount, Environment.ProcessorCount); // Async fetch for ip locations var ipLocWaiter = new ManualResetEventSlim(); var ipLocations = new IpLocation[recordCount]; var offset = 20 * recordCount; var buffer = new byte[offset]; fr.Read(buffer, 0, offset); ThreadPool.QueueUserWorkItem(FetchIpLocations, new ThreadParams<IpLocation> { Buffer = buffer, RecordCount = recordCount, Waiter = ipLocWaiter, Result = ipLocations }); // Async multithreaded fetch for ip locations int locWaiterThreadCount = Environment.ProcessorCount; var locWaiter = new Dictionary<int, LocationArgs>(); for (int i = 0; i < locWaiterThreadCount; i++) { locWaiter[i] = new LocationArgs(recordCount / locWaiterThreadCount); } offset = 96 * recordCount; for (int i = 0; i < locWaiterThreadCount; i++) { buffer = new byte[offset / locWaiterThreadCount]; fr.Read(buffer, 0, offset / locWaiterThreadCount); ThreadPool.QueueUserWorkItem(FetchLocations, new ThreadParams<Location> { Buffer = buffer, RecordCount = recordCount / locWaiterThreadCount, Waiter = locWaiter[i].Waiter, Result = locWaiter[i].Data }); } // Async fetch for indexes offset = 4 * recordCount; buffer = new byte[offset]; fr.Read(buffer, 0, offset); var indexWaiter = new ManualResetEventSlim(); var indexes = new uint[recordCount]; ThreadPool.QueueUserWorkItem(FetchIndexes, new ThreadParams<uint> { Buffer = buffer, RecordCount = recordCount, Waiter = indexWaiter, Result = indexes }); // Fetch for header FetchHeader(headerBuffer, recordCount); ipLocWaiter.Wait(); indexWaiter.Wait(); var locations = new List<Location>(recordCount); for (int i = 0; i < locWaiterThreadCount; i++) { var locationArgs = locWaiter[i]; locationArgs.Waiter.Wait(); locations.InsertRange(locWaiterThreadCount * i, locationArgs.Data); } IpLocations = ipLocations; Locations = locations .OrderBy(l => l.City); Indexes = indexes; } }
/// <summary> /// Fetch ip locations /// </summary> /// <param name="data">Parameters for async thread starting (ThreadParams<IpLocation/>)</param> private static void FetchIpLocations(object data) { var pars = (ThreadParams<IpLocation>)data; var position = 0; var buffer = pars.Buffer; var recordCount = pars.RecordCount; var ipLocations = pars.Result; for (int i = 0; i < recordCount; i++) { var fromIp = CustomBitConvert.ToUInt64(buffer, position); position += 8; var toIp = CustomBitConvert.ToUInt64(buffer, position); position += 8; var index = CustomBitConvert.ToUInt32(buffer, position); position += 4; ipLocations[i] = new IpLocation { FromIp = fromIp, ToIp = toIp, Index = index }; } pars.Waiter.Set(); }