chunk_cache_in_memory.go 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. package chunk_cache
  2. import (
  3. "github.com/karlseguin/ccache/v2"
  4. "time"
  5. )
  6. var (
  7. _ ChunkCache = &ChunkCacheInMemory{}
  8. )
  9. // a global cache for recently accessed file chunks
  10. type ChunkCacheInMemory struct {
  11. cache *ccache.Cache
  12. }
  13. func (c *ChunkCacheInMemory) ReadChunkAt(data []byte, fileId string, offset uint64) (n int, err error) {
  14. return c.readChunkAt(data, fileId, offset)
  15. }
  16. func (c *ChunkCacheInMemory) IsInCache(fileId string, lockNeeded bool) (answer bool) {
  17. item := c.cache.Get(fileId)
  18. if item == nil {
  19. return false
  20. }
  21. return true
  22. }
  23. func (c *ChunkCacheInMemory) GetMaxFilePartSizeInCache() (answer uint64) {
  24. return 8 * 1024 * 1024
  25. }
  26. func NewChunkCacheInMemory(maxEntries int64) *ChunkCacheInMemory {
  27. pruneCount := maxEntries >> 3
  28. if pruneCount <= 0 {
  29. pruneCount = 500
  30. }
  31. return &ChunkCacheInMemory{
  32. cache: ccache.New(ccache.Configure().MaxSize(maxEntries).ItemsToPrune(uint32(pruneCount))),
  33. }
  34. }
  35. func (c *ChunkCacheInMemory) GetChunk(fileId string) []byte {
  36. item := c.cache.Get(fileId)
  37. if item == nil {
  38. return nil
  39. }
  40. data := item.Value().([]byte)
  41. item.Extend(time.Hour)
  42. return data
  43. }
  44. func (c *ChunkCacheInMemory) getChunkSlice(fileId string, offset, length uint64) ([]byte, error) {
  45. item := c.cache.Get(fileId)
  46. if item == nil {
  47. return nil, nil
  48. }
  49. data := item.Value().([]byte)
  50. item.Extend(time.Hour)
  51. wanted := min(int(length), len(data)-int(offset))
  52. if wanted < 0 {
  53. return nil, ErrorOutOfBounds
  54. }
  55. return data[offset : int(offset)+wanted], nil
  56. }
  57. func (c *ChunkCacheInMemory) readChunkAt(buffer []byte, fileId string, offset uint64) (int, error) {
  58. item := c.cache.Get(fileId)
  59. if item == nil {
  60. return 0, nil
  61. }
  62. data := item.Value().([]byte)
  63. item.Extend(time.Hour)
  64. wanted := min(len(buffer), len(data)-int(offset))
  65. if wanted < 0 {
  66. return 0, ErrorOutOfBounds
  67. }
  68. n := copy(buffer, data[offset:int(offset)+wanted])
  69. return n, nil
  70. }
  71. func (c *ChunkCacheInMemory) SetChunk(fileId string, data []byte) {
  72. localCopy := make([]byte, len(data))
  73. copy(localCopy, data)
  74. c.cache.Set(fileId, localCopy, time.Hour)
  75. }