1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.github.tonywasher.joceanus.prometheus.database;
18
19 import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
20 import io.github.tonywasher.joceanus.oceanus.logger.OceanusLogManager;
21 import io.github.tonywasher.joceanus.oceanus.logger.OceanusLogger;
22 import io.github.tonywasher.joceanus.oceanus.profile.OceanusProfile;
23 import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataSet;
24 import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataSet.PrometheusCryptographyDataType;
25 import io.github.tonywasher.joceanus.prometheus.exc.PrometheusIOException;
26 import io.github.tonywasher.joceanus.tethys.api.thread.TethysUIThreadStatusReport;
27
28 import java.sql.Connection;
29 import java.sql.DriverManager;
30 import java.sql.PreparedStatement;
31 import java.sql.SQLException;
32 import java.util.ArrayList;
33 import java.util.Iterator;
34 import java.util.List;
35 import java.util.ListIterator;
36 import java.util.Properties;
37
38
39
40
41 public abstract class PrometheusDataStore {
42
43
44
45 private static final int NUM_STEPS_PER_TABLE = 3;
46
47
48
49
50 private static final String PROPERTY_USER = "user";
51
52
53
54
55 private static final String PROPERTY_PASS = "password";
56
57
58
59
60 private static final String PROPERTY_INSTANCE = "instance";
61
62
63
64
65 private static final String PROPERTY_ENCRYPT = "encrypt";
66
67
68
69
70 private static final OceanusLogger LOGGER = OceanusLogManager.getLogger(PrometheusDataStore.class);
71
72
73
74
75 private Connection theConn;
76
77
78
79
80 private String theDatabase;
81
82
83
84
85 private final Integer theBatchSize;
86
87
88
89
90 private final PrometheusJDBCDriver theDriver;
91
92
93
94
95 private final List<PrometheusTableDataItem<?>> theTables;
96
97
98
99
100
101
102
103
104 protected PrometheusDataStore(final String pDatabase,
105 final PrometheusDBConfig pConfig) throws OceanusException {
106
107 try {
108
109 theBatchSize = pConfig.getBatchSize();
110
111
112 theDriver = pConfig.getDriver();
113
114
115 theDatabase = pDatabase;
116
117
118 final String myConnString = theDriver.getConnectionString(pDatabase, pConfig.getServer(), pConfig.getPort());
119
120
121 final Properties myProperties = new Properties();
122 final String myUser = pConfig.getUser();
123 final char[] myPass = pConfig.getPassword();
124 myProperties.setProperty(PROPERTY_USER, myUser);
125 myProperties.setProperty(PROPERTY_PASS, new String(myPass));
126
127
128 if (theDriver.useInstance()) {
129 final String myInstance = pConfig.getInstance();
130 myProperties.setProperty(PROPERTY_INSTANCE, myInstance);
131 myProperties.setProperty(PROPERTY_ENCRYPT, "false");
132 }
133
134
135 theConn = DriverManager.getConnection(myConnString, myProperties);
136
137
138 theConn.setCatalog(pDatabase);
139
140
141 theConn.setAutoCommit(false);
142
143
144 } catch (SQLException e) {
145 throw new PrometheusIOException("Failed to load driver", e);
146 }
147
148
149 theTables = new ArrayList<>();
150
151
152 for (PrometheusCryptographyDataType myType : PrometheusCryptographyDataType.values()) {
153
154 theTables.add(newTable(myType));
155 }
156 }
157
158
159
160
161
162
163
164 protected PrometheusDataStore(final PrometheusDBConfig pConfig) throws OceanusException {
165
166 try {
167
168 theBatchSize = pConfig.getBatchSize();
169
170
171 theDriver = pConfig.getDriver();
172
173
174 final String myConnString = theDriver.getConnectionString(pConfig.getServer(), pConfig.getPort());
175
176
177 final Properties myProperties = new Properties();
178 final String myUser = pConfig.getUser();
179 final char[] myPass = pConfig.getPassword();
180 myProperties.setProperty(PROPERTY_USER, myUser);
181 myProperties.setProperty(PROPERTY_PASS, new String(myPass));
182
183
184 if (theDriver.useInstance()) {
185 final String myInstance = pConfig.getInstance();
186 myProperties.setProperty(PROPERTY_INSTANCE, myInstance);
187 myProperties.setProperty(PROPERTY_ENCRYPT, "false");
188 }
189
190
191 theConn = DriverManager.getConnection(myConnString, myProperties);
192
193
194 theConn.setAutoCommit(false);
195
196
197 } catch (SQLException e) {
198 throw new PrometheusIOException("Failed to load driver", e);
199 }
200
201
202 theTables = new ArrayList<>();
203
204
205 for (PrometheusCryptographyDataType myType : PrometheusCryptographyDataType.values()) {
206
207 theTables.add(newTable(myType));
208 }
209 }
210
211
212
213
214
215
216 public String getName() {
217 return theDatabase;
218 }
219
220
221
222
223
224
225
226 void executeStatement(final String pStatement) throws OceanusException {
227
228 try (PreparedStatement myStmt = theConn.prepareStatement(pStatement)) {
229 theConn.setAutoCommit(true);
230 myStmt.execute();
231 theConn.setAutoCommit(false);
232
233 } catch (SQLException e) {
234 throw new PrometheusIOException("Failed to execute statement", e);
235 }
236 }
237
238
239
240
241
242
243
244 private PrometheusTableDataItem<?> newTable(final PrometheusCryptographyDataType pListType) {
245
246 switch (pListType) {
247 case CONTROLDATA:
248 return new PrometheusTableControlData(this);
249 case CONTROLKEY:
250 return new PrometheusTableControlKeys(this);
251 case CONTROLKEYSET:
252 return new PrometheusTableControlKeySet(this);
253 case DATAKEYSET:
254 return new PrometheusTableDataKeySet(this);
255 default:
256 throw new IllegalArgumentException(pListType.toString());
257 }
258 }
259
260
261
262
263
264
265 protected PrometheusJDBCDriver getDriver() {
266 return theDriver;
267 }
268
269
270
271
272
273
274 protected Connection getConn() {
275 return theConn;
276 }
277
278
279
280
281
282
283 protected void addTable(final PrometheusTableDataItem<?> pTable) {
284 pTable.getDefinition().resolveReferences(theTables);
285 theTables.add(pTable);
286 }
287
288
289
290
291 public void close() {
292
293 if (theConn == null) {
294 return;
295 }
296
297
298 try {
299
300 if (!theConn.getAutoCommit()) {
301 theConn.rollback();
302 }
303
304
305 for (PrometheusTableDataItem<?> myTable : theTables) {
306
307 myTable.closeStmt();
308 }
309
310
311 theConn.close();
312 theConn = null;
313
314
315 } catch (SQLException e) {
316 LOGGER.error("Failed to close database connection", e);
317 theConn = null;
318 }
319 }
320
321
322
323
324
325
326
327
328 public void loadDatabase(final TethysUIThreadStatusReport pReport,
329 final PrometheusDataSet pData) throws OceanusException {
330
331 pReport.initTask("loadDatabase");
332 pReport.setNumStages(theTables.size());
333
334
335 OceanusProfile myTask = pReport.getActiveTask();
336 myTask = myTask.startTask("loadDatabase");
337
338
339 for (PrometheusTableDataItem<?> myTable : theTables) {
340
341 myTask.startTask(myTable.getTableName());
342
343
344 myTable.loadItems(pReport, pData);
345 }
346
347
348 myTask.end();
349 }
350
351
352
353
354
355
356
357
358 public void updateDatabase(final TethysUIThreadStatusReport pReport,
359 final PrometheusDataSet pData) throws OceanusException {
360
361 final PrometheusBatchControl myBatch = new PrometheusBatchControl(theBatchSize);
362 pReport.setNumStages(NUM_STEPS_PER_TABLE * theTables.size());
363
364
365 OceanusProfile myTask = pReport.getActiveTask();
366 myTask = myTask.startTask("updateDatabase");
367
368
369 OceanusProfile myStage = myTask.startTask("insertData");
370 final Iterator<PrometheusTableDataItem<?>> myIterator = theTables.iterator();
371 while (myIterator.hasNext()) {
372 final PrometheusTableDataItem<?> myTable = myIterator.next();
373
374
375 myStage.startTask(myTable.getTableName());
376
377
378 myTable.insertItems(pReport, pData, myBatch);
379 }
380
381
382 myStage = myTask.startTask("updateData");
383 final ListIterator<PrometheusTableDataItem<?>> myListIterator = theTables.listIterator();
384 while (myListIterator.hasNext()) {
385 final PrometheusTableDataItem<?> myTable = myListIterator.next();
386
387
388 myStage.startTask(myTable.getTableName());
389
390
391 myTable.updateItems(pReport, myBatch);
392 }
393
394
395 myStage = myTask.startTask("deleteData");
396 while (myListIterator.hasPrevious()) {
397 final PrometheusTableDataItem<?> myTable = myListIterator.previous();
398
399
400 myStage.startTask(myTable.getTableName());
401
402
403 myTable.deleteItems(pReport, myBatch);
404 }
405
406
407 if (myBatch.isActive()) {
408
409 try {
410 theConn.commit();
411 } catch (SQLException e) {
412 close();
413 throw new PrometheusIOException("Failed to commit transaction", e);
414 }
415
416
417 myBatch.commitItems();
418 }
419
420
421 myTask.end();
422 }
423
424
425
426
427
428
429
430
431 public void createDatabase(final TethysUIThreadStatusReport pReport,
432 final String pDatabase) throws OceanusException {
433
434 pReport.setNumStages(2);
435
436
437 OceanusProfile myTask = pReport.getActiveTask();
438 myTask = myTask.startTask("dropDatabase");
439 executeStatement("DROP DATABASE IF EXISTS " + pDatabase);
440
441
442 myTask = myTask.startTask("createDatabase");
443 executeStatement("CREATE DATABASE " + pDatabase);
444
445
446 myTask.end();
447 }
448
449
450
451
452
453
454
455 public void createTables(final TethysUIThreadStatusReport pReport) throws OceanusException {
456
457 pReport.setNumStages(2);
458
459
460 dropTables(pReport);
461
462
463 OceanusProfile myTask = pReport.getActiveTask();
464 myTask = myTask.startTask("createTables");
465
466
467 final Iterator<PrometheusTableDataItem<?>> myIterator = theTables.iterator();
468 while (myIterator.hasNext()) {
469 final PrometheusTableDataItem<?> myTable = myIterator.next();
470
471
472 pReport.checkForCancellation();
473
474
475 myTask.startTask(myTable.getTableName());
476
477
478 myTable.createTable();
479 }
480
481
482 myTask.end();
483 }
484
485
486
487
488
489
490
491 private void dropTables(final TethysUIThreadStatusReport pReport) throws OceanusException {
492
493 OceanusProfile myTask = pReport.getActiveTask();
494 myTask = myTask.startTask("dropTables");
495
496
497 final ListIterator<PrometheusTableDataItem<?>> myIterator = theTables.listIterator(theTables.size());
498 while (myIterator.hasPrevious()) {
499 final PrometheusTableDataItem<?> myTable = myIterator.previous();
500
501
502 pReport.checkForCancellation();
503
504
505 myTask.startTask(myTable.getTableName());
506
507
508 myTable.dropTable();
509 }
510
511
512 myTask.end();
513 }
514
515
516
517
518
519
520
521 public void purgeTables(final TethysUIThreadStatusReport pReport) throws OceanusException {
522
523 pReport.setNumStages(1);
524
525
526 OceanusProfile myTask = pReport.getActiveTask();
527 myTask = myTask.startTask("purgeTables");
528
529
530 final ListIterator<PrometheusTableDataItem<?>> myIterator = theTables.listIterator(theTables.size());
531 while (myIterator.hasPrevious()) {
532 final PrometheusTableDataItem<?> myTable = myIterator.previous();
533
534
535 pReport.checkForCancellation();
536
537
538 myTask.startTask(myTable.getTableName());
539
540
541 myTable.purgeTable();
542 }
543
544
545 myTask.end();
546 }
547 }