/*
* ToroDB
* Copyright © 2014 8Kdata Technology (www.8kdata.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.torodb.mongodb.repl.oplogreplier.batch;
import com.eightkdata.mongowp.bson.BsonValue;
import com.eightkdata.mongowp.server.api.oplog.CollectionOplogOperation;
import com.eightkdata.mongowp.server.api.oplog.OplogOperation;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import com.torodb.mongodb.repl.oplogreplier.ApplierContext;
import com.torodb.mongodb.repl.oplogreplier.analyzed.AnalyzedOp;
import com.torodb.mongodb.repl.oplogreplier.analyzed.AnalyzedOpReducer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
public class CudAnalyzedOplogBatch extends AnalyzedOplogBatch {
private final List<OplogOperation> originalBatch;
private final Table<String, String, Map<BsonValue<?>, AnalyzedOp>> jobs;
public CudAnalyzedOplogBatch(List<OplogOperation> operations, ApplierContext context,
AnalyzedOpReducer analyzedOpReducer) {
this.originalBatch = operations;
jobs = HashBasedTable.create();
operations.stream()
.filter((OplogOperation op) -> {
switch (op.getType()) {
case DB_CMD: {
throw new AssertionError("cmd operations are not expected on "
+ CudAnalyzedOplogBatch.class.getSimpleName() + " but " + op
+ " was found");
}
case DB:
case NOOP: {
return false;
}
case DELETE:
case INSERT:
case UPDATE:
return true;
default: {
throw new AssertionError("Unexpected oplog operation with type "
+ op.getType());
}
}
})
.map(op -> (CollectionOplogOperation) op)
.forEach(op -> reduceToTableEntry(op, context, analyzedOpReducer));
}
public Stream<NamespaceJob> streamNamespaceJobs() {
return jobs.cellSet().stream().map(cell -> new NamespaceJob(cell.getRowKey(), cell
.getColumnKey(), cell.getValue().values()));
}
public List<OplogOperation> getOriginalBatch() {
return originalBatch;
}
@Override
public <R, A, T extends Throwable> R accept(AnalyzedOplogBatchVisitor<R, A, T> visitor, A arg)
throws T {
return visitor.visit(this, arg);
}
private void reduceToTableEntry(CollectionOplogOperation op, ApplierContext context,
AnalyzedOpReducer analyzedOpReducer) {
String database = op.getDatabase();
String collection = op.getCollection();
Map<BsonValue<?>, AnalyzedOp> byDocAnalyzedOps = jobs.get(database, collection);
if (byDocAnalyzedOps == null) {
byDocAnalyzedOps = new HashMap<>();
jobs.put(database, collection, byDocAnalyzedOps);
}
analyzedOpReducer.analyzeAndReduce(byDocAnalyzedOps, op, context);
}
}