diff --git a/src/fdcache_page.cpp b/src/fdcache_page.cpp index b47e8a3..332ed30 100644 --- a/src/fdcache_page.cpp +++ b/src/fdcache_page.cpp @@ -820,32 +820,21 @@ bool PageList::ClearAllModified() return Compress(); } -bool PageList::Serialize(CacheFileStat& file, ino_t inode) +bool PageList::Serialize(const CacheFileStat& file, ino_t inode) const { - if(!file.Open()){ - return false; - } - - // - // put to file - // + // make contents std::ostringstream ssall; ssall << inode << ":" << Size(); for(auto iter = pages.cbegin(); iter != pages.cend(); ++iter){ ssall << "\n" << iter->offset << ":" << iter->bytes << ":" << (iter->loaded ? "1" : "0") << ":" << (iter->modified ? "1" : "0"); } - - if(-1 == ftruncate(file.GetFd(), 0)){ - S3FS_PRN_ERR("failed to truncate file(to 0) for stats(%d)", errno); - return false; - } std::string strall = ssall.str(); - if(0 >= pwrite(file.GetFd(), strall.c_str(), strall.length(), 0)){ - S3FS_PRN_ERR("failed to write stats(%d)", errno); + + // over write + if(!file.OverWriteFile(strall)){ return false; } - return true; } diff --git a/src/fdcache_page.h b/src/fdcache_page.h index e11ac30..76e9dd9 100644 --- a/src/fdcache_page.h +++ b/src/fdcache_page.h @@ -94,7 +94,7 @@ class PageList void Clear(); bool Parse(off_t new_pos); - bool Serialize(CacheFileStat& file, ino_t inode); + bool Serialize(const CacheFileStat& file, ino_t inode) const; public: static void FreeList(fdpage_list_t& list); diff --git a/src/fdcache_stat.cpp b/src/fdcache_stat.cpp index be68fe6..3edb501 100644 --- a/src/fdcache_stat.cpp +++ b/src/fdcache_stat.cpp @@ -193,6 +193,49 @@ bool CacheFileStat::SetPath(const char* tpath, bool is_open) return Open(); } +// [NOTE] +// There is no need to check whether the file is open because using rename(). +// +bool CacheFileStat::OverWriteFile(const std::string& strall) const +{ + // make temporary file path(in same cache directory) + std::string sfile_path; + if(0 != CacheFileStat::MakeCacheFileStatPath(path.c_str(), sfile_path, true)){ + S3FS_PRN_ERR("failed to create cache stat file path(%s)", path.c_str()); + return false; + } + std::string strTmpFile = mydirname(sfile_path) + "/.tmpstat.XXXXXX"; + strTmpFile.push_back('\0'); // terminate with a null character and allocate space for it. + + // open temporary file(mode: 0600) + // + // [TODO] + // Currently, use "&str[pos]" to make it possible to build with C++14. + // Once we support C++17 or later, we will use "str.data()". + // + int tmpfd; + if(-1 == (tmpfd = mkstemp(&strTmpFile[0]))){ // NOLINT(readability-container-data-pointer) + S3FS_PRN_ERR("failed to create temporary cache stat file path(%s) for %s cache", strTmpFile.c_str(), sfile_path.c_str()); + return false; + } + + // write contents + if(0 >= pwrite(tmpfd, strall.c_str(), strall.length(), 0)){ + S3FS_PRN_ERR("failed to write stats to temporary file(%d)", errno); + close(tmpfd); + return false; + } + close(tmpfd); + + // rename + if(0 != rename(strTmpFile.c_str(), sfile_path.c_str())){ + S3FS_PRN_ERR("failed to rename temporary cache stat file path(%s) to %s cache", strTmpFile.c_str(), sfile_path.c_str()); + unlink(strTmpFile.c_str()); + return false; + } + return true; +} + bool CacheFileStat::RawOpen(bool readonly) { if(path.empty()){ diff --git a/src/fdcache_stat.h b/src/fdcache_stat.h index 8134166..38b03dc 100644 --- a/src/fdcache_stat.h +++ b/src/fdcache_stat.h @@ -56,6 +56,7 @@ class CacheFileStat bool Release(); bool SetPath(const char* tpath, bool is_open = true); int GetFd() const { return fd; } + bool OverWriteFile(const std::string& strall) const; }; #endif // S3FS_FDCACHE_STAT_H_ diff --git a/src/test_page_list.cpp b/src/test_page_list.cpp index b99de34..931d7cd 100644 --- a/src/test_page_list.cpp +++ b/src/test_page_list.cpp @@ -22,7 +22,8 @@ #include "fdcache_stat.h" #include "test_util.h" -bool CacheFileStat::Open() { return false; } // NOLINT(readability-convert-member-functions-to-static) +bool CacheFileStat::Open() { return false; } // NOLINT(readability-convert-member-functions-to-static) +bool CacheFileStat::OverWriteFile(const std::string& strall) const { return false; } // NOLINT(readability-convert-member-functions-to-static) void test_compress() {