···154154 end
155155 xks = XKS.new(path: path, block_size: 1024, extent_block_count: extent_block_count, lsm_subtable_size: 1024, lsm_memtable_size_limit: 4096)
156156157157- # Write initial meta pairs
158158- meta_mutations = Enum.map(meta_pairs, fn {k, v} -> {:write, k, v} end)
159159- XKS.apply_batch(xks, @meta_partition, prev_version, meta_mutations)
160160- XKS.maybe_rotate_memtable(xks, @meta_partition)
161161-162162- # Write the first extent
163163- write_new_extent(xks, prev_version, %{
157157+ # Write first extent and meta pairs
158158+ first_extent = %{
164159 i: 0,
165160 extent: FreeList.reserve_extent(xks.free_list),
166161 size: 0,
167162 nonce: make_nonce(),
168168- })
163163+ }
164164+165165+ state_mutations = [pack_extent_mutation(first_extent)]
166166+ meta_mutations = Enum.map(meta_pairs, fn {k, v} -> {:write, k, v} end)
167167+168168+ partitioned_batches = [
169169+ {@state_partition, state_mutations},
170170+ {@meta_partition, meta_mutations},
171171+ ]
172172+ XKS.apply_partitioned_batches(xks, prev_version, partitioned_batches)
169173170174 # Put and commit the initial state of the TLog
171175 state_fields = %{
···896900 # TODO: strong_rand_bytes(16)
897901 nonce_i = Enum.random(1..1_000_000_000)
898902 <<nonce_i::integer-64, nonce_i::integer-64>>
899899- end
900900-901901- defp write_new_extent(%XKS{} = xks, version, extent) do
902902- XKS.apply_batch(xks, @state_partition, version, [pack_extent_mutation(extent)])
903903 end
904904905905 defp pack_extent_mutation(%{i: i, extent: extent, size: size, nonce: nonce} = _extent) do
+13-1
lib/xks/xks.ex
···295295 },
296296 } = xks
297297 prev_version = :atomics.get(version_atomic, 1)
298298- assert version > prev_version
298298+ case version == 0 and xks.sequence == 0 do
299299+ true ->
300300+ # Allow a write at zero, one time, as long as this is a new XKS
301301+ #
302302+ # It would be nicer to initialize `version_atomic` to -1 and avoid this,
303303+ # but that would require a signed version
304304+ # TODO: find a less hacky way to ensure this is the first write
305305+ assert :ets.first(xks.manifest) == :"$end_of_table"
306306+ false ->
307307+ assert version != 0
308308+ # Ensure writes are strictly monotonic
309309+ assert version > prev_version
310310+ end
299311300312 Enum.each(partitioned_batches, fn {partition, mutations} ->
301313 assert is_integer(partition)