diff options
author | Erlang/OTP <otp@erlang.org> | 2020-03-04 08:23:51 +0100 |
---|---|---|
committer | Erlang/OTP <otp@erlang.org> | 2020-03-04 08:23:51 +0100 |
commit | c91f1fade8d284cad95f9da235f87db2eaed0060 (patch) | |
tree | aa080485aedee946f7eb5083518b1654a505ec9c | |
parent | d7b423584bc4f950f0208d3d4108d26bf6da905e (diff) | |
parent | bf77ccc9550ff7f43016e55f7ad810b8aa166c2e (diff) | |
download | erlang-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.c | 5 | ||||
-rw-r--r-- | erts/emulator/beam/erl_db_util.c | 3 | ||||
-rw-r--r-- | lib/stdlib/test/ets_SUITE.erl | 30 |
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) -> |