Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/mount: add an option cache-eviction to specify the policy #3478

Merged
merged 3 commits into from
Apr 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions cmd/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,11 @@ func clientFlags() []cli.Flag {
Value: "full",
Usage: "checksum level (none, full, shrink, extend)",
},
&cli.StringFlag{
Name: "cache-eviction",
Value: "2-random",
Usage: "cache eviction policy (none or 2-random)",
},
&cli.StringFlag{
Name: "cache-scan-interval",
Value: "3600",
Expand Down
1 change: 1 addition & 0 deletions cmd/mount.go
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ func getChunkConf(c *cli.Context, format *meta.Format) *chunk.Config {
CacheMode: os.FileMode(cm),
CacheFullBlock: !c.Bool("cache-partial-only"),
CacheChecksum: c.String("verify-cache-checksum"),
CacheEviction: c.String("cache-eviction"),
CacheScanInterval: duration(c.String("cache-scan-interval")),
AutoCreate: true,
}
Expand Down
7 changes: 7 additions & 0 deletions pkg/chunk/cached_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,7 @@ type Config struct {
CacheMode os.FileMode
CacheSize int64
CacheChecksum string
CacheEviction string
CacheScanInterval time.Duration
FreeSpace float32
AutoCreate bool
Expand Down Expand Up @@ -574,6 +575,12 @@ func (c *Config) SelfCheck(uuid string) {
c.CacheChecksum = CsFull
}
}
if c.CacheEviction == "" {
c.CacheEviction = "2-random"
} else if c.CacheEviction != "2-random" && c.CacheEviction != "none" {
logger.Warnf("cache-eviction should be one of [2-random, none]")
c.CacheEviction = "2-random"
}
}

