cache.go 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131
  1. package cache
  2. import (
  3. "encoding/gob"
  4. "fmt"
  5. "io"
  6. "os"
  7. "runtime"
  8. "sync"
  9. "time"
  10. )
  11. type Item struct {
  12. Object interface{}
  13. Expiration int64
  14. }
  15. // Returns true if the item has expired.
  16. func (item Item) Expired() bool {
  17. if item.Expiration == 0 {
  18. return false
  19. }
  20. return time.Now().UnixNano() > item.Expiration
  21. }
  22. const (
  23. // For use with functions that take an expiration time.
  24. NoExpiration time.Duration = -1
  25. // For use with functions that take an expiration time. Equivalent to
  26. // passing in the same expiration duration as was given to New() or
  27. // NewFrom() when the cache was created (e.g. 5 minutes.)
  28. DefaultExpiration time.Duration = 0
  29. )
  30. type Cache struct {
  31. *cache
  32. // If this is confusing, see the comment at the bottom of New()
  33. }
  34. type cache struct {
  35. defaultExpiration time.Duration
  36. items map[string]Item
  37. mu sync.RWMutex
  38. onEvicted func(string, interface{})
  39. janitor *janitor
  40. }
  41. // Add an item to the cache, replacing any existing item. If the duration is 0
  42. // (DefaultExpiration), the cache's default expiration time is used. If it is -1
  43. // (NoExpiration), the item never expires.
  44. func (c *cache) Set(k string, x interface{}, d time.Duration) {
  45. // "Inlining" of set
  46. var e int64
  47. if d == DefaultExpiration {
  48. d = c.defaultExpiration
  49. }
  50. if d > 0 {
  51. e = time.Now().Add(d).UnixNano()
  52. }
  53. c.mu.Lock()
  54. c.items[k] = Item{
  55. Object: x,
  56. Expiration: e,
  57. }
  58. // TODO: Calls to mu.Unlock are currently not deferred because defer
  59. // adds ~200 ns (as of go1.)
  60. c.mu.Unlock()
  61. }
  62. func (c *cache) set(k string, x interface{}, d time.Duration) {
  63. var e int64
  64. if d == DefaultExpiration {
  65. d = c.defaultExpiration
  66. }
  67. if d > 0 {
  68. e = time.Now().Add(d).UnixNano()
  69. }
  70. c.items[k] = Item{
  71. Object: x,
  72. Expiration: e,
  73. }
  74. }
  75. // Add an item to the cache, replacing any existing item, using the default
  76. // expiration.
  77. func (c *cache) SetDefault(k string, x interface{}) {
  78. c.Set(k, x, DefaultExpiration)
  79. }
  80. // Add an item to the cache only if an item doesn't already exist for the given
  81. // key, or if the existing item has expired. Returns an error otherwise.
  82. func (c *cache) Add(k string, x interface{}, d time.Duration) error {
  83. c.mu.Lock()
  84. _, found := c.get(k)
  85. if found {
  86. c.mu.Unlock()
  87. return fmt.Errorf("Item %s already exists", k)
  88. }
  89. c.set(k, x, d)
  90. c.mu.Unlock()
  91. return nil
  92. }
  93. // Set a new value for the cache key only if it already exists, and the existing
  94. // item hasn't expired. Returns an error otherwise.
  95. func (c *cache) Replace(k string, x interface{}, d time.Duration) error {
  96. c.mu.Lock()
  97. _, found := c.get(k)
  98. if !found {
  99. c.mu.Unlock()
  100. return fmt.Errorf("Item %s doesn't exist", k)
  101. }
  102. c.set(k, x, d)
  103. c.mu.Unlock()
  104. return nil
  105. }
  106. // Get an item from the cache. Returns the item or nil, and a bool indicating
  107. // whether the key was found.
  108. func (c *cache) Get(k string) (interface{}, bool) {
  109. c.mu.RLock()
  110. // "Inlining" of get and Expired
  111. item, found := c.items[k]
  112. if !found {
  113. c.mu.RUnlock()
  114. return nil, false
  115. }
  116. if item.Expiration > 0 {
  117. if time.Now().UnixNano() > item.Expiration {
  118. c.mu.RUnlock()
  119. return nil, false
  120. }
  121. }
  122. c.mu.RUnlock()
  123. return item.Object, true
  124. }
  125. func (c *cache) get(k string) (interface{}, bool) {
  126. item, found := c.items[k]
  127. if !found {
  128. return nil, false
  129. }
  130. // "Inlining" of Expired
  131. if item.Expiration > 0 {
  132. if time.Now().UnixNano() > item.Expiration {
  133. return nil, false
  134. }
  135. }
  136. return item.Object, true
  137. }
  138. // Increment an item of type int, int8, int16, int32, int64, uintptr, uint,
  139. // uint8, uint32, or uint64, float32 or float64 by n. Returns an error if the
  140. // item's value is not an integer, if it was not found, or if it is not
  141. // possible to increment it by n. To retrieve the incremented value, use one
  142. // of the specialized methods, e.g. IncrementInt64.
  143. func (c *cache) Increment(k string, n int64) error {
  144. c.mu.Lock()
  145. v, found := c.items[k]
  146. if !found || v.Expired() {
  147. c.mu.Unlock()
  148. return fmt.Errorf("Item %s not found", k)
  149. }
  150. switch v.Object.(type) {
  151. case int:
  152. v.Object = v.Object.(int) + int(n)
  153. case int8:
  154. v.Object = v.Object.(int8) + int8(n)
  155. case int16:
  156. v.Object = v.Object.(int16) + int16(n)
  157. case int32:
  158. v.Object = v.Object.(int32) + int32(n)
  159. case int64:
  160. v.Object = v.Object.(int64) + n
  161. case uint:
  162. v.Object = v.Object.(uint) + uint(n)
  163. case uintptr:
  164. v.Object = v.Object.(uintptr) + uintptr(n)
  165. case uint8:
  166. v.Object = v.Object.(uint8) + uint8(n)
  167. case uint16:
  168. v.Object = v.Object.(uint16) + uint16(n)
  169. case uint32:
  170. v.Object = v.Object.(uint32) + uint32(n)
  171. case uint64:
  172. v.Object = v.Object.(uint64) + uint64(n)
  173. case float32:
  174. v.Object = v.Object.(float32) + float32(n)
  175. case float64:
  176. v.Object = v.Object.(float64) + float64(n)
  177. default:
  178. c.mu.Unlock()
  179. return fmt.Errorf("The value for %s is not an integer", k)
  180. }
  181. c.items[k] = v
  182. c.mu.Unlock()
  183. return nil
  184. }
  185. // Increment an item of type float32 or float64 by n. Returns an error if the
  186. // item's value is not floating point, if it was not found, or if it is not
  187. // possible to increment it by n. Pass a negative number to decrement the
  188. // value. To retrieve the incremented value, use one of the specialized methods,
  189. // e.g. IncrementFloat64.
  190. func (c *cache) IncrementFloat(k string, n float64) error {
  191. c.mu.Lock()
  192. v, found := c.items[k]
  193. if !found || v.Expired() {
  194. c.mu.Unlock()
  195. return fmt.Errorf("Item %s not found", k)
  196. }
  197. switch v.Object.(type) {
  198. case float32:
  199. v.Object = v.Object.(float32) + float32(n)
  200. case float64:
  201. v.Object = v.Object.(float64) + n
  202. default:
  203. c.mu.Unlock()
  204. return fmt.Errorf("The value for %s does not have type float32 or float64", k)
  205. }
  206. c.items[k] = v
  207. c.mu.Unlock()
  208. return nil
  209. }
  210. // Increment an item of type int by n. Returns an error if the item's value is
  211. // not an int, or if it was not found. If there is no error, the incremented
  212. // value is returned.
  213. func (c *cache) IncrementInt(k string, n int) (int, error) {
  214. c.mu.Lock()
  215. v, found := c.items[k]
  216. if !found || v.Expired() {
  217. c.mu.Unlock()
  218. return 0, fmt.Errorf("Item %s not found", k)
  219. }
  220. rv, ok := v.Object.(int)
  221. if !ok {
  222. c.mu.Unlock()
  223. return 0, fmt.Errorf("The value for %s is not an int", k)
  224. }
  225. nv := rv + n
  226. v.Object = nv
  227. c.items[k] = v
  228. c.mu.Unlock()
  229. return nv, nil
  230. }
  231. // Increment an item of type int8 by n. Returns an error if the item's value is
  232. // not an int8, or if it was not found. If there is no error, the incremented
  233. // value is returned.
  234. func (c *cache) IncrementInt8(k string, n int8) (int8, error) {
  235. c.mu.Lock()
  236. v, found := c.items[k]
  237. if !found || v.Expired() {
  238. c.mu.Unlock()
  239. return 0, fmt.Errorf("Item %s not found", k)
  240. }
  241. rv, ok := v.Object.(int8)
  242. if !ok {
  243. c.mu.Unlock()
  244. return 0, fmt.Errorf("The value for %s is not an int8", k)
  245. }
  246. nv := rv + n
  247. v.Object = nv
  248. c.items[k] = v
  249. c.mu.Unlock()
  250. return nv, nil
  251. }
  252. // Increment an item of type int16 by n. Returns an error if the item's value is
  253. // not an int16, or if it was not found. If there is no error, the incremented
  254. // value is returned.
  255. func (c *cache) IncrementInt16(k string, n int16) (int16, error) {
  256. c.mu.Lock()
  257. v, found := c.items[k]
  258. if !found || v.Expired() {
  259. c.mu.Unlock()
  260. return 0, fmt.Errorf("Item %s not found", k)
  261. }
  262. rv, ok := v.Object.(int16)
  263. if !ok {
  264. c.mu.Unlock()
  265. return 0, fmt.Errorf("The value for %s is not an int16", k)
  266. }
  267. nv := rv + n
  268. v.Object = nv
  269. c.items[k] = v
  270. c.mu.Unlock()
  271. return nv, nil
  272. }
  273. // Increment an item of type int32 by n. Returns an error if the item's value is
  274. // not an int32, or if it was not found. If there is no error, the incremented
  275. // value is returned.
  276. func (c *cache) IncrementInt32(k string, n int32) (int32, error) {
  277. c.mu.Lock()
  278. v, found := c.items[k]
  279. if !found || v.Expired() {
  280. c.mu.Unlock()
  281. return 0, fmt.Errorf("Item %s not found", k)
  282. }
  283. rv, ok := v.Object.(int32)
  284. if !ok {
  285. c.mu.Unlock()
  286. return 0, fmt.Errorf("The value for %s is not an int32", k)
  287. }
  288. nv := rv + n
  289. v.Object = nv
  290. c.items[k] = v
  291. c.mu.Unlock()
  292. return nv, nil
  293. }
  294. // Increment an item of type int64 by n. Returns an error if the item's value is
  295. // not an int64, or if it was not found. If there is no error, the incremented
  296. // value is returned.
  297. func (c *cache) IncrementInt64(k string, n int64) (int64, error) {
  298. c.mu.Lock()
  299. v, found := c.items[k]
  300. if !found || v.Expired() {
  301. c.mu.Unlock()
  302. return 0, fmt.Errorf("Item %s not found", k)
  303. }
  304. rv, ok := v.Object.(int64)
  305. if !ok {
  306. c.mu.Unlock()
  307. return 0, fmt.Errorf("The value for %s is not an int64", k)
  308. }
  309. nv := rv + n
  310. v.Object = nv
  311. c.items[k] = v
  312. c.mu.Unlock()
  313. return nv, nil
  314. }
  315. // Increment an item of type uint by n. Returns an error if the item's value is
  316. // not an uint, or if it was not found. If there is no error, the incremented
  317. // value is returned.
  318. func (c *cache) IncrementUint(k string, n uint) (uint, error) {
  319. c.mu.Lock()
  320. v, found := c.items[k]
  321. if !found || v.Expired() {
  322. c.mu.Unlock()
  323. return 0, fmt.Errorf("Item %s not found", k)
  324. }
  325. rv, ok := v.Object.(uint)
  326. if !ok {
  327. c.mu.Unlock()
  328. return 0, fmt.Errorf("The value for %s is not an uint", k)
  329. }
  330. nv := rv + n
  331. v.Object = nv
  332. c.items[k] = v
  333. c.mu.Unlock()
  334. return nv, nil
  335. }
  336. // Increment an item of type uintptr by n. Returns an error if the item's value
  337. // is not an uintptr, or if it was not found. If there is no error, the
  338. // incremented value is returned.
  339. func (c *cache) IncrementUintptr(k string, n uintptr) (uintptr, error) {
  340. c.mu.Lock()
  341. v, found := c.items[k]
  342. if !found || v.Expired() {
  343. c.mu.Unlock()
  344. return 0, fmt.Errorf("Item %s not found", k)
  345. }
  346. rv, ok := v.Object.(uintptr)
  347. if !ok {
  348. c.mu.Unlock()
  349. return 0, fmt.Errorf("The value for %s is not an uintptr", k)
  350. }
  351. nv := rv + n
  352. v.Object = nv
  353. c.items[k] = v
  354. c.mu.Unlock()
  355. return nv, nil
  356. }
  357. // Increment an item of type uint8 by n. Returns an error if the item's value
  358. // is not an uint8, or if it was not found. If there is no error, the
  359. // incremented value is returned.
  360. func (c *cache) IncrementUint8(k string, n uint8) (uint8, error) {
  361. c.mu.Lock()
  362. v, found := c.items[k]
  363. if !found || v.Expired() {
  364. c.mu.Unlock()
  365. return 0, fmt.Errorf("Item %s not found", k)
  366. }
  367. rv, ok := v.Object.(uint8)
  368. if !ok {
  369. c.mu.Unlock()
  370. return 0, fmt.Errorf("The value for %s is not an uint8", k)
  371. }
  372. nv := rv + n
  373. v.Object = nv
  374. c.items[k] = v
  375. c.mu.Unlock()
  376. return nv, nil
  377. }
  378. // Increment an item of type uint16 by n. Returns an error if the item's value
  379. // is not an uint16, or if it was not found. If there is no error, the
  380. // incremented value is returned.
  381. func (c *cache) IncrementUint16(k string, n uint16) (uint16, error) {
  382. c.mu.Lock()
  383. v, found := c.items[k]
  384. if !found || v.Expired() {
  385. c.mu.Unlock()
  386. return 0, fmt.Errorf("Item %s not found", k)
  387. }
  388. rv, ok := v.Object.(uint16)
  389. if !ok {
  390. c.mu.Unlock()
  391. return 0, fmt.Errorf("The value for %s is not an uint16", k)
  392. }
  393. nv := rv + n
  394. v.Object = nv
  395. c.items[k] = v
  396. c.mu.Unlock()
  397. return nv, nil
  398. }
  399. // Increment an item of type uint32 by n. Returns an error if the item's value
  400. // is not an uint32, or if it was not found. If there is no error, the
  401. // incremented value is returned.
  402. func (c *cache) IncrementUint32(k string, n uint32) (uint32, error) {
  403. c.mu.Lock()
  404. v, found := c.items[k]
  405. if !found || v.Expired() {
  406. c.mu.Unlock()
  407. return 0, fmt.Errorf("Item %s not found", k)
  408. }
  409. rv, ok := v.Object.(uint32)
  410. if !ok {
  411. c.mu.Unlock()
  412. return 0, fmt.Errorf("The value for %s is not an uint32", k)
  413. }
  414. nv := rv + n
  415. v.Object = nv
  416. c.items[k] = v
  417. c.mu.Unlock()
  418. return nv, nil
  419. }
  420. // Increment an item of type uint64 by n. Returns an error if the item's value
  421. // is not an uint64, or if it was not found. If there is no error, the
  422. // incremented value is returned.
  423. func (c *cache) IncrementUint64(k string, n uint64) (uint64, error) {
  424. c.mu.Lock()
  425. v, found := c.items[k]
  426. if !found || v.Expired() {
  427. c.mu.Unlock()
  428. return 0, fmt.Errorf("Item %s not found", k)
  429. }
  430. rv, ok := v.Object.(uint64)
  431. if !ok {
  432. c.mu.Unlock()
  433. return 0, fmt.Errorf("The value for %s is not an uint64", k)
  434. }
  435. nv := rv + n
  436. v.Object = nv
  437. c.items[k] = v
  438. c.mu.Unlock()
  439. return nv, nil
  440. }
  441. // Increment an item of type float32 by n. Returns an error if the item's value
  442. // is not an float32, or if it was not found. If there is no error, the
  443. // incremented value is returned.
  444. func (c *cache) IncrementFloat32(k string, n float32) (float32, error) {
  445. c.mu.Lock()
  446. v, found := c.items[k]
  447. if !found || v.Expired() {
  448. c.mu.Unlock()
  449. return 0, fmt.Errorf("Item %s not found", k)
  450. }
  451. rv, ok := v.Object.(float32)
  452. if !ok {
  453. c.mu.Unlock()
  454. return 0, fmt.Errorf("The value for %s is not an float32", k)
  455. }
  456. nv := rv + n
  457. v.Object = nv
  458. c.items[k] = v
  459. c.mu.Unlock()
  460. return nv, nil
  461. }
  462. // Increment an item of type float64 by n. Returns an error if the item's value
  463. // is not an float64, or if it was not found. If there is no error, the
  464. // incremented value is returned.
  465. func (c *cache) IncrementFloat64(k string, n float64) (float64, error) {
  466. c.mu.Lock()
  467. v, found := c.items[k]
  468. if !found || v.Expired() {
  469. c.mu.Unlock()
  470. return 0, fmt.Errorf("Item %s not found", k)
  471. }
  472. rv, ok := v.Object.(float64)
  473. if !ok {
  474. c.mu.Unlock()
  475. return 0, fmt.Errorf("The value for %s is not an float64", k)
  476. }
  477. nv := rv + n
  478. v.Object = nv
  479. c.items[k] = v
  480. c.mu.Unlock()
  481. return nv, nil
  482. }
  483. // Decrement an item of type int, int8, int16, int32, int64, uintptr, uint,
  484. // uint8, uint32, or uint64, float32 or float64 by n. Returns an error if the
  485. // item's value is not an integer, if it was not found, or if it is not
  486. // possible to decrement it by n. To retrieve the decremented value, use one
  487. // of the specialized methods, e.g. DecrementInt64.
  488. func (c *cache) Decrement(k string, n int64) error {
  489. // TODO: Implement Increment and Decrement more cleanly.
  490. // (Cannot do Increment(k, n*-1) for uints.)
  491. c.mu.Lock()
  492. v, found := c.items[k]
  493. if !found || v.Expired() {
  494. c.mu.Unlock()
  495. return fmt.Errorf("Item not found")
  496. }
  497. switch v.Object.(type) {
  498. case int:
  499. v.Object = v.Object.(int) - int(n)
  500. case int8:
  501. v.Object = v.Object.(int8) - int8(n)
  502. case int16:
  503. v.Object = v.Object.(int16) - int16(n)
  504. case int32:
  505. v.Object = v.Object.(int32) - int32(n)
  506. case int64:
  507. v.Object = v.Object.(int64) - n
  508. case uint:
  509. v.Object = v.Object.(uint) - uint(n)
  510. case uintptr:
  511. v.Object = v.Object.(uintptr) - uintptr(n)
  512. case uint8:
  513. v.Object = v.Object.(uint8) - uint8(n)
  514. case uint16:
  515. v.Object = v.Object.(uint16) - uint16(n)
  516. case uint32:
  517. v.Object = v.Object.(uint32) - uint32(n)
  518. case uint64:
  519. v.Object = v.Object.(uint64) - uint64(n)
  520. case float32:
  521. v.Object = v.Object.(float32) - float32(n)
  522. case float64:
  523. v.Object = v.Object.(float64) - float64(n)
  524. default:
  525. c.mu.Unlock()
  526. return fmt.Errorf("The value for %s is not an integer", k)
  527. }
  528. c.items[k] = v
  529. c.mu.Unlock()
  530. return nil
  531. }
  532. // Decrement an item of type float32 or float64 by n. Returns an error if the
  533. // item's value is not floating point, if it was not found, or if it is not
  534. // possible to decrement it by n. Pass a negative number to decrement the
  535. // value. To retrieve the decremented value, use one of the specialized methods,
  536. // e.g. DecrementFloat64.
  537. func (c *cache) DecrementFloat(k string, n float64) error {
  538. c.mu.Lock()
  539. v, found := c.items[k]
  540. if !found || v.Expired() {
  541. c.mu.Unlock()
  542. return fmt.Errorf("Item %s not found", k)
  543. }
  544. switch v.Object.(type) {
  545. case float32:
  546. v.Object = v.Object.(float32) - float32(n)
  547. case float64:
  548. v.Object = v.Object.(float64) - n
  549. default:
  550. c.mu.Unlock()
  551. return fmt.Errorf("The value for %s does not have type float32 or float64", k)
  552. }
  553. c.items[k] = v
  554. c.mu.Unlock()
  555. return nil
  556. }
  557. // Decrement an item of type int by n. Returns an error if the item's value is
  558. // not an int, or if it was not found. If there is no error, the decremented
  559. // value is returned.
  560. func (c *cache) DecrementInt(k string, n int) (int, error) {
  561. c.mu.Lock()
  562. v, found := c.items[k]
  563. if !found || v.Expired() {
  564. c.mu.Unlock()
  565. return 0, fmt.Errorf("Item %s not found", k)
  566. }
  567. rv, ok := v.Object.(int)
  568. if !ok {
  569. c.mu.Unlock()
  570. return 0, fmt.Errorf("The value for %s is not an int", k)
  571. }
  572. nv := rv - n
  573. v.Object = nv
  574. c.items[k] = v
  575. c.mu.Unlock()
  576. return nv, nil
  577. }
  578. // Decrement an item of type int8 by n. Returns an error if the item's value is
  579. // not an int8, or if it was not found. If there is no error, the decremented
  580. // value is returned.
  581. func (c *cache) DecrementInt8(k string, n int8) (int8, error) {
  582. c.mu.Lock()
  583. v, found := c.items[k]
  584. if !found || v.Expired() {
  585. c.mu.Unlock()
  586. return 0, fmt.Errorf("Item %s not found", k)
  587. }
  588. rv, ok := v.Object.(int8)
  589. if !ok {
  590. c.mu.Unlock()
  591. return 0, fmt.Errorf("The value for %s is not an int8", k)
  592. }
  593. nv := rv - n
  594. v.Object = nv
  595. c.items[k] = v
  596. c.mu.Unlock()
  597. return nv, nil
  598. }
  599. // Decrement an item of type int16 by n. Returns an error if the item's value is
  600. // not an int16, or if it was not found. If there is no error, the decremented
  601. // value is returned.
  602. func (c *cache) DecrementInt16(k string, n int16) (int16, error) {
  603. c.mu.Lock()
  604. v, found := c.items[k]
  605. if !found || v.Expired() {
  606. c.mu.Unlock()
  607. return 0, fmt.Errorf("Item %s not found", k)
  608. }
  609. rv, ok := v.Object.(int16)
  610. if !ok {
  611. c.mu.Unlock()
  612. return 0, fmt.Errorf("The value for %s is not an int16", k)
  613. }
  614. nv := rv - n
  615. v.Object = nv
  616. c.items[k] = v
  617. c.mu.Unlock()
  618. return nv, nil
  619. }
  620. // Decrement an item of type int32 by n. Returns an error if the item's value is
  621. // not an int32, or if it was not found. If there is no error, the decremented
  622. // value is returned.
  623. func (c *cache) DecrementInt32(k string, n int32) (int32, error) {
  624. c.mu.Lock()
  625. v, found := c.items[k]
  626. if !found || v.Expired() {
  627. c.mu.Unlock()
  628. return 0, fmt.Errorf("Item %s not found", k)
  629. }
  630. rv, ok := v.Object.(int32)
  631. if !ok {
  632. c.mu.Unlock()
  633. return 0, fmt.Errorf("The value for %s is not an int32", k)
  634. }
  635. nv := rv - n
  636. v.Object = nv
  637. c.items[k] = v
  638. c.mu.Unlock()
  639. return nv, nil
  640. }
  641. // Decrement an item of type int64 by n. Returns an error if the item's value is
  642. // not an int64, or if it was not found. If there is no error, the decremented
  643. // value is returned.
  644. func (c *cache) DecrementInt64(k string, n int64) (int64, error) {
  645. c.mu.Lock()
  646. v, found := c.items[k]
  647. if !found || v.Expired() {
  648. c.mu.Unlock()
  649. return 0, fmt.Errorf("Item %s not found", k)
  650. }
  651. rv, ok := v.Object.(int64)
  652. if !ok {
  653. c.mu.Unlock()
  654. return 0, fmt.Errorf("The value for %s is not an int64", k)
  655. }
  656. nv := rv - n
  657. v.Object = nv
  658. c.items[k] = v
  659. c.mu.Unlock()
  660. return nv, nil
  661. }
  662. // Decrement an item of type uint by n. Returns an error if the item's value is
  663. // not an uint, or if it was not found. If there is no error, the decremented
  664. // value is returned.
  665. func (c *cache) DecrementUint(k string, n uint) (uint, error) {
  666. c.mu.Lock()
  667. v, found := c.items[k]
  668. if !found || v.Expired() {
  669. c.mu.Unlock()
  670. return 0, fmt.Errorf("Item %s not found", k)
  671. }
  672. rv, ok := v.Object.(uint)
  673. if !ok {
  674. c.mu.Unlock()
  675. return 0, fmt.Errorf("The value for %s is not an uint", k)
  676. }
  677. nv := rv - n
  678. v.Object = nv
  679. c.items[k] = v
  680. c.mu.Unlock()
  681. return nv, nil
  682. }
  683. // Decrement an item of type uintptr by n. Returns an error if the item's value
  684. // is not an uintptr, or if it was not found. If there is no error, the
  685. // decremented value is returned.
  686. func (c *cache) DecrementUintptr(k string, n uintptr) (uintptr, error) {
  687. c.mu.Lock()
  688. v, found := c.items[k]
  689. if !found || v.Expired() {
  690. c.mu.Unlock()
  691. return 0, fmt.Errorf("Item %s not found", k)
  692. }
  693. rv, ok := v.Object.(uintptr)
  694. if !ok {
  695. c.mu.Unlock()
  696. return 0, fmt.Errorf("The value for %s is not an uintptr", k)
  697. }
  698. nv := rv - n
  699. v.Object = nv
  700. c.items[k] = v
  701. c.mu.Unlock()
  702. return nv, nil
  703. }
  704. // Decrement an item of type uint8 by n. Returns an error if the item's value is
  705. // not an uint8, or if it was not found. If there is no error, the decremented
  706. // value is returned.
  707. func (c *cache) DecrementUint8(k string, n uint8) (uint8, error) {
  708. c.mu.Lock()
  709. v, found := c.items[k]
  710. if !found || v.Expired() {
  711. c.mu.Unlock()
  712. return 0, fmt.Errorf("Item %s not found", k)
  713. }
  714. rv, ok := v.Object.(uint8)
  715. if !ok {
  716. c.mu.Unlock()
  717. return 0, fmt.Errorf("The value for %s is not an uint8", k)
  718. }
  719. nv := rv - n
  720. v.Object = nv
  721. c.items[k] = v
  722. c.mu.Unlock()
  723. return nv, nil
  724. }
  725. // Decrement an item of type uint16 by n. Returns an error if the item's value
  726. // is not an uint16, or if it was not found. If there is no error, the
  727. // decremented value is returned.
  728. func (c *cache) DecrementUint16(k string, n uint16) (uint16, error) {
  729. c.mu.Lock()
  730. v, found := c.items[k]
  731. if !found || v.Expired() {
  732. c.mu.Unlock()
  733. return 0, fmt.Errorf("Item %s not found", k)
  734. }
  735. rv, ok := v.Object.(uint16)
  736. if !ok {
  737. c.mu.Unlock()
  738. return 0, fmt.Errorf("The value for %s is not an uint16", k)
  739. }
  740. nv := rv - n
  741. v.Object = nv
  742. c.items[k] = v
  743. c.mu.Unlock()
  744. return nv, nil
  745. }
  746. // Decrement an item of type uint32 by n. Returns an error if the item's value
  747. // is not an uint32, or if it was not found. If there is no error, the
  748. // decremented value is returned.
  749. func (c *cache) DecrementUint32(k string, n uint32) (uint32, error) {
  750. c.mu.Lock()
  751. v, found := c.items[k]
  752. if !found || v.Expired() {
  753. c.mu.Unlock()
  754. return 0, fmt.Errorf("Item %s not found", k)
  755. }
  756. rv, ok := v.Object.(uint32)
  757. if !ok {
  758. c.mu.Unlock()
  759. return 0, fmt.Errorf("The value for %s is not an uint32", k)
  760. }
  761. nv := rv - n
  762. v.Object = nv
  763. c.items[k] = v
  764. c.mu.Unlock()
  765. return nv, nil
  766. }
  767. // Decrement an item of type uint64 by n. Returns an error if the item's value
  768. // is not an uint64, or if it was not found. If there is no error, the
  769. // decremented value is returned.
  770. func (c *cache) DecrementUint64(k string, n uint64) (uint64, error) {
  771. c.mu.Lock()
  772. v, found := c.items[k]
  773. if !found || v.Expired() {
  774. c.mu.Unlock()
  775. return 0, fmt.Errorf("Item %s not found", k)
  776. }
  777. rv, ok := v.Object.(uint64)
  778. if !ok {
  779. c.mu.Unlock()
  780. return 0, fmt.Errorf("The value for %s is not an uint64", k)
  781. }
  782. nv := rv - n
  783. v.Object = nv
  784. c.items[k] = v
  785. c.mu.Unlock()
  786. return nv, nil
  787. }
  788. // Decrement an item of type float32 by n. Returns an error if the item's value
  789. // is not an float32, or if it was not found. If there is no error, the
  790. // decremented value is returned.
  791. func (c *cache) DecrementFloat32(k string, n float32) (float32, error) {
  792. c.mu.Lock()
  793. v, found := c.items[k]
  794. if !found || v.Expired() {
  795. c.mu.Unlock()
  796. return 0, fmt.Errorf("Item %s not found", k)
  797. }
  798. rv, ok := v.Object.(float32)
  799. if !ok {
  800. c.mu.Unlock()
  801. return 0, fmt.Errorf("The value for %s is not an float32", k)
  802. }
  803. nv := rv - n
  804. v.Object = nv
  805. c.items[k] = v
  806. c.mu.Unlock()
  807. return nv, nil
  808. }
  809. // Decrement an item of type float64 by n. Returns an error if the item's value
  810. // is not an float64, or if it was not found. If there is no error, the
  811. // decremented value is returned.
  812. func (c *cache) DecrementFloat64(k string, n float64) (float64, error) {
  813. c.mu.Lock()
  814. v, found := c.items[k]
  815. if !found || v.Expired() {
  816. c.mu.Unlock()
  817. return 0, fmt.Errorf("Item %s not found", k)
  818. }
  819. rv, ok := v.Object.(float64)
  820. if !ok {
  821. c.mu.Unlock()
  822. return 0, fmt.Errorf("The value for %s is not an float64", k)
  823. }
  824. nv := rv - n
  825. v.Object = nv
  826. c.items[k] = v
  827. c.mu.Unlock()
  828. return nv, nil
  829. }
  830. // Delete an item from the cache. Does nothing if the key is not in the cache.
  831. func (c *cache) Delete(k string) {
  832. c.mu.Lock()
  833. v, evicted := c.delete(k)
  834. c.mu.Unlock()
  835. if evicted {
  836. c.onEvicted(k, v)
  837. }
  838. }
  839. func (c *cache) delete(k string) (interface{}, bool) {
  840. if c.onEvicted != nil {
  841. if v, found := c.items[k]; found {
  842. delete(c.items, k)
  843. return v.Object, true
  844. }
  845. }
  846. delete(c.items, k)
  847. return nil, false
  848. }
  849. type keyAndValue struct {
  850. key string
  851. value interface{}
  852. }
  853. // Delete all expired items from the cache.
  854. func (c *cache) DeleteExpired() {
  855. var evictedItems []keyAndValue
  856. now := time.Now().UnixNano()
  857. c.mu.Lock()
  858. for k, v := range c.items {
  859. // "Inlining" of expired
  860. if v.Expiration > 0 && now > v.Expiration {
  861. ov, evicted := c.delete(k)
  862. if evicted {
  863. evictedItems = append(evictedItems, keyAndValue{k, ov})
  864. }
  865. }
  866. }
  867. c.mu.Unlock()
  868. for _, v := range evictedItems {
  869. c.onEvicted(v.key, v.value)
  870. }
  871. }
  872. // Sets an (optional) function that is called with the key and value when an
  873. // item is evicted from the cache. (Including when it is deleted manually, but
  874. // not when it is overwritten.) Set to nil to disable.
  875. func (c *cache) OnEvicted(f func(string, interface{})) {
  876. c.mu.Lock()
  877. c.onEvicted = f
  878. c.mu.Unlock()
  879. }
  880. // Write the cache's items (using Gob) to an io.Writer.
  881. //
  882. // NOTE: This method is deprecated in favor of c.Items() and NewFrom() (see the
  883. // documentation for NewFrom().)
  884. func (c *cache) Save(w io.Writer) (err error) {
  885. enc := gob.NewEncoder(w)
  886. defer func() {
  887. if x := recover(); x != nil {
  888. err = fmt.Errorf("Error registering item types with Gob library")
  889. }
  890. }()
  891. c.mu.RLock()
  892. defer c.mu.RUnlock()
  893. for _, v := range c.items {
  894. gob.Register(v.Object)
  895. }
  896. err = enc.Encode(&c.items)
  897. return
  898. }
  899. // Save the cache's items to the given filename, creating the file if it
  900. // doesn't exist, and overwriting it if it does.
  901. //
  902. // NOTE: This method is deprecated in favor of c.Items() and NewFrom() (see the
  903. // documentation for NewFrom().)
  904. func (c *cache) SaveFile(fname string) error {
  905. fp, err := os.Create(fname)
  906. if err != nil {
  907. return err
  908. }
  909. err = c.Save(fp)
  910. if err != nil {
  911. fp.Close()
  912. return err
  913. }
  914. return fp.Close()
  915. }
  916. // Add (Gob-serialized) cache items from an io.Reader, excluding any items with
  917. // keys that already exist (and haven't expired) in the current cache.
  918. //
  919. // NOTE: This method is deprecated in favor of c.Items() and NewFrom() (see the
  920. // documentation for NewFrom().)
  921. func (c *cache) Load(r io.Reader) error {
  922. dec := gob.NewDecoder(r)
  923. items := map[string]Item{}
  924. err := dec.Decode(&items)
  925. if err == nil {
  926. c.mu.Lock()
  927. defer c.mu.Unlock()
  928. for k, v := range items {
  929. ov, found := c.items[k]
  930. if !found || ov.Expired() {
  931. c.items[k] = v
  932. }
  933. }
  934. }
  935. return err
  936. }
  937. // Load and add cache items from the given filename, excluding any items with
  938. // keys that already exist in the current cache.
  939. //
  940. // NOTE: This method is deprecated in favor of c.Items() and NewFrom() (see the
  941. // documentation for NewFrom().)
  942. func (c *cache) LoadFile(fname string) error {
  943. fp, err := os.Open(fname)
  944. if err != nil {
  945. return err
  946. }
  947. err = c.Load(fp)
  948. if err != nil {
  949. fp.Close()
  950. return err
  951. }
  952. return fp.Close()
  953. }
  954. // Copies all unexpired items in the cache into a new map and returns it.
  955. func (c *cache) Items() map[string]Item {
  956. c.mu.RLock()
  957. defer c.mu.RUnlock()
  958. m := make(map[string]Item, len(c.items))
  959. now := time.Now().UnixNano()
  960. for k, v := range c.items {
  961. // "Inlining" of Expired
  962. if v.Expiration > 0 {
  963. if now > v.Expiration {
  964. continue
  965. }
  966. }
  967. m[k] = v
  968. }
  969. return m
  970. }
  971. // Returns the number of items in the cache. This may include items that have
  972. // expired, but have not yet been cleaned up.
  973. func (c *cache) ItemCount() int {
  974. c.mu.RLock()
  975. n := len(c.items)
  976. c.mu.RUnlock()
  977. return n
  978. }
  979. // Delete all items from the cache.
  980. func (c *cache) Flush() {
  981. c.mu.Lock()
  982. c.items = map[string]Item{}
  983. c.mu.Unlock()
  984. }
  985. type janitor struct {
  986. Interval time.Duration
  987. stop chan bool
  988. }
  989. func (j *janitor) Run(c *cache) {
  990. j.stop = make(chan bool)
  991. ticker := time.NewTicker(j.Interval)
  992. for {
  993. select {
  994. case <-ticker.C:
  995. c.DeleteExpired()
  996. case <-j.stop:
  997. ticker.Stop()
  998. return
  999. }
  1000. }
  1001. }
  1002. func stopJanitor(c *Cache) {
  1003. c.janitor.stop <- true
  1004. }
  1005. func runJanitor(c *cache, ci time.Duration) {
  1006. j := &janitor{
  1007. Interval: ci,
  1008. }
  1009. c.janitor = j
  1010. go j.Run(c)
  1011. }
  1012. func newCache(de time.Duration, m map[string]Item) *cache {
  1013. if de == 0 {
  1014. de = -1
  1015. }
  1016. c := &cache{
  1017. defaultExpiration: de,
  1018. items: m,
  1019. }
  1020. return c
  1021. }
  1022. func newCacheWithJanitor(de time.Duration, ci time.Duration, m map[string]Item) *Cache {
  1023. c := newCache(de, m)
  1024. // This trick ensures that the janitor goroutine (which--granted it
  1025. // was enabled--is running DeleteExpired on c forever) does not keep
  1026. // the returned C object from being garbage collected. When it is
  1027. // garbage collected, the finalizer stops the janitor goroutine, after
  1028. // which c can be collected.
  1029. C := &Cache{c}
  1030. if ci > 0 {
  1031. runJanitor(c, ci)
  1032. runtime.SetFinalizer(C, stopJanitor)
  1033. }
  1034. return C
  1035. }
  1036. // Return a new cache with a given default expiration duration and cleanup
  1037. // interval. If the expiration duration is less than one (or NoExpiration),
  1038. // the items in the cache never expire (by default), and must be deleted
  1039. // manually. If the cleanup interval is less than one, expired items are not
  1040. // deleted from the cache before calling c.DeleteExpired().
  1041. func New(defaultExpiration, cleanupInterval time.Duration) *Cache {
  1042. items := make(map[string]Item)
  1043. return newCacheWithJanitor(defaultExpiration, cleanupInterval, items)
  1044. }
  1045. // Return a new cache with a given default expiration duration and cleanup
  1046. // interval. If the expiration duration is less than one (or NoExpiration),
  1047. // the items in the cache never expire (by default), and must be deleted
  1048. // manually. If the cleanup interval is less than one, expired items are not
  1049. // deleted from the cache before calling c.DeleteExpired().
  1050. //
  1051. // NewFrom() also accepts an items map which will serve as the underlying map
  1052. // for the cache. This is useful for starting from a deserialized cache
  1053. // (serialized using e.g. gob.Encode() on c.Items()), or passing in e.g.
  1054. // make(map[string]Item, 500) to improve startup performance when the cache
  1055. // is expected to reach a certain minimum size.
  1056. //
  1057. // Only the cache's methods synchronize access to this map, so it is not
  1058. // recommended to keep any references to the map around after creating a cache.
  1059. // If need be, the map can be accessed at a later point using c.Items() (subject
  1060. // to the same caveat.)
  1061. //
  1062. // Note regarding serialization: When using e.g. gob, make sure to
  1063. // gob.Register() the individual types stored in the cache before encoding a
  1064. // map retrieved with c.Items(), and to register those same types before
  1065. // decoding a blob containing an items map.
  1066. func NewFrom(defaultExpiration, cleanupInterval time.Duration, items map[string]Item) *Cache {
  1067. return newCacheWithJanitor(defaultExpiration, cleanupInterval, items)
  1068. }