Skip to content

Commit ca9856e

Browse files
committed
Document new access order checking feature.
1 parent 142bef9 commit ca9856e

File tree

5 files changed

+104
-0
lines changed

5 files changed

+104
-0
lines changed

Change-Log.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
### vNext
2+
* [Java, C++, C#] Add support to [check the safe usage of flyweights (w.r.t. field access order)](./Safe-Flyweight-Usage). [PR #948](https://github.com/real-logic/simple-binary-encoding/pull/948).
3+
14
### 1.27.0 (11 Oct 2022)
25
* [Java] Add preview support for package override on types from SBE 2.0. [PR #904](https://github.com/real-logic/simple-binary-encoding/pull/904), [PR #915](https://github.com/real-logic/simple-binary-encoding/pull/915).
36
* Add support for transforming a schema to generate code for older versions when checking compatibility.

Home.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ The SBE tool can be used as a library enabling on-the-fly decoding of messages,
1313
1. [C++ Users Guide](wiki/Cpp-User-Guide)
1414
1. [CSharp Users Guide](wiki/CSharp-User-Guide)
1515
1. [Golang Users Guide](wiki/Golang-User-Guide)
16+
1. [Safe Flyweight Usage](wiki/Safe-Flyweight-Usage)
1617
1. [FIX/SBE XML Primer](wiki/FIX-SBE-XML-Primer)
1718
1. [Message Extension/Versioning](wiki/Message-Versioning)
1819
1. [Intermediate Representation](wiki/Intermediate-Representation)

Safe-Flyweight-Usage.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
The encoders and decoders that SBE generates in Java (and other languages without approximations of session types) require developers to follow a strict contract:
2+
3+
- Developers must encode/decode all repeating groups and variable-length data fields in the order in which they appear in the schema.
4+
- Developers must explicitly encode/decode/skip all present groups and variable-length data, i.e., no implicit skipping.
5+
- Developers must call next() before encoding/decoding each repeating group element.
6+
7+
When encoding, failure to follow the contract can produce invalid messages that do not conform to the format described in the associated SBE schema.
8+
9+
When decoding, failure to follow the contract can result in the misinterpretation of valid messages.
10+
11+
### Checking field access order
12+
13+
SBE can generate runtime checks that ensure the correct usage of flyweight encoders/decoders/codecs (w.r.t. field access order) in Java, C++ and C#.
14+
15+
To generate these runtime checks, pass `-Dsbe.generate.access.order.checks=true` when running the SBE tool.
16+
17+
By default, the generated checks are disabled, using conditional compilation, as they have a significant performance overhead. When running our car benchmarks, we see approximately 50% fewer encodes/decodes per second.
18+
We expect that teams will enable these runtime checks in non-production environments and in their tests.
19+
20+
To enable the runtime checks:
21+
22+
* In Java, set the `sbe.generate.access.order.checks` system property to `true`.
23+
* In C++, define the `ENABLE_ACCESS_ORDER_CHECKS` symbol when compiling.
24+
* In C#, define the `ENABLE_ACCESS_ORDER_CHECKS` symbol when building.
25+
26+
### Checking complete encoding
27+
28+
When runtime checks are enabled, in addition to checking fields are encoded/decoded in the correct order, you can also check that you've fully encoded a message. I.e., that you haven't omitted any groups or variable length fields from the end of the message.
29+
To do so, call the `checkEncodingIsComplete()` method on the flyweight encoder for the message.
30+
31+
### Understanding errors
32+
33+
Once runtime checks are enabled, you may start to see some errors if you have some incorrect (or very unusual) uses of flyweight encoders/decoders/codecs.
34+
35+
For example, if you have a message schema with two variable length fields:
36+
37+
```xml
38+
<sbe:message name="SendChatMessage" id="99">
39+
<field name="chatId" id="1" type="int64"/>
40+
<data name="subject" id="2" type="varDataEncoding"/> <!-- subject first -->
41+
<data name="body" id="3" type="varDataEncoding"/> <!-- body second -->
42+
</sbe:message>
43+
```
44+
45+
and you accidentally encode these in a different order to the schema:
46+
47+
```java
48+
final SendChatMessageEncoder encoder = new SendChatMessageEncoder()
49+
.wrapAndApplyHeader(buffer, OFFSET, messageHeaderEncoder);
50+
51+
encoder.chatId(1)
52+
.body("About 1 ft tall and furry.") // body first
53+
.subject("Missing cat"); // subject second
54+
```
55+
56+
you will an exception like this one at runtime:
57+
58+
```
59+
Illegal field access order.
60+
Cannot access field "body" in state: V0_BLOCK.
61+
Expected one of these transitions: ["chatId(?)", "subject(?)"].
62+
Please see the diagram in the Javadoc of the inner class #CodecStates.
63+
```
64+
65+
The exception tells us:
66+
67+
- The current codec state is `V0_BLOCK`.
68+
- We cannot call `body` when the codec is in this state.
69+
- But we can call either `chatId` or `subject` in this state.
70+
71+
It also says where we can find more information. The `CodecStates` class documentation holds a dot diagram of the state machine:
72+
73+
```java
74+
/**
75+
* The states in which a encoder/decoder/codec can live.
76+
*
77+
* <p>The state machine diagram below, encoded in the dot language, describes
78+
* the valid state transitions according to the order in which fields may be
79+
* accessed safely. Tools such as PlantUML and Graphviz can render it.
80+
*
81+
* <pre>{@code
82+
* digraph G {
83+
* NOT_WRAPPED -> V0_BLOCK [label=" wrap(version=0) "];
84+
* V0_BLOCK -> V0_BLOCK [label=" chatId(?) "];
85+
* V0_BLOCK -> V0_SUBJECT_DONE [label=" subject(?) "];
86+
* V0_SUBJECT_DONE -> V0_BODY_DONE [label=" body(?) "];
87+
* }
88+
* }</pre>
89+
*/
90+
private static class CodecStates
91+
{
92+
// ...
93+
}
94+
```
95+
96+
We can use a tool, e.g., [PlantText](http://planttext.com), to render the dot diagram and reveal the state machine diagram.
97+
98+
![State Machine Example](./State-Machine-Example.png)

Sbe-Tool-Guide.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ The tool supports the following options:
2525
* `sbe.keyword.append.token`: String to append to schema tokens that collide with reserved words in the target language.
2626
* `sbe.decode.unknown.enum.values`: Support unknown decoded enum values.
2727
* `sbe.csharp.generate.namespace.dir`: Should a directory be created for the namespace under the output directory? Defaults to `true`.
28+
* `sbe.generate.access.order.checks`: Generate code to check flyweight methods are accessed in a valid order? Defaults to `false`. This option is supported by the Java, C#, and C++ generators. Requires platform-specific configuration to enable the checks at runtime, e.g., setting a system property or constant symbol.
29+
* `sbe.cpp.disable.implicit.copying`: Disable generation of copy constructors and copy assignment operators? Defaults to `false`.
2830

2931
The SBE tool can be used with Maven
3032
[see](https://github.com/real-logic/simple-binary-encoding/wiki/Sbe-Tool-Maven)

State-Machine-Example.png

27.5 KB
Loading

0 commit comments

Comments
 (0)