mirror of
https://github.com/s3fs-fuse/s3fs-fuse.git
synced 2024-12-23 01:08:54 +00:00
Additional bug fixing for not creating zero-byte object
This commit is contained in:
parent
42f5965d8a
commit
b5fef788da
@ -100,7 +100,9 @@ inline bool IsExpireStatCacheTime(const struct timespec& ts, const time_t& expir
|
||||
{
|
||||
struct timespec nowts;
|
||||
SetStatCacheTime(nowts);
|
||||
return ((ts.tv_sec + expire) < nowts.tv_sec);
|
||||
nowts.tv_sec -= expire;
|
||||
|
||||
return (0 < CompareStatCacheTime(nowts, ts));
|
||||
}
|
||||
|
||||
//
|
||||
@ -258,7 +260,7 @@ bool StatCache::GetStat(const std::string& key, struct stat* pst, headers_t* met
|
||||
|
||||
if(iter != stat_cache.end() && (*iter).second){
|
||||
stat_cache_entry* ent = (*iter).second;
|
||||
if(!IsExpireTime || !IsExpireStatCacheTime(ent->cache_date, ExpireTime)){
|
||||
if(0 < ent->notruncate || !IsExpireTime || !IsExpireStatCacheTime(ent->cache_date, ExpireTime)){
|
||||
if(ent->noobjcache){
|
||||
if(!IsCacheNoObject){
|
||||
// need to delete this cache.
|
||||
@ -343,7 +345,8 @@ bool StatCache::IsNoObjectCache(const std::string& key, bool overcheck)
|
||||
}
|
||||
|
||||
if(iter != stat_cache.end() && (*iter).second) {
|
||||
if(!IsExpireTime || !IsExpireStatCacheTime((*iter).second->cache_date, ExpireTime)){
|
||||
stat_cache_entry* ent = (*iter).second;
|
||||
if(0 < ent->notruncate || !IsExpireTime || !IsExpireStatCacheTime((*iter).second->cache_date, ExpireTime)){
|
||||
if((*iter).second->noobjcache){
|
||||
// noobjcache = true means no object.
|
||||
SetStatCacheTime((*iter).second->cache_date);
|
||||
@ -434,6 +437,47 @@ bool StatCache::AddStat(const std::string& key, headers_t& meta, bool forcedir,
|
||||
return true;
|
||||
}
|
||||
|
||||
// [NOTE]
|
||||
// Updates only meta data if cached data exists.
|
||||
// And when these are updated, it also updates the cache time.
|
||||
//
|
||||
bool StatCache::UpdateMetaStats(const std::string& key, headers_t& meta)
|
||||
{
|
||||
if(CacheSize < 1){
|
||||
return true;
|
||||
}
|
||||
S3FS_PRN_INFO3("update stat cache entry[path=%s]", key.c_str());
|
||||
|
||||
AutoLock lock(&StatCache::stat_cache_lock);
|
||||
stat_cache_t::iterator iter = stat_cache.find(key);
|
||||
if(stat_cache.end() == iter || !(iter->second)){
|
||||
return true;
|
||||
}
|
||||
stat_cache_entry* ent = iter->second;
|
||||
|
||||
// update only meta keys
|
||||
for(headers_t::iterator metaiter = meta.begin(); metaiter != meta.end(); ++metaiter){
|
||||
std::string tag = lower(metaiter->first);
|
||||
std::string value = metaiter->second;
|
||||
if(tag == "content-type"){
|
||||
ent->meta[metaiter->first] = value;
|
||||
}else if(tag == "content-length"){
|
||||
ent->meta[metaiter->first] = value;
|
||||
}else if(tag == "etag"){
|
||||
ent->meta[metaiter->first] = value;
|
||||
}else if(tag == "last-modified"){
|
||||
ent->meta[metaiter->first] = value;
|
||||
}else if(is_prefix(tag.c_str(), "x-amz")){
|
||||
ent->meta[tag] = value; // key is lower case for "x-amz"
|
||||
}
|
||||
}
|
||||
|
||||
// Update time.
|
||||
SetStatCacheTime(ent->cache_date);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StatCache::AddNoObjectCache(const std::string& key)
|
||||
{
|
||||
if(!IsCacheNoObject){
|
||||
|
@ -158,6 +158,9 @@ class StatCache
|
||||
// Add stat cache
|
||||
bool AddStat(const std::string& key, headers_t& meta, bool forcedir = false, bool no_truncate = false);
|
||||
|
||||
// Update meta stats
|
||||
bool UpdateMetaStats(const std::string& key, headers_t& meta);
|
||||
|
||||
// Change no truncate flag
|
||||
void ChangeNoTruncateFlag(const std::string& key, bool no_truncate);
|
||||
|
||||
|
49
src/s3fs.cpp
49
src/s3fs.cpp
@ -385,7 +385,6 @@ static int get_object_attribute(const char* path, struct stat* pstbuf, headers_t
|
||||
strpath += "/";
|
||||
}
|
||||
if(StatCache::getStatCacheData()->GetStat(strpath, pstat, pheader, overcheck, pisforce)){
|
||||
StatCache::getStatCacheData()->ChangeNoTruncateFlag(strpath, add_no_truncate_cache);
|
||||
return 0;
|
||||
}
|
||||
if(StatCache::getStatCacheData()->IsNoObjectCache(strpath)){
|
||||
@ -980,7 +979,16 @@ static int s3fs_create(const char* _path, mode_t mode, struct fuse_file_info* fi
|
||||
meta["x-amz-meta-atime"] = str(now);
|
||||
meta["x-amz-meta-mtime"] = str(now);
|
||||
meta["x-amz-meta-ctime"] = str(now);
|
||||
if(!StatCache::getStatCacheData()->AddStat(path, meta)){
|
||||
|
||||
// [NOTE] set no_truncate flag
|
||||
// At this point, the file has not been created(uploaded) and
|
||||
// the data is only present in the Stats cache.
|
||||
// The Stats cache should not be deleted automatically by
|
||||
// timeout. If this stats is deleted, s3fs will try to get it
|
||||
// from the server with a Head request and will get an
|
||||
// unexpected error because the result object does not exist.
|
||||
//
|
||||
if(!StatCache::getStatCacheData()->AddStat(path, meta, false, true)){
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@ -1066,9 +1074,9 @@ static int s3fs_unlink(const char* _path)
|
||||
}
|
||||
S3fsCurl s3fscurl;
|
||||
result = s3fscurl.DeleteRequest(path);
|
||||
FdManager::DeleteCacheFile(path);
|
||||
StatCache::getStatCacheData()->DelStat(path);
|
||||
StatCache::getStatCacheData()->DelSymlink(path);
|
||||
FdManager::DeleteCacheFile(path);
|
||||
S3FS_MALLOCTRIM(0);
|
||||
|
||||
return result;
|
||||
@ -1671,6 +1679,9 @@ static int s3fs_chmod(const char* _path, mode_t mode)
|
||||
// then the meta is pending and accumulated to be put after the upload is complete.
|
||||
S3FS_PRN_INFO("meta pending until upload is complete");
|
||||
need_put_header = false;
|
||||
|
||||
// If there is data in the Stats cache, update the Stats cache.
|
||||
StatCache::getStatCacheData()->UpdateMetaStats(strpath, updatemeta);
|
||||
}
|
||||
}
|
||||
if(need_put_header){
|
||||
@ -1845,6 +1856,9 @@ static int s3fs_chown(const char* _path, uid_t uid, gid_t gid)
|
||||
// then the meta is pending and accumulated to be put after the upload is complete.
|
||||
S3FS_PRN_INFO("meta pending until upload is complete");
|
||||
need_put_header = false;
|
||||
|
||||
// If there is data in the Stats cache, update the Stats cache.
|
||||
StatCache::getStatCacheData()->UpdateMetaStats(strpath, updatemeta);
|
||||
}
|
||||
}
|
||||
if(need_put_header){
|
||||
@ -2026,6 +2040,9 @@ static int s3fs_utimens(const char* _path, const struct timespec ts[2])
|
||||
need_put_header = false;
|
||||
ent->SetHoldingMtime(ts[1]); // ts[1] is mtime
|
||||
|
||||
// If there is data in the Stats cache, update the Stats cache.
|
||||
StatCache::getStatCacheData()->UpdateMetaStats(strpath, updatemeta);
|
||||
|
||||
}else{
|
||||
S3FS_PRN_INFO("meta is not pending, but need to keep current mtime.");
|
||||
|
||||
@ -2223,15 +2240,20 @@ static int s3fs_open(const char* _path, struct fuse_file_info* fi)
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
// clear stat for reading fresh stat.
|
||||
// (if object stat is changed, we refresh it. then s3fs gets always
|
||||
// stat when s3fs open the object).
|
||||
// [NOTE]
|
||||
// Delete the Stats cache only if the file is not open.
|
||||
// If the file is open, the stats cache will not be deleted as
|
||||
// there are cases where the object does not exist on the server
|
||||
// and only the Stats cache exists.
|
||||
//
|
||||
if(StatCache::getStatCacheData()->HasStat(path)){
|
||||
// flush any dirty data so that subsequent stat gets correct size
|
||||
if((result = s3fs_flush(_path, fi)) != 0){
|
||||
S3FS_PRN_ERR("could not flush(%s): result=%d", path, result);
|
||||
AutoFdEntity autoent_local;
|
||||
if(NULL == autoent_local.ExistOpen(path, -1, true)){
|
||||
if((result = s3fs_flush(_path, fi)) != 0){
|
||||
S3FS_PRN_ERR("could not flush(%s): result=%d", path, result);
|
||||
}
|
||||
StatCache::getStatCacheData()->DelStat(path);
|
||||
}
|
||||
StatCache::getStatCacheData()->DelStat(path);
|
||||
}
|
||||
|
||||
int mask = (O_RDONLY != (fi->flags & O_ACCMODE) ? W_OK : R_OK);
|
||||
@ -2390,6 +2412,7 @@ static int s3fs_flush(const char* _path, struct fuse_file_info* fi)
|
||||
ent->UpdateMtime(true); // clear the flag not to update mtime.
|
||||
ent->UpdateCtime();
|
||||
result = ent->Flush(false);
|
||||
StatCache::getStatCacheData()->DelStat(path);
|
||||
}
|
||||
S3FS_MALLOCTRIM(0);
|
||||
|
||||
@ -3048,6 +3071,9 @@ static int s3fs_setxattr(const char* path, const char* name, const char* value,
|
||||
// then the meta is pending and accumulated to be put after the upload is complete.
|
||||
S3FS_PRN_INFO("meta pending until upload is complete");
|
||||
need_put_header = false;
|
||||
|
||||
// If there is data in the Stats cache, update the Stats cache.
|
||||
StatCache::getStatCacheData()->UpdateMetaStats(strpath, updatemeta);
|
||||
}
|
||||
}
|
||||
if(need_put_header){
|
||||
@ -3318,6 +3344,9 @@ static int s3fs_removexattr(const char* path, const char* name)
|
||||
// then the meta is pending and accumulated to be put after the upload is complete.
|
||||
S3FS_PRN_INFO("meta pending until upload is complete");
|
||||
need_put_header = false;
|
||||
|
||||
// If there is data in the Stats cache, update the Stats cache.
|
||||
StatCache::getStatCacheData()->UpdateMetaStats(strpath, updatemeta);
|
||||
}
|
||||
}
|
||||
if(need_put_header){
|
||||
|
Loading…
Reference in New Issue
Block a user