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.

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