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 }