mirror of
https://github.com/s3fs-fuse/s3fs-fuse.git
synced 2025-02-08 21:48:26 +00:00
In memory cache for softlinks with cache out
This commit is contained in:
parent
bdfb9ee815
commit
23945a0130
@ -156,13 +156,13 @@ time to wait between read/write activity before giving up.
|
|||||||
specify the maximum number of keys returned by S3 list object API. The default is 1000. you can set this value to 1000 or more.
|
specify the maximum number of keys returned by S3 list object API. The default is 1000. you can set this value to 1000 or more.
|
||||||
.TP
|
.TP
|
||||||
\fB\-o\fR max_stat_cache_size (default="100,000" entries (about 40MB))
|
\fB\-o\fR max_stat_cache_size (default="100,000" entries (about 40MB))
|
||||||
maximum number of entries in the stat cache
|
maximum number of entries in the stat cache and symbolic link cache.
|
||||||
.TP
|
.TP
|
||||||
\fB\-o\fR stat_cache_expire (default is no expire)
|
\fB\-o\fR stat_cache_expire (default is no expire)
|
||||||
specify expire time (seconds) for entries in the stat cache. This expire time indicates the time since stat cached.
|
specify expire time (seconds) for entries in the stat cache and symbolic link cache. This expire time indicates the time since cached.
|
||||||
.TP
|
.TP
|
||||||
\fB\-o\fR stat_cache_interval_expire (default is no expire)
|
\fB\-o\fR stat_cache_interval_expire (default is no expire)
|
||||||
specify expire time (seconds) for entries in the stat cache. This expire time is based on the time from the last access time of the stat cache.
|
specify expire time (seconds) for entries in the stat cache and symbolic link cache. This expire time is based on the time from the last access time of those cache.
|
||||||
This option is exclusive with stat_cache_expire, and is left for compatibility with older versions.
|
This option is exclusive with stat_cache_expire, and is left for compatibility with older versions.
|
||||||
.TP
|
.TP
|
||||||
\fB\-o\fR enable_noobj_cache (default is disable)
|
\fB\-o\fR enable_noobj_cache (default is disable)
|
||||||
|
184
src/cache.cpp
184
src/cache.cpp
@ -114,7 +114,7 @@ inline bool IsExpireStatCacheTime(const struct timespec& ts, const time_t& expir
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// For cache out
|
// For stats cache out
|
||||||
//
|
//
|
||||||
typedef std::vector<stat_cache_t::iterator> statiterlist_t;
|
typedef std::vector<stat_cache_t::iterator> statiterlist_t;
|
||||||
|
|
||||||
@ -132,6 +132,25 @@ struct sort_statiterlist{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// For symbolic link cache out
|
||||||
|
//
|
||||||
|
typedef std::vector<symlink_cache_t::iterator> symlinkiterlist_t;
|
||||||
|
|
||||||
|
struct sort_symlinkiterlist{
|
||||||
|
// ascending order
|
||||||
|
bool operator()(const symlink_cache_t::iterator& src1, const symlink_cache_t::iterator& src2) const
|
||||||
|
{
|
||||||
|
int result = CompareStatCacheTime(src1->second->cache_date, src2->second->cache_date); // use the same as Stats
|
||||||
|
if(0 == result){
|
||||||
|
if(src1->second->hit_count < src2->second->hit_count){
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (result < 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Static
|
// Static
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
@ -344,7 +363,7 @@ bool StatCache::IsNoObjectCache(const string& key, bool overcheck)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StatCache::AddStat(std::string& key, headers_t& meta, bool forcedir, bool no_truncate)
|
bool StatCache::AddStat(const std::string& key, headers_t& meta, bool forcedir, bool no_truncate)
|
||||||
{
|
{
|
||||||
if(!no_truncate && CacheSize< 1){
|
if(!no_truncate && CacheSize< 1){
|
||||||
return true;
|
return true;
|
||||||
@ -408,10 +427,18 @@ bool StatCache::AddStat(std::string& key, headers_t& meta, bool forcedir, bool n
|
|||||||
}
|
}
|
||||||
stat_cache[key] = ent;
|
stat_cache[key] = ent;
|
||||||
|
|
||||||
|
// check symbolic link cache
|
||||||
|
if(!S_ISLNK(ent->stbuf.st_mode)){
|
||||||
|
if(symlink_cache.end() != symlink_cache.find(key)){
|
||||||
|
// if symbolic link cache has key, thus remove it.
|
||||||
|
DelSymlink(key.c_str(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StatCache::AddNoObjectCache(string& key)
|
bool StatCache::AddNoObjectCache(const string& key)
|
||||||
{
|
{
|
||||||
if(!IsCacheNoObject){
|
if(!IsCacheNoObject){
|
||||||
return true; // pretend successful
|
return true; // pretend successful
|
||||||
@ -459,6 +486,12 @@ bool StatCache::AddNoObjectCache(string& key)
|
|||||||
}
|
}
|
||||||
stat_cache[key] = ent;
|
stat_cache[key] = ent;
|
||||||
|
|
||||||
|
// check symbolic link cache
|
||||||
|
if(symlink_cache.end() != symlink_cache.find(key)){
|
||||||
|
// if symbolic link cache has key, thus remove it.
|
||||||
|
DelSymlink(key.c_str(), true);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -571,6 +604,151 @@ bool StatCache::DelStat(const char* key, bool lock_already_held)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool StatCache::GetSymlink(const string& key, string& value)
|
||||||
|
{
|
||||||
|
bool is_delete_cache = false;
|
||||||
|
string strpath = key;
|
||||||
|
|
||||||
|
AutoLock lock(&StatCache::stat_cache_lock);
|
||||||
|
|
||||||
|
symlink_cache_t::iterator iter = symlink_cache.find(strpath);
|
||||||
|
if(iter != symlink_cache.end() && iter->second){
|
||||||
|
symlink_cache_entry* ent = iter->second;
|
||||||
|
if(!IsExpireTime || !IsExpireStatCacheTime(ent->cache_date, ExpireTime)){ // use the same as Stats
|
||||||
|
// found
|
||||||
|
S3FS_PRN_DBG("symbolic link cache hit [path=%s][time=%lld.%09ld][hit count=%lu]",
|
||||||
|
strpath.c_str(), static_cast<long long>(ent->cache_date.tv_sec), ent->cache_date.tv_nsec, ent->hit_count);
|
||||||
|
|
||||||
|
value = ent->link;
|
||||||
|
|
||||||
|
ent->hit_count++;
|
||||||
|
if(IsExpireIntervalType){
|
||||||
|
SetStatCacheTime(ent->cache_date);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}else{
|
||||||
|
// timeout
|
||||||
|
is_delete_cache = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(is_delete_cache){
|
||||||
|
DelSymlink(strpath.c_str(), /*lock_already_held=*/ true);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StatCache::AddSymlink(const string& key, const string& value)
|
||||||
|
{
|
||||||
|
if(CacheSize< 1){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
S3FS_PRN_INFO3("add symbolic link cache entry[path=%s, value=%s]", key.c_str(), value.c_str());
|
||||||
|
|
||||||
|
bool found;
|
||||||
|
bool do_truncate;
|
||||||
|
{
|
||||||
|
AutoLock lock(&StatCache::stat_cache_lock);
|
||||||
|
found = symlink_cache.end() != symlink_cache.find(key);
|
||||||
|
do_truncate = symlink_cache.size() > CacheSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(found){
|
||||||
|
DelSymlink(key.c_str());
|
||||||
|
}else{
|
||||||
|
if(do_truncate){
|
||||||
|
if(!TruncateSymlink()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// make new
|
||||||
|
symlink_cache_entry* ent = new symlink_cache_entry();
|
||||||
|
ent->link = value;
|
||||||
|
ent->hit_count = 0;
|
||||||
|
SetStatCacheTime(ent->cache_date); // Set time(use the same as Stats).
|
||||||
|
|
||||||
|
// add
|
||||||
|
AutoLock lock(&StatCache::stat_cache_lock);
|
||||||
|
|
||||||
|
symlink_cache_t::iterator iter = symlink_cache.find(key); // recheck for same key exists
|
||||||
|
if(symlink_cache.end() != iter){
|
||||||
|
delete iter->second;
|
||||||
|
symlink_cache.erase(iter);
|
||||||
|
}
|
||||||
|
symlink_cache[key] = ent;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StatCache::TruncateSymlink()
|
||||||
|
{
|
||||||
|
AutoLock lock(&StatCache::stat_cache_lock);
|
||||||
|
|
||||||
|
if(symlink_cache.empty()){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1) erase over expire time
|
||||||
|
if(IsExpireTime){
|
||||||
|
for(symlink_cache_t::iterator iter = symlink_cache.begin(); iter != symlink_cache.end(); ){
|
||||||
|
symlink_cache_entry* entry = iter->second;
|
||||||
|
if(!entry || IsExpireStatCacheTime(entry->cache_date, ExpireTime)){ // use the same as Stats
|
||||||
|
delete entry;
|
||||||
|
symlink_cache.erase(iter++);
|
||||||
|
}else{
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) check stat cache count
|
||||||
|
if(symlink_cache.size() < CacheSize){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3) erase from the old cache in order
|
||||||
|
size_t erase_count= symlink_cache.size() - CacheSize + 1;
|
||||||
|
symlinkiterlist_t erase_iters;
|
||||||
|
for(symlink_cache_t::iterator iter = symlink_cache.begin(); iter != symlink_cache.end(); ++iter){
|
||||||
|
erase_iters.push_back(iter);
|
||||||
|
sort(erase_iters.begin(), erase_iters.end(), sort_symlinkiterlist());
|
||||||
|
if(erase_count < erase_iters.size()){
|
||||||
|
erase_iters.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(symlinkiterlist_t::iterator iiter = erase_iters.begin(); iiter != erase_iters.end(); ++iiter){
|
||||||
|
symlink_cache_t::iterator siter = *iiter;
|
||||||
|
|
||||||
|
S3FS_PRN_DBG("truncate symbolic link cache[path=%s]", siter->first.c_str());
|
||||||
|
delete siter->second;
|
||||||
|
symlink_cache.erase(siter);
|
||||||
|
}
|
||||||
|
S3FS_MALLOCTRIM(0);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StatCache::DelSymlink(const char* key, bool lock_already_held)
|
||||||
|
{
|
||||||
|
if(!key){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
S3FS_PRN_INFO3("delete symbolic link cache entry[path=%s]", key);
|
||||||
|
|
||||||
|
AutoLock lock(&StatCache::stat_cache_lock, lock_already_held ? AutoLock::ALREADY_LOCKED : AutoLock::NONE);
|
||||||
|
|
||||||
|
symlink_cache_t::iterator iter;
|
||||||
|
if(symlink_cache.end() != (iter = symlink_cache.find(string(key)))){
|
||||||
|
delete iter->second;
|
||||||
|
symlink_cache.erase(iter);
|
||||||
|
}
|
||||||
|
S3FS_MALLOCTRIM(0);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Functions
|
// Functions
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
|
51
src/cache.h
51
src/cache.h
@ -24,7 +24,7 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
// Struct
|
// Struct for stats cache
|
||||||
//
|
//
|
||||||
struct stat_cache_entry {
|
struct stat_cache_entry {
|
||||||
struct stat stbuf;
|
struct stat stbuf;
|
||||||
@ -45,20 +45,46 @@ struct stat_cache_entry {
|
|||||||
|
|
||||||
typedef std::map<std::string, stat_cache_entry*> stat_cache_t; // key=path
|
typedef std::map<std::string, stat_cache_entry*> stat_cache_t; // key=path
|
||||||
|
|
||||||
|
//
|
||||||
|
// Struct for symbolic link cache
|
||||||
|
//
|
||||||
|
struct symlink_cache_entry {
|
||||||
|
std::string link;
|
||||||
|
unsigned long hit_count;
|
||||||
|
struct timespec cache_date; // The function that operates timespec uses the same as Stats
|
||||||
|
|
||||||
|
symlink_cache_entry() : link(""), hit_count(0) {
|
||||||
|
cache_date.tv_sec = 0;
|
||||||
|
cache_date.tv_nsec = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::map<std::string, symlink_cache_entry*> symlink_cache_t;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Class
|
// Class
|
||||||
//
|
//
|
||||||
|
// [NOTE] About Symbolic link cache
|
||||||
|
// The Stats cache class now also has a symbolic link cache.
|
||||||
|
// It is possible to take out the Symbolic link cache in another class,
|
||||||
|
// but the cache out etc. should be synchronized with the Stats cache
|
||||||
|
// and implemented in this class.
|
||||||
|
// Symbolic link cache size and timeout use the same settings as Stats
|
||||||
|
// cache. This simplifies user configuration, and from a user perspective,
|
||||||
|
// the symbolic link cache appears to be included in the Stats cache.
|
||||||
|
//
|
||||||
class StatCache
|
class StatCache
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
static StatCache singleton;
|
static StatCache singleton;
|
||||||
static pthread_mutex_t stat_cache_lock;
|
static pthread_mutex_t stat_cache_lock;
|
||||||
stat_cache_t stat_cache;
|
stat_cache_t stat_cache;
|
||||||
bool IsExpireTime;
|
bool IsExpireTime;
|
||||||
bool IsExpireIntervalType; // if this flag is true, cache data is updated at last access time.
|
bool IsExpireIntervalType; // if this flag is true, cache data is updated at last access time.
|
||||||
time_t ExpireTime;
|
time_t ExpireTime;
|
||||||
unsigned long CacheSize;
|
unsigned long CacheSize;
|
||||||
bool IsCacheNoObject;
|
bool IsCacheNoObject;
|
||||||
|
symlink_cache_t symlink_cache;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StatCache();
|
StatCache();
|
||||||
@ -68,6 +94,8 @@ class StatCache
|
|||||||
bool GetStat(const std::string& key, struct stat* pst, headers_t* meta, bool overcheck, const char* petag, bool* pisforce);
|
bool GetStat(const std::string& key, struct stat* pst, headers_t* meta, bool overcheck, const char* petag, bool* pisforce);
|
||||||
// Truncate stat cache
|
// Truncate stat cache
|
||||||
bool TruncateCache(void);
|
bool TruncateCache(void);
|
||||||
|
// Truncate symbolic link cache
|
||||||
|
bool TruncateSymlink(void);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Reference singleton
|
// Reference singleton
|
||||||
@ -111,10 +139,10 @@ class StatCache
|
|||||||
|
|
||||||
// Cache For no object
|
// Cache For no object
|
||||||
bool IsNoObjectCache(const std::string& key, bool overcheck = true);
|
bool IsNoObjectCache(const std::string& key, bool overcheck = true);
|
||||||
bool AddNoObjectCache(std::string& key);
|
bool AddNoObjectCache(const std::string& key);
|
||||||
|
|
||||||
// Add stat cache
|
// Add stat cache
|
||||||
bool AddStat(std::string& key, headers_t& meta, bool forcedir = false, bool no_truncate = false);
|
bool AddStat(const std::string& key, headers_t& meta, bool forcedir = false, bool no_truncate = false);
|
||||||
|
|
||||||
// Change no truncate flag
|
// Change no truncate flag
|
||||||
void ChangeNoTruncateFlag(const std::string& key, bool no_truncate);
|
void ChangeNoTruncateFlag(const std::string& key, bool no_truncate);
|
||||||
@ -124,6 +152,11 @@ class StatCache
|
|||||||
bool DelStat(std::string& key, bool lock_already_held = false) {
|
bool DelStat(std::string& key, bool lock_already_held = false) {
|
||||||
return DelStat(key.c_str(), lock_already_held);
|
return DelStat(key.c_str(), lock_already_held);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cache for symbolic link
|
||||||
|
bool GetSymlink(const std::string& key, std::string& value);
|
||||||
|
bool AddSymlink(const std::string& key, const std::string& value);
|
||||||
|
bool DelSymlink(const char* key, bool lock_already_held = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
82
src/s3fs.cpp
82
src/s3fs.cpp
@ -910,40 +910,54 @@ static int s3fs_readlink(const char* _path, char* buf, size_t size)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
WTF8_ENCODE(path)
|
WTF8_ENCODE(path)
|
||||||
// Open
|
string strValue;
|
||||||
FdEntity* ent;
|
|
||||||
if(NULL == (ent = get_local_fent(path))){
|
|
||||||
S3FS_PRN_ERR("could not get fent(file=%s)", path);
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
// Get size
|
|
||||||
off_t readsize;
|
|
||||||
if(!ent->GetSize(readsize)){
|
|
||||||
S3FS_PRN_ERR("could not get file size(file=%s)", path);
|
|
||||||
FdManager::get()->Close(ent);
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
if(static_cast<off_t>(size) <= readsize){
|
|
||||||
readsize = size - 1;
|
|
||||||
}
|
|
||||||
// Read
|
|
||||||
ssize_t ressize;
|
|
||||||
if(0 > (ressize = ent->Read(buf, 0, readsize))){
|
|
||||||
S3FS_PRN_ERR("could not read file(file=%s, ressize=%jd)", path, (intmax_t)ressize);
|
|
||||||
FdManager::get()->Close(ent);
|
|
||||||
return static_cast<int>(ressize);
|
|
||||||
}
|
|
||||||
buf[ressize] = '\0';
|
|
||||||
|
|
||||||
// check buf if it has space words.
|
// check symblic link cache
|
||||||
string strTmp = trim(string(buf));
|
if(!StatCache::getStatCacheData()->GetSymlink(string(path), strValue)){
|
||||||
// decode wtf8. This will always be shorter
|
// not found in cache, then open the path
|
||||||
if(use_wtf8){
|
FdEntity* ent;
|
||||||
strTmp = s3fs_wtf8_decode(strTmp);
|
if(NULL == (ent = get_local_fent(path))){
|
||||||
}
|
S3FS_PRN_ERR("could not get fent(file=%s)", path);
|
||||||
strncpy(buf, strTmp.c_str(), size);
|
return -EIO;
|
||||||
|
}
|
||||||
|
// Get size
|
||||||
|
off_t readsize;
|
||||||
|
if(!ent->GetSize(readsize)){
|
||||||
|
S3FS_PRN_ERR("could not get file size(file=%s)", path);
|
||||||
|
FdManager::get()->Close(ent);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
if(static_cast<off_t>(size) <= readsize){
|
||||||
|
readsize = size - 1;
|
||||||
|
}
|
||||||
|
// Read
|
||||||
|
ssize_t ressize;
|
||||||
|
if(0 > (ressize = ent->Read(buf, 0, readsize))){
|
||||||
|
S3FS_PRN_ERR("could not read file(file=%s, ressize=%jd)", path, (intmax_t)ressize);
|
||||||
|
FdManager::get()->Close(ent);
|
||||||
|
return static_cast<int>(ressize);
|
||||||
|
}
|
||||||
|
buf[ressize] = '\0';
|
||||||
|
|
||||||
|
// close
|
||||||
|
FdManager::get()->Close(ent);
|
||||||
|
|
||||||
|
// check buf if it has space words.
|
||||||
|
strValue = trim(string(buf));
|
||||||
|
|
||||||
|
// decode wtf8. This will always be shorter
|
||||||
|
if(use_wtf8){
|
||||||
|
strValue = s3fs_wtf8_decode(strValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add symblic link cache
|
||||||
|
if(!StatCache::getStatCacheData()->AddSymlink(string(path), strValue)){
|
||||||
|
S3FS_PRN_ERR("failed to add symbolic link cache for %s", path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// copy result
|
||||||
|
strncpy(buf, strValue.c_str(), size);
|
||||||
|
|
||||||
FdManager::get()->Close(ent);
|
|
||||||
S3FS_MALLOCTRIM(0);
|
S3FS_MALLOCTRIM(0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1150,6 +1164,7 @@ static int s3fs_unlink(const char* _path)
|
|||||||
result = s3fscurl.DeleteRequest(path);
|
result = s3fscurl.DeleteRequest(path);
|
||||||
FdManager::DeleteCacheFile(path);
|
FdManager::DeleteCacheFile(path);
|
||||||
StatCache::getStatCacheData()->DelStat(path);
|
StatCache::getStatCacheData()->DelStat(path);
|
||||||
|
StatCache::getStatCacheData()->DelSymlink(path);
|
||||||
S3FS_MALLOCTRIM(0);
|
S3FS_MALLOCTRIM(0);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -1279,6 +1294,9 @@ static int s3fs_symlink(const char* _from, const char* _to)
|
|||||||
FdManager::get()->Close(ent);
|
FdManager::get()->Close(ent);
|
||||||
|
|
||||||
StatCache::getStatCacheData()->DelStat(to);
|
StatCache::getStatCacheData()->DelStat(to);
|
||||||
|
if(!StatCache::getStatCacheData()->AddSymlink(string(to), strFrom)){
|
||||||
|
S3FS_PRN_ERR("failed to add symbolic link cache for %s", to);
|
||||||
|
}
|
||||||
S3FS_MALLOCTRIM(0);
|
S3FS_MALLOCTRIM(0);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -1199,18 +1199,20 @@ void show_help ()
|
|||||||
" API. The default is 1000. you can set this value to 1000 or more.\n"
|
" API. The default is 1000. you can set this value to 1000 or more.\n"
|
||||||
"\n"
|
"\n"
|
||||||
" max_stat_cache_size (default=\"100,000\" entries (about 40MB))\n"
|
" max_stat_cache_size (default=\"100,000\" entries (about 40MB))\n"
|
||||||
" - maximum number of entries in the stat cache\n"
|
" - maximum number of entries in the stat cache, and this maximum is\n"
|
||||||
|
" also treated as the number of symbolic link cache.\n"
|
||||||
"\n"
|
"\n"
|
||||||
" stat_cache_expire (default is no expire)\n"
|
" stat_cache_expire (default is no expire)\n"
|
||||||
" - specify expire time (seconds) for entries in the stat cache.\n"
|
" - specify expire time (seconds) for entries in the stat cache.\n"
|
||||||
" This expire time indicates the time since stat cached.\n"
|
" This expire time indicates the time since stat cached. and this\n"
|
||||||
|
" is also set to the expire time of the symbolic link cache.\n"
|
||||||
"\n"
|
"\n"
|
||||||
" stat_cache_interval_expire (default is no expire)\n"
|
" stat_cache_interval_expire (default is no expire)\n"
|
||||||
" - specify expire time (seconds) for entries in the stat cache.\n"
|
" - specify expire time (seconds) for entries in the stat cache(and\n"
|
||||||
|
" symbolic link cache).\n"
|
||||||
" This expire time is based on the time from the last access time\n"
|
" This expire time is based on the time from the last access time\n"
|
||||||
" of the stat cache. This option is exclusive with\n"
|
" of the stat cache. This option is exclusive with stat_cache_expire,\n"
|
||||||
" stat_cache_expire, and is left for compatibility with older\n"
|
" and is left for compatibility with older versions.\n"
|
||||||
" versions.\n"
|
|
||||||
"\n"
|
"\n"
|
||||||
" enable_noobj_cache (default is disable)\n"
|
" enable_noobj_cache (default is disable)\n"
|
||||||
" - enable cache entries for the object which does not exist.\n"
|
" - enable cache entries for the object which does not exist.\n"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user