From 38b74d1999280bc0a26e35fa94df90ce344d45f4 Mon Sep 17 00:00:00 2001 From: Adin Schmahmann Date: Tue, 25 Aug 2020 10:07:30 -0400 Subject: [PATCH 1/2] feat: use deferred initialization of the asnStore --- asn.go | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/asn.go b/asn.go index dd01ece..9ed8412 100644 --- a/asn.go +++ b/asn.go @@ -8,14 +8,10 @@ import ( "github.com/libp2p/go-cidranger" ) -var Store *asnStore +var Store *indirectAsnStore func init() { - s, err := NewAsnStore() - if err != nil { - panic(err) - } - Store = s + Store = &indirectAsnStore{} } type networkWithAsn struct { @@ -56,6 +52,17 @@ func (a *asnStore) AsnForIPv6(ip net.IP) (string, error) { // NewAsnStore returns a `asnStore` that can be queried for the Autonomous System Numbers // for a given IP address or a multiaddress which contains an IP address. func NewAsnStore() (*asnStore, error) { + if Store.store == nil { + store, err := newAsnStore() + if err != nil { + return nil, err + } + Store.store = store + } + return Store.store, nil +} + +func newAsnStore() (*asnStore, error) { cr := cidranger.NewPCTrieRanger() for k, v := range ipv6CidrToAsnMap { @@ -71,3 +78,22 @@ func NewAsnStore() (*asnStore, error) { return &asnStore{cr}, nil } + +type indirectAsnStore struct { + store *asnStore +} + +// AsnForIPv6 returns the AS number for the given IPv6 address. +// If no mapping exists for the given IP, this function will +// return an empty ASN and a nil error. +func (a *indirectAsnStore) AsnForIPv6(ip net.IP) (string, error) { + if a.store == nil { + store, err := newAsnStore() + if err != nil { + panic(err) + } + a.store = store + } + + return a.store.AsnForIPv6(ip) +} From d8ddb2ebb4e46f7360fcf1887a9d60eefdf608ef Mon Sep 17 00:00:00 2001 From: Adin Schmahmann Date: Tue, 25 Aug 2020 11:23:16 -0400 Subject: [PATCH 2/2] feat: use background goroutine for indirectAsnStore initialization --- asn.go | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/asn.go b/asn.go index 9ed8412..86be800 100644 --- a/asn.go +++ b/asn.go @@ -11,7 +11,7 @@ import ( var Store *indirectAsnStore func init() { - Store = &indirectAsnStore{} + Store = newIndirectAsnStore() } type networkWithAsn struct { @@ -49,19 +49,6 @@ func (a *asnStore) AsnForIPv6(ip net.IP) (string, error) { return n.asn, nil } -// NewAsnStore returns a `asnStore` that can be queried for the Autonomous System Numbers -// for a given IP address or a multiaddress which contains an IP address. -func NewAsnStore() (*asnStore, error) { - if Store.store == nil { - store, err := newAsnStore() - if err != nil { - return nil, err - } - Store.store = store - } - return Store.store, nil -} - func newAsnStore() (*asnStore, error) { cr := cidranger.NewPCTrieRanger() @@ -81,19 +68,30 @@ func newAsnStore() (*asnStore, error) { type indirectAsnStore struct { store *asnStore + doneLoading chan struct{} } // AsnForIPv6 returns the AS number for the given IPv6 address. // If no mapping exists for the given IP, this function will // return an empty ASN and a nil error. func (a *indirectAsnStore) AsnForIPv6(ip net.IP) (string, error) { - if a.store == nil { + <-a.doneLoading + return a.store.AsnForIPv6(ip) +} + +func newIndirectAsnStore() *indirectAsnStore { + a := &indirectAsnStore{ + doneLoading: make(chan struct{}), + } + + go func() { + defer close(a.doneLoading) store, err := newAsnStore() if err != nil { panic(err) } a.store = store - } + }() - return a.store.AsnForIPv6(ip) + return a }