Current section

Files

Jump to
erldns src erldns_storage_json.erl
Raw

src/erldns_storage_json.erl

%% Copyright (c) 2015, SiftLogic LLC
%% Copyright (c) 2015-2020, DNSimple Corporation
%%
%% Permission to use, copy, modify, and/or distribute this software for any
%% purpose with or without fee is hereby granted, provided that the above
%% copyright notice and this permission notice appear in all copies.
%%
%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-module(erldns_storage_json).
%% API
-export([
create/1,
insert/2,
delete_table/1,
delete/2,
select_delete/2,
backup_table/1,
backup_tables/0,
select/2,
select/3,
foldl/3,
empty_table/1,
list_table/1
]).
%% Public API
%% @doc Create ets table wrapper. Use match cases for adding different options to the table.
-spec create(atom()) -> ok | not_implemented | {error, Reason :: term()}.
create(schema) ->
not_implemented;
create(Name = zones) ->
create_ets_table(Name, set);
create(Name = zone_records_typed) ->
create_ets_table(Name, ordered_set);
create(Name = authorities) ->
create_ets_table(Name, set);
%% These tables should always use ets. Due to their functionality
create(Name = packet_cache) ->
create_ets_table(Name, set);
create(Name = host_throttle) ->
create_ets_table(Name, set);
create(Name = lookup_table) ->
create_ets_table(Name, bag);
create(Name = handler_registry) ->
create_ets_table(Name, set);
create(Name = sync_counters) ->
create_ets_table(Name, set).
%% @doc Insert value in ets table.
-spec insert(atom(), tuple()) -> ok.
insert(Table, Value) ->
true = ets:insert(Table, Value),
ok.
%% @doc Delete entire ets table.
-spec delete_table(atom()) -> ok.
delete_table(Table) ->
true = ets:delete(Table),
ok.
%% @doc Delete an entry in the ets table.Ets always returns true for this function.
-spec delete(atom(), term()) -> ok.
delete(Table, Key) ->
ets:delete(Table, Key),
ok.
%% @doc Delete entries in the ets table that match the provided spec.
-spec select_delete(atom(), list()) -> {ok, Count :: integer()} | {error, Reason :: term()}.
select_delete(Table, MatchSpec) ->
Count = ets:select_delete(Table, MatchSpec),
{ok, Count}.
%% @doc Backup a specific ets table.
%% https://github.com/SiftLogic/erl-dns/issues/3
-spec backup_table(atom()) -> ok | {error, Reason :: term()}.
backup_table(_Table) ->
{error, not_implemented}.
%% @doc Should backup all ets tables.
%% https://github.com/SiftLogic/erl-dns/issues/3
-spec backup_tables() -> ok | {error, Reason :: term()}.
backup_tables() ->
{error, not_implemented}.
%% @doc Select from ets using key, value.
-spec select(atom(), term()) -> [tuple()].
select(Table, Key) ->
ets:lookup(Table, Key).
%% #doc Select from ets using match specs.
-spec select(atom(), list(), integer() | infinite) -> tuple() | '$end_of_table'.
select(Table, MatchSpec, infinite) ->
ets:select(Table, MatchSpec);
select(Table, MatchSpec, Limit) ->
ets:select(Table, MatchSpec, Limit).
%% @doc Wrapper for foldl in ets.
-spec foldl(fun(), list(), atom()) -> Acc :: term() | {error, Reason :: term()}.
foldl(Fun, Acc, Table) ->
ets:foldl(Fun, Acc, Table).
%% @doc Empty ets table. Ets always returns true for this function.
-spec empty_table(atom()) -> ok.
empty_table(Table) ->
ets:delete_all_objects(Table),
ok.
%% @doc Lists the ets table
-spec list_table(atom()) -> term() | {error, term()}.
list_table(TableName) ->
try
ets:tab2list(TableName)
catch
error:R ->
{error, R}
end.
%% Internal methods
-spec create_ets_table(ets:tab(), ets:type()) -> ok | {error, Reason :: term()}.
create_ets_table(Name, Type) ->
case ets:info(Name) of
undefined ->
case ets:new(Name, [Type, public, named_table]) of
Name ->
ok;
Error ->
{error, Error}
end;
_InfoList ->
ok
end.