@@ -904,29 +904,40 @@ code CLASS::backup(const event_handler& handler, bool prune) NOEXCEPT
904904
905905 static const auto primary = configuration_.path / schema::dir::primary;
906906 static const auto secondary = configuration_.path / schema::dir::secondary;
907+ static const auto temporary = configuration_.path / schema::dir::temporary;
907908
908909 handler (event_t ::archive_snapshot, table_t ::store);
909910
911+ // Ensure existing and empty /temporary.
912+ if ((ec = file::clear_directory_ex (temporary))) return ec;
913+
914+ // Ensure no /primary.
910915 if (file::is_directory (primary))
911916 {
912- // Delete /secondary, rename /primary to /secondary .
917+ // Delete /secondary.
913918 if ((ec = file::clear_directory_ex (secondary))) return ec;
914919 if ((ec = file::remove_ex (secondary))) return ec;
920+
921+ // Rename /primary to /secondary (atomic).
915922 if ((ec = file::rename_ex (primary, secondary))) return ec;
916923 }
917924
918- // Dump /heads memory maps to /primary.
919- if ((ec = file::clear_directory_ex (primary))) return ec;
920- ec = dump (primary, handler);
925+ // Dump /heads memory maps to /temporary.
926+ if ((ec = dump (temporary, handler)))
927+ {
928+ // Failed dump, clear temporary and rename secondary to primary.
929+ if (file::clear_directory (temporary) && file::remove (temporary))
930+ file::rename (secondary, primary);
921931
922- // If failed clear primary and rename secondary to primary .
923- if (ec && file::clear_directory (primary) && file::remove (primary))
924- /* bool */ file::rename (secondary, primary);
932+ // Return original fault .
933+ return ec;
934+ }
925935
926- return ec;
936+ // Rename /temporary to /primary (atomic).
937+ return file::rename_ex (temporary, primary);
927938}
928939
929- // Dump memory maps of /heads to new files in /primary .
940+ // Dump memory maps of /heads to new files in /temporary .
930941// Heads are copied from RAM, not flushed to disk and copied as files.
931942TEMPLATE
932943code CLASS::dump (const path& folder,
@@ -1037,17 +1048,21 @@ code CLASS::restore(const event_handler& handler) NOEXCEPT
10371048 static const auto heads = configuration_.path / schema::dir::heads;
10381049 static const auto primary = configuration_.path / schema::dir::primary;
10391050 static const auto secondary = configuration_.path / schema::dir::secondary;
1051+ static const auto temporary = configuration_.path / schema::dir::temporary;
10401052
10411053 handler (event_t ::recover_snapshot, table_t ::store);
10421054
1055+ // Clean up any residual /temporary.
1056+ file::clear_directory (temporary);
1057+ file::remove (temporary);
1058+
10431059 if (file::is_directory (primary))
10441060 {
10451061 // Clear invalid /heads, recover from /primary, clone to /primary.
10461062 ec = file::clear_directory_ex (heads);
10471063 if (!ec) ec = file::remove_ex (heads);
10481064 if (!ec) ec = file::rename_ex (primary, heads);
10491065 if (!ec) ec = file::copy_directory_ex (heads, primary);
1050- if (ec) /* bool */ file::remove_ex (primary);
10511066 }
10521067 else if (file::is_directory (secondary))
10531068 {
@@ -1056,7 +1071,6 @@ code CLASS::restore(const event_handler& handler) NOEXCEPT
10561071 if (!ec) ec = file::remove_ex (heads);
10571072 if (!ec) ec = file::rename_ex (secondary, heads);
10581073 if (!ec) ec = file::copy_directory_ex (heads, primary);
1059- if (ec) /* bool */ file::remove_ex (secondary);
10601074 }
10611075 else
10621076 {
0 commit comments