summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErlang/OTP <otp@erlang.org>2020-03-04 08:23:51 +0100
committerErlang/OTP <otp@erlang.org>2020-03-04 08:23:51 +0100
commitc91f1fade8d284cad95f9da235f87db2eaed0060 (patch)
treeaa080485aedee946f7eb5083518b1654a505ec9c
parentd7b423584bc4f950f0208d3d4108d26bf6da905e (diff)
parentbf77ccc9550ff7f43016e55f7ad810b8aa166c2e (diff)
downloaderlang-c91f1fade8d284cad95f9da235f87db2eaed0060.tar.gz
Merge branch 'sverker/ets-update-counter-fix/ERL-1127/OTP-16404' into maint-21
* sverker/ets-update-counter-fix/ERL-1127/OTP-16404: erts: Fix bug in ets:update_counter causing wrong table size
-rw-r--r--erts/emulator/beam/erl_db_hash.c5
-rw-r--r--erts/emulator/beam/erl_db_util.c3
-rw-r--r--lib/stdlib/test/ets_SUITE.erl30
3 files changed, 32 insertions, 6 deletions
diff --git a/erts/emulator/beam/erl_db_hash.c b/erts/emulator/beam/erl_db_hash.c
index 42d7909a08..77ae3f5774 100644
--- a/erts/emulator/beam/erl_db_hash.c
+++ b/erts/emulator/beam/erl_db_hash.c
@@ -3129,16 +3129,19 @@ db_finalize_dbterm_hash(int cret, DbUpdateHandle* handle)
}
WUNLOCK_HASH(lck);
- erts_atomic_dec_nob(&tb->common.nitems);
+ if (!(handle->flags & DB_INC_TRY_GROW))
+ erts_atomic_dec_nob(&tb->common.nitems);
try_shrink(tb);
} else {
if (handle->flags & DB_MUST_RESIZE) {
+ ASSERT(cret == DB_ERROR_NONE);
db_finalize_resize(handle, offsetof(HashDbTerm,dbterm));
free_me = b;
}
if (handle->flags & DB_INC_TRY_GROW) {
int nactive;
int nitems = erts_atomic_inc_read_nob(&tb->common.nitems);
+ ASSERT(cret == DB_ERROR_NONE);
WUNLOCK_HASH(lck);
nactive = NACTIVE(tb);
diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c
index e2c029c244..eb5cc969c4 100644
--- a/erts/emulator/beam/erl_db_util.c
+++ b/erts/emulator/beam/erl_db_util.c
@@ -2844,9 +2844,6 @@ Eterm db_add_counter(Eterm** hpp, Wterm counter, Eterm incr)
/* Must be called to read elements after db_lookup_dbterm.
** Will decompress if needed.
-** HEALFWORD_HEAP:
-** Will convert from relative to Wterm format if needed.
-** (but only on top level, tuples and lists will still contain rterms)
*/
Wterm db_do_read_element(DbUpdateHandle* handle, Sint position)
{
diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl
index 433b812fd5..d259fd0a91 100644
--- a/lib/stdlib/test/ets_SUITE.erl
+++ b/lib/stdlib/test/ets_SUITE.erl
@@ -2236,35 +2236,61 @@ update_counter_with_default_do(Opts) ->
T1 = ets_new(a, [set | Opts]),
%% Insert default object.
3 = ets:update_counter(T1, foo, 2, {beaufort,1}),
+ 1 = ets:info(T1, size),
%% Increment.
5 = ets:update_counter(T1, foo, 2, {cabecou,1}),
+ 1 = ets:info(T1, size),
%% Increment with list.
[9] = ets:update_counter(T1, foo, [{2,4}], {camembert,1}),
+ 1 = ets:info(T1, size),
%% Same with non-immediate key.
3 = ets:update_counter(T1, {foo,bar}, 2, {{chaource,chevrotin},1}),
+ 2 = ets:info(T1, size),
5 = ets:update_counter(T1, {foo,bar}, 2, {{cantal,comté},1}),
+ 2 = ets:info(T1, size),
[9] = ets:update_counter(T1, {foo,bar}, [{2,4}], {{emmental,de,savoie},1}),
+ 2 = ets:info(T1, size),
+ %% default counter is not an integer.
+ {'EXIT',{badarg,_}} = (catch ets:update_counter(T1, qux, 3, {saint,félicien})),
+ 2 = ets:info(T1, size),
+ %% No third element in default value.
+ {'EXIT',{badarg,_}} = (catch ets:update_counter(T1, qux, [{3,1}], {roquefort,1})),
+ 2 = ets:info(T1, size),
+
%% Same with ordered set.
T2 = ets_new(b, [ordered_set | Opts]),
3 = ets:update_counter(T2, foo, 2, {maroilles,1}),
+ 1 = ets:info(T2, size),
5 = ets:update_counter(T2, foo, 2, {mimolette,1}),
+ 1 = ets:info(T2, size),
[9] = ets:update_counter(T2, foo, [{2,4}], {morbier,1}),
+ 1 = ets:info(T2, size),
3 = ets:update_counter(T2, {foo,bar}, 2, {{laguiole},1}),
+ 2 = ets:info(T2, size),
5 = ets:update_counter(T2, {foo,bar}, 2, {{saint,nectaire},1}),
+ 2 = ets:info(T2, size),
[9] = ets:update_counter(T2, {foo,bar}, [{2,4}], {{rocamadour},1}),
+ 2 = ets:info(T2, size),
%% Arithmetically-equal keys.
3 = ets:update_counter(T2, 1.0, 2, {1,1}),
+ 3 = ets:info(T2, size),
5 = ets:update_counter(T2, 1, 2, {1,1}),
+ 3 = ets:info(T2, size),
7 = ets:update_counter(T2, 1, 2, {1.0,1}),
+ 3 = ets:info(T2, size),
%% Same with reversed type difference.
3 = ets:update_counter(T2, 2, 2, {2.0,1}),
+ 4 = ets:info(T2, size),
5 = ets:update_counter(T2, 2.0, 2, {2.0,1}),
+ 4 = ets:info(T2, size),
7 = ets:update_counter(T2, 2.0, 2, {2,1}),
- %% bar is not an integer.
+ 4 = ets:info(T2, size),
+ %% default counter is not an integer.
{'EXIT',{badarg,_}} = (catch ets:update_counter(T1, qux, 3, {saint,félicien})),
+ 4 = ets:info(T2, size),
%% No third element in default value.
{'EXIT',{badarg,_}} = (catch ets:update_counter(T1, qux, [{3,1}], {roquefort,1})),
-
+ 4 = ets:info(T2, size),
ok.
update_counter_table_growth(_Config) ->