Current section

Files

Jump to
nuamnesia lib amnesia backup.ex
Raw

lib/amnesia/backup.ex

# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
# Version 2, December 2004
#
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
#
# 0. You just DO WHAT THE FUCK YOU WANT TO.
defmodule Amnesia.Backup do
@moduledoc """
This module provides a behavior to implement a backup module and helpers to
use backups.
"""
alias Amnesia.Helper.Options
@type o :: { :ok, any } | { :error, any }
@type i :: { :module, atom } | { :scope, :global | :local } | { :directory, String.t }
@type r :: [{ :module, atom } |
{ :keep | :skip | :clear | :recreate, atom | [atom] } |
{ :default, :keep | :skip | :clear | :recreate }]
@doc """
Open the backup for writing.
"""
@callback open_write(any) :: o
@doc """
Write the given terms to the backup.
"""
@callback write(any, [any]) :: o
@doc """
Commit the write to the backup.
"""
@callback commit_write(any) :: o
@doc """
Close the backup if the backup is interrupted.
"""
@callback abort_write(any) :: o
@doc """
Open the backup for reading.
"""
@callback open_read(any) :: o
@doc """
Read terms from the backup.
"""
@callback read(any) :: { :ok, any, [any] } | { :error, any }
@doc """
Close the backup.
"""
@callback close_read(any) :: o
@doc """
Create a checkpoint, see `mnesia:activate_checkpoint`.
It's important to backup the metadata table, to avoid bugs when restoring the database.
Example to backup on a file called "backup" the table Account as well the metadata table:
```
Amnesia.Backup.checkpoint(%{
name: 'backup',
max: [Database.Account, Database]
})
```
"""
@spec checkpoint(Keyword.t) :: { :ok, any, [node] } | { :error, any }
def checkpoint(options) do
args = Keyword.new
|> Options.update(:name, options[:name])
|> Options.update(:max, options[:max])
|> Options.update(:min, options[:min])
|> Options.update(:allow_remote, options[:remote])
|> Options.update(:ram_overrides_dump, options[:override])
:mnesia.activate_checkpoint(args)
end
@doc """
Create a checkpoint with the given name, see `mnesia:activate_checkpoint`.
"""
@spec checkpoint(any, Keyword.t) :: { :ok, any, [node] } | { :error, any }
def checkpoint(name, options) do
checkpoint(Keyword.put_new(options, :name, name))
end
@doc """
Start a backup with the default backup module, see `mnesia:backup`.
"""
@spec start(any) :: :ok | { :error, any }
def start(data) do
:mnesia.backup(data)
end
@doc """
Start a backup of a given checkpoint, see `mnesia:backup_checkpoint`.
"""
@spec start(any, any) :: :ok | { :error, any }
def start(name, data) do
:mnesia.backup_checkpoint(name, data)
end
@doc """
Traverse a backup, see `mnesia:traverse_backup`.
"""
@spec traverse(any, any, any, ([tuple], any -> any)) :: { :ok, any } | { :error, any }
def traverse(source, target, acc, fun) do
:mnesia.traverse_backup(source, target, fun, acc)
end
@doc """
Traverse a backup with custom backup modules, see `mnesia:traverse_backup`.
"""
@spec traverse(atom, any, atom, any, any, ([tuple], any -> any)) :: { :ok, any } | { :error, any }
def traverse(source, source_data, target, target_data, acc, fun) do
:mnesia.traverse_backup(source_data, source, target_data, target, fun, acc)
end
@doc """
Restore a backup, see `mnesia:restore`.
"""
@spec restore(any, r) :: [atom] | { :error, any }
def restore(data, options) do
args = Keyword.new
|> Options.update(:module, options[:module])
|> Options.update(:keep_tables, options[:keep] |> Options.normalize)
|> Options.update(:clear_tables, options[:clear] |> Options.normalize)
|> Options.update(:recreate_tables, options[:recreate] |> Options.normalize)
|> Options.update(:skip_tables, options[:skip] |> Options.normalize)
args = Options.update(args, :default,
case options[:default] do
:keep -> :keep_tables
:skip -> :skip_tables
:clear -> :clear_tables
:recreate -> :recreate_tables
nil -> nil
end)
:mnesia.restore(data, args)
end
@doc """
Restore a backup with the given module, see `mnesia:restore`.
"""
@spec restore(atom, any, r) :: { :atomic, [atom] } | { :aborted, any }
def restore(module, data, options) do
restore(data, Keyword.put(options, :module, module))
end
@doc """
Install a fallback with the default backup module, see `mnesia:install_fallback`.
"""
@spec install(any) :: :ok | { :error, any }
def install(data) do
:mnesia.install_fallback(data)
end
@doc """
Install a fallback with the given backup module, see `mnesia:install_fallback`.
"""
@spec install(atom | any) :: :ok | { :error, any }
def install(module, data) do
:mnesia.install_fallback(data, module)
end
@doc """
Install a fallback with the given backup module and options, see `mnesia:install_fallback`.
"""
@spec install(atom, any, i) :: :ok | { :error, any }
def install(module, data, options) do
args = [module: module]
|> Options.update(:scope, options[:module])
|> Options.update(:mnesia_dir, options[:directory])
:mnesia.install_fallback(data, args)
end
@doc """
Uninstall a fallback, see `mnesia:uninstall_fallback`.
"""
@spec uninstall :: :ok | { :error, any }
def uninstall do
:mnesia.uninstall_fallback
end
@doc """
Uninstall a fallback, see `mnesia:uninstall_fallback`.
"""
@spec uninstall(i) :: :ok | { :error, any }
def uninstall(options) do
args = Keyword.new
|> Options.update(:module, options[:module])
|> Options.update(:scope, options[:module])
|> Options.update(:mnesia_dir, options[:directory])
:mnesia.uninstall_fallback(args)
end
@doc """
Uninstall a fallback, see `mnesia:uninstall_fallback`.
"""
@spec uninstall(atom, i) :: :ok | { :error, any }
def uninstall(module, options) do
uninstall(Keyword.put(options, :module, module))
end
@doc false
defmacro __using__(_opts) do
quote do
@behaviour Amnesia.Backup
@doc """
Start a backup, see `mnesia:backup`.
"""
@spec start(any) :: :ok | { :error, any }
def start(data) do
:mnesia.backup(data, __MODULE__)
end
@doc """
Start a backup of the given checkpoint, see `mnesia:backup_checkpoint`.
"""
@spec start(any, any) :: :ok | { :error, any }
def start(name, data) do
:mnesia.backup_checkpoint(name, data, __MODULE__)
end
@doc """
Traverse a backup, see `mnesia:traverse_backup`.
"""
@spec traverse(any, any, any, ([tuple], any -> any)) :: { :ok, any } | { :error, any }
def traverse(data, target, acc, fun) do
:mnesia.traverse_backup(data, __MODULE__, target, fun, acc)
end
@doc """
Traverse a backup targeting a custom backup module, see
`mnesia:traverse_backup`.
"""
@spec traverse(any, atom, any, any, ([tuple], any -> any)) :: { :ok, any } | { :error, any }
def traverse(data, target, target_data, acc, fun) do
:mnesia.traverse_backup(data, target_data, target, fun, acc)
end
@doc """
Restore a backup, see `mnesia:restore`.
"""
@spec restore(any, Amnesia.Backup.r) :: { :atomic, [atom] } | { :aborted, any }
def restore(data, options) do
Amnesia.Backup.restore(__MODULE__, data, options)
end
@doc """
Install a fallback, see `mnesia:install_fallback`.
"""
@spec install(any) :: :ok | { :error, any }
def install(data) do
Amnesia.Backup.install(__MODULE__, data, [scope: :global])
end
@doc """
Install a fallback, see `mnesia:install_fallback`.
"""
@spec install(any, Amnesia.Backup.i) :: :ok | { :error, any }
def install(data, options) do
Amnesia.Backup.install(__MODULE__, data, options)
end
@doc """
Uninstall a fallback, see `mnesia:uninstall_fallback`.
"""
@spec uninstall :: :ok | { :error, any }
def uninstall do
Amnesia.Backup.uninstall(__MODULE__, [scope: :global])
end
@doc """
Uninstall a fallback, see `mnesia:uninstall_fallback`.
"""
@spec uninstall(atom, Amnesia.Backup.i) :: :ok | { :error, any }
def uninstall(options) do
Amnesia.Backup.uninstall(__MODULE__, options)
end
end
end
end