From 8e59fbec0063231c0571a5627255ac4244312903 Mon Sep 17 00:00:00 2001
From: Gareth Tribello <gt@eider.asg>
Date: Fri, 26 Jul 2013 09:24:56 +0100
Subject: [PATCH] Better backup of old files in analysis routines

In analysis runs results from previous analysis are saved as
analysis.0.<filename>, analysis.1.<filename> etc.  If the calculation
is NOT restarted and there are files with these names hanging about they are
renamed bck.0.analysis.0.<filename> bck.0.analysis.1.<filename> etc.
---
 src/analysis/Analysis.cpp  |  9 +++++
 src/analysis/Analysis.h    |  4 +++
 src/analysis/Histogram.cpp |  3 +-
 src/tools/OFile.cpp        | 67 ++++++++++++++++++++++++--------------
 src/tools/OFile.h          |  8 +++++
 5 files changed, 66 insertions(+), 25 deletions(-)

diff --git a/src/analysis/Analysis.cpp b/src/analysis/Analysis.cpp
index e4ab30dc8..dd8ff1722 100644
--- a/src/analysis/Analysis.cpp
+++ b/src/analysis/Analysis.cpp
@@ -192,6 +192,15 @@ void Analysis::readDataFromFile( const std::string& filename ){
   if(old_norm>0) firstAnalysisDone=true;
 }
 
+void Analysis::parseOutputFile( const std::string& key, std::string& filename ){
+  parse(key,filename);
+  if( !plumed.getRestart() ){
+      OFile ofile; ofile.link(*this);
+      ofile.setBackupString("analysis");
+      ofile.backupAllFiles(filename);
+  } 
+}
+
 void Analysis::prepare(){
   if(needeng) plumed.getAtoms().setCollectEnergy(true);
 }
diff --git a/src/analysis/Analysis.h b/src/analysis/Analysis.h
index 6358c1adb..3e2f50066 100644
--- a/src/analysis/Analysis.h
+++ b/src/analysis/Analysis.h
@@ -88,6 +88,10 @@ private:
 /// you probably need getNormalization()
   double retrieveNorm() const ;
 protected:
+/// This is used to read in output file names for analysis methods.  When
+/// this method is used and the calculation is not restarted old analysis
+/// files are backed up.
+  void parseOutputFile( const std::string& key, std::string& filename );
 /// Return the number of arguments (this overwrites the one in ActionWithArguments)
   unsigned getNumberOfArguments() const;
 /// Return the number of data points
diff --git a/src/analysis/Histogram.cpp b/src/analysis/Histogram.cpp
index aaa6cfd62..2e8d39111 100644
--- a/src/analysis/Histogram.cpp
+++ b/src/analysis/Histogram.cpp
@@ -124,7 +124,8 @@ gbin(getNumberOfArguments())
   parseVector("GRID_MIN",gmin);
   parseVector("GRID_MAX",gmax);
   parseVector("GRID_BIN",gbin);
-  parse("GRID_WFILE",gridfname); 
+  parseOutputFile("GRID_WFILE",gridfname); 
+
   // Read stuff for window functions
   parseVector("BANDWIDTH",bw);
   // Read the type of kernel we are using
diff --git a/src/tools/OFile.cpp b/src/tools/OFile.cpp
index caca9a9a7..7820ee202 100644
--- a/src/tools/OFile.cpp
+++ b/src/tools/OFile.cpp
@@ -215,6 +215,48 @@ void OFile::setBackupString( const std::string& str ){
   backstring=str;
 }
 
