Switch default stream output to Magnesium
[controller.git] / opendaylight / md-sal / sal-clustering-commons / src / main / java / org / opendaylight / controller / cluster / datastore / node / utils / stream / MagnesiumNode.java
1 /*
2  * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.cluster.datastore.node.utils.stream;
9
10 /**
11  * Magnesium encoding Node types. Encoded as a single byte, split as follows:
12  * <pre>
13  *   7 6 5 4 3 2 1 0
14  *  +-+-+-+-+-+-+-+-+
15  *  | P | A |  Type |
16  *  +-+-+-+-+-+-+-+-+
17  * </pre>
18  * The fields being:
19  * <ul>
20  *   <li>Bits 7 and 6 (most significant): predicate presence. Only valid for NODE_MAP_ENTRY and NODE_LEAF</li>
21  *   <li>Bits 5 and 4: addressing mode</li>
22  *   <li>Bits 3-0 (least significant) node type</li>
23  * </ul>
24  */
25 // TODO: restructure this into some concrete examples
26 //- a leaf referencing a previously-encoded NodeIdentifier would take
27 //6 bytes:
28 //  (byte)    NodeTypes.LEAF_NODE
29 //  (byte)    TokenTypes.IS_QNAME_CODE
30 //  (int)     code value
31 //where as new tokens can do that in as few as 2 bytes:
32 //  (byte)    NodeType.(NODE_LEAF | ADDR_LOOKUP_1B)
33 //  (byte)    code value
34 //with worst-case being 5 bytes:
35 //  (byte)    NodeType.(NODE_LEAF | ADDR_LOOKUP_4B)
36 //  (int)     code value
37 //- a map entry node referencing previously-encoded QNames and a single
38 //predicate would take a base of 15 bytes (not counting value object):
39 //  (byte)    NodeTypes.MAP_ENTRY_NODE
40 //  (byte)    TokenTypes.IS_QNAME_CODE
41 //  (int)     code value
42 //  (int)     size of predicates
43 //  (byte)    TokenTypes.IS_QNAME_CODE
44 //  (int)     code value
45 //whereas new tokens can do that in as few as 3 bytes:
46 //  (byte)    NodeType.(NODE_MAP_ENTRY | ADDR_LOOKUP_1B | PREDICATE_ONE)
47 //  (byte)    code value
48 //  (byte)    code value
49 //this ability is maintained for up to 255 predicates with:
50 //  (byte)    NodeType.(NODE_MAP_ENTRY | ADDR_LOOKUP_1B | PREDICATE_1B)
51 //  (byte)    code value
52 //  (byte)    size of predicates
53 //  (byte)    code value [0-255]
54 //- a leaf representing a key inside a map entry has the ability to skip
55 //value encoding by being as simple as:
56 //  (byte)    NodeTYpe.(NODE_LEAF | ADDR_LOOKUP_1B | PREDICATE_ONE)
57 //  (byte)    code value
58 //
59 final class MagnesiumNode {
60     /**
61      * End of node marker. Does not support addressing modes.
62      */
63     static final byte NODE_END             = 0x00; // N/A
64     /**
65      * A leaf node. Encoding can specify {@link #PREDICATE_ONE}, which indicates the value is skipped as the encoder
66      * has emitted a parent MapNode, whose identifier contains the value.
67      */
68     static final byte NODE_LEAF            = 0x01;
69     static final byte NODE_CONTAINER       = 0x02;
70     static final byte NODE_LIST            = 0x03;
71     static final byte NODE_MAP             = 0x04;
72     static final byte NODE_MAP_ORDERED     = 0x05;
73     static final byte NODE_LEAFSET         = 0x06;
74     static final byte NODE_LEAFSET_ORDERED = 0x07;
75     static final byte NODE_CHOICE          = 0x08;
76     static final byte NODE_AUGMENTATION    = 0x09;
77     static final byte NODE_ANYXML          = 0x0A;
78     static final byte NODE_LIST_ENTRY      = 0x0B;
79     static final byte NODE_LEAFSET_ENTRY   = 0x0C;
80     static final byte NODE_MAP_ENTRY       = 0x0D;
81
82     // TODO: either implement or remove this coding. While Lithium has emit code, it lacks the code do read such nodes,
83     //       which most probably means we do not need to bother ...
84     static final byte NODE_ANYXML_MODELED  = 0x0E;
85     // 0x0F reserved for anydata
86     static final byte TYPE_MASK            = 0x0F;
87
88
89     /**
90      * Inherit identifier from parent. This addressing mode is applicable in:
91      * <ul>
92      *   <li>{@link #NODE_END}, where an identifier is not applicable
93      *   <li>{@link #NODE_LIST_ENTRY}, where the NodeIdentifier is inherited from parent {@link #NODE_LIST}</li>
94      *   <li>{@link #NODE_MAP_ENTRY}, where the NodeIdentifier is inherited from parent {@link #NODE_MAP} or
95      *       {@link #NODE_MAP_ORDERED}</li>
96      *   <li>{@link #NODE_LEAFSET_ENTRY}, where the QName inherited from parent and the value is inferred from the
97      *       next {@link MagnesiumValue} encoded</li>
98      * </ul>
99      */
100     static final byte ADDR_PARENT     = 0x00;
101     /**
102      * Define a new QName-based identifier constant. For {@link #NODE_AUGMENTATION} this is a set of QNames. Assign
103      * a new linear key to this constant.
104      */
105     static final byte ADDR_DEFINE     = 0x10;
106     /**
107      * Reference a previously {@link #ADDR_DEFINE}d identifier constant. This node byte is followed by an unsigned
108      * byte, which holds the linear key previously defined (i.e. 0-255).
109      */
110     static final byte ADDR_LOOKUP_1B  = 0x20;
111     /**
112      * Reference a previously {@link #ADDR_DEFINE}d identifier constant. This node byte is followed by a signed int,
113      * which holds the linear key previously defined.
114      */
115     static final byte ADDR_LOOKUP_4B  = 0x30;
116     static final byte ADDR_MASK       = ADDR_LOOKUP_4B;
117
118     /**
119      * Predicate encoding: no predicates are present in a {@link #NODE_MAP_ENTRY}.
120      */
121     static final byte PREDICATE_ZERO = 0x00;
122
123     /**
124      * Predicate encoding: a single predicate is present in a {@link #NODE_MAP_ENTRY}. In case of {@link #NODE_LEAF}
125      * encoded as part of a {@link #NODE_MAP_ENTRY} this bit indicates the <strong>value</strong> is not encoded and
126      * should be looked up from the map entry's predicates.
127      *
128      * <p>
129      * The predicate is encoded as a {@link #ADDR_DEFINE} or {@link #ADDR_LOOKUP_1B}/{@link #ADDR_LOOKUP_4B},
130      * followed by an encoded {@link MagnesiumValue}.
131      */
132     static final byte PREDICATE_ONE   = 0x40;
133
134     /**
135      * Predicate encoding: 0-255 predicates are present, as specified by the following {@code unsigned byte}. This
136      * encoding is expected to be exceedingly rare. This should not be used to encode 0 or 1 predicate, those cases
137      * should be encoded as:
138      * <ul>
139      *   <li>no PREDICATE_* set when there are no predicates (probably not valid anyway)</li>
140      *   <li><{@link #PREDICATE_ONE} if there is only one predicate</li>
141      * </ul>
142      */
143     static final byte PREDICATE_1B    = (byte) 0x80;
144
145     /**
146      * Predicate encoding 0 - {@link Integer#MAX_VALUE} predicates are present, as specified by the following
147      * {@code int}. This should not be used where 0-255 predicates are present.
148      */
149     static final byte PREDICATE_4B    = (byte) (PREDICATE_ONE | PREDICATE_1B);
150     static final byte PREDICATE_MASK  = PREDICATE_4B;
151
152     private MagnesiumNode() {
153
154     }
155 }