9
9
import java .lang .reflect .Method ;
10
10
import java .math .BigInteger ;
11
11
import java .net .URI ;
12
- import java .util .Collection ;
13
- import java .util .Map ;
14
- import java .util .Random ;
15
- import java .util .Set ;
16
- import java .util .TreeMap ;
17
- import java .util .concurrent .ConcurrentHashMap ;
18
- import java .util .concurrent .ConcurrentMap ;
19
- import java .util .concurrent .ScheduledExecutorService ;
20
- import java .util .concurrent .ThreadLocalRandom ;
21
- import java .util .concurrent .TimeUnit ;
12
+ import java .util .*;
13
+ import java .util .concurrent .*;
22
14
import java .util .function .Predicate ;
23
15
import java .util .regex .Matcher ;
24
16
import java .util .regex .Pattern ;
@@ -38,8 +30,8 @@ public class DatasetManagerBusinessReflectionImpl {
38
30
private Random random = new Random ();
39
31
private Object stringCellDefinition ;
40
32
private Class <?> cellDefinitionClass ;
41
- private Object typeString ;
42
33
private Class <?> typeClass ;
34
+ private Set <String > customCells = (new ConcurrentHashMap <>()).newKeySet ();
43
35
44
36
@ Autowired
45
37
public DatasetManagerBusinessReflectionImpl (KitAwareClassLoaderDelegator kitAwareClassLoaderDelegator , ScheduledExecutorService poundingScheduler ) throws Exception {
@@ -58,11 +50,11 @@ public DatasetManagerBusinessReflectionImpl(KitAwareClassLoaderDelegator kitAwar
58
50
59
51
private void pound (Object datasetInstance , Integer intensity ) {
60
52
IntStream .range (0 , intensity ).forEach (value -> {
61
- insert (datasetInstance , Long . toString ( ThreadLocalRandom .current ().nextLong (0 , intensity * 1000 )), longString ( intensity ) );
62
- update (datasetInstance , Long . toString ( ThreadLocalRandom .current ().nextLong (0 , intensity * 1000 )), longString ( intensity ) );
63
- delete (datasetInstance , Long . toString ( ThreadLocalRandom .current ().nextLong (0 , intensity * 1000 ) ));
53
+ insert (datasetInstance , ThreadLocalRandom .current ().nextLong (0 , intensity * 1000 ), intensity );
54
+ update (datasetInstance , ThreadLocalRandom .current ().nextLong (0 , intensity * 1000 ), intensity );
55
+ delete (datasetInstance , ThreadLocalRandom .current ().nextLong (0 , intensity * 1000 ));
64
56
stream (datasetInstance );
65
- retrieve (datasetInstance , Long . toString ( ThreadLocalRandom .current ().nextLong (0 , intensity * 1000 ) ));
57
+ retrieve (datasetInstance , ThreadLocalRandom .current ().nextLong (0 , intensity * 1000 ));
66
58
});
67
59
try {
68
60
generateRandomFailure (datasetInstance );
@@ -75,10 +67,10 @@ private void generateRandomFailure(Object datasetInstance) {
75
67
int nextInt = ThreadLocalRandom .current ().nextInt (0 , 5 );
76
68
switch (nextInt ) {
77
69
case 0 :
78
- insert (datasetInstance , null , longString ( 0 ) );
70
+ insert (datasetInstance , null , 0 );
79
71
break ;
80
72
case 1 :
81
- update (datasetInstance , null , longString ( 0 ) );
73
+ update (datasetInstance , null , 0 );
82
74
break ;
83
75
case 2 :
84
76
retrieve (datasetInstance , null );
@@ -155,126 +147,214 @@ private void stream(Object datasetInstance) {
155
147
}
156
148
}
157
149
158
- private void delete (Object datasetInstance , String key ) {
150
+ private void delete (Object datasetInstance , Long key ) {
159
151
try {
160
152
Thread .currentThread ().setContextClassLoader (kitAwareClassLoaderDelegator .getUrlClassLoader ());
161
153
Object datasetWriterReader = retrieveDatasetWriterReader (datasetInstance );
162
154
Class <?> datasetWriterReaderClass = loadClass ("com.terracottatech.store.DatasetWriterReader" );
163
155
Method deleteMethod = datasetWriterReaderClass .getMethod ("delete" , Comparable .class );
164
- deleteMethod .invoke (datasetWriterReader , key );
156
+ deleteMethod .invoke (datasetWriterReader , longToKeyType ( getKeyTypeJDK ( datasetInstance ), key ) );
165
157
} catch (Exception e ) {
166
158
throw new RuntimeException (e );
167
159
}
168
160
}
169
161
170
- private void update (Object datasetInstance , String key , String value ) {
162
+ private void update (Object datasetInstance , Long key , Integer value ) {
171
163
try {
172
164
Thread .currentThread ().setContextClassLoader (kitAwareClassLoaderDelegator .getUrlClassLoader ());
173
165
Object datasetWriterReader = retrieveDatasetWriterReader (datasetInstance );
174
166
Class <?> datasetWriterReaderClass = loadClass ("com.terracottatech.store.DatasetWriterReader" );
175
167
176
168
Class <?> updateOperationClass = loadClass ("com.terracottatech.store.UpdateOperation" );
177
169
Method writeMethod = updateOperationClass .getMethod ("write" , cellDefinitionClass , Object .class );
178
- Object writeOperation = writeMethod .invoke (null , stringCellDefinition , value );
170
+ Object writeOperation = writeMethod .invoke (null , stringCellDefinition , longString ( value ) );
179
171
180
172
Method updateMethod = datasetWriterReaderClass .getMethod ("update" , Comparable .class , updateOperationClass );
181
173
182
- updateMethod .invoke (datasetWriterReader , key , writeOperation );
174
+ updateMethod .invoke (datasetWriterReader , longToKeyType ( getKeyTypeJDK ( datasetInstance ), key ) , writeOperation );
183
175
} catch (Exception e ) {
184
176
throw new RuntimeException (e );
185
177
}
186
178
}
187
179
188
- private void retrieve (Object datasetInstance , String key ) {
180
+ private void retrieve (Object datasetInstance , Long key ) {
189
181
try {
190
182
Thread .currentThread ().setContextClassLoader (kitAwareClassLoaderDelegator .getUrlClassLoader ());
191
183
Object datasetWriterReader = retrieveDatasetWriterReader (datasetInstance );
192
184
Class <?> datasetWriterReaderClass = loadClass ("com.terracottatech.store.DatasetWriterReader" );
193
185
Method getMethod = datasetWriterReaderClass .getMethod ("get" , Comparable .class );
194
- getMethod .invoke (datasetWriterReader , key );
186
+ getMethod .invoke (datasetWriterReader , longToKeyType ( getKeyTypeJDK ( datasetInstance ), key ) );
195
187
} catch (Exception e ) {
196
188
throw new RuntimeException (e );
197
189
}
198
190
}
199
191
200
192
private Object retrieveDatasetWriterReader (Object datasetInstance ) throws Exception {
201
193
Class <?> internalDatasetClass = loadClass ("com.terracottatech.store.internal.InternalDataset" );
194
+ Method writerReader = internalDatasetClass .getMethod ("writerReader" );
195
+ return writerReader .invoke (datasetInstance );
196
+ }
202
197
198
+ private Object retrieveDatasetReader (Object datasetInstance ) throws Exception {
199
+ Class <?> internalDatasetClass = loadClass ("com.terracottatech.store.internal.InternalDataset" );
200
+ Method reader = internalDatasetClass .getMethod ("reader" );
201
+ return reader .invoke (datasetInstance );
202
+ }
203
203
204
- Class <?> readVisibilityClas = loadClass ( "com.terracottatech.store.setting.ReadVisibility" );
205
- Class <?> readSettingsClass = loadClass ( "com.terracottatech.store.setting.ReadSettings" ) ;
206
-
207
- Class <?> writeVisibilityClas = loadClass ( "com.terracottatech.store.setting.WriteVisibility" );
208
- Class <?> writeSettingsClass = loadClass ( "com.terracottatech.store.setting.WriteSettings" );
209
-
210
-
211
- Field definitiveField = readVisibilityClas . getDeclaredField ( "DEFINITIVE" ) ;
212
- Object definitiveReadVisibility = definitiveField . get ( null );
213
- Method asReadSettingsMethod = readVisibilityClas . getMethod ( "asReadSettings" );
214
- Object definitiveReadVisibilityAsReadSettings = asReadSettingsMethod . invoke ( definitiveReadVisibility );
215
-
216
-
217
- Field immediateField = writeVisibilityClas . getDeclaredField ( "IMMEDIATE" );
218
- Object immediateWriteVisibility = immediateField . get ( null );
219
- Method asWriteSettingsMethod = writeVisibilityClas . getMethod ( "asWriteSettings" ) ;
220
- Object immediateWriteVisibilityAsWriteSettings = asWriteSettingsMethod . invoke ( immediateWriteVisibility );
221
-
222
- Method writerReader = internalDatasetClass . getMethod ( "writerReader" , readSettingsClass , writeSettingsClass );
204
+ private Object longToKeyType ( Class keyTypeJDK , Long internalKey ) {
205
+ Object key ;
206
+ if ( keyTypeJDK . equals ( String . class )) {
207
+ key = Long . toString ( internalKey );
208
+ } else if ( keyTypeJDK . equals ( Integer . class )) {
209
+ key = internalKey . intValue ();
210
+ } else if ( keyTypeJDK . equals ( Long . class )) {
211
+ key = internalKey ;
212
+ } else if ( keyTypeJDK . equals ( Double . class )) {
213
+ key = internalKey . doubleValue ( );
214
+ } else if ( keyTypeJDK . equals ( Boolean . class )) {
215
+ key = internalKey % 2 == 0 ;
216
+ } else if ( keyTypeJDK . equals ( Character . class )) {
217
+ key = Long . toString ( internalKey ). charAt ( 0 );
218
+ } else {
219
+ key = null ;
220
+ }
221
+ return key ;
222
+ }
223
223
224
- return writerReader .invoke (datasetInstance , definitiveReadVisibilityAsReadSettings , immediateWriteVisibilityAsWriteSettings );
224
+ private Class <?> getKeyTypeJDK (Object datasetInstance ) throws Exception {
225
+ Class <?> datasetReaderClass = loadClass ("com.terracottatech.store.DatasetReader" );
226
+ Method getKeyTypeMethod = datasetReaderClass .getMethod ("getKeyType" );
227
+ Object datasetReader = retrieveDatasetReader (datasetInstance );
228
+ Object keyType = getKeyTypeMethod .invoke (datasetReader );
229
+ Method getJDKTypeMethod = typeClass .getDeclaredMethod ("getJDKType" );
230
+ return (Class <?>) getJDKTypeMethod .invoke (keyType );
225
231
}
226
232
227
- private void insert (Object datasetInstance , String key , String value ) {
233
+ private void insert (Object datasetInstance , Long key , Integer value ) {
228
234
try {
229
235
Thread .currentThread ().setContextClassLoader (kitAwareClassLoaderDelegator .getUrlClassLoader ());
230
236
Object datasetWriterReader = retrieveDatasetWriterReader (datasetInstance );
231
-
232
237
Class <?> datasetWriterReaderClass = loadClass ("com.terracottatech.store.DatasetWriterReader" );
233
238
234
239
Class <?> cellClass = loadClass ("com.terracottatech.store.Cell" );
235
240
Class cellClasses = Array .newInstance (cellClass , 0 ).getClass ();
236
241
Method addMethod = datasetWriterReaderClass .getMethod ("add" , Comparable .class , cellClasses );
237
242
238
- Object [] cells ;
239
- if (key == null || Long . parseLong ( key ) % 2 == 0 ) {
240
- cells = generateOneCell (value , cellClass );
243
+ Object [] generatedCells ;
244
+ if (key == null || key % 2 == 0 ) {
245
+ generatedCells = generateOneCell (value , cellClass );
241
246
} else {
242
- cells = generateTwoCells (value , cellClass );
247
+ generatedCells = generateTwoCells (value , cellClass );
243
248
}
244
-
245
- addMethod .invoke (datasetWriterReader , key , cells );
246
-
249
+ Object [] customCells = generateCustomCells (value );
250
+ Object [] cells = (Object []) Array .newInstance (cellClass , generatedCells .length + customCells .length );
251
+ int i = 0 ;
252
+ for (Object c : generatedCells ) {
253
+ cells [i ++] = c ;
254
+ }
255
+ for (Object c : customCells ) {
256
+ cells [i ++] = c ;
257
+ }
258
+ addMethod .invoke (datasetWriterReader , longToKeyType (getKeyTypeJDK (datasetInstance ), key ), cells );
247
259
} catch (Exception e ) {
248
260
throw new RuntimeException (e );
249
261
}
250
262
}
251
263
252
- private Object [] generateTwoCells (String value , Class <?> cellClass ) throws Exception {
264
+ private Object [] generateTwoCells (Integer value , Class <?> cellClass ) throws Exception {
265
+ String valueStr = longString (value );
253
266
Method newCellMethod = cellDefinitionClass .getMethod ("newCell" , Object .class );
254
- Object stringCellValue = newCellMethod .invoke (stringCellDefinition , value );
267
+ Object stringCellValue = newCellMethod .invoke (stringCellDefinition , valueStr );
255
268
256
269
Method defineBytesMethod = cellDefinitionClass .getMethod ("defineBytes" , String .class );
257
270
Object bytesCellDefinition = defineBytesMethod .invoke (null , "myBytesCell" );
258
- Object bytesCellValue = newCellMethod .invoke (bytesCellDefinition , value .getBytes ());
271
+ Object bytesCellValue = newCellMethod .invoke (bytesCellDefinition , valueStr .getBytes ());
259
272
260
273
Object [] cells = (Object []) Array .newInstance (cellClass , 2 );
261
274
cells [0 ] = stringCellValue ;
262
275
cells [1 ] = bytesCellValue ;
263
276
return cells ;
264
277
}
265
278
266
- private Object [] generateOneCell (String value , Class <?> cellClass ) throws Exception {
279
+ private Object [] generateOneCell (Integer value , Class <?> cellClass ) throws Exception {
280
+ String valueStr = longString (value );
267
281
Class <?> cellDefinitionClass = loadClass ("com.terracottatech.store.definition.CellDefinition" );
268
282
Method newCellMethod = cellDefinitionClass .getMethod ("newCell" , Object .class );
269
283
Method defineBytesMethod = cellDefinitionClass .getMethod ("defineBytes" , String .class );
270
284
Object bytesCellDefinition = defineBytesMethod .invoke (null , "myBytesCell" );
271
- Object bytesCellValue = newCellMethod .invoke (bytesCellDefinition , value .getBytes ());
285
+ Object bytesCellValue = newCellMethod .invoke (bytesCellDefinition , valueStr .getBytes ());
272
286
273
287
Object [] cells = (Object []) Array .newInstance (cellClass , 1 );
274
288
cells [0 ] = bytesCellValue ;
275
289
return cells ;
276
290
}
277
291
292
+ private Object [] generateCustomCells (Integer value ) throws Exception {
293
+ String valueStr = longString (value );
294
+ Method newCellMethod = cellDefinitionClass .getMethod ("newCell" , Object .class );
295
+ List <Object > cells = new ArrayList <>();
296
+ for (String customCellStr : customCells ) {
297
+ String [] splitted = customCellStr .split (":" );
298
+ String cellName = splitted [0 ];
299
+ String cellType = splitted [1 ];
300
+ switch (cellType ) {
301
+ case "STRING" :
302
+ Object stringCellDefinition = cellDefinitionClass
303
+ .getMethod ("defineString" , String .class ).invoke (null , cellName );
304
+ cells .add (newCellMethod .invoke (stringCellDefinition , valueStr ));
305
+ break ;
306
+ case "INT" :
307
+ Object intCellDefinition = cellDefinitionClass
308
+ .getMethod ("defineInt" , String .class ).invoke (null , cellName );
309
+ cells .add (newCellMethod .invoke (intCellDefinition , ThreadLocalRandom .current ().nextInt (0 , value * 1000 )));
310
+ break ;
311
+ case "LONG" :
312
+ Object longCellDefinition = cellDefinitionClass
313
+ .getMethod ("defineLong" , String .class ).invoke (null , cellName );
314
+ cells .add (newCellMethod .invoke (longCellDefinition , ThreadLocalRandom .current ().nextLong (0 , value * 1000 )));
315
+ break ;
316
+ case "DOUBLE" :
317
+ Object doubleCellDefinition = cellDefinitionClass
318
+ .getMethod ("defineDouble" , String .class ).invoke (null , cellName );
319
+ cells .add (newCellMethod .invoke (doubleCellDefinition , ThreadLocalRandom .current ().nextDouble (0 , value * 1000 )));
320
+ break ;
321
+ case "BOOL" :
322
+ Object boolCellDefinition = cellDefinitionClass
323
+ .getMethod ("defineBool" , String .class ).invoke (null , cellName );
324
+ cells .add (newCellMethod .invoke (boolCellDefinition , ThreadLocalRandom .current ().nextInt (0 , value * 1000 ) % 2 == 0 ));
325
+ break ;
326
+ case "CHAR" :
327
+ Object charCellDefinition = cellDefinitionClass
328
+ .getMethod ("defineChar" , String .class ).invoke (null , cellName );
329
+ cells .add (newCellMethod .invoke (charCellDefinition , valueStr .charAt (0 )));
330
+ break ;
331
+ case "BYTES" :
332
+ Object bytesCellDefinition = cellDefinitionClass
333
+ .getMethod ("defineBytes" , String .class ).invoke (null , cellName );
334
+ cells .add (newCellMethod .invoke (bytesCellDefinition , valueStr .getBytes ()));
335
+ break ;
336
+ default :
337
+ throw new RuntimeException ("Cannot recognize cell type: " + cellType );
338
+ }
339
+ }
340
+ return cells .toArray ();
341
+ }
342
+
343
+ public void addCustomCell (String cellStr ) {
344
+ String [] splitted = cellStr .split (":" );
345
+ if (splitted .length == 2 ) {
346
+ String cellType = splitted [1 ];
347
+ Set <String > TYPES = new HashSet <>(Arrays .asList ("STRING" , "INT" , "LONG" , "DOUBLE" , "BOOL" , "CHAR" , "BYTES" ));
348
+ if (TYPES .contains (cellType )) {
349
+ customCells .add (cellStr );
350
+ }
351
+ }
352
+ }
353
+
354
+ public void removeCustomCell (String cellStr ) {
355
+ customCells .remove (cellStr );
356
+ }
357
+
278
358
private String longString (Integer intensity ) {
279
359
return new BigInteger (intensity * 10 , random ).toString (16 );
280
360
}
@@ -334,8 +414,6 @@ public void initializeDatasetManager(String terracottaServerUrl) {
334
414
335
415
private void initCommonObjectsAndClasses () throws Exception {
336
416
typeClass = loadClass ("com.terracottatech.store.Type" );
337
- Field typeStringField = typeClass .getDeclaredField ("STRING" );
338
- typeString = typeStringField .get (null );
339
417
340
418
cellDefinitionClass = loadClass ("com.terracottatech.store.definition.CellDefinition" );
341
419
Method defineStringMethod = cellDefinitionClass .getMethod ("defineString" , String .class );
@@ -403,7 +481,7 @@ public void createDataset(String datasetName, DatasetConfiguration datasetConfig
403
481
Object datasetConfigurationBuilt = buildMethod .invoke (datasetConfigurationBuilder );
404
482
405
483
Method createDatasetMethod = datasetManagerClass .getMethod ("createDataset" , String .class , typeClass , datasetConfigurationClass );
406
- Object datasetInstance = createDatasetMethod .invoke (datasetManager , datasetName , typeString , datasetConfigurationBuilt );
484
+ Object datasetInstance = createDatasetMethod .invoke (datasetManager , datasetName , toKeyType ( datasetConfiguration . getKeyType ()) , datasetConfigurationBuilt );
407
485
408
486
String instanceName = getInstanceName (datasetInstance );
409
487
Map <String , Object > instancesByName = new TreeMap <>();
@@ -414,6 +492,10 @@ public void createDataset(String datasetName, DatasetConfiguration datasetConfig
414
492
}
415
493
}
416
494
495
+ private Object toKeyType (String keyTypeStr ) throws ClassNotFoundException , NoSuchFieldException , IllegalAccessException {
496
+ return loadClass ("com.terracottatech.store.Type" ).getDeclaredField (keyTypeStr ).get (null );
497
+ }
498
+
417
499
private String getInstanceName (Object datasetInstance ) throws ClassNotFoundException , NoSuchMethodException , IllegalAccessException , InvocationTargetException {
418
500
Class <?> manageableDatasetClass = loadClass ("com.terracottatech.store.internal.InternalDataset" );
419
501
Method getStatisticsMethod = manageableDatasetClass .getMethod ("getStatistics" );
@@ -478,9 +560,10 @@ public void closeDatasetInstance(String datasetName, String instanceName) {
478
560
public String createDatasetInstance (String datasetName ) {
479
561
try {
480
562
Thread .currentThread ().setContextClassLoader (kitAwareClassLoaderDelegator .getUrlClassLoader ());
481
-
563
+ Method listDatasetsMethod = datasetManagerClass .getMethod ("listDatasets" );
564
+ Map <String , Object > datasetsByName = (Map <String , Object >) listDatasetsMethod .invoke (datasetManager );
482
565
Method getDatasetMethod = datasetManagerClass .getMethod ("getDataset" , String .class , typeClass );
483
- Object datasetInstance = getDatasetMethod .invoke (datasetManager , datasetName , typeString );
566
+ Object datasetInstance = getDatasetMethod .invoke (datasetManager , datasetName , datasetsByName . get ( datasetName ) );
484
567
String instanceName = getInstanceName (datasetInstance );
485
568
486
569
datasetInstancesByDatasetName .computeIfAbsent (datasetName , k -> new TreeMap <>());
0 commit comments