+void OFile::backupAllFiles( const std::string& str ){
+  plumed_assert( backstring!="bck" && plumed && !plumed->getRestart() );
+  size_t found=str.find_last_of("/\\");
+  std::string filename = str + plumed->getSuffix();
+  std::string directory=filename.substr(0,found+1);
+  std::string file=filename.substr(found+1);
+  if( FileExist(filename) ) backupFile("bck", filename);
+  for(int i=0;;i++){
+     std::string num; Tools::convert(i,num);
+     std::string filestr = directory + backstring + "." + num + "." + file;
+     if( !FileExist(filestr) ) break;
+     backupFile( "bck", filestr);
+  }
+}
+
+void OFile::backupFile( const std::string& bstring, const std::string& fname ){
+   int maxbackup=100;
+   if(std::getenv("PLUMED_MAXBACKUP")) Tools::convert(std::getenv("PLUMED_MAXBACKUP"),maxbackup);
+   if(maxbackup>0 && (!comm || comm->Get_rank()==0)){
+     FILE* ff=std::fopen(const_cast<char*>(fname.c_str()),"r");
+     FILE* fff=NULL;
+     if(ff){
+       std::string backup;
+       size_t found=fname.find_last_of("/\\");
+       std::string directory=fname.substr(0,found+1);
+       std::string file=fname.substr(found+1);
+       for(int i=0;;i++){
+         std::string num;
+         Tools::convert(i,num);
+         if(i>maxbackup) plumed_merror("cannot backup file "+file+" maximum number of backup is "+num+"\n");
+         backup=directory+bstring +"."+num+"."+file;
+         fff=std::fopen(backup.c_str(),"r");
+         if(!fff) break;
+       }
+       int check=rename(fname.c_str(),backup.c_str());
+       plumed_massert(check==0,"renaming "+fname+" into "+backup+" failed for some reason");
+     }
+     if(ff) std::fclose(ff);
+     if(fff) std::fclose(fff);
+   }
+}
+
 OFile& OFile::open(const std::string&path){
   plumed_assert(!cloned);
   eof=false;
@@ -227,30 +269,7 @@ OFile& OFile::open(const std::string&path){
   if(plumed && plumed->getRestart()){
      fp=std::fopen(const_cast<char*>(this->path.c_str()),"a");
   } else {
-     int maxbackup=100;
-     if(std::getenv("PLUMED_MAXBACKUP")) Tools::convert(std::getenv("PLUMED_MAXBACKUP"),maxbackup);
-     if(maxbackup>0 && (!comm || comm->Get_rank()==0)){
-       FILE* ff=std::fopen(const_cast<char*>(this->path.c_str()),"r");
-       FILE* fff=NULL;
-       if(ff){
-         std::string backup;
-         size_t found=this->path.find_last_of("/\\");
-         std::string directory=this->path.substr(0,found+1);
-         std::string file=this->path.substr(found+1);
-         for(int i=0;;i++){
-           std::string num;
-           Tools::convert(i,num);
-           if(i>maxbackup) plumed_merror("cannot backup file "+file+" maximum number of backup is "+num+"\n");
-           backup=directory+backstring +"."+num+"."+file;
-           fff=std::fopen(backup.c_str(),"r");
-           if(!fff) break;
-         }
-         int check=rename(this->path.c_str(),backup.c_str());
-         plumed_massert(check==0,"renaming "+this->path+" into "+backup+" failed for some reason");
-       }
-       if(ff) std::fclose(ff);
-       if(fff) std::fclose(fff);
-     }
+     backupFile( backstring, this->path );
      if(comm)comm->Barrier();
      fp=std::fopen(const_cast<char*>(this->path.c_str()),"w");
   }
diff --git a/src/tools/OFile.h b/src/tools/OFile.h
index cb96116f1..74732c167 100644
--- a/src/tools/OFile.h
+++ b/src/tools/OFile.h
@@ -134,6 +134,14 @@ public:
   OFile& link(OFile&);
 /// Set the string name to be used for automatic backup
   void setBackupString( const std::string& );
+/// Backup a file by giving it a different name
+  void backupFile( const std::string& bstring, const std::string& fname );
+/// This backs up all the files that would have been created with the
+/// name str.  It is used in analysis when you are not restarting.  Analysis 
+/// output files at different times, which are names analysis.0.<filename>,
+/// analysis.1.<filename> and <filename>, are backed up to bck.0.analysis.0.<filename>,
+/// bck.0.analysis.1.<filename> and bck.0.<filename>
+  void backupAllFiles( const std::string& str );
 /// Opens the file using automatic append/backup
   OFile& open(const std::string&name); 
 /// Set the prefix for output.
-- 
GitLab