15
15
*/
16
16
package io .reactivesocket ;
17
17
18
+ import uk .co .real_logic .agrona .DirectBuffer ;
19
+
18
20
import java .nio .ByteBuffer ;
19
21
20
22
/**
24
26
*/
25
27
public class Frame
26
28
{
29
+ private static final int INITIAL_MESSAGE_ARRAY_SIZE = 256 ;
27
30
// TODO: make thread local to demonstrate idea
28
31
private static final ThreadLocal <FrameFlyweight > FRAME_HANDLER = ThreadLocal .withInitial (FrameFlyweight ::new );
29
32
30
33
private Frame () {
31
34
}
32
35
33
36
// not final so we can reuse this object
34
- private ByteBuffer b ;
35
- private int streamId ;
36
- private FrameType type ;
37
- private String message ;
37
+ private ByteBuffer byteBuffer ;
38
+ private byte [] messageArray = new byte [INITIAL_MESSAGE_ARRAY_SIZE ];
39
+ private FrameType frameType ;
40
+
41
+ private long streamId ;
42
+ private int version ;
43
+ private int messageLength = 0 ;
38
44
39
- public ByteBuffer getBytes () {
40
- return b ;
45
+ public ByteBuffer getByteBuffer () {
46
+ return byteBuffer ;
41
47
}
42
48
43
49
public String getMessage () {
44
- if (type == null ) {
50
+ if (frameType == null ) {
45
51
decode ();
46
52
}
47
- return message ;
53
+ return new String ( messageArray , 0 , messageLength ) ;
48
54
}
49
55
50
- public int getStreamId () {
51
- if (type == null ) {
56
+ public long getStreamId () {
57
+ if (frameType == null ) {
52
58
decode ();
53
59
}
54
60
return streamId ;
55
61
}
56
62
57
63
public FrameType getMessageType () {
58
- if (type == null ) {
64
+ if (frameType == null ) {
65
+ decode ();
66
+ }
67
+ return frameType ;
68
+ }
69
+
70
+ public int getVersion ()
71
+ {
72
+ if (frameType == null )
73
+ {
59
74
decode ();
60
75
}
61
- return type ;
76
+ return version ;
62
77
}
63
78
64
79
/**
@@ -68,9 +83,8 @@ public FrameType getMessageType() {
68
83
*/
69
84
public void wrap (ByteBuffer b ) {
70
85
this .streamId = -1 ;
71
- this .type = null ;
72
- this .message = null ;
73
- this .b = b ;
86
+ this .frameType = null ;
87
+ this .byteBuffer = b ;
74
88
}
75
89
76
90
/**
@@ -81,7 +95,7 @@ public void wrap(ByteBuffer b) {
81
95
*/
82
96
public static Frame from (ByteBuffer b ) {
83
97
Frame f = new Frame ();
84
- f .b = b ;
98
+ f .byteBuffer = b ;
85
99
return f ;
86
100
}
87
101
@@ -92,11 +106,31 @@ public static Frame from(ByteBuffer b) {
92
106
* @param type
93
107
* @param message
94
108
*/
95
- public void wrap (int streamId , FrameType type , String message ) {
109
+ public void wrap (long streamId , FrameType type , String message ) {
96
110
this .streamId = streamId ;
97
- this .type = type ;
98
- this .message = message ;
99
- this .b = getBytes (streamId , type , message );
111
+ this .frameType = type ;
112
+
113
+ final byte [] messageBytes = message .getBytes ();
114
+ ensureMessageArrayCapacity (messageBytes .length );
115
+
116
+ System .arraycopy (messageBytes , 0 , this .messageArray , 0 , messageBytes .length );
117
+ this .messageLength = messageBytes .length ;
118
+
119
+ this .byteBuffer = createByteBufferAndEncode (streamId , type , messageBytes );
120
+ }
121
+
122
+ public void setFromDecode (final int version , final long streamId , final FrameType type )
123
+ {
124
+ this .version = version ;
125
+ this .streamId = streamId ;
126
+ this .frameType = type ;
127
+ }
128
+
129
+ public void setFromDecode (final DirectBuffer buffer , final int offset , final int messageLength )
130
+ {
131
+ ensureMessageArrayCapacity (messageLength );
132
+ this .messageLength = messageLength ;
133
+ buffer .getBytes (offset , this .messageArray , 0 , messageLength );
100
134
}
101
135
102
136
/**
@@ -107,47 +141,54 @@ public void wrap(int streamId, FrameType type, String message) {
107
141
* @param message
108
142
* @return
109
143
*/
110
- public static Frame from (int streamId , FrameType type , String message ) {
144
+ public static Frame from (long streamId , FrameType type , String message ) {
111
145
Frame f = new Frame ();
112
- f .b = getBytes (streamId , type , message );
113
146
f .streamId = streamId ;
114
- f .type = type ;
115
- f .message = message ;
147
+ f .frameType = type ;
148
+
149
+ final byte [] messageBytes = message .getBytes ();
150
+ f .ensureMessageArrayCapacity (messageBytes .length );
151
+
152
+ f .byteBuffer = createByteBufferAndEncode (streamId , type , messageBytes );
153
+
154
+ System .arraycopy (messageBytes , 0 , f .messageArray , 0 , messageBytes .length );
155
+ f .messageLength = messageBytes .length ;
116
156
return f ;
117
157
}
118
158
119
- private static ByteBuffer getBytes ( int messageId , FrameType type , String message ) {
159
+ private static ByteBuffer createByteBufferAndEncode ( long streamId , FrameType type , final byte [] message ) {
120
160
final FrameFlyweight frameFlyweight = FRAME_HANDLER .get ();
121
161
122
162
// TODO: allocation side effect of how this works currently with the rest of the machinery.
123
- final ByteBuffer buffer = ByteBuffer .allocate (FrameFlyweight .frameLength (message .length () ));
163
+ final ByteBuffer buffer = ByteBuffer .allocate (FrameFlyweight .frameLength (message .length ));
124
164
125
- frameFlyweight .encode (buffer , messageId , type , message . getBytes () );
165
+ frameFlyweight .encode (buffer , streamId , type , message );
126
166
return buffer ;
127
167
}
128
168
129
169
private void decode () {
130
170
final FrameFlyweight frameFlyweight = FRAME_HANDLER .get ();
131
171
132
- frameFlyweight .decode (b );
133
- this .type = frameFlyweight .messageType ();
134
- this .streamId = (int ) frameFlyweight .streamId (); // TODO: temp cast to only touch as little as possible
172
+ frameFlyweight .decode (this , byteBuffer );
173
+ }
135
174
136
- // TODO: temp allocation to touch as little as possible
137
- final byte [] data = new byte [frameFlyweight .dataLength ()];
138
- frameFlyweight .getDataBytes (data );
139
- this .message = new String (data );
175
+ private void ensureMessageArrayCapacity (final int length )
176
+ {
177
+ if (messageArray .length < length )
178
+ {
179
+ messageArray = new byte [length ];
180
+ }
140
181
}
141
182
142
183
@ Override
143
184
public String toString () {
144
- if (type == null ) {
185
+ if (frameType == null ) {
145
186
try {
146
187
decode ();
147
188
} catch (Exception e ) {
148
189
e .printStackTrace ();
149
190
}
150
191
}
151
- return "Frame => ID: " + streamId + " Type: " + type + " Data: " + message ;
192
+ return "Frame => ID: " + streamId + " Type: " + frameType + " Data: " + getMessage () ;
152
193
}
153
194
}
0 commit comments