searcher pool is ready
This commit is contained in:
parent
ab22a5e03c
commit
e73321a860
|
|
@ -11,9 +11,9 @@
|
||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/lionsoul2014/ip2region/binding/golang/xdb"
|
"github.com/lionsoul2014/ip2region/binding/golang/xdb"
|
||||||
)
|
)
|
||||||
|
|
@ -61,18 +61,19 @@ func NewSearcherPool(config *Config) (*SearcherPool, error) {
|
||||||
// Stat return the stat {loanCount, leftCount} info of the pool
|
// Stat return the stat {loanCount, leftCount} info of the pool
|
||||||
func (sp *SearcherPool) Stat() (int, int) {
|
func (sp *SearcherPool) Stat() (int, int) {
|
||||||
loanCount := int(atomic.LoadInt32(&sp.loanCount))
|
loanCount := int(atomic.LoadInt32(&sp.loanCount))
|
||||||
return loanCount, len(sp.pool) - loanCount
|
return loanCount, len(sp.pool)
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the loaned count
|
||||||
|
func (sp *SearcherPool) LoanCount() int {
|
||||||
|
return int(atomic.LoadInt32(&sp.loanCount))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sp *SearcherPool) BorrowSearcher() *xdb.Searcher {
|
func (sp *SearcherPool) BorrowSearcher() *xdb.Searcher {
|
||||||
select {
|
// @Note: still accept searcher borrow while closing
|
||||||
case <-sp.closing:
|
s := <-sp.pool
|
||||||
// stop searcher borrow while closing
|
atomic.AddInt32(&sp.loanCount, 1)
|
||||||
return nil
|
return s
|
||||||
case s := <-sp.pool:
|
|
||||||
atomic.AddInt32(&sp.loanCount, 1)
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sp *SearcherPool) ReturnSearcher(searcher *xdb.Searcher) {
|
func (sp *SearcherPool) ReturnSearcher(searcher *xdb.Searcher) {
|
||||||
|
|
@ -80,6 +81,9 @@ func (sp *SearcherPool) ReturnSearcher(searcher *xdb.Searcher) {
|
||||||
case <-sp.closing:
|
case <-sp.closing:
|
||||||
// manually close the searcher
|
// manually close the searcher
|
||||||
searcher.Close()
|
searcher.Close()
|
||||||
|
|
||||||
|
// decrease the loan count
|
||||||
|
atomic.AddInt32(&sp.loanCount, -1)
|
||||||
default:
|
default:
|
||||||
// return the searcher
|
// return the searcher
|
||||||
sp.pool <- searcher
|
sp.pool <- searcher
|
||||||
|
|
@ -87,9 +91,29 @@ func (sp *SearcherPool) ReturnSearcher(searcher *xdb.Searcher) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sp *SearcherPool) Close(ctx context.Context) {
|
func (sp *SearcherPool) Close() {
|
||||||
|
sp.CloseTimeout(time.Second * 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sp *SearcherPool) CloseTimeout(d time.Duration) {
|
||||||
close(sp.closing)
|
close(sp.closing)
|
||||||
for s := range sp.pool {
|
for {
|
||||||
s.Close()
|
timeout := false
|
||||||
|
select {
|
||||||
|
case s := <-sp.pool:
|
||||||
|
s.Close()
|
||||||
|
case <-time.After(d):
|
||||||
|
// check if all the loaned searchers was closed
|
||||||
|
timeout = true
|
||||||
|
}
|
||||||
|
|
||||||
|
lc, left := sp.LoanCount(), len(sp.pool)
|
||||||
|
if left == 0 && lc == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if timeout {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
// Copyright 2022 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.
|
||||||
|
|
||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestV4SearcherPool(t *testing.T) {
|
||||||
|
v4Config, err := NewV4Config(VIndexCache, "../../../data/ip2region_v4.xdb", 5)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to new v4 config: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
searcherPool, err := NewSearcherPool(v4Config)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create searcher pool: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ipString := "219.133.110.197"
|
||||||
|
for i := 0; i < 20; i++ {
|
||||||
|
searcher := searcherPool.BorrowSearcher()
|
||||||
|
region, err := searcher.SearchByStr(ipString)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to search(%s): %s", ipString, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("%2d->search(%s)=%s\n", i, ipString, region)
|
||||||
|
searcherPool.ReturnSearcher(searcher)
|
||||||
|
}
|
||||||
|
|
||||||
|
// borrow one at last for Close timeout wait testing ONLY
|
||||||
|
// searcherPool.BorrowSearcher()
|
||||||
|
|
||||||
|
// close the searcher pool
|
||||||
|
searcherPool.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestV6SearcherPool(t *testing.T) {
|
||||||
|
v6Config, err := NewV6Config(VIndexCache, "../../../data/ip2region_v6.xdb", 5)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to new v6 config: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
searcherPool, err := NewSearcherPool(v6Config)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create searcher pool: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ipString := "240e:3b7:3275:f090:d2a3:7d1a:dd90:c3b6"
|
||||||
|
for i := 0; i < 20; i++ {
|
||||||
|
searcher := searcherPool.BorrowSearcher()
|
||||||
|
region, err := searcher.SearchByStr(ipString)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to search(%s): %s", ipString, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("%2d->search(%s)=%s\n", i, ipString, region)
|
||||||
|
searcherPool.ReturnSearcher(searcher)
|
||||||
|
}
|
||||||
|
|
||||||
|
// borrow one at last for Close timeout wait testing ONLY
|
||||||
|
// searcherPool.BorrowSearcher()
|
||||||
|
|
||||||
|
// close the searcher pool
|
||||||
|
searcherPool.Close()
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue