diff --git a/binding/csharp/IP2Region.Net/Internal/Abstractions/AbstractCacheStrategy.cs b/binding/csharp/IP2Region.Net/Internal/Abstractions/AbstractCacheStrategy.cs deleted file mode 100644 index 909f75c..0000000 --- a/binding/csharp/IP2Region.Net/Internal/Abstractions/AbstractCacheStrategy.cs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2025 The Ip2Region Authors. All rights reserved. -// Use of this source code is governed by a Apache2.0-style -// license that can be found in the LICENSE file. -// @Author Alan -// @Date 2023/07/25 -// Updated by Argo Zhang at 2025/11/21 - -using System.Buffers; - -namespace IP2Region.Net.Internal.Abstractions; - -internal abstract class AbstractCacheStrategy(string xdbPath) -{ - protected const int HeaderInfoLength = 256; - protected const int VectorIndexSize = 8; - - private const int BufferSize = 64 * 1024; - - public int IoCount { get; private set; } - - protected FileStream XdbFileStream = new(xdbPath, FileMode.Open, FileAccess.Read, FileShare.Read, BufferSize, FileOptions.RandomAccess); - - public void ResetIoCount() - { - IoCount = 0; - } - - public virtual ReadOnlyMemory GetVectorIndex(int offset) => GetData(HeaderInfoLength + offset, VectorIndexSize); - - public virtual ReadOnlyMemory GetData(long offset, int length) - { - byte[] buffer = ArrayPool.Shared.Rent(length); - int totalBytesRead = 0; - try - { - XdbFileStream.Seek(offset, SeekOrigin.Begin); - - int bytesRead; - while (totalBytesRead < length) - { - bytesRead = XdbFileStream.Read(buffer, totalBytesRead, length); - totalBytesRead += bytesRead; - - IoCount++; - } - } - finally - { - ArrayPool.Shared.Return(buffer); - } - - return new ReadOnlyMemory(buffer, 0, totalBytesRead); - } -} diff --git a/binding/csharp/IP2Region.Net/Internal/CacheStrategyFactory.cs b/binding/csharp/IP2Region.Net/Internal/CacheStrategyFactory.cs index 084a3d0..ae9b01d 100644 --- a/binding/csharp/IP2Region.Net/Internal/CacheStrategyFactory.cs +++ b/binding/csharp/IP2Region.Net/Internal/CacheStrategyFactory.cs @@ -5,14 +5,13 @@ // @Date 2023/07/25 // Updated by Argo Zhang at 2025/11/21 -using IP2Region.Net.Internal.Abstractions; using IP2Region.Net.XDB; namespace IP2Region.Net.Internal; -class CacheStrategyFactory(string xdbPath) +static class CacheStrategyFactory { - public AbstractCacheStrategy CreateCacheStrategy(CachePolicy cachePolicy) => cachePolicy switch + public static ICacheStrategy CreateCacheStrategy(CachePolicy cachePolicy, string xdbPath) => cachePolicy switch { CachePolicy.Content => new ContentCacheStrategy(xdbPath), CachePolicy.VectorIndex => new VectorIndexCacheStrategy(xdbPath), diff --git a/binding/csharp/IP2Region.Net/Internal/ContentCacheStrategy.cs b/binding/csharp/IP2Region.Net/Internal/ContentCacheStrategy.cs index 135751d..693518e 100644 --- a/binding/csharp/IP2Region.Net/Internal/ContentCacheStrategy.cs +++ b/binding/csharp/IP2Region.Net/Internal/ContentCacheStrategy.cs @@ -5,20 +5,16 @@ // @Date 2023/07/25 // Updated by Argo Zhang at 2025/11/21 -using IP2Region.Net.Internal.Abstractions; - namespace IP2Region.Net.Internal; -class ContentCacheStrategy : AbstractCacheStrategy +class ContentCacheStrategy : FileCacheStrategy { private readonly ReadOnlyMemory _cacheData; public ContentCacheStrategy(string xdbPath) : base(xdbPath) { _cacheData = base.GetData(0, (int)XdbFileStream.Length); - XdbFileStream.Close(); - XdbFileStream.Dispose(); } - public override ReadOnlyMemory GetData(long offset = 0, int length = 0) => _cacheData.Slice((int)offset, length); + public override ReadOnlyMemory GetData(long offset, int length) => _cacheData.Slice((int)offset, length); } diff --git a/binding/csharp/IP2Region.Net/Internal/FileCacheStrategy.cs b/binding/csharp/IP2Region.Net/Internal/FileCacheStrategy.cs index 2a69364..224976a 100644 --- a/binding/csharp/IP2Region.Net/Internal/FileCacheStrategy.cs +++ b/binding/csharp/IP2Region.Net/Internal/FileCacheStrategy.cs @@ -5,11 +5,59 @@ // @Date 2023/07/25 // Updated by Argo Zhang at 2025/11/21 -using IP2Region.Net.Internal.Abstractions; +using System.Buffers; namespace IP2Region.Net.Internal; -class FileCacheStrategy(string xdbPath) : AbstractCacheStrategy(xdbPath) +class FileCacheStrategy(string xdbPath) : ICacheStrategy { + protected const int HeaderInfoLength = 256; + protected const int VectorIndexSize = 8; + protected const int BufferSize = 64 * 1024; + + protected FileStream XdbFileStream = new(xdbPath, FileMode.Open, FileAccess.Read, FileShare.Read, BufferSize, FileOptions.RandomAccess); + + public int IoCount { get; set; } + + public void ResetIoCount() + { + IoCount = 0; + } + + public virtual ReadOnlyMemory GetVectorIndex(int offset) => GetData(HeaderInfoLength + offset, VectorIndexSize); + + public virtual ReadOnlyMemory GetData(long offset, int length) + { + var buffer = ArrayPool.Shared.Rent(length); + try + { + int totalBytesRead = 0; + XdbFileStream.Seek(offset, SeekOrigin.Begin); + + int bytesRead; + while (totalBytesRead < length) + { + bytesRead = XdbFileStream.Read(buffer, totalBytesRead, length - totalBytesRead); + if (bytesRead == 0) + { + break; + } + + totalBytesRead += bytesRead; + IoCount++; + } + + var ret = new byte[totalBytesRead]; + if (totalBytesRead > 0) + { + Array.Copy(buffer, 0, ret, 0, totalBytesRead); + } + return ret; + } + finally + { + ArrayPool.Shared.Return(buffer); + } + } } diff --git a/binding/csharp/IP2Region.Net/Internal/ICacheStrategy.cs b/binding/csharp/IP2Region.Net/Internal/ICacheStrategy.cs new file mode 100644 index 0000000..0f01d4c --- /dev/null +++ b/binding/csharp/IP2Region.Net/Internal/ICacheStrategy.cs @@ -0,0 +1,19 @@ +// Copyright 2025 The Ip2Region Authors. All rights reserved. +// Use of this source code is governed by a Apache2.0-style +// license that can be found in the LICENSE file. +// @Author Alan +// @Date 2023/07/25 +// Updated by Argo Zhang at 2025/11/21 + +namespace IP2Region.Net.Internal; + +internal interface ICacheStrategy +{ + int IoCount { get; } + + void ResetIoCount(); + + ReadOnlyMemory GetVectorIndex(int offset); + + ReadOnlyMemory GetData(long offset, int length); +} diff --git a/binding/csharp/IP2Region.Net/Internal/VectorIndexCacheStrategy.cs b/binding/csharp/IP2Region.Net/Internal/VectorIndexCacheStrategy.cs index b5abc17..c7bdaf1 100644 --- a/binding/csharp/IP2Region.Net/Internal/VectorIndexCacheStrategy.cs +++ b/binding/csharp/IP2Region.Net/Internal/VectorIndexCacheStrategy.cs @@ -5,11 +5,9 @@ // @Date 2023/07/25 // Updated by Argo Zhang at 2025/11/21 -using IP2Region.Net.Internal.Abstractions; - namespace IP2Region.Net.Internal; -class VectorIndexCacheStrategy : AbstractCacheStrategy +class VectorIndexCacheStrategy : FileCacheStrategy { private const int VectorIndexRows = 256; private const int VectorIndexCols = 256; @@ -18,10 +16,7 @@ class VectorIndexCacheStrategy : AbstractCacheStrategy public VectorIndexCacheStrategy(string xdbPath) : base(xdbPath) { - XdbFileStream.Seek(HeaderInfoLength, SeekOrigin.Begin); - var buffer = new byte[VectorIndexRows * VectorIndexCols * VectorIndexSize]; - var length = XdbFileStream.Read(buffer, 0, buffer.Length); - _vectorCache = new ReadOnlyMemory(buffer); + _vectorCache = GetData(HeaderInfoLength, VectorIndexRows * VectorIndexCols * VectorIndexSize); } public override ReadOnlyMemory GetVectorIndex(int offset) => _vectorCache.Slice(offset, VectorIndexSize); diff --git a/binding/csharp/IP2Region.Net/XDB/Searcher.cs b/binding/csharp/IP2Region.Net/XDB/Searcher.cs index c631b31..81186b5 100644 --- a/binding/csharp/IP2Region.Net/XDB/Searcher.cs +++ b/binding/csharp/IP2Region.Net/XDB/Searcher.cs @@ -7,7 +7,6 @@ using IP2Region.Net.Abstractions; using IP2Region.Net.Internal; -using IP2Region.Net.Internal.Abstractions; using System.Buffers.Binary; using System.Diagnostics.CodeAnalysis; using System.Net; @@ -18,24 +17,18 @@ namespace IP2Region.Net.XDB; /// /// 实现类 /// -public class Searcher : ISearcher +/// +/// +/// +public class Searcher(CachePolicy cachePolicy, string xdbPath) : ISearcher { - private readonly AbstractCacheStrategy _cacheStrategy; + private readonly ICacheStrategy _cacheStrategy = CacheStrategyFactory.CreateCacheStrategy(cachePolicy, xdbPath); /// /// /// public int IoCount => _cacheStrategy.IoCount; - /// - /// - /// - public Searcher(CachePolicy cachePolicy, string dbPath) - { - var factory = new CacheStrategyFactory(dbPath); - _cacheStrategy = factory.CreateCacheStrategy(cachePolicy); - } - /// /// /// @@ -93,7 +86,7 @@ public class Searcher : ISearcher { int m = (int)(l + h) >> 1; - var p = (int)sPtr + m * indexSize; + var p = sPtr + m * indexSize; var buff = _cacheStrategy.GetData(p, indexSize); var s = buff.Span.Slice(0, length); @@ -114,7 +107,7 @@ public class Searcher : ISearcher } } - var regionBuff = _cacheStrategy.GetData((int)dataPtr, dataLen); + var regionBuff = _cacheStrategy.GetData(dataPtr, dataLen); return Encoding.UTF8.GetString(regionBuff.Span.ToArray()); }