mnesia:clear_table
Serge Aleynikov
serge@REDACTED
Tue Aug 16 13:48:26 CEST 2005
How much nicer would it be if do_clear_table were exported! :-)
If schema transaction don't support nesting, I am not sure your answer
clarifies why the following code should work if schema transaction don't
support nesting:
mnesia:transaction(
fun() ->
mnesia:clear_table(test),
end).
Indeed what led me to the original confusion was that my simple
prototype with clearing/loading a single table inside a transaction
worked, but when I extended that into multiple tables, it failed
miserably for the reason you indicated below.
So, is it expected that only a single schema trancation can be
encapsulated in another transaction, and is it safe to use the
transaction above?
Serge
Ulf Wiger (AL/EAB) wrote:
>
> mnesia:clear_table/1 calls mnesia_schema:clear_table/1,
> which in its turn does the following:
>
> clear_table(Tab) ->
> schema_transaction(fun() -> do_clear_table(Tab) end).
>
>
> Schema transactions don't support nesting... or you could
> possibly have a schema transaction at the top and nest
> regular transactions in it(*), but as mnesia_schema:do_clear_table/1
> is not exported, you'll have a hard time doing even that.
>
>
> (*) There may be serious issues with this - I can't say.
>
>
> If you really, really want to do this, and don't want to
> hack mnesia so as to export do_clear_table/1, you can
> emulate it easily enough. This is how it's implemented:
>
> do_clear_table(schema) ->
> mnesia:abort({bad_type, schema});
> do_clear_table(Tab) ->
> TidTs = get_tid_ts_and_lock(schema, write),
> get_tid_ts_and_lock(Tab, write),
> insert_schema_ops(TidTs, make_clear_table(Tab)).
>
> make_clear_table(Tab) ->
> ensure_writable(schema),
> Cs = val({Tab, cstruct}),
> ensure_active(Cs),
> ensure_writable(Tab),
> [{op, clear_table, cs2list(Cs)}].
>
> The functions that are not exported from mnesia_schema are:
> - do_clear_table/1
> - make_clear_table/1
> - ensure_writable/1
>
> ensure_writable/1 looks like this:
>
> ensure_writable(Tab) ->
> case val({Tab, where_to_write}) of
> [] -> mnesia:abort({read_only, Tab});
> _ -> ok
> end.
>
>
> So, you can copy the code for ensure_writable/1 and
> make_clear_table/1. Then, your code becomes:
>
> my_do_clear_table(schema) ->
> mnesia:abort({bad_type, schema});
> my_do_clear_table(Tab) ->
> TidTs = mnesia_schema:get_tid_ts_and_lock(schema, write),
> mnesia_schema:get_tid_ts_and_lock(Tab, write),
> mnesia_schema:insert_schema_ops(TidTs, my_make_clear_table(Tab)).
>
> my_make_clear_table(Tab) ->
> my_ensure_writable(schema),
> Cs = mnesia_lib:val({Tab, cstruct}),
> mnesia_schema:ensure_active(Cs),
> my_ensure_writable(Tab),
> [{op, clear_table, mnesia_schema:cs2list(Cs)}].
>
> my_ensure_writable(Tab) ->
> case mnesia_lib:val({Tab, where_to_write}) of
> [] -> mnesia:abort({read_only, Tab});
> _ -> ok
> end.
>
>
> Then you can combine this with other ops inside a
> top-level schema_transaction (important!)
>
>
> (n2@REDACTED)6> mnesia:create_table(test, [{ram_copies, [node()]}]).
> {atomic,ok}
> (n2@REDACTED)7> mnesia:create_table(test1, [{ram_copies,[node()]}]).
> {atomic,ok}
> (n2@REDACTED)8> mnesia:dirty_write({test,a,1}).
> ok
> (n2@REDACTED)9> mnesia:dirty_write({test1,a,1}).
> ok
> (n2@REDACTED)11> mnesia_schema:schema_transaction(fun() -> cleart:my_do_clear_table(test), cleart:my_do_clear_table(test1), mnesia:write({test,b,1}), mnesia:write({test1,b,1}) end).
> {atomic,ok}
> (n2@REDACTED)12> ets:tab2list(test).
> [{test,b,1}]
> (n2@REDACTED)13> mnesia_schema:schema_transaction(fun() -> cleart:my_do_clear_table(test), cleart:my_do_clear_table(test1), mnesia:transaction(fun() -> mnesia:write({test,b,1}), mnesia:write({test1,b,1}) end) end).
> {atomic,{atomic,ok}}
> (n2@REDACTED)14> ets:tab2list(test). [{test,b,1}]
>
>
>
> mnesia_schema:schema_transaction(
> fun() ->
> my_clear_table(Tab),
> mnesia:transaction(fun() ->
> ...
> end)).
>
> (:
>
> /Uffe
>
>
>>-----Original Message-----
>>From: owner-erlang-questions@REDACTED
>>[mailto:owner-erlang-questions@REDACTED]On Behalf Of Serge Aleynikov
>>Sent: den 16 augusti 2005 03:10
>>To: Claes Wikstrom
>>Cc: Erlang Questions
>>Subject: Re: mnesia:clear_table
>>
>>
>>Indeed when I do:
>>
>>F = fun() ->
>> mnesia:clear_table(Tab)
>> end,
>>mnesia:transaction(F).
>>
>>It works. That means that nested transactions are supported, however
>>this code returns an error:
>>
>>p>erl -sname t
>>Erlang (BEAM) emulator version 5.4.8 [source] [hipe] [threads:0]
>>Eshell V5.4.8 (abort with ^G)
>>(t@REDACTED)1> mnesia:create_schema([node()]).
>>ok
>>(t@REDACTED)2> mnesia:start().
>>ok
>>(t@REDACTED)3> mnesia:create_table(test, [{ram_copies, [node()]}]).
>>{atomic,ok}
>>(t@REDACTED)4> mnesia:create_table(test1, [{ram_copies,
>>[node()]}]).
>>
>>{atomic,ok}
>>(t@REDACTED)5> F = fun() -> mnesia:clear_table(test),
>>mnesia:clear_table(test1) end.
>>#Fun<erl_eval.20.102880425>
>>(t@REDACTED)6> mnesia:transaction(F).
>>
>>{atomic,{aborted,nested_transaction}}
>>
>>Am I doing something unconventional, or there is a limit on
>>the depth of
>>nested transactions?
>>
>>Serge
>>
>>Claes Wikstrom wrote:
>>
>>>Serge Aleynikov wrote:
>>>
>>>
>>>>Hi,
>>>>
>>>>I am wondering why the mnesia:clear_table/1 function is
>>
>>encapsulated
>>
>>>>in a transaction of its own. It prevents this function to
>>
>>be included
>>
>>>>in another transaction.
>>>>
>>>
>>>Transactions can be nested arbitrarily deep. Nesting doesn't
>>>come for free, but it works.
>>>
>>>
>>>/klacke
More information about the erlang-questions
mailing list