From 46001a9fa5f36e453b88c0074f7c82b6e684092b Mon Sep 17 00:00:00 2001 From: Martin Boehm Date: Tue, 26 Feb 2019 16:27:28 +0100 Subject: [PATCH] Evict old cached xpubs --- api/types.go | 1 + api/xpub.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/api/types.go b/api/types.go index 0d1f1b4f..7b4c6034 100644 --- a/api/types.go +++ b/api/types.go @@ -12,6 +12,7 @@ import ( const maxUint32 = ^uint32(0) const maxInt = int(^uint(0) >> 1) +const maxInt64 = int64(^uint64(0) >> 1) // GetAddressOption specifies what data returns GetAddress api call type GetAddressOption int diff --git a/api/xpub.go b/api/xpub.go index b257c9cb..e577f8fa 100644 --- a/api/xpub.go +++ b/api/xpub.go @@ -20,6 +20,9 @@ const maxAddressesGap = 10000 const txInput = 1 const txOutput = 2 +const xpubCacheSize = 512 +const xpubCacheExpirationSeconds = 7200 + var cachedXpubs = make(map[string]xpubData) var cachedXpubsMux sync.Mutex @@ -46,6 +49,7 @@ type xpubAddress struct { type xpubData struct { gap int + accessed int64 basePath string dataHeight uint32 dataHash string @@ -234,6 +238,28 @@ func (w *Worker) tokenFromXpubAddress(data *xpubData, ad *xpubAddress, changeInd } } +func evictXpubCacheItems() { + var oldestKey string + oldest := maxInt64 + now := time.Now().Unix() + count := 0 + for k, v := range cachedXpubs { + if v.accessed+xpubCacheExpirationSeconds < now { + delete(cachedXpubs, k) + count++ + } + if v.accessed < oldest { + oldestKey = k + oldest = v.accessed + } + } + if oldestKey != "" && oldest+xpubCacheExpirationSeconds >= now { + delete(cachedXpubs, oldestKey) + count++ + } + glog.Info("Evicted ", count, " items from xpub cache, oldest item accessed at ", time.Unix(oldest, 0), ", cache size ", len(cachedXpubs)) +} + func (w *Worker) getXpubData(xpub string, page int, txsOnPage int, option GetAddressOption, filter *AddressFilter, gap int) (*xpubData, uint32, error) { if w.chainType != bchain.ChainBitcoinType || len(xpub) != xpubLen { return nil, 0, ErrUnsupportedXpub @@ -309,7 +335,11 @@ func (w *Worker) getXpubData(xpub string, page int, txsOnPage int, option GetAdd } } } + data.accessed = time.Now().Unix() cachedXpubsMux.Lock() + if len(cachedXpubs) >= xpubCacheSize { + evictXpubCacheItems() + } cachedXpubs[xpub] = data cachedXpubsMux.Unlock() return &data, bestheight, nil