use foundationdb::{
options,
tuple::{pack, pack_with_versionstamp, unpack, Subspace, Versionstamp},
Database, FdbResult, RangeOption,
};
use futures::StreamExt;
#[tokio::main]
async fn main() {
let network = unsafe { foundationdb::boot() };
run_versionstamp_key_example()
.await
.expect("failed to run versionstamp example");
run_versionstamp_value_example()
.await
.expect("failed to run versionstamp example");
drop(network);
}
async fn run_versionstamp_key_example() -> FdbResult<()> {
println!("running example for setting versionstamped keys");
let db = Database::default()?;
let subspace = Subspace::all().subspace(&"versionstamp_example");
let (from, to) = subspace.range();
let trx_clear = db.create_trx()?;
trx_clear.clear_range(&from, &to);
trx_clear.commit().await?;
let trx_1 = db.create_trx()?;
let key_1_1 = subspace.pack_with_versionstamp(&("prefix", &Versionstamp::incomplete(2)));
let key_1_2 = subspace.pack_with_versionstamp(&("prefix", &Versionstamp::incomplete(1)));
let value_1_1 = "value_1_1";
let value_1_2 = "value_1_2";
trx_1.atomic_op(
&key_1_1,
&pack(&value_1_1),
options::MutationType::SetVersionstampedKey,
);
trx_1.atomic_op(
&key_1_2,
&pack(&value_1_2),
options::MutationType::SetVersionstampedKey,
);
let trx_2 = db.create_trx()?;
let key_2_1 = subspace.pack_with_versionstamp(&("prefix", &Versionstamp::incomplete(1)));
let key_2_2 = subspace.pack_with_versionstamp(&("prefix", &Versionstamp::incomplete(2)));
let value_2_1 = "value_2_1";
let value_2_2 = "value_2_2";
trx_2.atomic_op(
&key_2_1,
&pack(&value_2_1),
options::MutationType::SetVersionstampedKey,
);
trx_2.atomic_op(
&key_2_2,
&pack(&value_2_2),
options::MutationType::SetVersionstampedKey,
);
trx_2.commit().await?;
trx_1.commit().await?;
let trx = db.create_trx()?;
let range = RangeOption::from((from, to));
let mut kvs = trx.get_ranges_keyvalues(range, false);
while let Some(kv) = kvs.next().await {
let kv = kv?;
let (_, v) = subspace
.unpack::<(String, Versionstamp)>(kv.key())
.expect("failed to unpack key");
let value = unpack::<String>(kv.value()).expect("failed to unpack value");
println!(
"{:?} {}: {}",
v.transaction_version(),
v.user_version(),
value
);
}
Ok(())
}
async fn run_versionstamp_value_example() -> FdbResult<()> {
println!("running example for setting versionstamped values");
let db = Database::default()?;
let subspace = Subspace::all().subspace(&"versionstamp_example");
let (from, to) = subspace.range();
let trx_clear = db.create_trx()?;
trx_clear.clear_range(&from, &to);
trx_clear.commit().await?;
let trx = db.create_trx()?;
let key_tuple = ("data", &Versionstamp::incomplete(0));
let key = subspace.pack_with_versionstamp(&key_tuple);
let value = "some value";
trx.atomic_op(
&key,
&pack(&value),
options::MutationType::SetVersionstampedKey,
);
let index_key = subspace.pack(&"index");
trx.atomic_op(
&index_key,
&pack_with_versionstamp(&key_tuple),
options::MutationType::SetVersionstampedValue,
);
trx.commit().await?;
let trx = db.create_trx()?;
let index_kv = trx
.get(&index_key, false)
.await?
.expect("didn't find index");
let versionstamped_key =
unpack::<(String, Versionstamp)>(&index_kv).expect("failed to unpack value");
let versionstamped_value = trx
.get(&subspace.pack(&versionstamped_key), false)
.await?
.expect("didn't find reference");
let value = unpack::<String>(&versionstamped_value).expect("failed to unpack value");
println!("got back value {value}");
Ok(())
}