type cachedStore struct {
Expand Down
39 changes: 24 additions & 15 deletions pkg/chunk/disk_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,14 @@ type cacheStore struct {
pages map[string]*Page
m *cacheManagerMetrics

used int64
keys map[cacheKey]cacheItem
scanned bool
full bool
checksum string // checksum level
uploader func(key, path string, force bool) bool
used int64
keys map[cacheKey]cacheItem
scanned bool
stageFull bool
rawFull bool
eviction string
checksum string // checksum level
uploader func(key, path string, force bool) bool
}

func newCacheStore(m *cacheManagerMetrics, dir string, cacheSize int64, pendingPages int, config *Config, uploader func(key, path string, force bool) bool) *cacheStore {
Expand All @@ -94,6 +96,7 @@ func newCacheStore(m *cacheManagerMetrics, dir string, cacheSize int64, pendingP
mode: config.CacheMode,
capacity: cacheSize,
freeRatio: config.FreeSpace,
eviction: config.CacheEviction,
checksum: config.CacheChecksum,
hashPrefix: config.HashPrefix,
scanInterval: config.CacheScanInterval,
Expand Down Expand Up @@ -128,17 +131,18 @@ func (cache *cacheStore) stats() (int64, int64) {
func (cache *cacheStore) checkFreeSpace() {
for {
br, fr := cache.curFreeRatio()
cache.full = br < cache.freeRatio/2 || fr < cache.freeRatio/2
if br < cache.freeRatio || fr < cache.freeRatio {
cache.stageFull = br < cache.freeRatio/2 || fr < cache.freeRatio/2
cache.rawFull = br < cache.freeRatio || fr < cache.freeRatio
if cache.rawFull && cache.eviction != "none" {
logger.Tracef("Cleanup cache when check free space (%s): free ratio (%d%%), space usage (%d%%), inodes usage (%d%%)", cache.dir, int(cache.freeRatio*100), int(br*100), int(fr*100))
cache.Lock()
cache.cleanup()
cache.Unlock()

br, fr = cache.curFreeRatio()
if br < cache.freeRatio || fr < cache.freeRatio {
cache.uploadStaging()
}
cache.rawFull = br < cache.freeRatio || fr < cache.freeRatio
}
if cache.rawFull {
cache.uploadStaging()
}
time.Sleep(time.Second)
}
Expand Down Expand Up @@ -173,6 +177,11 @@ func (cache *cacheStore) cache(key string, p *Page, force bool) {
if cache.capacity == 0 {
return
}
if cache.rawFull && cache.eviction == "none" {
logger.Debugf("Caching directory is full (%s), drop %s (%d bytes)", cache.dir, key, len(p.Data))
cache.m.cacheDrops.Add(1)
return
}
cache.Lock()
defer cache.Unlock()
if _, ok := cache.pages[key]; ok {
Expand Down Expand Up @@ -394,16 +403,16 @@ func (cache *cacheStore) add(key string, size int32, atime uint32) {
cache.used += int64(size + 4096)
}

if cache.used > cache.capacity {
if cache.used > cache.capacity && cache.eviction != "none" {
logger.Debugf("Cleanup cache when add new data (%s): %d blocks (%d MB)", cache.dir, len(cache.keys), cache.used>>20)
cache.cleanup()
}
}

func (cache *cacheStore) stage(key string, data []byte, keepCache bool) (string, error) {
stagingPath := cache.stagePath(key)
if cache.full {
return stagingPath, errors.New("Space not enough on device")
if cache.stageFull {
return stagingPath, errors.New("space not enough on device")
}
err := cache.flushPage(stagingPath, data)
if err == nil {
Expand Down
7 changes: 7 additions & 0 deletions pkg/chunk/mem_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type memcache struct {
capacity int64
used int64
pages map[string]memItem
eviction string

metrics *cacheManagerMetrics
}
Expand All @@ -41,6 +42,7 @@ func newMemStore(config *Config, metrics *cacheManagerMetrics) *memcache {
c := &memcache{
capacity: config.CacheSize << 20,
pages: make(map[string]memItem),
eviction: config.CacheEviction,
metrics: metrics,
}
runtime.SetFinalizer(c, func(c *memcache) {
Expand Down Expand Up @@ -74,6 +76,11 @@ func (c *memcache) cache(key string, p *Page, force bool) {
}
c.Lock()
defer c.Unlock()
if c.used > c.capacity && c.eviction == "none" {
logger.Debugf("Caching is full, drop %s (%d bytes)", key, len(p.Data))
c.metrics.cacheDrops.Add(1)
return
}
if _, ok := c.pages[key]; ok {
return
}
Expand Down
2 changes: 2 additions & 0 deletions sdk/java/libjfs/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ type javaConf struct {
AutoCreate bool `json:"autoCreate"`
CacheFullBlock bool `json:"cacheFullBlock"`
CacheChecksum string `json:"cacheChecksum"`
CacheEviction string `json:"cacheEviction"`
CacheScanInterval int `json:"cacheScanInterval"`
Writeback bool `json:"writeback"`
MemorySize int `json:"memorySize"`
Expand Down Expand Up @@ -495,6 +496,7 @@ func jfs_init(cname, jsonConf, user, group, superuser, supergroup *C.char) uintp
AutoCreate: jConf.AutoCreate,
CacheFullBlock: jConf.CacheFullBlock,
CacheChecksum: jConf.CacheChecksum,
CacheEviction: jConf.CacheEviction,
CacheScanInterval: time.Second * time.Duration(jConf.CacheScanInterval),
MaxUpload: jConf.MaxUploads,
MaxRetries: jConf.IORetries,
Expand Down
1 change: 1 addition & 0 deletions sdk/java/src/main/java/io/juicefs/JuiceFileSystemImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ public void initialize(URI uri, Configuration conf) throws IOException {
obj.put("dirEntryTimeout", Float.valueOf(getConf(conf, "dir-entry-cache", "0.0")));
obj.put("cacheFullBlock", Boolean.valueOf(getConf(conf, "cache-full-block", "true")));
obj.put("cacheChecksum", getConf(conf, "verify-cache-checksum", "full"));
obj.put("cacheEviction", getConf(conf, "cache-eviction", "2-random"));
obj.put("cacheScanInterval", Integer.valueOf(getConf(conf, "cache-scan-interval", "300")));
obj.put("metacache", Boolean.valueOf(getConf(conf, "metacache", "true")));
obj.put("autoCreate", Boolean.valueOf(getConf(conf, "auto-create-cache-dir", "true")));
Expand Down