github.com/altipla-consulting/ravendb-go-client@v0.1.3/http_cache.go (about)

     1  package ravendb
     2  
     3  import (
     4  	//"fmt"
     5  
     6  	"math"
     7  	"sync/atomic"
     8  	"time"
     9  )
    10  
    11  // equivalent of com.google.common.cache.Cache, specialized for String -> HttpCacheItem mapping
    12  // TODO: match semantics
    13  type genericCache struct {
    14  	softValues    bool
    15  	maximumWeight int
    16  	weighter      func(string, *httpCacheItem) int
    17  
    18  	data map[string]*httpCacheItem
    19  }
    20  
    21  func (c *genericCache) size() int {
    22  	return len(c.data)
    23  }
    24  
    25  func (c *genericCache) invalidateAll() {
    26  	c.data = nil
    27  }
    28  
    29  func (c *genericCache) getIfPresent(uri string) *httpCacheItem {
    30  	return c.data[uri]
    31  }
    32  
    33  func (c *genericCache) put(uri string, i *httpCacheItem) {
    34  	//fmt.Printf("genericCache.put(): url: %s, changeVector: %s, len(result): %d\n", uri, *i.changeVector, len(i.payload))
    35  
    36  	// TODO: probably implement cache eviction
    37  	c.data[uri] = i
    38  }
    39  
    40  type httpCache struct {
    41  	items      *genericCache
    42  	generation int32 // atomic
    43  }
    44  
    45  func (c *httpCache) incGeneration() {
    46  	atomic.AddInt32(&c.generation, 1)
    47  }
    48  
    49  func (c *httpCache) getGeneration() int {
    50  	v := atomic.LoadInt32(&c.generation)
    51  	return int(v)
    52  }
    53  
    54  func newHttpCache(size int) *httpCache {
    55  	if size == 0 {
    56  		size = 1 * 1024 * 1024 // TODO: check what is default size of com.google.common.cache.Cache is
    57  	}
    58  	cache := &genericCache{
    59  		softValues:    true,
    60  		maximumWeight: size,
    61  		weighter: func(k string, v *httpCacheItem) int {
    62  			return len(v.payload) + 20
    63  		},
    64  		data: map[string]*httpCacheItem{},
    65  	}
    66  	return &httpCache{
    67  		items: cache,
    68  	}
    69  }
    70  
    71  func (c *httpCache) GetNumberOfItems() int {
    72  	return c.items.size()
    73  }
    74  
    75  func (c *httpCache) close() {
    76  	c.items.invalidateAll()
    77  	c.items = nil
    78  }
    79  
    80  func (c *httpCache) set(url string, changeVector *string, result []byte) {
    81  	httpCacheItem := newHttpCacheItem()
    82  	httpCacheItem.changeVector = changeVector
    83  	httpCacheItem.payload = result
    84  	httpCacheItem.cache = c
    85  	httpCacheItem.generation = c.getGeneration()
    86  	c.items.put(url, httpCacheItem)
    87  }
    88  
    89  // returns cacheItem, changeVector and response
    90  func (c *httpCache) get(url string) (*releaseCacheItem, *string, []byte) {
    91  	item := c.items.getIfPresent(url)
    92  	if item != nil {
    93  		//fmt.Printf("HttpCache.get(): found url: %s, changeVector: %s, len(payload): %d\n", url, *item.changeVector, len(item.payload))
    94  		return newReleaseCacheItem(item), item.changeVector, item.payload
    95  	}
    96  
    97  	//fmt.Printf("HttpCache.get(): didn't find url: %s\n", url)
    98  	return newReleaseCacheItem(nil), nil, nil
    99  }
   100  
   101  func (c *httpCache) setNotFound(url string) {
   102  	//fmt.Printf("HttpCache.setNotFound(): url: %s\n", url)
   103  	httpCacheItem := newHttpCacheItem()
   104  	s := "404 response"
   105  	httpCacheItem.changeVector = &s
   106  	httpCacheItem.cache = c
   107  	httpCacheItem.generation = c.getGeneration()
   108  
   109  	c.items.put(url, httpCacheItem)
   110  }
   111  
   112  type releaseCacheItem struct {
   113  	item *httpCacheItem
   114  }
   115  
   116  func newReleaseCacheItem(item *httpCacheItem) *releaseCacheItem {
   117  	return &releaseCacheItem{
   118  		item: item,
   119  	}
   120  }
   121  
   122  func (i *releaseCacheItem) notModified() {
   123  	if i.item != nil {
   124  		i.item.lastServerUpdate = time.Now()
   125  	}
   126  }
   127  
   128  func (i *releaseCacheItem) getAge() time.Duration {
   129  	if i.item == nil {
   130  		return time.Duration(math.MaxInt64)
   131  	}
   132  	return time.Since(i.item.lastServerUpdate)
   133  }
   134  
   135  func (i *releaseCacheItem) getMightHaveBeenModified() bool {
   136  	currGen := i.item.generation
   137  	itemGen := i.item.cache.getGeneration()
   138  	return currGen != itemGen
   139  }
   140  
   141  func (i *releaseCacheItem) close() {
   142  	// no-op
   143  }