Does ets provide a means to do an Update & Read in one go - like an Increment Operation?

2k views Asked by At

I initialize a named ets table in my start(_StartType, _StartArgs) -> function, before setting up my standard Cowboy web handling routines.

ets:new(req_stats,[named_table,public]),ets:insert(req_stats,{req_count,0})

I have this function:

 count_req()->
    [{_,Cnt}]=ets:lookup(req_stats,req_count),
    ets:insert(req_stats,Cnt+1),
    Cnt+1.

My concern is this;

If i call count_req() for each web request under high load, i WILL most likely end up with an inaccurate count, because [{_,Cnt}]=ets:lookup(req_stats,req_count) could be updated several times before I return Cnt+1

Does ets provide a means to do an update & read in one go - like an increment operation?

Thanks.

1

There are 1 answers

3
legoscia On BEST ANSWER

You can use ets:update_counter/3:

ets:update_counter(req_stats, req_count, {2, 1})

That is, increment the 2nd element of the tuple by 1, and return the new value.


In Erlang/OTP 18.0 (released on 2015-06-24), ets:update_counter/4 was introduced. It lets you provide a default value, to be used if the key is not yet present in the table. So if you want the counter to become 1 after the first time you increment it, give 0 as the default value:

1> ets:new(req_stats, [named_table]).
req_stats
2> ets:tab2list(req_stats).
[]
3> ets:update_counter(req_stats, req_count, {2, 1}, {req_count, 0}).
1
4> ets:tab2list(req_stats).
[{req_count,1}]