···6677- [X] BeginBuffer server (batch get_read_version requests)
88- [X] Use slots to spawn servers
99-- [ ] Range clears
99+- [X] Range clears
1010 - [X] Support write conflict ranges in VersionMap (decreased bench_rw from 28k to 24k TPS)
1111- - [ ] Add clear_range() to Transaction
1212- - [ ] Slice range clear mutations in CommitBuffer
1313- - [ ] Apply range clears on Storage servers
1111+ - [X] Add clear_range() to Transaction
1212+ - [X] Slice range clear mutations in ShardTagMap
1313+ - [X] Test range clears in Model workload
1414- [ ] Storage server handling
1515 - [X] Spawn servers using slots in Manager
1616 - [ ] Add unknown servers to meta keyspace in Distributor
+41-25
lib/shard_tag_map.ex
···5959 %{shard_map: shard_map, tlog_ids: all_tlog_ids} = stm
6060 tlog_mutations = Map.new(stm.tlog_ids, fn id -> {id, []} end)
61616262- Enum.reduce(mutations, {tlog_mutations, 0}, fn mut, {acc, i} ->
6363- {tlogs, tags} =
6464- case mutation_key(mut) do
6565- special_server_keys_prefix() <> rest ->
6666- # Special server_keys mutations are sent only to that particular Storage server
6767- [id, _sk] = unpack_server_keys_key(rest)
6868- tags = [id]
6969- # Send to all TLogs for simplicity (shard moves should never be a bottleneck)
7070- {all_tlog_ids, tags}
6262+ Enum.reduce(mutations, {tlog_mutations, 0}, fn
6363+ {:clear_range, sk, ek}, {acc, i} ->
6464+ shards = DenseShardMap.shards_for_range(shard_map, sk, ek)
71657272- meta_prefix() <> _ = key ->
7373- {_sk, _ek, {_tlogs, tags, _from_tags}} = DenseShardMap.shard_for_key(shard_map, key)
7474- # Additionally tag meta mutations with meta tag (-1)
7575- tags = [meta_tag() | tags]
7676- # Send meta mutations to all tlogs
7777- {all_tlog_ids, tags}
6666+ # Split the range across shard boundaries and create a mutation for each
6767+ intersect_ranges({sk, ek}, shards)
6868+ |> Enum.reduce({acc, i}, fn {sk, ek, {tlogs, tags, _from}}, {acc, i} ->
6969+ tagged_mut = {tags, {i, {:clear_range, sk, ek}}}
78707979- key ->
8080- {_sk, _ek, {tlogs, tags, _from_tags}} = DenseShardMap.shard_for_key(shard_map, key)
8181- # Send to pre-computed tlogs/tags for this shard
8282- {tlogs, tags}
8383- end
7171+ acc = Enum.reduce(tlogs, acc, fn tlog_id, acc ->
7272+ Map.update!(acc, tlog_id, &[tagged_mut | &1])
7373+ end)
7474+ {acc, i + 1}
7575+ end)
84768585- tagged_mut = {tags, {i, mut}}
8686- acc = Enum.reduce(tlogs, acc, fn tlog_id, acc ->
8787- Map.update!(acc, tlog_id, &[tagged_mut | &1])
8888- end)
8989- {acc, i + 1}
7777+ # Single-key mutations (:write and :clear)
7878+ mut, {acc, i} ->
7979+ {tlogs, tags} =
8080+ case mutation_key(mut) do
8181+ special_server_keys_prefix() <> rest ->
8282+ # Special server_keys mutations are sent only to that particular Storage server
8383+ [id, _sk] = unpack_server_keys_key(rest)
8484+ tags = [id]
8585+ # Send to all TLogs for simplicity (shard moves should never be a bottleneck)
8686+ {all_tlog_ids, tags}
8787+8888+ meta_prefix() <> _ = key ->
8989+ {_sk, _ek, {_tlogs, tags, _from_tags}} = DenseShardMap.shard_for_key(shard_map, key)
9090+ # Additionally tag meta mutations with meta tag (-1)
9191+ tags = [meta_tag() | tags]
9292+ # Send meta mutations to all tlogs
9393+ {all_tlog_ids, tags}
9494+9595+ key ->
9696+ {_sk, _ek, {tlogs, tags, _from_tags}} = DenseShardMap.shard_for_key(shard_map, key)
9797+ # Send to pre-computed tlogs/tags for this shard
9898+ {tlogs, tags}
9999+ end
100100+101101+ tagged_mut = {tags, {i, mut}}
102102+ acc = Enum.reduce(tlogs, acc, fn tlog_id, acc ->
103103+ Map.update!(acc, tlog_id, &[tagged_mut | &1])
104104+ end)
105105+ {acc, i + 1}
90106 end)
91107 |> then(fn {tlog_mutations, _i} ->
92108 Map.new(tlog_mutations, fn {tlog_id, mutations_reversed} -> {tlog_id, Enum.reverse(mutations_reversed)} end)
+8
lib/transaction.ex
···241241 |> add_write_confict(key)
242242 end
243243244244+ @spec clear_range(TxnState.t, binary, binary) :: TxnState.t
245245+ def clear_range(%TxnState{} = txn, start_key, end_key)
246246+ when is_binary(start_key) and is_binary(end_key) and start_key < end_key do
247247+ txn
248248+ |> add_mutation({:clear_range, start_key, end_key})
249249+ |> add_write_confict({start_key, end_key})
250250+ end
251251+244252 @spec add_mutation(TxnState.t, Utils.mutation) :: TxnState.t
245253 defp add_mutation(%TxnState{} = txn, mutation) do
246254 %TxnState{txn | mutations: [mutation | txn.mutations]}