http urls monitor.

cache.go 4.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // Copyright (c) 2014-present José Carlos Nieto, https://menteslibres.net/xiam
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining
  4. // a copy of this software and associated documentation files (the
  5. // "Software"), to deal in the Software without restriction, including
  6. // without limitation the rights to use, copy, modify, merge, publish,
  7. // distribute, sublicense, and/or sell copies of the Software, and to
  8. // permit persons to whom the Software is furnished to do so, subject to
  9. // the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be
  12. // included in all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  15. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  16. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  17. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  18. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  19. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  20. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. package cache
  22. import (
  23. "container/list"
  24. "errors"
  25. "fmt"
  26. "strconv"
  27. "sync"
  28. "upper.io/db.v3/internal/cache/hashstructure"
  29. )
  30. const defaultCapacity = 128
  31. // Cache holds a map of volatile key -> values.
  32. type Cache struct {
  33. cache map[string]*list.Element
  34. li *list.List
  35. capacity int
  36. mu sync.RWMutex
  37. }
  38. type item struct {
  39. key string
  40. value interface{}
  41. }
  42. // NewCacheWithCapacity initializes a new caching space with the given
  43. // capacity.
  44. func NewCacheWithCapacity(capacity int) (*Cache, error) {
  45. if capacity < 1 {
  46. return nil, errors.New("Capacity must be greater than zero.")
  47. }
  48. return &Cache{
  49. cache: make(map[string]*list.Element),
  50. li: list.New(),
  51. capacity: capacity,
  52. }, nil
  53. }
  54. // NewCache initializes a new caching space with default settings.
  55. func NewCache() *Cache {
  56. c, err := NewCacheWithCapacity(defaultCapacity)
  57. if err != nil {
  58. panic(err.Error()) // Should never happen as we're not providing a negative defaultCapacity.
  59. }
  60. return c
  61. }
  62. // Read attempts to retrieve a cached value as a string, if the value does not
  63. // exists returns an empty string and false.
  64. func (c *Cache) Read(h Hashable) (string, bool) {
  65. if v, ok := c.ReadRaw(h); ok {
  66. if s, ok := v.(string); ok {
  67. return s, true
  68. }
  69. }
  70. return "", false
  71. }
  72. // ReadRaw attempts to retrieve a cached value as an interface{}, if the value
  73. // does not exists returns nil and false.
  74. func (c *Cache) ReadRaw(h Hashable) (interface{}, bool) {
  75. c.mu.RLock()
  76. defer c.mu.RUnlock()
  77. data, ok := c.cache[h.Hash()]
  78. if ok {
  79. return data.Value.(*item).value, true
  80. }
  81. return nil, false
  82. }
  83. // Write stores a value in memory. If the value already exists its overwritten.
  84. func (c *Cache) Write(h Hashable, value interface{}) {
  85. key := h.Hash()
  86. c.mu.Lock()
  87. defer c.mu.Unlock()
  88. if el, ok := c.cache[key]; ok {
  89. el.Value.(*item).value = value
  90. c.li.MoveToFront(el)
  91. return
  92. }
  93. c.cache[key] = c.li.PushFront(&item{key, value})
  94. for c.li.Len() > c.capacity {
  95. el := c.li.Remove(c.li.Back())
  96. delete(c.cache, el.(*item).key)
  97. if p, ok := el.(*item).value.(HasOnPurge); ok {
  98. p.OnPurge()
  99. }
  100. }
  101. }
  102. // Clear generates a new memory space, leaving the old memory unreferenced, so
  103. // it can be claimed by the garbage collector.
  104. func (c *Cache) Clear() {
  105. c.mu.Lock()
  106. defer c.mu.Unlock()
  107. for _, el := range c.cache {
  108. if p, ok := el.Value.(*item).value.(HasOnPurge); ok {
  109. p.OnPurge()
  110. }
  111. }
  112. c.cache = make(map[string]*list.Element)
  113. c.li.Init()
  114. }
  115. // Hash returns a hash of the given struct.
  116. func Hash(v interface{}) string {
  117. q, err := hashstructure.Hash(v, nil)
  118. if err != nil {
  119. panic(fmt.Sprintf("Could not hash struct: ", err.Error()))
  120. }
  121. return strconv.FormatUint(q, 10)
  122. }
  123. type hash struct {
  124. name string
  125. }
  126. func (h *hash) Hash() string {
  127. return h.name
  128. }
  129. // String returns a Hashable that produces a hash equal to the given string.
  130. func String(s string) Hashable {
  131. return &hash{s}
  132. }