Erlang Thursday – ETS Introduction, Part 1

Today’s Erlang Thursday starts the beginning of an intro to the ets module, and ETS in general.

ETS stands for Erlang Term Storage, and is a in-memory store for Erlang terms, a.k.a pieces of an Erlang data type, that provides constant access time to the data stored.

ETS can be thought of as a key/value store style storage, and it uses the concept of tables as the way of grouping together data.

One of the first things that is useful to know is that ETS tables are created by a process which, unless transfered to another process, is the owner of the table.

When the owner dies, the table gets deleted, and is no longer accessible.

Let’s see what this would look like.

First, after starting a new Erlang shell, we will check the PID (process identifier) of the shell we are in.

self().
% <0.34.0>

We then will create a new ETS table. We will be going into future details about the various ways new tables can be created in future posts, so for now, we will just create a new table by only specifying a name and empty list of options.

TableId = ets:new(table, []).
% 20496

Capturing table id, we will take a look at the info that ETS knows about that table with ets:info/1.

ets:info(TableId).
% [{read_concurrency,false},
%  {write_concurrency,false},
%  {compressed,false},
%  {memory,305},
%  {owner,<0.34.0>},
%  {heir,none},
%  {name,table},
%  {size,0},
%  {node,nonode@nohost},
%  {named_table,false},
%  {type,set},
%  {keypos,1},
%  {protection,protected}]

Time to cause the owning process to crash. In this case we’ll do a bad pattern match to cause a bad match exception.

1 = 2.
% ** exception error: no match of right hand side value 2

And let’s check the PID of the process to double check that the shell has indeed started a new process for us to run in.

self().
% <0.40.0>

And yes, the PID self() returned is different than the PID we got when we called self() the first time.

Time to look at the info for the table we created earlier again and see what we get.

ets:info(TableId).
% undefined

undefined. So we no longer have any table found by ETS for that table id.

We take a secondary look using ets:all/0 to see if we can see if it might be floating around somewhere still but the call to ets:info/1 is just not returning for the table id.

ets:all().
% [8207,file_io_servers,inet_hosts_file_byaddr,
%  inet_hosts_file_byname,inet_hosts_byaddr,inet_hosts_byname,
%  inet_cache,inet_db,global_pid_ids,global_pid_names,
%  global_names_ext,global_names,global_locks,4098,1,ac_tab]

Doesn’t look like it, so let’s create another table with the same table name as before.

Table2Id = ets:new(table, []).
% 24592

That succeeds and doesn’t complain about trying to create a table with the same name as an existing table.

We will call ets:all/0 again, and we can see there is an item in the list with the id that was returned from ets:new/2.

ets:all().
% [24592,8207,file_io_servers,inet_hosts_file_byaddr,
%  inet_hosts_file_byname,inet_hosts_byaddr,inet_hosts_byname,
%  inet_cache,inet_db,global_pid_ids,global_pid_names,
%  global_names_ext,global_names,global_locks,4098,1,ac_tab]

Time to crash the process again.

1 = 2.
% ** exception error: no match of right hand side value 2

We note that we do have a new PID again.

self().
% <0.47.0>

And if we call ets:all/0 one more time, we can see that the table identifier that was previously in the list has gone away.

ets:all().
% [8207,file_io_servers,inet_hosts_file_byaddr,
%  inet_hosts_file_byname,inet_hosts_byaddr,inet_hosts_byname,
%  inet_cache,inet_db,global_pid_ids,global_pid_names,
%  global_names_ext,global_names,global_locks,4098,1,ac_tab]

So with this initial look at ETS, we have demonstrated an owning process crash does remove the table, and we have also gotten an preview of a couple of the functions in the ets module, specifically ets:new/2, ets:info/1, and ets:all/0.

We will continue looking at the overview of ETS for a few posts, while doing some cursory coverage of some of the functions in the ets module, and after that, we will then start to get into the specifics of the different functions in the ets module.

–Proctor