implement dirsync() and syncing on tmpfstreams
authorGerd von Egidy <gerd.von.egidy@intra2net.com>
Thu, 11 Mar 2010 11:31:29 +0000 (12:31 +0100)
committerGerd von Egidy <gerd.von.egidy@intra2net.com>
Thu, 11 Mar 2010 11:32:34 +0000 (12:32 +0100)
src/filefunc.cpp
src/filefunc.hxx
src/tmpfstream.hpp
src/tmpfstream_impl.hpp
test/test_tmpfstream.cpp

index c0995e6..b43ef48 100644 (file)
@@ -616,6 +616,25 @@ std::string normalize_path(const std::string& path)
 
 
 /**
+ * @brief calls fsync on a given directory to sync all it's metadata
+ * @param path the path of the directory.
+ * @return true if successful
+ */
+bool dirsync(const std::string& path)
+{
+    // sync the directory the file is in
+    DIR* dir=opendir(path.c_str());
+    if (dir == NULL)
+        return false;
+
+    int ret=fsync(dirfd(dir));
+
+    closedir(dir);
+
+    return (ret==0);
+}
+
+/**
  * @brief changes the file(/path) mode.
  * @param path the path to change the mode for.
  * @param mode the new file mode.
index 920a10f..f236246 100644 (file)
@@ -152,6 +152,8 @@ std::string dirname(const std::string& path);
 
 std::string normalize_path(const std::string& path);
 
+bool dirsync(const std::string& path);
+
 bool chmod(const std::string& path, int mode);
 bool chown(const std::string& path, const I2n::User& user, const I2n::Group& group= I2n::Group());
 
index e4aac49..5f460e8 100644 (file)
@@ -40,6 +40,7 @@ class tmpfstreamTempl : public bio::stream<Device, Tr, Alloc>
 private:
     std::string tmpfilename;
     bool unlinked;
+    int fd;
 
 public:
     tmpfstreamTempl()
@@ -69,6 +70,8 @@ public:
         { return unlinked; }
 
     bool move(const std::string& targetpath, bool overwrite=false);
+
+    bool sync();
 };
 
 template< typename Device,
index 2de4a91..ee558af 100644 (file)
@@ -56,7 +56,7 @@ bool tmpfstreamTempl<Device,Tr,Alloc>::open(const std::string& tmpnametemplate,
     if (mode & std::ios_base::app)
         flags |= O_APPEND;
 
-    int fd=mkostemp(chbuf,flags);
+    fd=mkostemp(chbuf,flags);
     tmpfilename=chbuf;
     delete[] chbuf;
 
@@ -131,13 +131,30 @@ bool tmpfstreamTempl<Device,Tr,Alloc>::move(const std::string& targetpath,
 }
 
 template< typename Device, typename Tr, typename Alloc >
+bool tmpfstreamTempl<Device,Tr,Alloc>::sync()
+{
+    if (!tmpfstreamTempl<Device,Tr,Alloc>::is_open())
+        return false;
+
+    tmpfstreamTempl<Device,Tr,Alloc>::flush();
+
+    // sync the file itself
+    if (fsync(fd) != 0)
+        return false;
+
+    // sync the dir: both is needed for data + metadata sync
+    return dirsync(dirname(get_tmp_filename()));
+}
+
+template< typename Device, typename Tr, typename Alloc >
 void tmpfcopystreamTempl<Device,Tr,Alloc>::close()
 {
     if (!tmpfstreamTempl<Device,Tr,Alloc>::is_open() || 
          tmpfstreamTempl<Device,Tr,Alloc>::is_unlinked())
         return;
 
-    // TODO full sync
+    if (get_full_sync())
+        tmpfstreamTempl<Device,Tr,Alloc>::sync();
 
     // close the underlying filedescriptor
     tmpfstreamTempl<Device,Tr,Alloc>::close();
@@ -145,6 +162,9 @@ void tmpfcopystreamTempl<Device,Tr,Alloc>::close()
     tmpfstreamTempl<Device,Tr,Alloc>::set_file_mode(filemode_on_close);
 
     move(get_original_filename(),true);
+
+    if (get_full_sync())
+        dirsync(dirname(get_original_filename()));
 }
 
 }
index 24bd8ac..c9e2612 100644 (file)
@@ -105,7 +105,7 @@ BOOST_AUTO_TEST_CASE(TmpofstreamMove1)
     BOOST_CHECK_EQUAL( true, stat.is_regular_file() );
 
     tmpf << "hello world" << endl;
-    tmpf.flush();
+    BOOST_CHECK_EQUAL( true, tmpf.sync() );
 
     BOOST_CHECK_EQUAL( true, tmpf.move(".foobar",false) );