Skip to content

Restore counter-based CAS semantics in segcache#23

Closed
thinkingfish wants to merge 1 commit into
mainfrom
claude/quirky-planck-nt1xap
Closed

Restore counter-based CAS semantics in segcache#23
thinkingfish wants to merge 1 commit into
mainfrom
claude/quirky-planck-nt1xap

Conversation

@thinkingfish

Copy link
Copy Markdown
Member

Summary

The hashtable rewrite (#10) replaced the per-bucket CAS counter with the item's packed location bits as the CAS token. This regressed memcache CAS semantics for downstream consumers: the cas stored integration test receives EXISTS where STORED is expected, which is why the downstream segcache git dependency has stayed pinned at 5d1d870.

Two concrete problems with location-derived tokens:

  • Tokens are no longer small, deterministic, monotonically increasing integers (1, 2, 3, …), which downstream memcache integration tests depend on.
  • Tokens silently change whenever an item is relocated (e.g. by merge eviction copying items to a new segment), invalidating outstanding tokens even though the value never changed.

Fix

Restore the original semantics with a per-bucket AtomicU32 CAS counter in MultiChoiceHashtable, indexed by a key's primary (first-choice) bucket — the new symmetric-slot bucket design has no metadata word to hold it, so the counters live in a parallel array (4 bytes per 64-byte bucket):

  • incremented on every successful hashtable insert
  • incremented again on a successful CAS check, matching the original double-bump behavior of try_update_cas + insert
  • left untouched by relocation (cas_location), removal, and ghost conversion
  • reset by clear()

Item::cas() and Segcache::cas() now read this counter instead of the location bits. The cas() lookup also counts as a hit (frequency update) again, as it did in the original implementation.

Testing

  • New test_cas_value_counter unit test covers the counter lifecycle at the hashtable level (insert bumps, relocation/removal don't, clear resets).
  • New cas_deterministic end-to-end test pins the exact token sequence the original implementation produced (1 after first set, 2 after overwrite, 4 after a successful CAS).
  • cargo test --workspace, cargo test -p segcache --features loom -- loom (CI invocation, 8/8 models pass), and cargo clippy --all-targets are all green.

After this lands, the downstream dependency bump past c2f43b8 should no longer regress the cas stored test.

https://claude.ai/code/session_01B7MKPvEtTUmRX996r1uKku


Generated by Claude Code

The hashtable rewrite (#10) replaced the per-bucket CAS counter with the
item's packed location bits as the CAS token. This regressed memcache CAS
semantics for downstream consumers: tokens were no longer small,
deterministic, monotonically increasing integers, and they changed
whenever an item was relocated. The memcache 'cas stored' integration
test fails with EXISTS where STORED is expected.

Restore the original semantics with a per-bucket atomic CAS counter,
indexed by a key's primary (first-choice) bucket:

- incremented on every successful hashtable insert
- incremented again on a successful CAS check, matching the original
  double-bump behavior of try_update_cas + insert
- left untouched by relocation (cas_location), removal, and ghost
  conversion
- reset by clear()

Item::cas() and the cas() operation now read this counter instead of
the location bits. Add unit tests covering the counter lifecycle and an
end-to-end test pinning the exact token sequence the original
implementation produced.

https://claude.ai/code/session_01B7MKPvEtTUmRX996r1uKku
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants