mirror of
https://github.com/s3fs-fuse/s3fs-fuse.git
synced 2024-12-24 01:35:26 +00:00
Merge pull request #1125 from ggtakec/fix_nocopyapi_copy
Fixed simple copy with nocpoyapi and modify flag in fdcache
This commit is contained in:
commit
2a779df4fd
185
src/fdcache.cpp
185
src/fdcache.cpp
@ -244,9 +244,16 @@ void PageList::FreeList(fdpage_list_t& list)
|
|||||||
list.clear();
|
list.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
PageList::PageList(off_t size, bool is_loaded)
|
PageList::PageList(off_t size, bool is_loaded, bool is_modified)
|
||||||
{
|
{
|
||||||
Init(size, is_loaded);
|
Init(size, is_loaded, is_modified);
|
||||||
|
}
|
||||||
|
|
||||||
|
PageList::PageList(const PageList& other)
|
||||||
|
{
|
||||||
|
for(fdpage_list_t::const_iterator iter = other.pages.begin(); iter != other.pages.end(); ++iter){
|
||||||
|
pages.push_back(*iter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PageList::~PageList()
|
PageList::~PageList()
|
||||||
@ -259,10 +266,10 @@ void PageList::Clear()
|
|||||||
PageList::FreeList(pages);
|
PageList::FreeList(pages);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PageList::Init(off_t size, bool is_loaded)
|
bool PageList::Init(off_t size, bool is_loaded, bool is_modified)
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
fdpage page(0, size, is_loaded);
|
fdpage page(0, size, is_loaded, is_modified);
|
||||||
pages.push_back(page);
|
pages.push_back(page);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -276,23 +283,33 @@ off_t PageList::Size() const
|
|||||||
return riter->next();
|
return riter->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PageList::Compress()
|
bool PageList::Compress(bool force_modified)
|
||||||
{
|
{
|
||||||
bool is_first = true;
|
bool is_first = true;
|
||||||
bool is_last_loaded = false;
|
bool is_last_loaded = false;
|
||||||
|
bool is_last_modified = false;
|
||||||
|
|
||||||
for(fdpage_list_t::iterator iter = pages.begin(); iter != pages.end(); ){
|
for(fdpage_list_t::iterator iter = pages.begin(); iter != pages.end(); ){
|
||||||
if(is_first){
|
if(is_first){
|
||||||
is_first = false;
|
is_first = false;
|
||||||
is_last_loaded = iter->loaded;
|
is_last_loaded = force_modified ? true : iter->loaded;
|
||||||
|
is_last_modified = iter->modified;
|
||||||
++iter;
|
++iter;
|
||||||
}else{
|
}else{
|
||||||
if(is_last_loaded == iter->loaded){
|
if(is_last_modified == iter->modified){
|
||||||
fdpage_list_t::iterator biter = iter;
|
if(force_modified || is_last_loaded == iter->loaded){
|
||||||
--biter;
|
fdpage_list_t::iterator biter = iter;
|
||||||
biter->bytes += iter->bytes;
|
--biter;
|
||||||
iter = pages.erase(iter);
|
biter->bytes += iter->bytes;
|
||||||
|
iter = pages.erase(iter);
|
||||||
|
}else{
|
||||||
|
is_last_loaded = iter->loaded;
|
||||||
|
is_last_modified = iter->modified;
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
is_last_loaded = iter->loaded;
|
is_last_loaded = force_modified ? true : iter->loaded;
|
||||||
|
is_last_modified = iter->modified;
|
||||||
++iter;
|
++iter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -307,7 +324,7 @@ bool PageList::Parse(off_t new_pos)
|
|||||||
// nothing to do
|
// nothing to do
|
||||||
return true;
|
return true;
|
||||||
}else if(iter->offset < new_pos && new_pos < iter->next()){
|
}else if(iter->offset < new_pos && new_pos < iter->next()){
|
||||||
fdpage page(iter->offset, new_pos - iter->offset, iter->loaded);
|
fdpage page(iter->offset, new_pos - iter->offset, iter->loaded, false);
|
||||||
iter->bytes -= (new_pos - iter->offset);
|
iter->bytes -= (new_pos - iter->offset);
|
||||||
iter->offset = new_pos;
|
iter->offset = new_pos;
|
||||||
pages.insert(iter, page);
|
pages.insert(iter, page);
|
||||||
@ -317,16 +334,16 @@ bool PageList::Parse(off_t new_pos)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PageList::Resize(off_t size, bool is_loaded)
|
bool PageList::Resize(off_t size, bool is_loaded, bool is_modified)
|
||||||
{
|
{
|
||||||
off_t total = Size();
|
off_t total = Size();
|
||||||
|
|
||||||
if(0 == total){
|
if(0 == total){
|
||||||
Init(size, is_loaded);
|
Init(size, is_loaded, is_modified);
|
||||||
|
|
||||||
}else if(total < size){
|
}else if(total < size){
|
||||||
// add new area
|
// add new area
|
||||||
fdpage page(total, (size - total), is_loaded);
|
fdpage page(total, (size - total), is_loaded, is_modified);
|
||||||
pages.push_back(page);
|
pages.push_back(page);
|
||||||
|
|
||||||
}else if(size < total){
|
}else if(size < total){
|
||||||
@ -365,22 +382,22 @@ bool PageList::IsPageLoaded(off_t start, off_t size) const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PageList::SetPageLoadedStatus(off_t start, off_t size, bool is_loaded, bool is_compress)
|
bool PageList::SetPageLoadedStatus(off_t start, off_t size, bool is_loaded, bool is_modified, bool is_compress)
|
||||||
{
|
{
|
||||||
off_t now_size = Size();
|
off_t now_size = Size();
|
||||||
|
|
||||||
if(now_size <= start){
|
if(now_size <= start){
|
||||||
if(now_size < start){
|
if(now_size < start){
|
||||||
// add
|
// add
|
||||||
Resize(start, false);
|
Resize(start, false, is_modified); // set modified flag from now end pos to specified start pos.
|
||||||
}
|
}
|
||||||
Resize(start + size, is_loaded);
|
Resize(start + size, is_loaded, is_modified);
|
||||||
|
|
||||||
}else if(now_size <= start + size){
|
}else if(now_size <= start + size){
|
||||||
// cut
|
// cut
|
||||||
Resize(start, false);
|
Resize(start, false, false); // not changed loaded/modified flags in existing area.
|
||||||
// add
|
// add
|
||||||
Resize(start + size, is_loaded);
|
Resize(start + size, is_loaded, is_modified);
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
// start-size are inner pages area
|
// start-size are inner pages area
|
||||||
@ -395,7 +412,8 @@ bool PageList::SetPageLoadedStatus(off_t start, off_t size, bool is_loaded, bool
|
|||||||
}else if(start + size <= iter->offset){
|
}else if(start + size <= iter->offset){
|
||||||
break;
|
break;
|
||||||
}else{
|
}else{
|
||||||
iter->loaded = is_loaded;
|
iter->loaded = is_loaded;
|
||||||
|
iter->modified = is_modified;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -407,7 +425,7 @@ bool PageList::FindUnloadedPage(off_t start, off_t& resstart, off_t& ressize) co
|
|||||||
{
|
{
|
||||||
for(fdpage_list_t::const_iterator iter = pages.begin(); iter != pages.end(); ++iter){
|
for(fdpage_list_t::const_iterator iter = pages.begin(); iter != pages.end(); ++iter){
|
||||||
if(start <= iter->end()){
|
if(start <= iter->end()){
|
||||||
if(!iter->loaded){
|
if(!iter->loaded && !iter->modified){ // Do not load unloaded and modified areas
|
||||||
resstart = iter->offset;
|
resstart = iter->offset;
|
||||||
ressize = iter->bytes;
|
ressize = iter->bytes;
|
||||||
return true;
|
return true;
|
||||||
@ -428,7 +446,7 @@ off_t PageList::GetTotalUnloadedPageSize(off_t start, off_t size) const
|
|||||||
if(next <= iter->offset){
|
if(next <= iter->offset){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(iter->loaded){
|
if(iter->loaded || iter->modified){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
off_t tmpsize;
|
off_t tmpsize;
|
||||||
@ -467,8 +485,8 @@ int PageList::GetUnloadedPages(fdpage_list_t& unloaded_list, off_t start, off_t
|
|||||||
if(next <= iter->offset){
|
if(next <= iter->offset){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(iter->loaded){
|
if(iter->loaded || iter->modified){
|
||||||
continue; // already loaded
|
continue; // already loaded or modified
|
||||||
}
|
}
|
||||||
|
|
||||||
// page area
|
// page area
|
||||||
@ -482,13 +500,33 @@ int PageList::GetUnloadedPages(fdpage_list_t& unloaded_list, off_t start, off_t
|
|||||||
// merge to before page
|
// merge to before page
|
||||||
riter->bytes += page_size;
|
riter->bytes += page_size;
|
||||||
}else{
|
}else{
|
||||||
fdpage page(page_start, page_size, false);
|
fdpage page(page_start, page_size, false, false);
|
||||||
unloaded_list.push_back(page);
|
unloaded_list.push_back(page);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return unloaded_list.size();
|
return unloaded_list.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PageList::IsModified(void) const
|
||||||
|
{
|
||||||
|
for(fdpage_list_t::const_iterator iter = pages.begin(); iter != pages.end(); ++iter){
|
||||||
|
if(iter->modified){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PageList::ClearAllModified(void)
|
||||||
|
{
|
||||||
|
for(fdpage_list_t::iterator iter = pages.begin(); iter != pages.end(); ++iter){
|
||||||
|
if(iter->modified){
|
||||||
|
iter->modified = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Compress();
|
||||||
|
}
|
||||||
|
|
||||||
bool PageList::Serialize(CacheFileStat& file, bool is_output)
|
bool PageList::Serialize(CacheFileStat& file, bool is_output)
|
||||||
{
|
{
|
||||||
if(!file.Open()){
|
if(!file.Open()){
|
||||||
@ -502,7 +540,7 @@ bool PageList::Serialize(CacheFileStat& file, bool is_output)
|
|||||||
ssall << Size();
|
ssall << Size();
|
||||||
|
|
||||||
for(fdpage_list_t::iterator iter = pages.begin(); iter != pages.end(); ++iter){
|
for(fdpage_list_t::iterator iter = pages.begin(); iter != pages.end(); ++iter){
|
||||||
ssall << "\n" << iter->offset << ":" << iter->bytes << ":" << (iter->loaded ? "1" : "0");
|
ssall << "\n" << iter->offset << ":" << iter->bytes << ":" << (iter->loaded ? "1" : "0") << ":" << (iter->modified ? "1" : "0");
|
||||||
}
|
}
|
||||||
|
|
||||||
string strall = ssall.str();
|
string strall = ssall.str();
|
||||||
@ -523,7 +561,7 @@ bool PageList::Serialize(CacheFileStat& file, bool is_output)
|
|||||||
}
|
}
|
||||||
if(0 >= st.st_size){
|
if(0 >= st.st_size){
|
||||||
// nothing
|
// nothing
|
||||||
Init(0, false);
|
Init(0, false, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
char* ptmp = new char[st.st_size + 1];
|
char* ptmp = new char[st.st_size + 1];
|
||||||
@ -571,8 +609,14 @@ bool PageList::Serialize(CacheFileStat& file, bool is_output)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
bool is_loaded = (1 == s3fs_strtoofft(part.c_str()) ? true : false);
|
bool is_loaded = (1 == s3fs_strtoofft(part.c_str()) ? true : false);
|
||||||
|
bool is_modified;
|
||||||
|
if(!getline(ssparts, part, ':')){
|
||||||
|
is_modified = false; // old version does not have this part.
|
||||||
|
}else{
|
||||||
|
is_modified = (1 == s3fs_strtoofft(part.c_str()) ? true : false);
|
||||||
|
}
|
||||||
// add new area
|
// add new area
|
||||||
SetPageLoadedStatus(offset, size, is_loaded);
|
SetPageLoadedStatus(offset, size, is_loaded, is_modified);
|
||||||
}
|
}
|
||||||
delete[] ptmp;
|
delete[] ptmp;
|
||||||
if(is_err){
|
if(is_err){
|
||||||
@ -597,7 +641,7 @@ void PageList::Dump()
|
|||||||
|
|
||||||
S3FS_PRN_DBG("pages = {");
|
S3FS_PRN_DBG("pages = {");
|
||||||
for(fdpage_list_t::iterator iter = pages.begin(); iter != pages.end(); ++iter, ++cnt){
|
for(fdpage_list_t::iterator iter = pages.begin(); iter != pages.end(); ++iter, ++cnt){
|
||||||
S3FS_PRN_DBG(" [%08d] -> {%014lld - %014lld : %s}", cnt, static_cast<long long int>(iter->offset), static_cast<long long int>(iter->bytes), iter->loaded ? "true" : "false");
|
S3FS_PRN_DBG(" [%08d] -> {%014lld - %014lld : %s / %s}", cnt, static_cast<long long int>(iter->offset), static_cast<long long int>(iter->bytes), iter->loaded ? "loaded" : "unloaded", iter->modified ? "modified" : "not modified");
|
||||||
}
|
}
|
||||||
S3FS_PRN_DBG("}");
|
S3FS_PRN_DBG("}");
|
||||||
}
|
}
|
||||||
@ -624,7 +668,7 @@ int FdEntity::FillFile(int fd, unsigned char byte, off_t size, off_t start)
|
|||||||
//------------------------------------------------
|
//------------------------------------------------
|
||||||
FdEntity::FdEntity(const char* tpath, const char* cpath)
|
FdEntity::FdEntity(const char* tpath, const char* cpath)
|
||||||
: is_lock_init(false), refcnt(0), path(SAFESTRPTR(tpath)),
|
: is_lock_init(false), refcnt(0), path(SAFESTRPTR(tpath)),
|
||||||
fd(-1), pfile(NULL), size_orgmeta(0), upload_id(""), mp_start(0), mp_size(0), is_modify(false),
|
fd(-1), pfile(NULL), size_orgmeta(0), upload_id(""), mp_start(0), mp_size(0),
|
||||||
cachepath(SAFESTRPTR(cpath)), mirrorpath("")
|
cachepath(SAFESTRPTR(cpath)), mirrorpath("")
|
||||||
{
|
{
|
||||||
try{
|
try{
|
||||||
@ -681,11 +725,10 @@ void FdEntity::Clear()
|
|||||||
mirrorpath.erase();
|
mirrorpath.erase();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pagelist.Init(0, false);
|
pagelist.Init(0, false, false);
|
||||||
refcnt = 0;
|
refcnt = 0;
|
||||||
path = "";
|
path = "";
|
||||||
cachepath = "";
|
cachepath = "";
|
||||||
is_modify = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FdEntity::Close()
|
void FdEntity::Close()
|
||||||
@ -824,7 +867,7 @@ int FdEntity::Open(headers_t* pmeta, off_t size, time_t time, bool no_fd_lock_wa
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
// resize page list
|
// resize page list
|
||||||
if(!pagelist.Resize(size, false)){
|
if(!pagelist.Resize(size, false, false)){
|
||||||
S3FS_PRN_ERR("failed to truncate temporary file information(%d).", fd);
|
S3FS_PRN_ERR("failed to truncate temporary file information(%d).", fd);
|
||||||
if(0 < refcnt){
|
if(0 < refcnt){
|
||||||
refcnt--;
|
refcnt--;
|
||||||
@ -875,13 +918,13 @@ int FdEntity::Open(headers_t* pmeta, off_t size, time_t time, bool no_fd_lock_wa
|
|||||||
// check size, st_size, loading stat file
|
// check size, st_size, loading stat file
|
||||||
if(-1 == size){
|
if(-1 == size){
|
||||||
if(st.st_size != pagelist.Size()){
|
if(st.st_size != pagelist.Size()){
|
||||||
pagelist.Resize(st.st_size, false);
|
pagelist.Resize(st.st_size, false, false);
|
||||||
need_save_csf = true; // need to update page info
|
need_save_csf = true; // need to update page info
|
||||||
}
|
}
|
||||||
size = st.st_size;
|
size = st.st_size;
|
||||||
}else{
|
}else{
|
||||||
if(size != pagelist.Size()){
|
if(size != pagelist.Size()){
|
||||||
pagelist.Resize(size, false);
|
pagelist.Resize(size, false, false);
|
||||||
need_save_csf = true; // need to update page info
|
need_save_csf = true; // need to update page info
|
||||||
}
|
}
|
||||||
if(size != st.st_size){
|
if(size != st.st_size){
|
||||||
@ -898,9 +941,9 @@ int FdEntity::Open(headers_t* pmeta, off_t size, time_t time, bool no_fd_lock_wa
|
|||||||
need_save_csf = true; // need to update page info
|
need_save_csf = true; // need to update page info
|
||||||
if(-1 == size){
|
if(-1 == size){
|
||||||
size = 0;
|
size = 0;
|
||||||
pagelist.Init(0, false);
|
pagelist.Init(0, false, false);
|
||||||
}else{
|
}else{
|
||||||
pagelist.Resize(size, false);
|
pagelist.Resize(size, false, false);
|
||||||
is_truncate = true;
|
is_truncate = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -937,9 +980,9 @@ int FdEntity::Open(headers_t* pmeta, off_t size, time_t time, bool no_fd_lock_wa
|
|||||||
}
|
}
|
||||||
if(-1 == size){
|
if(-1 == size){
|
||||||
size = 0;
|
size = 0;
|
||||||
pagelist.Init(0, false);
|
pagelist.Init(0, false, false);
|
||||||
}else{
|
}else{
|
||||||
pagelist.Resize(size, false);
|
pagelist.Resize(size, false, false);
|
||||||
is_truncate = true;
|
is_truncate = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -964,8 +1007,7 @@ int FdEntity::Open(headers_t* pmeta, off_t size, time_t time, bool no_fd_lock_wa
|
|||||||
}
|
}
|
||||||
|
|
||||||
// init internal data
|
// init internal data
|
||||||
refcnt = 1;
|
refcnt = 1;
|
||||||
is_modify = false;
|
|
||||||
|
|
||||||
// set original headers and size in it.
|
// set original headers and size in it.
|
||||||
if(pmeta){
|
if(pmeta){
|
||||||
@ -1019,9 +1061,6 @@ bool FdEntity::OpenAndLoadAll(headers_t* pmeta, off_t* size, bool force_load)
|
|||||||
S3FS_PRN_ERR("could not download, result(%d)", result);
|
S3FS_PRN_ERR("could not download, result(%d)", result);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(is_modify){
|
|
||||||
is_modify = false;
|
|
||||||
}
|
|
||||||
if(size){
|
if(size){
|
||||||
*size = pagelist.Size();
|
*size = pagelist.Size();
|
||||||
}
|
}
|
||||||
@ -1176,7 +1215,7 @@ bool FdEntity::SetAllStatus(bool is_loaded)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Reinit
|
// Reinit
|
||||||
pagelist.Init(st.st_size, is_loaded);
|
pagelist.Init(st.st_size, is_loaded, false);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1208,7 +1247,6 @@ int FdEntity::Load(off_t start, off_t size, bool lock_already_held)
|
|||||||
// original file size(on S3) is smaller than request.
|
// original file size(on S3) is smaller than request.
|
||||||
need_load_size = (iter->next() <= size_orgmeta ? iter->bytes : (size_orgmeta - iter->offset));
|
need_load_size = (iter->next() <= size_orgmeta ? iter->bytes : (size_orgmeta - iter->offset));
|
||||||
}
|
}
|
||||||
off_t over_size = iter->bytes - need_load_size;
|
|
||||||
|
|
||||||
// download
|
// download
|
||||||
if(S3fsCurl::GetMultipartSize() <= need_load_size && !nomultipart){
|
if(S3fsCurl::GetMultipartSize() <= need_load_size && !nomultipart){
|
||||||
@ -1226,19 +1264,8 @@ int FdEntity::Load(off_t start, off_t size, bool lock_already_held)
|
|||||||
if(0 != result){
|
if(0 != result){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize for the area of over original size
|
|
||||||
if(0 < over_size){
|
|
||||||
if(0 != (result = FdEntity::FillFile(fd, 0, over_size, iter->offset + need_load_size))){
|
|
||||||
S3FS_PRN_ERR("failed to fill rest bytes for fd(%d). errno(%d)", fd, result);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// set modify flag
|
|
||||||
is_modify = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set loaded flag
|
// Set loaded flag
|
||||||
pagelist.SetPageLoadedStatus(iter->offset, iter->bytes, true);
|
pagelist.SetPageLoadedStatus(iter->offset, iter->bytes, true, false);
|
||||||
}
|
}
|
||||||
PageList::FreeList(unloaded_list);
|
PageList::FreeList(unloaded_list);
|
||||||
}
|
}
|
||||||
@ -1363,8 +1390,6 @@ int FdEntity::NoCacheLoadAndPost(off_t start, off_t size)
|
|||||||
S3FS_PRN_ERR("failed to fill rest bytes for fd(%d). errno(%d)", tmpfd, result);
|
S3FS_PRN_ERR("failed to fill rest bytes for fd(%d). errno(%d)", tmpfd, result);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// set modify flag
|
|
||||||
is_modify = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
@ -1384,18 +1409,19 @@ int FdEntity::NoCacheLoadAndPost(off_t start, off_t size)
|
|||||||
// set loaded flag
|
// set loaded flag
|
||||||
if(!iter->loaded){
|
if(!iter->loaded){
|
||||||
if(iter->offset < start){
|
if(iter->offset < start){
|
||||||
fdpage page(iter->offset, start - iter->offset, iter->loaded);
|
fdpage page(iter->offset, start - iter->offset, iter->loaded, false);
|
||||||
iter->bytes -= (start - iter->offset);
|
iter->bytes -= (start - iter->offset);
|
||||||
iter->offset = start;
|
iter->offset = start;
|
||||||
pagelist.pages.insert(iter, page);
|
pagelist.pages.insert(iter, page);
|
||||||
}
|
}
|
||||||
if(0 != size && start + size < iter->next()){
|
if(0 != size && start + size < iter->next()){
|
||||||
fdpage page(iter->offset, start + size - iter->offset, true);
|
fdpage page(iter->offset, start + size - iter->offset, true, false);
|
||||||
iter->bytes -= (start + size - iter->offset);
|
iter->bytes -= (start + size - iter->offset);
|
||||||
iter->offset = start + size;
|
iter->offset = start + size;
|
||||||
pagelist.pages.insert(iter, page);
|
pagelist.pages.insert(iter, page);
|
||||||
}else{
|
}else{
|
||||||
iter->loaded = true;
|
iter->loaded = true;
|
||||||
|
iter->modified = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1494,7 +1520,7 @@ int FdEntity::RowFlush(const char* tpath, bool force_sync)
|
|||||||
}
|
}
|
||||||
AutoLock auto_lock(&fdent_data_lock);
|
AutoLock auto_lock(&fdent_data_lock);
|
||||||
|
|
||||||
if(!force_sync && !is_modify){
|
if(!force_sync && !pagelist.IsModified()){
|
||||||
// nothing to update.
|
// nothing to update.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1600,7 +1626,7 @@ int FdEntity::RowFlush(const char* tpath, bool force_sync)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(0 == result){
|
if(0 == result){
|
||||||
is_modify = false;
|
pagelist.ClearAllModified();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1613,9 +1639,9 @@ bool FdEntity::ReserveDiskSpace(off_t size)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!is_modify){
|
if(!pagelist.IsModified()){
|
||||||
// try to clear all cache for this fd.
|
// try to clear all cache for this fd.
|
||||||
pagelist.Init(pagelist.Size(), false);
|
pagelist.Init(pagelist.Size(), false, false);
|
||||||
if(-1 == ftruncate(fd, 0) || -1 == ftruncate(fd, pagelist.Size())){
|
if(-1 == ftruncate(fd, 0) || -1 == ftruncate(fd, pagelist.Size())){
|
||||||
S3FS_PRN_ERR("failed to truncate temporary file(%d).", fd);
|
S3FS_PRN_ERR("failed to truncate temporary file(%d).", fd);
|
||||||
return false;
|
return false;
|
||||||
@ -1641,7 +1667,7 @@ ssize_t FdEntity::Read(char* bytes, off_t start, size_t size, bool force_load)
|
|||||||
AutoLock auto_lock(&fdent_data_lock);
|
AutoLock auto_lock(&fdent_data_lock);
|
||||||
|
|
||||||
if(force_load){
|
if(force_load){
|
||||||
pagelist.SetPageLoadedStatus(start, size, false);
|
pagelist.SetPageLoadedStatus(start, size, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t rsize;
|
ssize_t rsize;
|
||||||
@ -1711,7 +1737,7 @@ ssize_t FdEntity::Write(const char* bytes, off_t start, size_t size)
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
// add new area
|
// add new area
|
||||||
pagelist.SetPageLoadedStatus(pagelist.Size(), start - pagelist.Size(), false);
|
pagelist.SetPageLoadedStatus(pagelist.Size(), start - pagelist.Size(), false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
int result = 0;
|
int result = 0;
|
||||||
@ -1755,11 +1781,8 @@ ssize_t FdEntity::Write(const char* bytes, off_t start, size_t size)
|
|||||||
S3FS_PRN_ERR("pwrite failed. errno(%d)", errno);
|
S3FS_PRN_ERR("pwrite failed. errno(%d)", errno);
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
if(!is_modify){
|
|
||||||
is_modify = true;
|
|
||||||
}
|
|
||||||
if(0 < wsize){
|
if(0 < wsize){
|
||||||
pagelist.SetPageLoadedStatus(start, wsize, true);
|
pagelist.SetPageLoadedStatus(start, wsize, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load uninitialized area which starts from (start + size) to EOF after writing.
|
// Load uninitialized area which starts from (start + size) to EOF after writing.
|
||||||
@ -1803,7 +1826,7 @@ void FdEntity::CleanupCache()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_modify) {
|
if(pagelist.IsModified()){
|
||||||
// cache is not committed to s3, cannot cleanup
|
// cache is not committed to s3, cannot cleanup
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2152,6 +2175,10 @@ FdEntity* FdManager::Open(const char* path, headers_t* pmeta, off_t size, time_t
|
|||||||
// found
|
// found
|
||||||
ent = (*iter).second;
|
ent = (*iter).second;
|
||||||
ent->Dup();
|
ent->Dup();
|
||||||
|
if(ent->IsModified()){
|
||||||
|
// If the file is being modified, it will not be resized.
|
||||||
|
size = -1;
|
||||||
|
}
|
||||||
close = true;
|
close = true;
|
||||||
|
|
||||||
}else if(is_create){
|
}else if(is_create){
|
||||||
|
@ -58,9 +58,10 @@ struct fdpage
|
|||||||
off_t offset;
|
off_t offset;
|
||||||
off_t bytes;
|
off_t bytes;
|
||||||
bool loaded;
|
bool loaded;
|
||||||
|
bool modified;
|
||||||
|
|
||||||
fdpage(off_t start = 0, off_t size = 0, bool is_loaded = false)
|
fdpage(off_t start = 0, off_t size = 0, bool is_loaded = false, bool is_modified = false)
|
||||||
: offset(start), bytes(size), loaded(is_loaded) {}
|
: offset(start), bytes(size), loaded(is_loaded), modified(is_modified) {}
|
||||||
|
|
||||||
off_t next(void) const { return (offset + bytes); }
|
off_t next(void) const { return (offset + bytes); }
|
||||||
off_t end(void) const { return (0 < bytes ? offset + bytes - 1 : 0); }
|
off_t end(void) const { return (0 < bytes ? offset + bytes - 1 : 0); }
|
||||||
@ -72,6 +73,7 @@ class FdEntity;
|
|||||||
//
|
//
|
||||||
// Management of loading area/modifying
|
// Management of loading area/modifying
|
||||||
//
|
//
|
||||||
|
// cppcheck-suppress copyCtorAndEqOperator
|
||||||
class PageList
|
class PageList
|
||||||
{
|
{
|
||||||
friend class FdEntity; // only one method access directly pages.
|
friend class FdEntity; // only one method access directly pages.
|
||||||
@ -81,25 +83,30 @@ class PageList
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void Clear(void);
|
void Clear(void);
|
||||||
bool Compress(void);
|
bool Compress(bool force_modified = false);
|
||||||
bool Parse(off_t new_pos);
|
bool Parse(off_t new_pos);
|
||||||
|
bool RawGetUnloadPageList(fdpage_list_t& dlpages, off_t offset, off_t size);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void FreeList(fdpage_list_t& list);
|
static void FreeList(fdpage_list_t& list);
|
||||||
|
|
||||||
explicit PageList(off_t size = 0, bool is_loaded = false);
|
explicit PageList(off_t size = 0, bool is_loaded = false, bool is_modified = false);
|
||||||
|
explicit PageList(const PageList& other);
|
||||||
~PageList();
|
~PageList();
|
||||||
|
|
||||||
bool Init(off_t size, bool is_loaded);
|
bool Init(off_t size, bool is_loaded, bool is_modified);
|
||||||
off_t Size(void) const;
|
off_t Size(void) const;
|
||||||
bool Resize(off_t size, bool is_loaded);
|
bool Resize(off_t size, bool is_loaded, bool is_modified);
|
||||||
|
|
||||||
bool IsPageLoaded(off_t start = 0, off_t size = 0) const; // size=0 is checking to end of list
|
bool IsPageLoaded(off_t start = 0, off_t size = 0) const; // size=0 is checking to end of list
|
||||||
bool SetPageLoadedStatus(off_t start, off_t size, bool is_loaded = true, bool is_compress = true);
|
bool SetPageLoadedStatus(off_t start, off_t size, bool is_loaded = true, bool is_modified = false, bool is_compress = true);
|
||||||
bool FindUnloadedPage(off_t start, off_t& resstart, off_t& ressize) const;
|
bool FindUnloadedPage(off_t start, off_t& resstart, off_t& ressize) const;
|
||||||
off_t GetTotalUnloadedPageSize(off_t start = 0, off_t size = 0) const; // size=0 is checking to end of list
|
off_t GetTotalUnloadedPageSize(off_t start = 0, off_t size = 0) const; // size=0 is checking to end of list
|
||||||
int GetUnloadedPages(fdpage_list_t& unloaded_list, off_t start = 0, off_t size = 0) const; // size=0 is checking to end of list
|
int GetUnloadedPages(fdpage_list_t& unloaded_list, off_t start = 0, off_t size = 0) const; // size=0 is checking to end of list
|
||||||
|
|
||||||
|
bool IsModified(void) const;
|
||||||
|
bool ClearAllModified(void);
|
||||||
|
|
||||||
bool Serialize(CacheFileStat& file, bool is_output);
|
bool Serialize(CacheFileStat& file, bool is_output);
|
||||||
void Dump(void);
|
void Dump(void);
|
||||||
};
|
};
|
||||||
@ -125,7 +132,6 @@ class FdEntity
|
|||||||
etaglist_t etaglist; // for no cached multipart uploading when no disk space
|
etaglist_t etaglist; // for no cached multipart uploading when no disk space
|
||||||
off_t mp_start; // start position for no cached multipart(write method only)
|
off_t mp_start; // start position for no cached multipart(write method only)
|
||||||
off_t mp_size; // size for no cached multipart(write method only)
|
off_t mp_size; // size for no cached multipart(write method only)
|
||||||
bool is_modify; // if file is changed, this flag is true
|
|
||||||
std::string cachepath; // local cache file path
|
std::string cachepath; // local cache file path
|
||||||
// (if this is empty, does not load/save pagelist.)
|
// (if this is empty, does not load/save pagelist.)
|
||||||
std::string mirrorpath; // mirror file path to local cache file path
|
std::string mirrorpath; // mirror file path to local cache file path
|
||||||
@ -153,6 +159,7 @@ class FdEntity
|
|||||||
const char* GetPath(void) const { return path.c_str(); }
|
const char* GetPath(void) const { return path.c_str(); }
|
||||||
void SetPath(const std::string &newpath) { path = newpath; }
|
void SetPath(const std::string &newpath) { path = newpath; }
|
||||||
int GetFd(void) const { return fd; }
|
int GetFd(void) const { return fd; }
|
||||||
|
bool IsModified(void) const { return pagelist.IsModified(); }
|
||||||
|
|
||||||
bool GetStats(struct stat& st, bool lock_already_held = false);
|
bool GetStats(struct stat& st, bool lock_already_held = false);
|
||||||
int SetCtime(time_t time);
|
int SetCtime(time_t time);
|
||||||
|
@ -512,6 +512,17 @@ function test_rm_rf_dir {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test_copy_file {
|
||||||
|
describe "Test simple copy"
|
||||||
|
|
||||||
|
dd if=/dev/urandom of=/tmp/simple_file bs=1024 count=1
|
||||||
|
cp /tmp/simple_file copied_simple_file
|
||||||
|
cmp /tmp/simple_file copied_simple_file
|
||||||
|
|
||||||
|
rm /tmp/simple_file
|
||||||
|
rm copied_simple_file
|
||||||
|
}
|
||||||
|
|
||||||
function test_write_after_seek_ahead {
|
function test_write_after_seek_ahead {
|
||||||
describe "Test writes succeed after a seek ahead"
|
describe "Test writes succeed after a seek ahead"
|
||||||
dd if=/dev/zero of=testfile seek=1 count=1 bs=1024
|
dd if=/dev/zero of=testfile seek=1 count=1 bs=1024
|
||||||
@ -589,6 +600,7 @@ function add_all_tests {
|
|||||||
add_tests test_mtime_file
|
add_tests test_mtime_file
|
||||||
add_tests test_update_time
|
add_tests test_update_time
|
||||||
add_tests test_rm_rf_dir
|
add_tests test_rm_rf_dir
|
||||||
|
add_tests test_copy_file
|
||||||
add_tests test_write_after_seek_ahead
|
add_tests test_write_after_seek_ahead
|
||||||
add_tests test_overwrite_existing_file_range
|
add_tests test_overwrite_existing_file_range
|
||||||
add_tests test_concurrency
|
add_tests test_concurrency
|
||||||
|
Loading…
Reference in New Issue
Block a user