*/
private static final ActionRowKeyAndOp makeNewLiveCubeOp(Deserializer<?> deserializer, Collection<Result> liveCubeResults,
Collection<Result> snapshotResults, Collection<Result> backfilledResults, Context ctx)
throws IOException {
Op liveCubeOp = null;
Op snapshotOp = null;
Op backfilledOp = null;
byte[] rowKey = null;
if(!liveCubeResults.isEmpty()) {
Result result = liveCubeResults.iterator().next();
liveCubeOp = deserializer.fromBytes(result.value());
rowKey = result.getRow();
}
if(!snapshotResults.isEmpty()) {
Result result = snapshotResults.iterator().next();
snapshotOp = deserializer.fromBytes(result.value());
rowKey = result.getRow();
}
if(!backfilledResults.isEmpty()) {
Result result = backfilledResults.iterator().next();
backfilledOp = deserializer.fromBytes(result.value());
rowKey = result.getRow();
}
/*
* Merge the live cube table, the snapshot table, and the backfill table. We assume that the
* snapshot table contains the values that existing before the backfill began, which means
* that we can estimate the values that arrived since the snapshot by (live-snapshot). By
* adding the recently-arrived values to the backfilled values, we solve the problem of data
* arriving during the snapshot that might not otherwise have been counted.
*
* The following if-else statements enumerate all 8 possibilities of presence/absence of
* snapshot row, backfill row, and livecube row.
*/
// Case: snapshot exists, backfill exists, liveCube exists
// If live == snap:
// new value is backfill
// Else:
// new value is (live-snap) + backfill
if(snapshotOp != null && backfilledOp != null && liveCubeOp != null) {
DebugHack.log("HBaseBackfillMergeMapper 1");
if(liveCubeOp.equals(snapshotOp)) {
return new ActionRowKeyAndOp(Action.OVERWRITE, rowKey, backfilledOp);
}
Op newLiveCubeValue = (liveCubeOp.subtract(snapshotOp)).add(backfilledOp);
if(newLiveCubeValue.equals(liveCubeOp)) {
return new ActionRowKeyAndOp(Action.LEAVE_ALONE, rowKey, null);
} else {
return new ActionRowKeyAndOp(Action.OVERWRITE, rowKey, newLiveCubeValue);
}
}
// Case: snapshot exists, backfill empty, liveCube exists
// If live == snap:
// no ops occurred during snapshot, delete row
// Else
// New value is (live-snap)
else if(snapshotOp != null && backfilledOp == null && liveCubeOp != null) {
DebugHack.log("HBaseBackfillMergeMapper 2");
if(liveCubeOp.equals(snapshotOp)) {
DebugHack.log("HBaseBackfillMergeMapper 2.1");
return new ActionRowKeyAndOp(Action.DELETE, rowKey, null);
} else {
DebugHack.log("HBaseBackfillMergeMapper 2.2");
Op newLiveCubeValue = liveCubeOp.subtract(snapshotOp);
return new ActionRowKeyAndOp(Action.OVERWRITE, rowKey, newLiveCubeValue);
}
}
// Case: snapshot empty, backfill exists, liveCube exists
// New value is backfill + live
else if(snapshotOp == null && backfilledOp != null && liveCubeOp != null) {
DebugHack.log("HBaseBackfillMergeMapper 3");
Op newLiveCubeValue = backfilledOp.add(liveCubeOp);
return new ActionRowKeyAndOp(Action.OVERWRITE, rowKey, newLiveCubeValue);
}
// Case: snapshot empty, backfill exists, liveCube empty
// New value is backfill