> ## 9 Appendix B: The Backup Call Back Interface

> ### 9.1 mnesia_backup callback behavior

>     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
>     %%
>     %% This module contains one implementation of callback functions
>     %% used by Mnesia at backup and restore. The user may however
>     %% write an own module the same interface as mnesia_backup and
>     %% configure Mnesia so the alternate module performs the actual
>     %% accesses to the backup media. This means that the user may put
>     %% the backup on medias that Mnesia does not know about, possibly
>     %% on hosts where Erlang is not running.
>     %%
>     %% The OpaqueData argument is never interpreted by other parts of
>     %% Mnesia. It is the property of this module. Alternate implementations
>     %% of this module may have different interpretations of OpaqueData.
>     %% The OpaqueData argument given to open_write/1 and open_read/1
>     %% are forwarded directly from the user.
>     %%
>     %% All functions must return {ok, NewOpaqueData} or {error, Reason}.
>     %%
>     %% The NewOpaqueData arguments returned by backup callback functions will
>     %% be given as input when the next backup callback function is invoked.
>     %% If any return value does not match {ok, _} the backup will be aborted.
>     %%
>     %% The NewOpaqueData arguments returned by restore callback functions will
>     %% be given as input when the next restore callback function is invoked
>     %% If any return value does not match {ok, _} the restore will be aborted.
>     %%
>     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

>     -module(mnesia_backup).
>     -behaviour(mnesia_backup).

>     -include_lib("kernel/include/file.hrl").

>     -export([
>              %% Write access
>              open_write/1,
>              write/2,
>              commit_write/1,
>              abort_write/1,

>              %% Read access
>              open_read/1,
>              read/1,
>              close_read/1
>             ]).

>     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
>     %% Backup callback interface
>     -record(backup, {tmp_file, file, file_desc}).

>     %% Opens backup media for write
>     %%
>     %% Returns {ok, OpaqueData} or {error, Reason}
>     open_write(OpaqueData) ->
>         File = OpaqueData,
>         Tmp = lists:concat([File,".BUPTMP"]),
>         file:delete(Tmp),
>         file:delete(File),
>         case disk_log:open([{name, make_ref()},
>                             {file, Tmp},
>                             {repair, false},
>                             {linkto, self()}]) of
>             {ok, Fd} ->
>                 {ok, #backup{tmp_file = Tmp, file = File, file_desc = Fd}};
>             {error, Reason} ->
>                 {error, Reason}
>         end.

>     %% Writes BackupItems to the backup media
>     %%
>     %% Returns {ok, OpaqueData} or {error, Reason}
>     write(OpaqueData, BackupItems) ->
>         B = OpaqueData,
>         case disk_log:log_terms(B#backup.file_desc, BackupItems) of
>             ok ->
>                 {ok, B};
>             {error, Reason} ->
>                 abort_write(B),
>                 {error, Reason}
>         end.

>     %% Closes the backup media after a successful backup
>     %%
>     %% Returns {ok, ReturnValueToUser} or {error, Reason}
>     commit_write(OpaqueData) ->
>         B = OpaqueData,
>         case disk_log:sync(B#backup.file_desc) of
>             ok ->
>                 case disk_log:close(B#backup.file_desc) of
>                     ok ->
>                         case file:rename(B#backup.tmp_file, B#backup.file) of
>                            ok ->
>                                 {ok, B#backup.file};
>                            {error, Reason} ->
>                                 {error, Reason}
>                         end;
>                     {error, Reason} ->
>                         {error, Reason}
>                 end;
>             {error, Reason} ->
>                 {error, Reason}
>         end.

>     %% Closes the backup media after an interrupted backup
>     %%
>     %% Returns {ok, ReturnValueToUser} or {error, Reason}
>     abort_write(BackupRef) ->
>         Res = disk_log:close(BackupRef#backup.file_desc),
>         file:delete(BackupRef#backup.tmp_file),
>         case Res of
>             ok ->
>                 {ok, BackupRef#backup.file};
>             {error, Reason} ->
>                 {error, Reason}
>         end.

>     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
>     %% Restore callback interface

>     -record(restore, {file, file_desc, cont}).

>     %% Opens backup media for read
>     %%
>     %% Returns {ok, OpaqueData} or {error, Reason}
>     open_read(OpaqueData) ->
>         File = OpaqueData,
>         case file:read_file_info(File) of
>             {error, Reason} ->
>                 {error, Reason};
>             _FileInfo -> %% file exists
>                 case disk_log:open([{file, File},
>                                     {name, make_ref()},
>                                     {repair, false},
>                                     {mode, read_only},
>                                     {linkto, self()}]) of
>                     {ok, Fd} ->
>                         {ok, #restore{file = File, file_desc = Fd, cont = start}};
>                     {repaired, Fd, _, {badbytes, 0}} ->
>                         {ok, #restore{file = File, file_desc = Fd, cont = start}};
>                     {repaired, Fd, _, _} ->
>                         {ok, #restore{file = File, file_desc = Fd, cont = start}};
>                     {error, Reason} ->
>                         {error, Reason}
>                 end
>         end.

>     %% Reads BackupItems from the backup media
>     %%
>     %% Returns {ok, OpaqueData, BackupItems} or {error, Reason}
>     %%
>     %% BackupItems == [] is interpreted as eof
>     read(OpaqueData) ->
>         R = OpaqueData,
>         Fd = R#restore.file_desc,
>         case disk_log:chunk(Fd, R#restore.cont) of
>             {error, Reason} ->
>                 {error, {"Possibly truncated", Reason}};
>             eof ->
>                 {ok, R, []};
>             {Cont, []} ->
>                 read(R#restore{cont = Cont});
>             {Cont, BackupItems} ->
>                 {ok, R#restore{cont = Cont}, BackupItems}
>         end.

>     %% Closes the backup media after restore
>     %%
>     %% Returns {ok, ReturnValueToUser} or {error, Reason}
>     close_read(OpaqueData) ->
>         R = OpaqueData,
>         case disk_log:close(R#restore.file_desc) of
>             ok -> {ok, R#restore.file};
>             {error, Reason} -> {error, Reason}
>         end.

Copyright © 1991-2003 Ericsson Utvecklings AB