/*
* 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.analyzed;
import com.eightkdata.mongowp.server.api.oplog.CollectionOplogOperation;
import com.eightkdata.mongowp.server.api.oplog.UpdateOplogOperation;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
public enum AnalyzedOpType {
NOOP(false, false, false) {
@Override
protected AnalyzedOpType andThenInsert() {
return DELETE_CREATE;
}
@Override
protected AnalyzedOpType andThenUpdateMod() {
return UPDATE_MOD;
}
@Override
protected AnalyzedOpType andThenUpdateSet() {
return UPDATE_SET;
}
@Override
protected AnalyzedOpType andThenUpsertMod() {
return UPSERT_MOD;
}
@Override
protected AnalyzedOpType andThenUpsertSet() {
return DELETE_CREATE;
}
@Override
protected AnalyzedOpType andThenDelete() {
return DELETE;
}
},
DELETE_CREATE(false, false, true) {
@Override
protected AnalyzedOpType andThenInsert() {
return DELETE_CREATE;
}
@Override
protected AnalyzedOpType andThenUpdateMod() {
return DELETE_CREATE;
}
@Override
protected AnalyzedOpType andThenUpdateSet() {
return DELETE_CREATE;
}
@Override
protected AnalyzedOpType andThenUpsertMod() {
return DELETE_CREATE;
}
@Override
protected AnalyzedOpType andThenUpsertSet() {
return DELETE_CREATE;
}
@Override
protected AnalyzedOpType andThenDelete() {
return DELETE;
}
},
UPDATE_MOD(true, true, true) {
@Override
protected AnalyzedOpType andThenInsert() {
return UPDATE_SET;
}
@Override
protected AnalyzedOpType andThenUpdateMod() {
return UPDATE_MOD;
}
@Override
protected AnalyzedOpType andThenUpdateSet() {
return UPDATE_SET;
}
@Override
protected AnalyzedOpType andThenUpsertMod() {
return UPDATE_MOD;
}
@Override
protected AnalyzedOpType andThenUpsertSet() {
return UPDATE_SET;
}
@Override
protected AnalyzedOpType andThenDelete() {
return UPDATE_DELETE;
}
},
UPDATE_SET(true, false, true) {
@Override
protected AnalyzedOpType andThenInsert() {
return UPDATE_SET;
}
@Override
protected AnalyzedOpType andThenUpdateMod() {
return UPDATE_SET;
}
@Override
protected AnalyzedOpType andThenUpdateSet() {
return UPDATE_SET;
}
@Override
protected AnalyzedOpType andThenUpsertMod() {
return UPDATE_SET;
}
@Override
protected AnalyzedOpType andThenUpsertSet() {
return UPDATE_SET;
}
@Override
protected AnalyzedOpType andThenDelete() {
return UPDATE_DELETE;
}
},
UPSERT_MOD(false, true, true) {
@Override
protected AnalyzedOpType andThenInsert() {
return DELETE_CREATE;
}
@Override
protected AnalyzedOpType andThenUpdateMod() {
return UPDATE_MOD;
}
@Override
protected AnalyzedOpType andThenUpdateSet() {
return DELETE_CREATE;
}
@Override
protected AnalyzedOpType andThenUpsertMod() {
return UPSERT_MOD;
}
@Override
protected AnalyzedOpType andThenUpsertSet() {
return DELETE_CREATE;
}
@Override
protected AnalyzedOpType andThenDelete() {
return DELETE;
}
},
DELETE(false, false, true) {
@Override
protected AnalyzedOpType andThenInsert() {
return DELETE_CREATE;
}
@Override
protected AnalyzedOpType andThenUpdateMod() {
return ERROR;
}
@Override
protected AnalyzedOpType andThenUpdateSet() {
return ERROR;
}
@Override
protected AnalyzedOpType andThenUpsertMod() {
return DELETE_CREATE;
}
@Override
protected AnalyzedOpType andThenUpsertSet() {
return DELETE_CREATE;
}
@Override
protected AnalyzedOpType andThenDelete() {
return DELETE;
}
},
UPDATE_DELETE(true, false, true) {
@Override
protected AnalyzedOpType andThenInsert() {
return UPDATE_SET;
}
@Override
protected AnalyzedOpType andThenUpdateMod() {
return ERROR;
}
@Override
protected AnalyzedOpType andThenUpdateSet() {
return ERROR;
}
@Override
protected AnalyzedOpType andThenUpsertMod() {
return UPDATE_SET;
}
@Override
protected AnalyzedOpType andThenUpsertSet() {
return UPDATE_SET;
}
@Override
protected AnalyzedOpType andThenDelete() {
return UPDATE_DELETE;
}
},
ERROR(true, false, true) {
@Override
protected AnalyzedOpType andThenInsert() {
return ERROR;
}
@Override
protected AnalyzedOpType andThenUpdateMod() {
return ERROR;
}
@Override
protected AnalyzedOpType andThenUpdateSet() {
return ERROR;
}
@Override
protected AnalyzedOpType andThenUpsertMod() {
return ERROR;
}
@Override
protected AnalyzedOpType andThenUpsertSet() {
return ERROR;
}
@Override
protected AnalyzedOpType andThenDelete() {
return ERROR;
}
};
private final boolean requiresMatch;
private final boolean requiresFetch;
private final boolean deletes;
private AnalyzedOpType(boolean requiresMatch, boolean requiresFetch, boolean deletes) {
this.requiresMatch = requiresMatch;
this.requiresFetch = requiresFetch;
this.deletes = deletes;
}
public boolean requiresToFetchToroId() {
return requiresMatch || requiresFetch || deletes;
}
public boolean requiresMatch() {
return requiresMatch;
}
public boolean requiresFetch() {
return requiresFetch;
}
public boolean deletes() {
return deletes;
}
@SuppressFBWarnings(value = {"BC_UNCONFIRMED_CAST"},
justification = "Cast is ligthly enforced by class implementation. We ignore this but maybe "
+ "visitor pattern should be used to prevent errors")
public AnalyzedOpType andThen(CollectionOplogOperation colOp) {
switch (colOp.getType()) {
case DELETE:
return andThenDelete();
case INSERT:
return andThenInsert();
case UPDATE: {
UpdateOplogOperation updateOp = (UpdateOplogOperation) colOp;
if (updateOp.isUpsert()) {
if (UpdateActionsTool.isSetModification(updateOp)) {
return andThenUpsertSet();
} else {
return andThenUpsertMod();
}
} else {
if (UpdateActionsTool.isSetModification(updateOp)) {
return andThenUpdateSet();
} else {
return andThenUpdateMod();
}
}
}
default: {
throw new AssertionError("Unexpected oplog operation type on a collection oplog op: "
+ colOp.getType());
}
}
}
protected abstract AnalyzedOpType andThenInsert();
protected abstract AnalyzedOpType andThenUpdateMod();
protected abstract AnalyzedOpType andThenUpdateSet();
protected abstract AnalyzedOpType andThenUpsertMod();
protected abstract AnalyzedOpType andThenUpsertSet();
protected abstract AnalyzedOpType andThenDelete();
}