You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
2.9 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. package chunk_cache
  2. import (
  3. "sync"
  4. "github.com/chrislusf/seaweedfs/weed/glog"
  5. "github.com/chrislusf/seaweedfs/weed/storage/needle"
  6. )
  7. type ChunkCache interface {
  8. GetChunk(fileId string, minSize uint64) (data []byte)
  9. SetChunk(fileId string, data []byte)
  10. }
  11. // a global cache for recently accessed file chunks
  12. type TieredChunkCache struct {
  13. memCache *ChunkCacheInMemory
  14. diskCaches []*OnDiskCacheLayer
  15. sync.RWMutex
  16. onDiskCacheSizeLimit0 uint64
  17. onDiskCacheSizeLimit1 uint64
  18. }
  19. func NewTieredChunkCache(maxEntries int64, dir string, diskSizeInUnit int64, unitSize int64) *TieredChunkCache {
  20. c := &TieredChunkCache{
  21. memCache: NewChunkCacheInMemory(maxEntries),
  22. }
  23. c.diskCaches = make([]*OnDiskCacheLayer, 3)
  24. c.onDiskCacheSizeLimit0 = uint64(unitSize)
  25. c.onDiskCacheSizeLimit1 = 4 * c.onDiskCacheSizeLimit0
  26. c.diskCaches[0] = NewOnDiskCacheLayer(dir, "c0_1", diskSizeInUnit*unitSize/4, 4)
  27. c.diskCaches[1] = NewOnDiskCacheLayer(dir, "c1_4", diskSizeInUnit*unitSize/4, 4)
  28. c.diskCaches[2] = NewOnDiskCacheLayer(dir, "cache", diskSizeInUnit*unitSize/2, 4)
  29. return c
  30. }
  31. func (c *TieredChunkCache) GetChunk(fileId string, minSize uint64) (data []byte) {
  32. if c == nil {
  33. return
  34. }
  35. c.RLock()
  36. defer c.RUnlock()
  37. return c.doGetChunk(fileId, minSize)
  38. }
  39. func (c *TieredChunkCache) doGetChunk(fileId string, minSize uint64) (data []byte) {
  40. if minSize < c.onDiskCacheSizeLimit0 {
  41. data = c.memCache.GetChunk(fileId)
  42. if len(data) >= int(minSize) {
  43. return data
  44. }
  45. }
  46. fid, err := needle.ParseFileIdFromString(fileId)
  47. if err != nil {
  48. glog.Errorf("failed to parse file id %s", fileId)
  49. return nil
  50. }
  51. if minSize < c.onDiskCacheSizeLimit0 {
  52. data = c.diskCaches[0].getChunk(fid.Key)
  53. if len(data) >= int(minSize) {
  54. return data
  55. }
  56. }
  57. if minSize < c.onDiskCacheSizeLimit1 {
  58. data = c.diskCaches[1].getChunk(fid.Key)
  59. if len(data) >= int(minSize) {
  60. return data
  61. }
  62. }
  63. {
  64. data = c.diskCaches[2].getChunk(fid.Key)
  65. if len(data) >= int(minSize) {
  66. return data
  67. }
  68. }
  69. return nil
  70. }
  71. func (c *TieredChunkCache) SetChunk(fileId string, data []byte) {
  72. if c == nil {
  73. return
  74. }
  75. c.Lock()
  76. defer c.Unlock()
  77. glog.V(4).Infof("SetChunk %s size %d\n", fileId, len(data))
  78. c.doSetChunk(fileId, data)
  79. }
  80. func (c *TieredChunkCache) doSetChunk(fileId string, data []byte) {
  81. if len(data) < int(c.onDiskCacheSizeLimit0) {
  82. c.memCache.SetChunk(fileId, data)
  83. }
  84. fid, err := needle.ParseFileIdFromString(fileId)
  85. if err != nil {
  86. glog.Errorf("failed to parse file id %s", fileId)
  87. return
  88. }
  89. if len(data) < int(c.onDiskCacheSizeLimit0) {
  90. c.diskCaches[0].setChunk(fid.Key, data)
  91. } else if len(data) < int(c.onDiskCacheSizeLimit1) {
  92. c.diskCaches[1].setChunk(fid.Key, data)
  93. } else {
  94. c.diskCaches[2].setChunk(fid.Key, data)
  95. }
  96. }
  97. func (c *TieredChunkCache) Shutdown() {
  98. if c == nil {
  99. return
  100. }
  101. c.Lock()
  102. defer c.Unlock()
  103. for _, diskCache := range c.diskCaches {
  104. diskCache.shutdown()
  105. }
  106. }