27
27
import com .apple .foundationdb .record .logging .LogMessageKeys ;
28
28
import com .apple .foundationdb .record .metadata .RecordType ;
29
29
import com .apple .foundationdb .tuple .Tuple ;
30
- import com .google .common .annotations .VisibleForTesting ;
31
30
import com .google .protobuf .Message ;
32
- import com .apple .foundationdb .annotation .SpotBugsSuppressWarnings ;
33
31
34
32
import javax .annotation .Nonnull ;
35
33
import javax .annotation .Nullable ;
36
34
import java .nio .ByteBuffer ;
37
35
import java .nio .ByteOrder ;
38
36
import java .security .GeneralSecurityException ;
39
- import java .util .Arrays ;
40
37
import java .util .concurrent .ThreadLocalRandom ;
41
38
import java .util .zip .DataFormatException ;
42
39
import java .util .zip .Deflater ;
50
47
* added in the future.
51
48
*
52
49
* <p>
53
- * This serializer will begin each serialized string with a one-byte prefix
50
+ * This serializer will begin each serialized string with a prefix
51
+ * (see {@link TransformedRecordSerializerPrefix} for details)
54
52
* containing information about which transformations were performed. This
55
53
* way, when deserializing, it can detect which transformations were applied
56
54
* so it knows which ones it needs to use to restore the original record.
78
76
*/
79
77
@ API (API .Status .UNSTABLE )
80
78
public class TransformedRecordSerializer <M extends Message > implements RecordSerializer <M > {
81
- @ VisibleForTesting
82
- protected static final int ENCODING_ENCRYPTED = 1 ;
83
- @ VisibleForTesting
84
- protected static final int ENCODING_CLEAR = 2 ;
85
- @ VisibleForTesting
86
- protected static final int ENCODING_COMPRESSED = 4 ;
87
- // TODO: Can remove this after transition to write everything with _CLEAR.
88
- protected static final int ENCODING_PROTO_MESSAGE_FIELD = 0x02 ;
89
- protected static final int ENCODING_PROTO_TYPE_MASK = 0x07 ;
90
79
protected static final int DEFAULT_COMPRESSION_LEVEL = Deflater .BEST_COMPRESSION ;
91
80
protected static final int MIN_COMPRESSION_VERSION = 1 ;
92
81
protected static final int MAX_COMPRESSION_VERSION = 1 ;
@@ -110,53 +99,7 @@ protected TransformedRecordSerializer(@Nonnull RecordSerializer<M> inner,
110
99
this .writeValidationRatio = writeValidationRatio ;
111
100
}
112
101
113
- @ SpotBugsSuppressWarnings ("EI_EXPOSE_REP" )
114
- protected static class TransformState {
115
- public boolean compressed ;
116
- public boolean encrypted ;
117
-
118
- @ Nonnull public byte [] data ;
119
- public int offset ;
120
- public int length ;
121
-
122
- public TransformState (@ Nonnull byte [] data ) {
123
- this (data , 0 , data .length );
124
- }
125
-
126
- public TransformState (@ Nonnull byte [] data , int offset , int length ) {
127
- this .compressed = false ;
128
- this .encrypted = false ;
129
- this .data = data ;
130
- this .offset = offset ;
131
- this .length = length ;
132
- }
133
-
134
- @ Nonnull
135
- public byte [] getDataArray () {
136
- if (offset == 0 && length == data .length ) {
137
- return data ;
138
- } else {
139
- byte [] newData = Arrays .copyOfRange (data , offset , offset + length );
140
- offset = 0 ;
141
- length = newData .length ;
142
- data = newData ;
143
- return newData ;
144
- }
145
- }
146
-
147
-
148
- public void setDataArray (@ Nonnull byte [] data ) {
149
- setDataArray (data , 0 , data .length );
150
- }
151
-
152
- public void setDataArray (@ Nonnull byte [] data , int offset , int length ) {
153
- this .data = data ;
154
- this .offset = offset ;
155
- this .length = length ;
156
- }
157
- }
158
-
159
- protected void compress (@ Nonnull TransformState state , @ Nullable StoreTimer timer ) {
102
+ protected void compress (@ Nonnull TransformedRecordSerializerState state , @ Nullable StoreTimer timer ) {
160
103
long startTime = System .nanoTime ();
161
104
162
105
increment (timer , Counts .RECORD_BYTES_BEFORE_COMPRESSION , state .length );
@@ -209,7 +152,7 @@ private void increment(@Nullable StoreTimer timer, StoreTimer.Count counter, int
209
152
}
210
153
}
211
154
212
- protected void encrypt (@ Nonnull TransformState state , @ Nullable StoreTimer timer ) throws GeneralSecurityException {
155
+ protected void encrypt (@ Nonnull TransformedRecordSerializerState state , @ Nullable StoreTimer timer ) throws GeneralSecurityException {
213
156
throw new RecordSerializationException ("this serializer cannot encrypt" );
214
157
}
215
158
@@ -225,7 +168,7 @@ public byte[] serialize(@Nonnull RecordMetaData metaData,
225
168
@ Nullable StoreTimer timer ) {
226
169
byte [] innerSerialized = inner .serialize (metaData , recordType , rec , timer );
227
170
228
- TransformState state = new TransformState (innerSerialized );
171
+ TransformedRecordSerializerState state = new TransformedRecordSerializerState (innerSerialized );
229
172
230
173
if (compressWhenSerializing ) {
231
174
compress (state , timer );
@@ -241,32 +184,16 @@ public byte[] serialize(@Nonnull RecordMetaData metaData,
241
184
}
242
185
}
243
186
244
- int code ;
245
- if (state .compressed || state .encrypted ) {
246
- code = 0 ;
247
- if (state .compressed ) {
248
- code = code | ENCODING_COMPRESSED ;
249
- }
250
- if (state .encrypted ) {
251
- code = code | ENCODING_ENCRYPTED ;
252
- }
253
- } else {
254
- code = ENCODING_CLEAR ;
255
- }
256
-
257
- int size = state .length + 1 ;
258
- byte [] serialized = new byte [size ];
259
- serialized [0 ] = (byte ) code ;
260
- System .arraycopy (state .data , state .offset , serialized , 1 , state .length );
187
+ TransformedRecordSerializerPrefix .encodePrefix (state );
261
188
262
189
if (shouldValidateSerialization ()) {
263
- validateSerialization (metaData , recordType , rec , serialized , timer );
190
+ validateSerialization (metaData , recordType , rec , state . getDataArray () , timer );
264
191
}
265
192
266
- return serialized ;
193
+ return state . getDataArray () ;
267
194
}
268
195
269
- protected void decompress (@ Nonnull TransformState state , @ Nullable StoreTimer timer ) throws DataFormatException {
196
+ protected void decompress (@ Nonnull TransformedRecordSerializerState state , @ Nullable StoreTimer timer ) throws DataFormatException {
270
197
final long startTime = System .nanoTime ();
271
198
272
199
// At the moment, there is only one compression version, so
@@ -305,7 +232,7 @@ protected void decompress(@Nonnull TransformState state, @Nullable StoreTimer ti
305
232
}
306
233
}
307
234
308
- protected void decrypt (@ Nonnull TransformState state , @ Nullable StoreTimer timer ) throws GeneralSecurityException {
235
+ protected void decrypt (@ Nonnull TransformedRecordSerializerState state , @ Nullable StoreTimer timer ) throws GeneralSecurityException {
309
236
throw new RecordSerializationException ("this serializer cannot decrypt" );
310
237
}
311
238
@@ -316,52 +243,35 @@ public M deserialize(@Nonnull RecordMetaData metaData,
316
243
@ Nonnull Tuple primaryKey ,
317
244
@ Nonnull byte [] serialized ,
318
245
@ Nullable StoreTimer timer ) {
319
- int encoding = serialized [0 ];
320
- if (encoding != ENCODING_CLEAR && (encoding & ENCODING_PROTO_TYPE_MASK ) == ENCODING_PROTO_MESSAGE_FIELD ) {
321
- // TODO: Can remove this after transition to write everything with _CLEAR.
246
+ TransformedRecordSerializerState state = new TransformedRecordSerializerState (serialized );
247
+ if (!TransformedRecordSerializerPrefix .decodePrefix (state , primaryKey )) {
322
248
return inner .deserialize (metaData , primaryKey , serialized , timer );
323
- } else {
324
- TransformState state = new TransformState (serialized , 1 , serialized .length - 1 );
325
- if (encoding != ENCODING_CLEAR ) {
326
- if ((encoding & ENCODING_COMPRESSED ) == ENCODING_COMPRESSED ) {
327
- state .compressed = true ;
328
- }
329
- if ((encoding & ENCODING_ENCRYPTED ) == ENCODING_ENCRYPTED ) {
330
- state .encrypted = true ;
331
- }
332
- if ((encoding & ~(ENCODING_COMPRESSED | ENCODING_ENCRYPTED )) != 0 ) {
333
- throw new RecordSerializationException ("unrecognized transformation encoding" )
334
- .addLogInfo (LogMessageKeys .META_DATA_VERSION , metaData .getVersion ())
335
- .addLogInfo (LogMessageKeys .PRIMARY_KEY , primaryKey )
336
- .addLogInfo ("encoding" , encoding );
337
- }
338
- }
339
- if (state .encrypted ) {
340
- try {
341
- decrypt (state , timer );
342
- } catch (RecordCoreException ex ) {
343
- throw ex .addLogInfo (LogMessageKeys .META_DATA_VERSION , metaData .getVersion ())
344
- .addLogInfo (LogMessageKeys .PRIMARY_KEY , primaryKey );
345
- } catch (GeneralSecurityException ex ) {
346
- throw new RecordSerializationException ("decryption error" , ex )
347
- .addLogInfo (LogMessageKeys .META_DATA_VERSION , metaData .getVersion ())
348
- .addLogInfo (LogMessageKeys .PRIMARY_KEY , primaryKey );
349
- }
249
+ }
250
+ if (state .encrypted ) {
251
+ try {
252
+ decrypt (state , timer );
253
+ } catch (RecordCoreException ex ) {
254
+ throw ex .addLogInfo (LogMessageKeys .META_DATA_VERSION , metaData .getVersion ())
255
+ .addLogInfo (LogMessageKeys .PRIMARY_KEY , primaryKey );
256
+ } catch (GeneralSecurityException ex ) {
257
+ throw new RecordSerializationException ("decryption error" , ex )
258
+ .addLogInfo (LogMessageKeys .META_DATA_VERSION , metaData .getVersion ())
259
+ .addLogInfo (LogMessageKeys .PRIMARY_KEY , primaryKey );
350
260
}
351
- if ( state . compressed ) {
352
- try {
353
- decompress ( state , timer );
354
- } catch ( RecordCoreException ex ) {
355
- throw ex . addLogInfo ( LogMessageKeys . META_DATA_VERSION , metaData . getVersion ())
356
- .addLogInfo (LogMessageKeys .PRIMARY_KEY , primaryKey );
357
- } catch ( DataFormatException ex ) {
358
- throw new RecordSerializationException ( "decompression error" , ex )
359
- . addLogInfo ( LogMessageKeys . META_DATA_VERSION , metaData . getVersion () )
360
- .addLogInfo (LogMessageKeys .PRIMARY_KEY , primaryKey );
361
- }
261
+ }
262
+ if ( state . compressed ) {
263
+ try {
264
+ decompress ( state , timer );
265
+ } catch ( RecordCoreException ex ) {
266
+ throw ex .addLogInfo (LogMessageKeys .META_DATA_VERSION , metaData . getVersion ())
267
+ . addLogInfo ( LogMessageKeys . PRIMARY_KEY , primaryKey );
268
+ } catch ( DataFormatException ex ) {
269
+ throw new RecordSerializationException ( "decompression error" , ex )
270
+ .addLogInfo (LogMessageKeys .META_DATA_VERSION , metaData . getVersion ())
271
+ . addLogInfo ( LogMessageKeys . PRIMARY_KEY , primaryKey );
362
272
}
363
- return inner .deserialize (metaData , primaryKey , state .getDataArray (), timer );
364
273
}
274
+ return inner .deserialize (metaData , primaryKey , state .getDataArray (), timer );
365
275
}
366
276
367
277
@ Nonnull
0 commit comments