diff --git a/src/Database.cpp b/src/Database.cpp index 4df697bd..a22a16fc 100644 --- a/src/Database.cpp +++ b/src/Database.cpp @@ -33,6 +33,7 @@ #include #include #include +#include //////////////////////////////////////////////////////////////////////////////// Database::iterator::iterator (files_iterator fbegin, files_iterator fend) : @@ -257,7 +258,7 @@ void Database::commit () file.commit (); } - File::write (_location + "/tags.data", _tagInfoDatabase.toJson ()); + AtomicFile::write (_location + "/tags.data", _tagInfoDatabase.toJson ()); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/Datafile.cpp b/src/Datafile.cpp index 22fe00ef..c504cc48 100644 --- a/src/Datafile.cpp +++ b/src/Datafile.cpp @@ -32,11 +32,12 @@ #include #include #include +#include //////////////////////////////////////////////////////////////////////////////// void Datafile::initialize (const std::string& name) { - _file = File (name); + _file = Path (name); // From the name, which is of the form YYYY-MM.data, extract the YYYY and MM. auto basename = _file.name (); @@ -129,24 +130,25 @@ void Datafile::commit () // The _dirty flag indicates that the file needs to be written. if (_dirty) { - if (_file.open ()) + AtomicFile file (_file); + if (file.open ()) { - _file.lock (); - _file.truncate (); - _file.append (std::string ("")); // Seek to EOF. - // Sort the intervals by ascending start time. std::sort (_lines.begin (), _lines.end ()); // Write out all the lines. + file.truncate (); for (auto& line : _lines) - _file.write_raw (line + '\n'); + { + file.write_raw (line + '\n'); + } - _file.close (); _dirty = false; } else + { throw format ("Could not write to data file {1}", _file._data); + } } } @@ -168,21 +170,20 @@ std::string Datafile::dump () const //////////////////////////////////////////////////////////////////////////////// void Datafile::load_lines () { - if (_file.open ()) + AtomicFile file (_file); + if (file.open ()) { - _file.lock (); - // Load the data. std::vector read_lines; - _file.read (read_lines); - _file.close (); + file.read (read_lines); + file.close (); // Append the lines that were read. for (auto& line : read_lines) _lines.push_back (line); _lines_loaded = true; - debug (format ("{1}: {2} intervals", _file.name (), read_lines.size ())); + debug (format ("{1}: {2} intervals", file.name (), read_lines.size ())); } } diff --git a/src/Datafile.h b/src/Datafile.h index f73c1d81..ff281cd2 100644 --- a/src/Datafile.h +++ b/src/Datafile.h @@ -53,7 +53,7 @@ private: void load_lines (); private: - File _file {}; + Path _file {}; bool _dirty {false}; std::vector _lines {}; bool _lines_loaded {false}; diff --git a/src/Journal.cpp b/src/Journal.cpp index 8b9252a5..d31cc264 100644 --- a/src/Journal.cpp +++ b/src/Journal.cpp @@ -24,7 +24,7 @@ // //////////////////////////////////////////////////////////////////////////////// -#include +#include #include #include #include @@ -54,19 +54,9 @@ void Journal::endTransaction () throw "Call to end non-existent transaction"; } - File undo (_location); + AtomicFile::append (_location, _currentTransaction->toString ()); - if (undo.open ()) - { - undo.append (_currentTransaction->toString()); - - undo.close (); - _currentTransaction.reset (); - } - else - { - throw format ("Unable to write the undo transaction to {1}", undo._data); - } + _currentTransaction.reset (); } //////////////////////////////////////////////////////////////////////////////// @@ -102,7 +92,7 @@ void Journal::recordUndoAction ( //////////////////////////////////////////////////////////////////////////////// Transaction Journal::popLastTransaction () { - File undo (_location); + AtomicFile undo (_location); std::vector read_lines; undo.read (read_lines); @@ -125,8 +115,8 @@ Transaction Journal::popLastTransaction () Transaction last = transactions.back (); transactions.pop_back (); - File::remove (undo._data); undo.open (); + undo.truncate (); for (auto& transaction : transactions) { diff --git a/src/Journal.h b/src/Journal.h index cc57d96e..8e3e58ee 100644 --- a/src/Journal.h +++ b/src/Journal.h @@ -37,6 +37,8 @@ class Journal { public: Journal() = default; + Journal(const Journal&) = delete; + Journal& operator= (const Journal&) = delete; void initialize(const std::string&); diff --git a/src/Rules.cpp b/src/Rules.cpp index cc943429..058a01ec 100644 --- a/src/Rules.cpp +++ b/src/Rules.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include //////////////////////////////////////////////////////////////////////////////// @@ -123,8 +124,17 @@ void Rules::load (const std::string& file, int nest /* = 1 */) // Read the file, then parse the contents. std::string contents; - if (File::read (file, contents) && contents.length ()) - parse (contents, nest); + try + { + AtomicFile::read (file, contents); + if (contents.length ()) + { + parse (contents, nest); + } + } + catch (...) + { + } } //////////////////////////////////////////////////////////////////////////////// @@ -624,7 +634,9 @@ bool Rules::setConfigVariable ( } if (change) - File::write (rules.file (), lines); + { + AtomicFile::write (rules.file (), lines); + } return change; } @@ -648,7 +660,7 @@ int Rules::unsetConfigVariable ( // Read config file as lines of text. std::vector lines; - File::read (rules.file (), lines); + AtomicFile::read (rules.file (), lines); // If there is a non-comment line containing the entry in flattened form: // a.b.c = value @@ -703,7 +715,9 @@ int Rules::unsetConfigVariable ( } if (change) - File::write (rules.file (), lines); + { + AtomicFile::write (rules.file (), lines); + } if (change && found) return 0; diff --git a/src/timew.cpp b/src/timew.cpp index 4bde0d8b..a0e9572d 100644 --- a/src/timew.cpp +++ b/src/timew.cpp @@ -25,6 +25,7 @@ //////////////////////////////////////////////////////////////////////////////// #include +#include #include #include #include @@ -96,6 +97,8 @@ int main (int argc, const char** argv) // Save any outstanding changes. database.commit (); + + AtomicFile::finalize_all (); } catch (const std::string& error)