input ip type changed to any to supports string or bytes ip
This commit is contained in:
parent
e1f0d5126a
commit
5cb17713a7
|
|
@ -39,8 +39,8 @@ if err != nil {
|
|||
}
|
||||
|
||||
// 4. Export the ip2region service for concurrent dual-version IP address queries, for example:
|
||||
v4Region, err := ip2region.SearchByStr("113.92.157.29") // Perform IPv4 query
|
||||
v6Region, err := ip2region.SearchByStr("240e:3b7:3272:d8d0:db09:c067:8d59:539e") // Perform IPv6 query
|
||||
v4Region, err := ip2region.Search("113.92.157.29") // Perform IPv4 query
|
||||
v6Region, err := ip2region.Search("240e:3b7:3272:d8d0:db09:c067:8d59:539e") // Perform IPv6 query
|
||||
|
||||
|
||||
// 5. When the parent service needs to be closed, close the ip2region query service as well
|
||||
|
|
@ -60,8 +60,7 @@ ip2region.Close()
|
|||
The location information query API prototypes are:
|
||||
|
||||
```go
|
||||
SearchByStr(string) (string, error)
|
||||
Search([]byte) (string, error)
|
||||
Search(string | []byte) (string, error)
|
||||
```
|
||||
|
||||
If a query fails, the `error` will contain specific error details. If successful, it returns the `region` string. If the specified IP cannot be found, it returns an empty string `""`.
|
||||
|
|
@ -121,9 +120,9 @@ func main() {
|
|||
var ip = "1.2.3.4" // IPv4
|
||||
// ip = "240e:3b7:3272:d8d0:db09:c067:8d59:539e" // IPv6
|
||||
var tStart = time.Now()
|
||||
region, err := searcher.SearchByStr(ip)
|
||||
region, err := searcher.Search(ip)
|
||||
if err != nil {
|
||||
fmt.Printf("failed to SearchIP(%s): %s\n", ip, err)
|
||||
fmt.Printf("failed to Search(%s): %s\n", ip, err)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ if err != nil {
|
|||
}
|
||||
|
||||
// 4,导出 ip2region 服务进行双版本的IP地址的并发查询,例如:
|
||||
v4Region, err := ip2region.SearchByStr("113.92.157.29") // 进行 IPv4 查询
|
||||
v6Region, err := ip2region.SearchByStr("240e:3b7:3272:d8d0:db09:c067:8d59:539e") // 进行 IPv6 查询
|
||||
v4Region, err := ip2region.Search("113.92.157.29") // 进行 IPv4 查询
|
||||
v6Region, err := ip2region.Search("240e:3b7:3272:d8d0:db09:c067:8d59:539e") // 进行 IPv6 查询
|
||||
|
||||
|
||||
// 5,在服务需要关闭的时候,同时关闭 ip2region 查询服务
|
||||
|
|
@ -55,8 +55,7 @@ ip2region.Close()
|
|||
### 关于查询 API
|
||||
定位信息查询 API 原型为:
|
||||
```go
|
||||
SearchByStr(string) (string, error)
|
||||
Search([]byte) (string, error)
|
||||
Search(string | []byte) (string, error)
|
||||
```
|
||||
查询出错则 error 会包含具体的错误信息,查询成功会返回字符串的 `region` 信息,如果指定的 IP 查询不到则会返回空字符串 `""`。
|
||||
|
||||
|
|
@ -111,9 +110,9 @@ func main() {
|
|||
var ip = "1.2.3.4" // IPv4
|
||||
// ip = "240e:3b7:3272:d8d0:db09:c067:8d59:539e" // IPv6
|
||||
var tStart = time.Now()
|
||||
region, err := searcher.SearchByStr(ip)
|
||||
region, err := searcher.Search(ip)
|
||||
if err != nil {
|
||||
fmt.Printf("failed to SearchIP(%s): %s\n", ip, err)
|
||||
fmt.Printf("failed to Search(%s): %s\n", ip, err)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ type 'quit' to exit
|
|||
}
|
||||
|
||||
tStart := time.Now()
|
||||
region, err := ip2region.SearchByStr(line)
|
||||
region, err := ip2region.Search(line)
|
||||
if err != nil {
|
||||
fmt.Printf("\x1b[0;31m{err: %s}\x1b[0m\n", err.Error())
|
||||
} else {
|
||||
|
|
@ -339,7 +339,13 @@ func testBench() {
|
|||
return
|
||||
}
|
||||
|
||||
for _, ip := range [][]byte{sip, eip} {
|
||||
mip, err := xdb.IPMiddle(sip, eip)
|
||||
if err != nil {
|
||||
fmt.Printf("IPMiddle(%s,%s): %s", xdb.IP2String(sip), xdb.IP2String(eip), err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, ip := range [][]byte{sip, mip, eip} {
|
||||
sTime := time.Now()
|
||||
region, err := searcher.Search(ip)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -118,16 +118,21 @@ func NewIp2RegionWithPath(v4XdbPath string, v6XdbPath string) (*Ip2Region, error
|
|||
return NewIp2Region(v4Config, v6Config)
|
||||
}
|
||||
|
||||
func (ip2r *Ip2Region) SearchByStr(ipStr string) (string, error) {
|
||||
ipBytes, err := xdb.ParseIP(ipStr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
func (ip2r *Ip2Region) Search(ip any) (string, error) {
|
||||
var err error
|
||||
var ipBytes []byte
|
||||
switch v := ip.(type) {
|
||||
case string:
|
||||
ipBytes, err = xdb.ParseIP(v)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("parse ip %s: %w", v, err)
|
||||
}
|
||||
case []byte:
|
||||
ipBytes = v
|
||||
default:
|
||||
return "", fmt.Errorf("invalid ip value type %s", v)
|
||||
}
|
||||
|
||||
return ip2r.Search(ipBytes)
|
||||
}
|
||||
|
||||
func (ip2r *Ip2Region) Search(ipBytes []byte) (string, error) {
|
||||
if l := len(ipBytes); l == 4 {
|
||||
return ip2r.v4Search(ipBytes)
|
||||
} else if l == 16 {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ func TestV4SearcherPool(t *testing.T) {
|
|||
ipString := "219.133.110.197"
|
||||
for i := 0; i < 20; i++ {
|
||||
searcher := searcherPool.BorrowSearcher()
|
||||
region, err := searcher.SearchByStr(ipString)
|
||||
region, err := searcher.Search(ipString)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to search(%s): %s", ipString, err)
|
||||
}
|
||||
|
|
@ -53,7 +53,7 @@ func TestV6SearcherPool(t *testing.T) {
|
|||
ipString := "240e:3b7:3275:f090:d2a3:7d1a:dd90:c3b6"
|
||||
for i := 0; i < 20; i++ {
|
||||
searcher := searcherPool.BorrowSearcher()
|
||||
region, err := searcher.SearchByStr(ipString)
|
||||
region, err := searcher.Search(ipString)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to search(%s): %s", ipString, err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,20 +89,24 @@ func (s *Searcher) GetIOCount() int {
|
|||
return s.ioCount
|
||||
}
|
||||
|
||||
// SearchByStr find the region for the specified ip string
|
||||
func (s *Searcher) SearchByStr(str string) (string, error) {
|
||||
ip, err := ParseIP(str)
|
||||
if err != nil {
|
||||
return "", err
|
||||
// Search the region for the specified string or bytes ip address
|
||||
func (s *Searcher) Search(ip any) (string, error) {
|
||||
var err error
|
||||
var ipBytes []byte
|
||||
switch v := ip.(type) {
|
||||
case string:
|
||||
ipBytes, err = ParseIP(v)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("parse ip %s: %w", v, err)
|
||||
}
|
||||
case []byte:
|
||||
ipBytes = v
|
||||
default:
|
||||
return "", fmt.Errorf("invalid ip value type %s", v)
|
||||
}
|
||||
|
||||
return s.Search(ip)
|
||||
}
|
||||
|
||||
// Search find the region for the specified long ip
|
||||
func (s *Searcher) Search(ip []byte) (string, error) {
|
||||
// ip version check
|
||||
if len(ip) != s.version.Bytes {
|
||||
if len(ipBytes) != s.version.Bytes {
|
||||
return "", fmt.Errorf("invalid ip address(%s expected)", s.version.Name)
|
||||
}
|
||||
|
||||
|
|
@ -110,7 +114,7 @@ func (s *Searcher) Search(ip []byte) (string, error) {
|
|||
s.ioCount = 0
|
||||
|
||||
// locate the segment index block based on the vector index
|
||||
var il0, il1 = int(ip[0]), int(ip[1])
|
||||
var il0, il1 = int(ipBytes[0]), int(ipBytes[1])
|
||||
var idx = il0*VectorIndexCols*VectorIndexSize + il1*VectorIndexSize
|
||||
var sPtr, ePtr = uint32(0), uint32(0)
|
||||
if s.vectorIndex != nil {
|
||||
|
|
@ -139,7 +143,7 @@ func (s *Searcher) Search(ip []byte) (string, error) {
|
|||
}
|
||||
|
||||
// binary search the segment index to get the region
|
||||
var bytes, dBytes = len(ip), len(ip) << 1
|
||||
var bytes, dBytes = len(ipBytes), len(ipBytes) << 1
|
||||
var segIndexSize = uint32(s.version.SegmentIndexSize)
|
||||
var dataLen, dataPtr = 0, uint32(0)
|
||||
var buff = make([]byte, segIndexSize)
|
||||
|
|
@ -153,9 +157,9 @@ func (s *Searcher) Search(ip []byte) (string, error) {
|
|||
}
|
||||
|
||||
// decode the data step by step to reduce the unnecessary operations
|
||||
if s.version.IPCompare(ip, buff[0:bytes]) < 0 {
|
||||
if s.version.IPCompare(ipBytes, buff[0:bytes]) < 0 {
|
||||
h = m - 1
|
||||
} else if s.version.IPCompare(ip, buff[bytes:dBytes]) > 0 {
|
||||
} else if s.version.IPCompare(ipBytes, buff[bytes:dBytes]) > 0 {
|
||||
l = m + 1
|
||||
} else {
|
||||
dataLen = int(binary.LittleEndian.Uint16(buff[dBytes:]))
|
||||
|
|
@ -171,7 +175,7 @@ func (s *Searcher) Search(ip []byte) (string, error) {
|
|||
|
||||
// load and return the region data
|
||||
var regionBuff = make([]byte, dataLen)
|
||||
err := s.read(int64(dataPtr), regionBuff)
|
||||
err = s.read(int64(dataPtr), regionBuff)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("read region at %d: %w", dataPtr, err)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue