updating a newly created table within the same transaction
Ulf Wiger (TN/EAB)
ulf.wiger@REDACTED
Mon Jul 17 19:37:02 CEST 2006
I keep running into the nuisance that I can't create a mnesia table and
then write to it in the same transaction. Currently, one has to use
mnesia's restore for that kind of thing - not quite as convenient.
Here's a patch (not quite finished) that seems to do the trick.
Example:
5> mnesia_schema:schema_transaction(fun() ->
mnesia_schema:do_create_table(mnesia_schema:list2cs([{name,test}])),
mnesia:write({test,a,17}) end).
{atomic,ok}
6> ets:tab2list(test).
[{test,a,17}]
...and it also fixes the slight bug that one has been able to read from
a table that's just been deleted, as long as one does it within the same
transaction (mnesia doesn't detect that it's been deleted until it tries
to commit the update.)
7> mnesia_schema:schema_transaction(fun() ->
mnesia_schema:do_delete_table(test), mnesia:activity(transaction,fun()
-> mnesia:write({test,b,18}) end) end).
{aborted,{aborted,{no_exists,test}}}
Patches, relative to mnesia-4.3.1 (OTP R11B) below, and attached, an
access module that is automatically used as a wrapper to any
user-defined access module, if mnesia_tm detects that it's a schema
transaction (first time I've ever found a use for parameterized modules
;) The access module only handles write and delete at this time. The
idea is that it needs to emulate all ops using only the transaction
store (objects in a newly created table cannot be anywhere else until
the transaction is committed.)
BR,
Ulf W
> diff mnesia_schema.erl
$OTP_ROOT/lib/mnesia-4.3.1/src/mnesia_schema.erl
107d106
< -export([is_schema_transaction/0]).
591,598d589
< is_schema_transaction() ->
< case process_info(self(), initial_call) of
< {_, {?MODULE, schema_coordinator,_}} ->
< true;
< _ ->
< false
< end.
<
615,618c606
< Res = case catch mnesia:activity(transaction, Fun) of
< {'EXIT', BadRes} -> {aborted, BadRes};
< GoodRes -> {atomic, GoodRes}
< end,
---
> Res = mnesia:transaction(Fun),
> diff mnesia_tm.erl $OTP_ROOT/lib/mnesia-4.3.1/src/mnesia_tm.erl
62d61
< tab_info = [],
772c771
< transaction(OldTidTs, Fun, Args, Retries, Mod0, Type) ->
---
> transaction(OldTidTs, Fun, Args, Retries, Mod, Type) ->
774,779d772
< Mod = case mnesia_schema:is_schema_transaction() of
< true ->
< mnesia_schema_access:new(Mod0);
< false ->
< Mod0
< end,
1161,1164c1154
< case catch begin
< Prep1 = do_arrange_schema(Tid, Store, Prep),
< do_arrange(Tid, Store, Key, Prep1, N)
< end of
---
> case catch do_arrange(Tid, Store, Key, Prep, N) of
1194,1207d1183
< do_arrange_schema(Tid, Store, Prep) ->
< SchemaKey = op,
< Items = ?ets_lookup(Store, SchemaKey),
< TabInfo =
< lists:foldl(
< fun({op, delete_table, [{name, Tab}|_]}, I) ->
< orddict:store(Tab, [], I);
< ({op, _, [{name, Tab}|_] = Opts}, I) ->
< orddict:store(Tab, Opts, I);
< (_, I) ->
< I
< end, orddict:new(), Items),
< prepare_schema_items(Tid, Items, Prep#prep{tab_info = TabInfo}).
<
1216,1217c1192,1194
< %%% schema items handled separately
< do_arrange(Tid, Store, ?ets_next(Store, SchemaKey), Prep, N + 1);
---
> Items = ?ets_lookup(Store, SchemaKey), %% Store is a bag
> P2 = prepare_schema_items(Tid, Items, Prep),
> do_arrange(Tid, Store, ?ets_next(Store, SchemaKey), P2, N + 1);
1258c1235
< prepare_items(Tid, Tab, Key, Items, #prep{tab_info = []} = Prep) ->
---
> prepare_items(Tid, Tab, Key, Items, Prep) ->
1272,1297c1249
< end;
<
< prepare_items(Tid, Tab, Key, Items, #prep{tab_info = TI} = Prep) ->
< case orddict:find(Tab, TI) of
< {ok, []} ->
< mnesia:abort({no_exists, Tab});
< {ok, TabInfo} ->
< Snmp = proplists:get_value(snmp, TabInfo),
< Types = % where_to_commit
< where_to_commit(TabInfo, [node() | nodes()]),
< Recs2 = do_prepare_items(Tid, Tab, Key, Types,
< Snmp, Items, Prep#prep.records),
< Prep2 = Prep#prep{records = Recs2, prev_tab = Tab,
< prev_types = Types, prev_snmp = Snmp},
< check_prep(Prep2, Types);
< error ->
< mnesia:abort({no_exists, Tab})
< end.
<
< where_to_commit(TI, LiveNodes) ->
< Cs = fun(Type) ->
< [{N, Type} || N <- proplists:get_value(Type, TI),
< lists:member(N, LiveNodes)]
< end,
< lists:concat([Cs(T) || T <- [ram_copies, disc_copies,
disc_only_copies]]).
<
---
> end.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: mnesia_schema_access.erl
Type: application/octet-stream
Size: 4992 bytes
Desc: mnesia_schema_access.erl
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20060717/a7c205fc/attachment.obj>
More information about the erlang-questions
mailing list