mnesia_backup.erl

来自「OTP是开放电信平台的简称」· ERL 代码 · 共 199 行

ERL
199
字号
%% ``The contents of this file are subject to the Erlang Public License,%% Version 1.1, (the "License"); you may not use this file except in%% compliance with the License. You should have received a copy of the%% Erlang Public License along with this software. If not, it can be%% retrieved via the world wide web at http://www.erlang.org/.%% %% Software distributed under the License is distributed on an "AS IS"%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See%% the License for the specific language governing rights and limitations%% under the License.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %%     $Id$%%%%-behaviour(mnesia_backup).%0%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 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).-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 eofread(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, _BadBytes} ->            {ok, R#restore{cont = Cont}, BackupItems};        {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.%0

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?