1
1
package datastax .cdm .job ;
2
2
3
3
import com .datastax .oss .driver .api .core .CqlSession ;
4
+ import com .datastax .oss .driver .api .core .cql .BoundStatement ;
4
5
import com .datastax .oss .driver .api .core .cql .Row ;
6
+ import com .datastax .oss .driver .api .core .data .UdtValue ;
5
7
import datastax .cdm .data .EnhancedPK ;
6
8
import datastax .cdm .data .PKFactory ;
7
9
import datastax .cdm .data .Record ;
15
17
import java .util .ArrayList ;
16
18
import java .util .List ;
17
19
import java .util .concurrent .atomic .AtomicLong ;
20
+ import java .util .stream .IntStream ;
18
21
19
22
public class CopyPKJobSession extends AbstractJobSession {
20
23
@@ -25,6 +28,14 @@ public class CopyPKJobSession extends AbstractJobSession {
25
28
protected AtomicLong skipCounter = new AtomicLong (0 );
26
29
protected AtomicLong writeCounter = new AtomicLong (0 );
27
30
31
+ private AtomicLong correctedMissingCounter = new AtomicLong (0 );
32
+ private AtomicLong correctedMismatchCounter = new AtomicLong (0 );
33
+ private AtomicLong validCounter = new AtomicLong (0 );
34
+ private AtomicLong mismatchCounter = new AtomicLong (0 );
35
+ private AtomicLong skippedCounter = new AtomicLong (0 );
36
+ private AtomicLong failedRowCounter = new AtomicLong (0 );
37
+
38
+
28
39
private final PKFactory pkFactory ;
29
40
private final List <MigrateDataType > originPKTypes ;
30
41
private final boolean isCounterTable ;
@@ -112,5 +123,136 @@ private EnhancedPK toEnhancedPK(String rowString) {
112
123
}
113
124
return pkFactory .toEnhancedPK (values , pkFactory .getPKTypes (PKFactory .Side .ORIGIN ));
114
125
}
126
+ /*
127
+ // FR: THIS ENTIRE THING NEEDS TO BE MOVED FROM HERE TO DIFFJOBSESSION CLASS
128
+ @SuppressWarnings("unchecked")
129
+ public void getRowAndDiff(List<SplitPartitions.PKRows> rowsList) {
130
+ for (SplitPartitions.PKRows rows : rowsList) {
131
+ rows.pkRows.parallelStream().forEach(row -> {
132
+ readCounter.incrementAndGet();
133
+ EnhancedPK pk = toEnhancedPK(row);
134
+ if (null == pk || pk.isError()) {
135
+ missingCounter.incrementAndGet();
136
+ logger.error("Could not build PK object with value <{}>; error is: {}", row, (null == pk ? "null" : pk.getMessages()));
137
+ return;
138
+ }
139
+ int maxAttempts = maxRetriesRowFailure;
140
+ Row sourceRow = null;
141
+ int diffAttempt = 0;
142
+ for (int retryCount = 1; retryCount <= maxAttempts; retryCount++) {
143
+ try {
144
+ sourceRow = originSelectByPKStatement.getRecord(pk).getOriginRow();
145
+ if (sourceRow != null) {
146
+ Row astraRow = cqlHelper.getTargetSelectByPKStatement().getRecord(pk).getTargetRow();
147
+ diffAttempt++;
148
+ diff(sourceRow, astraRow, diffAttempt);
149
+ } else {
150
+ logger.error("Could not find row with primary-key: {} on source", row);
151
+ }
152
+ retryCount = maxAttempts;
153
+ } catch (Exception e) {
154
+ logger.error("Could not find row with primary-key: {} retry# {}", row, retryCount, e);
155
+ if (retryCount == maxAttempts) {
156
+ logFailedRecordInFile(sourceRow);
157
+ }
158
+ }
159
+ }
160
+ });
161
+ }
162
+ printValidationCounts(true);
163
+ }
164
+
165
+ private void diff(Row sourceRow, Row astraRow, int diffAttempt) {
166
+ if (astraRow == null) {
167
+ if (diffAttempt == 1) {
168
+ missingCounter.incrementAndGet();
169
+ logger.info("Missing target row found for key: {}", getKey(sourceRow));
170
+ }
171
+ targetSession.execute(bindInsert(targetInsertStatement, sourceRow, null));
172
+ correctedMissingCounter.incrementAndGet();
173
+ logger.info("Inserted missing row in target: {}", getKey(sourceRow));
174
+ } else {
175
+ String diffData = isDifferent(sourceRow, astraRow);
176
+ if (!diffData.isEmpty()) {
177
+ if (diffAttempt == 1) {
178
+ mismatchCounter.incrementAndGet();
179
+ logger.info("Mismatch row found for key: {} Mismatch: {}", getKey(sourceRow), diffData);
180
+ }
181
+
182
+ Record record = new Record(pkFactory.getTargetPK(sourceRow), astraRow, null);
183
+ if (isCounterTable) cqlHelper.getTargetUpdateStatement().putRecord(record);
184
+ else cqlHelper.getTargetInsertStatement().putRecord(record);
185
+ correctedMismatchCounter.incrementAndGet();
186
+ logger.info("Updated mismatch row in target: {}", getKey(sourceRow));
187
+ } else {
188
+ validCounter.incrementAndGet();
189
+ }
190
+ }
191
+ }
192
+
193
+ private String isDifferent(Row sourceRow, Row astraRow) {
194
+ StringBuffer diffData = new StringBuffer();
195
+ IntStream.range(0, selectColTypes.size()).parallel().forEach(index -> {
196
+ MigrateDataType dataType = selectColTypes.get(index);
197
+ Object source = getData(dataType, index, sourceRow);
198
+ Object astra = getData(dataType, index, astraRow);
199
+
200
+ boolean isDiff = dataType.diff(source, astra);
201
+ if (isDiff) {
202
+ if (dataType.typeClass.equals(UdtValue.class)) {
203
+ String sourceUdtContent = ((UdtValue) source).getFormattedContents();
204
+ String astraUdtContent = ((UdtValue) astra).getFormattedContents();
205
+ if (!sourceUdtContent.equals(astraUdtContent)) {
206
+ diffData.append("(Index: " + index + " Origin: " + sourceUdtContent + " Target: "
207
+ + astraUdtContent + ") ");
208
+ }
209
+ } else {
210
+ diffData.append("(Index: " + index + " Origin: " + source + " Target: " + astra + ") ");
211
+ }
212
+ }
213
+ });
214
+
215
+ return diffData.toString();
216
+ }
115
217
218
+ private void logFailedRecordInFile(Row sourceRow) {
219
+ try {
220
+ failedRowCounter.getAndIncrement();
221
+ Util.FileAppend(rowExceptionDir, exceptionFileName, getKey(sourceRow));
222
+ logger.error("Failed to validate row: {} after {} retry.", getKey(sourceRow));
223
+ } catch (Exception exp) {
224
+ logger.error("Error occurred while writing to key {} to file ", getKey(sourceRow), exp);
225
+ }
226
+ }
227
+ */
228
+ public void printValidationCounts (boolean isFinal ) {
229
+ String msg = "ThreadID: " + Thread .currentThread ().getId ();
230
+ if (isFinal ) {
231
+ logger .info (
232
+ "################################################################################################" );
233
+
234
+ logger .info ("ThreadID: {} Read Record Count: {}" , Thread .currentThread ().getId (), readCounter .get ());
235
+ logger .info ("{} Mismatch Record Count: {}" , msg , mismatchCounter .get ());
236
+ logger .info ("{} Corrected Mismatch Record Count: {}" , msg , correctedMismatchCounter .get ());
237
+ logger .info ("ThreadID: {} Missing Record Count: {}" , Thread .currentThread ().getId (), missingCounter .get ());
238
+ logger .info ("{} Corrected Missing Record Count: {}" , msg , correctedMissingCounter .get ());
239
+ logger .info ("{} Skipped Record Count: {}" , msg , skippedCounter .get ());
240
+ logger .info ("{} Failed row Count: {}" , msg , failedRowCounter .get ());
241
+ logger .info ("{} Valid Record Count: {}" , msg , validCounter .get ());
242
+ }
243
+
244
+ logger .debug ("ThreadID: {} Read Record Count: {}" , Thread .currentThread ().getId (), readCounter .get ());
245
+ logger .debug ("{} Mismatch Record Count: {}" , msg , mismatchCounter .get ());
246
+ logger .debug ("{} Corrected Mismatch Record Count: {}" , msg , correctedMismatchCounter .get ());
247
+ logger .debug ("ThreadID: {} Missing Record Count: {}" , Thread .currentThread ().getId (), missingCounter .get ());
248
+ logger .debug ("{} Corrected Missing Record Count: {}" , msg , correctedMissingCounter .get ());
249
+ logger .debug ("{} Skipped Record Count: {}" , msg , skippedCounter .get ());
250
+ logger .debug ("{} Failed row Count: {}" , msg , failedRowCounter .get ());
251
+ logger .info ("{} Valid Record Count: {}" , msg , validCounter .get ());
252
+
253
+ if (isFinal ) {
254
+ logger .info (
255
+ "################################################################################################" );
256
+ }
257
+ }
116
258
}
0 commit comments