public sealed class IpLookupService : IIpLookupService
{
private readonly ManualResetEventSlim _manualResetEventSlim;
private readonly ILogger<IpLookupService> _logger;
private Reader _reader;
private int _threadExecutionCount;
private const int UpdateDelay = 100;
private const int UpdateRetryCount = 5;
public string FileName { get; private set; }
public bool TryGetLocation(IPAddress ipAddress, [NotNullWhen(true)] out Location? location)
{
try
{
_manualResetEventSlim.Wait();
Interlocked.Increment(ref _threadExecutionCount);
location = _reader.Find<Location>(ipAddress);
return location is not null;
}
catch
{
location = null;
return false;
}
finally
{
Interlocked.Decrement(ref _threadExecutionCount);
}
}
public async Task<bool> UpdateDatabase(string fileName)
{
try
{
_manualResetEventSlim.Reset();
int i = 0;
while (i < UpdateRetryCount && _threadExecutionCount != 0)
{
await Task.Delay(UpdateDelay);
i++;
}
if (_threadExecutionCount != 0)
{
return false;
}
var newReader = new Reader(fileName, FileAccessMode.MemoryMapped);
_reader.Dispose();
_reader = newReader;
FileName = fileName;
return true;
}
catch (Exception ex)
{
return false;
}
finally
{
_manualResetEventSlim.Set();
}
}
}
public sealed class IpLookupService : IIpLookupService
{
private readonly ManualResetEventSlim _manualResetEventSlim;
private readonly ILogger<IpLookupService> _logger;
private Reader _reader;
private int _threadExecutionCount;
private const int UpdateDelay = 100;
private const int UpdateRetryCount = 5;
public string FileName { get; private set; }
public bool TryGetLocation(IPAddress ipAddress, [NotNullWhen(true)] out Location? location)
{
try
{
_manualResetEventSlim.Wait();
Interlocked.Increment(ref _threadExecutionCount);
location = _reader.Find<Location>(ipAddress);
return location is not null;
}
catch
{
location = null;
return false;
}
finally
{
Interlocked.Decrement(ref _threadExecutionCount);
}
}
public async Task<bool> UpdateDatabase(string fileName)
{
try
{
_manualResetEventSlim.Reset();
int i = 0;
while (i < UpdateRetryCount && _threadExecutionCount != 0)
{
await Task.Delay(UpdateDelay);
i++;
}
if (_threadExecutionCount != 0)
{
return false;
}
var newReader = new Reader(fileName, FileAccessMode.MemoryMapped);
_reader.Dispose();
_reader = newReader;
FileName = fileName;
return true;
}
catch (Exception ex)
{
return false;
}
finally
{
_manualResetEventSlim.Set();
}
}
}