diff options
author | Simon MacMullen <simon@rabbitmq.com> | 2010-11-18 13:25:36 +0000 |
---|---|---|
committer | Simon MacMullen <simon@rabbitmq.com> | 2010-11-18 13:25:36 +0000 |
commit | 09a05a6c8a202ba81b26678d8477e2fb6aac9e6c (patch) | |
tree | 03c1e91ad7c378af29523f3ec047bbe60f335a44 | |
parent | 631f130edc3f8fbb704e1c1390925b8d7009b103 (diff) | |
download | rabbitmq-server-09a05a6c8a202ba81b26678d8477e2fb6aac9e6c.tar.gz |
Take a backup before upgrading.
-rw-r--r-- | src/rabbit_misc.erl | 32 | ||||
-rw-r--r-- | src/rabbit_upgrade.erl | 25 |
2 files changed, 53 insertions, 4 deletions
diff --git a/src/rabbit_misc.erl b/src/rabbit_misc.erl index 9290508f..44fbe4ad 100644 --- a/src/rabbit_misc.erl +++ b/src/rabbit_misc.erl @@ -61,7 +61,7 @@ -export([sort_field_table/1]). -export([pid_to_string/1, string_to_pid/1]). -export([version_compare/2, version_compare/3]). --export([recursive_delete/1, dict_cons/3, orddict_cons/3, +-export([recursive_delete/1, recursive_copy/2, dict_cons/3, orddict_cons/3, unlink_and_capture_exit/1]). -export([get_options/2]). -export([all_module_attributes/1, build_acyclic_graph/4]). @@ -184,6 +184,9 @@ -spec(recursive_delete/1 :: ([file:filename()]) -> rabbit_types:ok_or_error({file:filename(), any()})). +-spec(recursive_copy/2 :: + (file:filename(), file:filename()) + -> rabbit_types:ok_or_error({file:filename(), file:filename(), any()})). -spec(dict_cons/3 :: (any(), any(), dict()) -> dict()). -spec(orddict_cons/3 :: (any(), any(), orddict:orddict()) -> orddict:orddict()). -spec(unlink_and_capture_exit/1 :: (pid()) -> 'ok'). @@ -684,6 +687,33 @@ recursive_delete1(Path) -> end end. +recursive_copy(Src, Dest) -> + case filelib:is_dir(Src) of + false -> case file:copy(Src, Dest) of + {ok, _Bytes} -> ok; + {error, enoent} -> ok; %% Path doesn't exist anyway + {error, Err} -> {error, {Src, Dest, Err}} + end; + true -> case file:list_dir(Src) of + {ok, FileNames} -> + case file:make_dir(Dest) of + ok -> + lists:foldl( + fun (FileName, ok) -> + recursive_copy( + filename:join(Src, FileName), + filename:join(Dest, FileName)); + (_FileName, Error) -> + Error + end, ok, FileNames); + {error, Err} -> + {error, {Src, Dest, Err}} + end; + {error, Err} -> + {error, {Src, Dest, Err}} + end + end. + dict_cons(Key, Value, Dict) -> dict:update(Key, fun (List) -> [Value | List] end, [Value], Dict). diff --git a/src/rabbit_upgrade.erl b/src/rabbit_upgrade.erl index 9522227e..4b7b4342 100644 --- a/src/rabbit_upgrade.erl +++ b/src/rabbit_upgrade.erl @@ -120,14 +120,33 @@ heads(G) -> %% ------------------------------------------------------------------- apply_upgrades(Upgrades) -> - LockFile = lock_filename(), + LockFile = lock_filename(dir()), case file:open(LockFile, [write, exclusive]) of {ok, Lock} -> ok = file:close(Lock), + BackupDir = dir() ++ "-upgrade-backup", info("Upgrades: ~w to apply~n", [length(Upgrades)]), + case rabbit_misc:recursive_copy(dir(), BackupDir) of + ok -> + %% We need to make the backup after creating the lock file + %% so that it protects us from trying to overwrite the + %% backup. Unfortunately this means the lock file exists in + %% the backup too, which is not intuitive. Remove it. + ok = file:delete(lock_filename(BackupDir)), + ok; + {error, E} -> + %% If we can't backup, the upgrade hasn't started hence we + %% don't need the lockfile since the real mnesia dir is the + %% good one. + ok = file:delete(LockFile), + exit({could_not_back_up_mnesia_dir, E}) + end, + info("Upgrades: Mnesia dir backed up to ~p~n", [BackupDir]), [apply_upgrade(Upgrade) || Upgrade <- Upgrades], - info("Upgrades: All applied~n", []), + info("Upgrades: All upgrades applied successfully~n", []), ok = write_version(), + ok = rabbit_misc:recursive_delete([BackupDir]), + info("Upgrades: Mnesia backup removed~n", []), ok = file:delete(LockFile); {error, eexist} -> exit(previous_upgrade_failed); @@ -145,7 +164,7 @@ dir() -> rabbit_mnesia:dir(). schema_filename() -> filename:join(dir(), ?VERSION_FILENAME). -lock_filename() -> filename:join(dir(), ?LOCK_FILENAME). +lock_filename(Dir) -> filename:join(Dir, ?LOCK_FILENAME). %% NB: we cannot use rabbit_log here since it may not have been %% started yet |