# Implementing VersionStamps in bindings

**URL:** <https://forums.foundationdb.org/t/implementing-versionstamps-in-bindings/250>\
**Category:** FoundationDB Core\
**Created:** [April 24, 2018, 7:05pm UTC](https://forums.foundationdb.org/t/implementing-versionstamps-in-bindings/250 "2018-04-24T19:05:11Z")\
**Posts on this page:** 1\
**Showing post:** 5

<div class="post-metadata">

**Author:** ![alloc](https://sea1.discourse-cdn.com/foundationdb/user_avatar/forums.foundationdb.org/alloc/32/9_2.png) [@alloc](https://forums.foundationdb.org/u/alloc)\
**Post date:** [April 25, 2018, 4:57am UTC](https://forums.foundationdb.org/t/implementing-versionstamps-in-bindings/250/5 "2018-04-25T04:57:06Z")

</div>

> [@KrzysFR](#):
>
> So which is it? 12 bytes (10 + 2) or 10 bytes (8 + 2) ? Are the last 2 bytes of the transaction always 0?

Hm, yeah, this might have been an instance where brevity was chosen instead of clarity. Maybe a 12 byte “versionstamp” should have been an ExtendedVersionstamp or something to indicate it is different from a 10 byte versionstamp? ¯\_(ツ)\_/¯

> [@KrzysFR](#):
>
> Obvious problem is what if this pattern is used by random chance by the key itself? It cannot be something trivial like all zeros, or all FF. Maybe $VERSTAMP!$ or something like that?

This can be improved somewhat by the fact that it will be the magic string preceded by the versionstamp type code, which might make it less likely to collide (or, well, maybe not). We ultimately decided that a magic string was more error prone than the extra methods were bad ergonomically, so we went with what’s in the codebase now. To handle subspaces, we added methods to pack a tuple with a prefix so that the prefix length gets added in to the offset correctly. It doesn’t quite work for suffixes, but that seems to be less common.

> [@KrzysFR](#):
>
> So what is the “operation counter within a transaction”?

What are your order of operations? The get\_versionstamp method is somewhat weird, but you have to call the future before it is committed, and then that future will be ready only after the commit. So something like:

```java
CompletableFuture<byte[]> vsFuture = tr.getVersionstamp();
tr.commit().join(); // blocking call to wait on commit
byte[] versionstamp = vsFuture.join(); // non-blocking call to get versionstamp

```

(But, like, in C# instead of Java.) I think you can get used\_during\_commit if you call `getVersionstamp` after commit rather than before.

> [@KrzysFR](#):
>
> in all my tests, the 2 bytes at ofset 8 and 9 are always 0. What are the conditions required to see a non-zero value there?

Are you only ever running one transaction at a time? You will only see a non-zero “batch version” (we call it) if there are multiple transactions being committed together at a single version, which can only happen if there are concurrent commits. The easiest way is to probably fire off multiple transactions and then wait for all of them.

> [@dave](#):
>
> The reason that the last 2 bytes can’t be filled in automatically is because you very well may want to insert logically-the-same versionstamped item in more than one index, in which case it’s critical that it get the exact same (12-byte) versionstamp in each place.

Just to expand on this a little, with versionstamps in particular, it’s often the case that you will want a forward index and a reverse index, i.e., `(keyspace_1, key) -> version` and `(keyspace_2, version) -> key`. There are a couple of reasons for this, but the most obvious is that as you don’t know what key you wrote if you only write the one with a version, then to remove that key, you have to somehow figure out what that version was. So you can either scan the keyspace\_2 (slow) or look it up in the other index (fast). The other less obvious reason is that if you get a `commit_uknown_result` error, then if all you had were the index with versions in `keyspace_2`, it would be really easy to add multiple entries in `keyspace_2` in subsequent retries by mistake. Having `keyspace_1` around let’s you either detect that you are in a retry loop and not write it again (essentially letting you know that your commit succeeded) or, if index maintenance is done correctly, lets you clean up `keyspace_1` and `keyspace_2` within the retry loop. But all of that depends on the versionstamp having the same user version each time for a logical record within the database.

---

_[View the full topic](https://forums.foundationdb.org/t/implementing-versionstamps-in-bindings/250)._
