I am trying to create a simple Erlang process with the access to ETS module.
My source code includes:
Process creation:
start_message_channel() ->
Table = ets:new(messages, [ordered_set, named_table]),
Channel = spawn(?MODULE, channel, []),
{Channel, {table, Table}}.
Process logic:
channel() ->
receive
{Sender, {send_message, {Message, Table}}} ->
ets:insert(Table, {message, Message}),
Sender ! {self(), {status, success}};
{Sender, {receive_message, Table}} ->
{message, Message} = ets:first(Table),
Sender ! {self(), {status, {success, Message}}};
_ ->
throw(incorrect_protocol_exception)
end.
Communication with process
send_message_to_message_channel({Channel, {table, Table}}, Message) ->
Channel ! {self(), {send_message, {Message, Table}}},
receive
{Channel, {status, success}} ->
io:format("Message sent!~n");
{Channel, {status, failure}} ->
io:format("Message failed to send!~n");
_ ->
throw(incorrect_protocol_exception)
end.
receive_message_from_message_channel({Channel, {table, Table}}) ->
Channel ! {self(), {receive_message, Table}},
receive
{Channel, {status, {success, Message}}} ->
io:format(Message);
{Channel, {status, failure}} ->
io:format("Message failed to receive!~n");
_ ->
throw(incorrect_protocol_exception)
end.
While executing function calls in Erlang terminal, I am getting error:
1> cd("C:/Users/dauma").
C:/Users/dauma
ok
2> c(message_channel).
{ok,message_channel}
3> Object = message_channel:start_message_channel().
{<0.59.0>,{table,messages}}
4> message_channel:send_message_to_message_channel(Object, "Hello World!").
=ERROR REPORT==== 19-May-2016::11:09:27 ===
Error in process <0.59.0> with exit value:
{badarg,[{ets,insert,[messages,"Hello World!"],[]},
{message_channel,channel,0,
[{file,"message_channel.erl"},{line,35}]}]}
Could anyone tell me, where might be the problem?
ETS tables are owned by an Erlang process, and have access controls. By default the table is protected
and can only be written to by the process that owns it, though it can be read from other processes.
If you want to read and write from a different process, use public
.
Table = ets:new(messages, [ordered_set, named_table, public])
You can also use private
, which means that only the owning process can read and write.
Per the documentation:
public
Any process may read or write to the table.protected
The owner process can read and write to the table. Other processes can only read the table. This is the default setting for the access rights.private
Only the owner process can read or write to the table.
In your example, you create the table in one process (the one calling start_message_channel
), and then you attempt to call ets:insert
from a different process: spawn(?MODULE, channel, [])
creates a new process, with channel
as its entry point.
Because your table is not marked as public
, the call to ets:insert
from the other process fails with badarg
.
Per the documentation, again:
In general, the functions below will exit with reason
badarg
if any argument is of the wrong format, if the table identifier is invalid or if the operation is denied due to table access rights (protected
orprivate
).
Side note: if you use named_table
, the value returned from ets:new
is the table name, so you can do this:
-define(TABLE, messages).
% later...
?TABLE = ets:new(?TABLE, [named_table, ordered_set, protected])
...and you don't need to store the returned value in state.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With