Skip to content

Commit e4cd9ff

Browse files
author
Vincent Rouillé
committed
fix versionstamp offset and bindingtester
1 parent 44f9c06 commit e4cd9ff

File tree

3 files changed

+83
-45
lines changed

3 files changed

+83
-45
lines changed

foundationdb-bindingtester/src/main.rs

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,14 @@ static RESULT_NOT_PRESENT: Element = Element::Bytes(Bytes(Cow::Borrowed(b"RESULT
2323
static GOT_READ_VERSION: Element = Element::Bytes(Bytes(Cow::Borrowed(b"GOT_READ_VERSION")));
2424
static GOT_COMMITTED_VERSION: Element =
2525
Element::Bytes(Bytes(Cow::Borrowed(b"GOT_COMMITTED_VERSION")));
26+
static GOT_APPROXIMATE_SIZE: Element =
27+
Element::Bytes(Bytes(Cow::Borrowed(b"GOT_APPROXIMATE_SIZE")));
2628
static ERROR_NONE: Element = Element::Bytes(Bytes(Cow::Borrowed(b"ERROR: NONE")));
2729
static ERROR_MULTIPLE: Element = Element::Bytes(Bytes(Cow::Borrowed(b"ERROR: MULTIPLE")));
2830
static OK: Element = Element::Bytes(Bytes(Cow::Borrowed(b"OK")));
2931

3032
use crate::fdb::options::{MutationType, StreamingMode};
33+
use tuple::VersionstampOffset;
3134
fn mutation_from_str(s: &str) -> MutationType {
3235
match s {
3336
"ADD" => MutationType::Add,
@@ -163,6 +166,7 @@ enum InstrCode {
163166
Reset,
164167
Cancel,
165168
GetCommittedVersion,
169+
GetApproximateSize,
166170
WaitFuture,
167171

168172
TuplePack,
@@ -238,6 +242,7 @@ impl Instr {
238242
"RESET" => Reset,
239243
"CANCEL" => Cancel,
240244
"GET_COMMITTED_VERSION" => GetCommittedVersion,
245+
"GET_APPROXIMATE_SIZE" => GetApproximateSize,
241246
"WAIT_FUTURE" => WaitFuture,
242247

243248
"TUPLE_PACK" => TuplePack,
@@ -399,7 +404,6 @@ impl TransactionState {
399404
fn as_mut(&mut self) -> &mut Transaction {
400405
use TransactionState as S;
401406

402-
println!("as_mut {:?}", self);
403407
self.reset();
404408
match *self {
405409
S::Transaction(ref mut tr) => tr,
@@ -414,7 +418,6 @@ impl TransactionState {
414418
fn take(&mut self, id: usize) -> Transaction {
415419
use TransactionState as S;
416420

417-
println!("take {:?}", self);
418421
self.reset();
419422
match std::mem::replace(self, S::Dead) {
420423
S::Transaction(tr) => {
@@ -1190,6 +1193,18 @@ impl StackMachine {
11901193
}
11911194
}
11921195

1196+
// Calls get_approximate_size and pushes the byte string "GOT_APPROXIMATE_SIZE"
1197+
// onto the stack. Note bindings may issue GET_RANGE calls with different
1198+
// limits, so these bindings can obtain different sizes back.
1199+
GetApproximateSize => {
1200+
debug!("get_approximate_size");
1201+
trx.as_mut()
1202+
.get_approximate_size()
1203+
.await
1204+
.expect("failed to get approximate size");
1205+
self.push(number, GOT_APPROXIMATE_SIZE.clone().into_owned());
1206+
}
1207+
11931208
// Pops the top item off the stack and pushes it back on. If the top item on
11941209
// the stack is a future, this will have the side effect of waiting on the
11951210
// result of the future and pushing the result on the stack. Does not change
@@ -1212,7 +1227,6 @@ impl StackMachine {
12121227
buf.push(element);
12131228
}
12141229
let tuple = Element::Tuple(buf);
1215-
debug!("tuple_packed {}", Bytes::from(pack(&tuple)));
12161230
self.push(number, Element::Bytes(pack(&tuple).into()));
12171231
}
12181232

@@ -1238,21 +1252,25 @@ impl StackMachine {
12381252
buf.push(element);
12391253
}
12401254

1241-
let tuple = Element::Tuple(buf);
1255+
let tuple = Element::Tuple(buf.clone());
12421256
let i = tuple.count_incomplete_versionstamp();
1243-
1244-
self.push(
1245-
number,
1246-
if i == 0 {
1247-
ERROR_NONE.clone().into_owned()
1248-
} else if i > 0 {
1249-
ERROR_MULTIPLE.clone().into_owned()
1250-
} else {
1251-
OK.clone().into_owned()
1252-
},
1253-
);
1254-
if i == 1 {
1255-
self.push(number, Element::Bytes(pack(&tuple).into()));
1257+
let mut vec = prefix.into_owned();
1258+
let offset = buf.pack_into_vec_with_versionstamp(&mut vec);
1259+
match offset {
1260+
VersionstampOffset::None { size: _ } => {
1261+
assert_eq!(i, 0);
1262+
self.push(number, ERROR_NONE.clone().into_owned());
1263+
}
1264+
VersionstampOffset::OneIncomplete { offset: _ } => {
1265+
assert_eq!(i, 1);
1266+
let data = Element::Bytes(vec.into());
1267+
self.push(number, OK.clone().into_owned());
1268+
self.push(number, data);
1269+
}
1270+
VersionstampOffset::MultipleIncomplete => {
1271+
assert!(i > 1);
1272+
self.push(number, ERROR_MULTIPLE.clone().into_owned());
1273+
}
12561274
}
12571275
}
12581276

foundationdb/src/tuple/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,10 @@ pub fn pack_into<T: TuplePack>(v: &T, output: &mut Vec<u8>) {
208208
///
209209
/// Panics if there is multiple versionstamp present or if the encoded data size doesn't fit in `u32`.
210210
pub fn pack_into_with_versionstamp<T: TuplePack>(v: &T, output: &mut Vec<u8>) {
211-
v.pack_into_vec_with_versionstamp(output)
211+
let offset = v.pack_into_vec_with_versionstamp(output);
212+
if let VersionstampOffset::MultipleIncomplete = offset {
213+
panic!("pack_into_with_versionstamp does not allow multiple versionstamps");
214+
}
212215
}
213216

214217
/// Unpack input

foundationdb/src/tuple/pack.rs

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use std::mem;
77
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
88
pub enum VersionstampOffset {
99
None { size: u32 },
10-
One { offset: u32 },
11-
Multiple,
10+
OneIncomplete { offset: u32 },
11+
MultipleIncomplete,
1212
}
1313
impl std::ops::AddAssign<u32> for VersionstampOffset {
1414
fn add_assign(&mut self, r: u32) {
@@ -23,14 +23,18 @@ impl std::ops::AddAssign for VersionstampOffset {
2323
(VersionstampOffset::None { size }, VersionstampOffset::None { size: r }) => {
2424
*size += r;
2525
}
26-
(VersionstampOffset::None { size }, VersionstampOffset::One { offset }) => {
27-
*self = VersionstampOffset::One {
26+
(VersionstampOffset::None { size }, VersionstampOffset::OneIncomplete { offset }) => {
27+
*self = VersionstampOffset::OneIncomplete {
2828
offset: *size + offset,
2929
};
3030
}
31-
(VersionstampOffset::One { .. }, VersionstampOffset::One { .. })
32-
| (VersionstampOffset::One { .. }, VersionstampOffset::Multiple) => {
33-
*self = VersionstampOffset::Multiple;
31+
(
32+
VersionstampOffset::OneIncomplete { .. },
33+
VersionstampOffset::OneIncomplete { .. },
34+
)
35+
| (VersionstampOffset::None { .. }, VersionstampOffset::MultipleIncomplete)
36+
| (VersionstampOffset::OneIncomplete { .. }, VersionstampOffset::MultipleIncomplete) => {
37+
*self = VersionstampOffset::MultipleIncomplete;
3438
}
3539
_ => {}
3640
}
@@ -69,7 +73,10 @@ pub trait TuplePack {
6973
/// Panics if there is multiple versionstamp present or if the encoded data size doesn't fit in `u32`.
7074
fn pack_to_vec_with_versionstamp(&self) -> Vec<u8> {
7175
let mut vec = Vec::new();
72-
self.pack_into_vec_with_versionstamp(&mut vec);
76+
let offset = self.pack_into_vec_with_versionstamp(&mut vec);
77+
if let VersionstampOffset::MultipleIncomplete = offset {
78+
panic!("pack_to_vec_with_versionstamp does not allow multiple versionstamps");
79+
}
7380
vec
7481
}
7582

@@ -86,21 +93,16 @@ pub trait TuplePack {
8693
///
8794
/// # Panics
8895
///
89-
/// Panics if there is multiple versionstamp present or if the encoded data size doesn't fit in `u32`.
90-
fn pack_into_vec_with_versionstamp(&self, output: &mut Vec<u8>) {
96+
/// Panics if the encoded data size doesn't fit in `u32`.
97+
fn pack_into_vec_with_versionstamp(&self, output: &mut Vec<u8>) -> VersionstampOffset {
9198
let mut offset = VersionstampOffset::None {
9299
size: u32::try_from(output.len()).expect(PACK_ERR_MSG),
93100
};
94101
offset += self.pack_root(output).expect(PACK_ERR_MSG);
95-
match offset {
96-
VersionstampOffset::None { size: _ } => {}
97-
VersionstampOffset::One { offset } => {
98-
output.extend_from_slice(&offset.to_le_bytes());
99-
}
100-
VersionstampOffset::Multiple => {
101-
panic!("pack_into_with_versionstamp does not allow multiple versionstamps");
102-
}
102+
if let VersionstampOffset::OneIncomplete { offset } = offset {
103+
output.extend_from_slice(&offset.to_le_bytes());
103104
}
105+
offset
104106
}
105107
}
106108

@@ -342,14 +344,16 @@ macro_rules! impl_ux {
342344
const SZ: usize = mem::size_of::<$ux>();
343345
let u = *self;
344346
let n = SZ - (u.leading_zeros() as usize) / 8;
347+
let mut offset = VersionstampOffset::None { size: n as u32 + 1 };
345348
if SZ <= MAX_SZ || n <= MAX_SZ {
346349
w.write_all(&[INTZERO + n as u8])?;
347350
} else {
348351
w.write_all(&[POSINTEND, n as u8])?;
349-
}
352+
offset += 1;
353+
};
350354
w.write_all(&u.to_be_bytes()[SZ - n..])?;
351355

352-
Ok(VersionstampOffset::None { size: n as u32 + 1 })
356+
Ok(offset)
353357
}
354358
}
355359

@@ -393,24 +397,27 @@ macro_rules! impl_ix {
393397
let i = *self;
394398
let u = self.wrapping_abs() as $ux;
395399
let n = SZ - (u.leading_zeros() as usize) / 8;
400+
let mut offset = VersionstampOffset::None { size: n as u32 + 1 };
396401
let arr = if i >= 0 {
397402
if SZ <= MAX_SZ || n <= MAX_SZ {
398403
w.write_all(&[INTZERO + n as u8])?;
399404
} else {
400405
w.write_all(&[POSINTEND, n as u8])?;
406+
offset += 1;
401407
}
402408
(u.to_be_bytes())
403409
} else {
404410
if SZ <= MAX_SZ || n <= MAX_SZ {
405411
w.write_all(&[INTZERO - n as u8])?;
406412
} else {
407413
w.write_all(&[NEGINTSTART, n as u8 ^ 0xff])?;
414+
offset += 1;
408415
}
409416
(i.wrapping_sub(1).to_be_bytes())
410417
};
411418
w.write_all(&arr[SZ - n..])?;
412419

413-
Ok(VersionstampOffset::None { size: n as u32 + 1 })
420+
Ok(offset)
414421
}
415422
}
416423

@@ -470,7 +477,7 @@ macro_rules! impl_fx {
470477
w.write_all(&[$code])?;
471478
w.write_all(&bytes)?;
472479
Ok(VersionstampOffset::None {
473-
size: std::mem::size_of::<$fx>() as u32 / 8 + 1,
480+
size: std::mem::size_of::<$fx>() as u32 + 1,
474481
})
475482
}
476483
}
@@ -558,12 +565,14 @@ mod bigint {
558565
}
559566
let (sign, mut bytes) = self.to_bytes_be();
560567
let n = bytes.len();
568+
let mut offset = VersionstampOffset::None { size: n as u32 + 1 };
561569
match sign {
562570
Sign::Minus => {
563571
if n <= MAX_SZ {
564572
w.write_all(&[INTZERO - n as u8])?;
565573
} else {
566574
w.write_all(&[NEGINTSTART, bigint_n(n)? ^ 0xff])?;
575+
offset += 1;
567576
}
568577
invert(&mut bytes);
569578
w.write_all(&bytes)?;
@@ -574,12 +583,13 @@ mod bigint {
574583
w.write_all(&[INTZERO + n as u8])?;
575584
} else {
576585
w.write_all(&[POSINTEND, bigint_n(n)?])?;
586+
offset += 1;
577587
}
578588
w.write_all(&bytes)?;
579589
}
580-
};
590+
}
581591

582-
Ok(VersionstampOffset::None { size: n as u32 + 1 })
592+
Ok(offset)
583593
}
584594
}
585595

@@ -626,14 +636,16 @@ mod bigint {
626636
}
627637
let bytes = self.to_bytes_be();
628638
let n = bytes.len();
639+
let mut offset = VersionstampOffset::None { size: n as u32 + 1 };
629640
if n <= MAX_SZ {
630641
w.write_all(&[INTZERO + n as u8])?;
631642
} else {
632643
w.write_all(&[POSINTEND, bigint_n(n)?])?;
644+
offset += 1;
633645
}
634646
w.write_all(&bytes)?;
635647

636-
Ok(VersionstampOffset::None { size: n as u32 + 1 })
648+
Ok(offset)
637649
}
638650
}
639651

@@ -995,10 +1007,11 @@ impl<'de> TupleUnpack<'de> for Element<'de> {
9951007
(input, Element::Uuid(v))
9961008
}
9971009
found => {
1010+
dbg!(Bytes::from(input));
9981011
return Err(PackError::BadCode {
9991012
found,
10001013
expected: None,
1001-
})
1014+
});
10021015
}
10031016
};
10041017

@@ -1025,7 +1038,11 @@ impl TuplePack for Versionstamp {
10251038
) -> io::Result<VersionstampOffset> {
10261039
w.write_all(&[VERSIONSTAMP])?;
10271040
w.write_all(self.as_bytes())?;
1028-
Ok(VersionstampOffset::One { offset: 1 })
1041+
if self.is_complete() {
1042+
Ok(VersionstampOffset::None { size: 1 + 12 })
1043+
} else {
1044+
Ok(VersionstampOffset::OneIncomplete { offset: 1 })
1045+
}
10291046
}
10301047
}
10311048

0 commit comments

Comments
 (0)