Search in sources :

Example 1 with SharedWriteTorodTransaction

use of com.torodb.torod.SharedWriteTorodTransaction in project torodb by torodb.

the class RecoveryService method dropDatabases.

private Status<?> dropDatabases() throws RollbackException, UserException, RollbackException {
    try (TorodConnection conn = server.getTorodServer().openConnection();
        SharedWriteTorodTransaction trans = conn.openWriteTransaction(false)) {
        List<String> dbs = trans.getDatabases();
        for (String dbName : dbs) {
            if (!dbName.equals("local")) {
                trans.dropDatabase(dbName);
            }
        }
        trans.commit();
    }
    return Status.ok();
}
Also used : SharedWriteTorodTransaction(com.torodb.torod.SharedWriteTorodTransaction) TorodConnection(com.torodb.torod.TorodConnection)

Example 2 with SharedWriteTorodTransaction

use of com.torodb.torod.SharedWriteTorodTransaction in project torodb by torodb.

the class RecoveryService method initialSync.

private boolean initialSync() throws TryAgainException, FatalErrorException {
    /*
     * 1. store that data is inconsistent 2. decide a sync source 3. lastRemoteOptime1 = get the
     * last optime of the sync source 4. clone all databases except local 5. lastRemoteOptime2 = get
     * the last optime of the sync source 6. apply remote oplog from lastRemoteOptime1 to
     * lastRemoteOptime2 7. lastRemoteOptime3 = get the last optime of the sync source 8. apply
     * remote oplog from lastRemoteOptime2 to lastRemoteOptime3 9. rebuild indexes 10. store
     * lastRemoteOptime3 as the last applied operation optime 11. store that data is consistent 12.
     * change replication state to SECONDARY
     */
    //TODO: Support fastsync (used to restore a node by copying the data from other up-to-date node)
    LOGGER.info("Starting initial sync");
    callback.setConsistentState(false);
    HostAndPort syncSource;
    try {
        syncSource = syncSourceProvider.newSyncSource();
        LOGGER.info("Using node " + syncSource + " to replicate from");
    } catch (NoSyncSourceFoundException ex) {
        throw new TryAgainException("No sync source");
    }
    MongoClient remoteClient;
    try {
        remoteClient = remoteClientFactory.createClient(syncSource);
    } catch (UnreachableMongoServerException ex) {
        throw new TryAgainException(ex);
    }
    try {
        LOGGER.debug("Remote client obtained");
        MongoConnection remoteConnection = remoteClient.openConnection();
        try (OplogReader reader = oplogReaderProvider.newReader(remoteConnection)) {
            OplogOperation lastClonedOp = reader.getLastOp();
            OpTime lastRemoteOptime1 = lastClonedOp.getOpTime();
            try (WriteOplogTransaction oplogTransaction = oplogManager.createWriteTransaction()) {
                LOGGER.info("Remote database cloning started");
                oplogTransaction.truncate();
                LOGGER.info("Local databases dropping started");
                Status<?> status = dropDatabases();
                if (!status.isOk()) {
                    throw new TryAgainException("Error while trying to drop collections: " + status);
                }
                LOGGER.info("Local databases dropping finished");
                if (!isRunning()) {
                    LOGGER.warn("Recovery stopped before it can finish");
                    return false;
                }
                LOGGER.info("Remote database cloning started");
                cloneDatabases(remoteClient);
                LOGGER.info("Remote database cloning finished");
                oplogTransaction.forceNewValue(lastClonedOp.getHash(), lastClonedOp.getOpTime());
            }
            if (!isRunning()) {
                LOGGER.warn("Recovery stopped before it can finish");
                return false;
            }
            TorodServer torodServer = server.getTorodServer();
            try (TorodConnection connection = torodServer.openConnection();
                SharedWriteTorodTransaction trans = connection.openWriteTransaction(false)) {
                OpTime lastRemoteOptime2 = reader.getLastOp().getOpTime();
                LOGGER.info("First oplog application started");
                applyOplog(reader, lastRemoteOptime1, lastRemoteOptime2);
                trans.commit();
                LOGGER.info("First oplog application finished");
                if (!isRunning()) {
                    LOGGER.warn("Recovery stopped before it can finish");
                    return false;
                }
                OplogOperation lastOperation = reader.getLastOp();
                OpTime lastRemoteOptime3 = lastOperation.getOpTime();
                LOGGER.info("Second oplog application started");
                applyOplog(reader, lastRemoteOptime2, lastRemoteOptime3);
                trans.commit();
                LOGGER.info("Second oplog application finished");
                if (!isRunning()) {
                    LOGGER.warn("Recovery stopped before it can finish");
                    return false;
                }
                LOGGER.info("Index rebuild started");
                rebuildIndexes();
                trans.commit();
                LOGGER.info("Index rebuild finished");
                if (!isRunning()) {
                    LOGGER.warn("Recovery stopped before it can finish");
                    return false;
                }
                trans.commit();
            }
        } catch (OplogStartMissingException ex) {
            throw new TryAgainException(ex);
        } catch (OplogOperationUnsupported ex) {
            throw new TryAgainException(ex);
        } catch (MongoException | RollbackException ex) {
            throw new TryAgainException(ex);
        } catch (OplogManagerPersistException ex) {
            throw new FatalErrorException();
        } catch (UserException ex) {
            throw new FatalErrorException(ex);
        }
        callback.setConsistentState(true);
        LOGGER.info("Initial sync finished");
    } finally {
        remoteClient.close();
    }
    return true;
}
Also used : OplogManagerPersistException(com.torodb.mongodb.repl.OplogManager.OplogManagerPersistException) SharedWriteTorodTransaction(com.torodb.torod.SharedWriteTorodTransaction) MongoException(com.eightkdata.mongowp.exceptions.MongoException) OplogOperationUnsupported(com.eightkdata.mongowp.exceptions.OplogOperationUnsupported) UnreachableMongoServerException(com.eightkdata.mongowp.client.core.UnreachableMongoServerException) OplogStartMissingException(com.eightkdata.mongowp.exceptions.OplogStartMissingException) RollbackException(com.torodb.core.transaction.RollbackException) OpTime(com.eightkdata.mongowp.OpTime) WriteOplogTransaction(com.torodb.mongodb.repl.OplogManager.WriteOplogTransaction) HostAndPort(com.google.common.net.HostAndPort) MongoClient(com.eightkdata.mongowp.client.core.MongoClient) TorodServer(com.torodb.torod.TorodServer) UserException(com.torodb.core.exceptions.user.UserException) NoSyncSourceFoundException(com.torodb.mongodb.repl.exceptions.NoSyncSourceFoundException) OplogOperation(com.eightkdata.mongowp.server.api.oplog.OplogOperation) MongoConnection(com.eightkdata.mongowp.client.core.MongoConnection) TorodConnection(com.torodb.torod.TorodConnection)

Example 3 with SharedWriteTorodTransaction

use of com.torodb.torod.SharedWriteTorodTransaction in project torodb by torodb.

the class DropIndexesReplImpl method apply.

@Override
public Status<DropIndexesResult> apply(Request req, Command<? super DropIndexesArgument, ? super DropIndexesResult> command, DropIndexesArgument arg, SharedWriteTorodTransaction trans) {
    int indexesBefore = (int) trans.getIndexesInfo(req.getDatabase(), arg.getCollection()).count();
    List<String> indexesToDrop;
    if (!arg.isDropAllIndexes()) {
        if (!arg.isDropByKeys()) {
            if (Constants.ID_INDEX.equals(arg.getIndexToDrop())) {
                LOGGER.warn("Trying to drop index {}. Ignoring the whole request", arg.getIndexToDrop());
                return Status.ok(new DropIndexesResult(indexesBefore));
            }
            indexesToDrop = Arrays.asList(arg.getIndexToDrop());
        } else {
            indexesToDrop = trans.getIndexesInfo(req.getDatabase(), arg.getCollection()).filter(index -> indexFieldsMatchKeys(index, arg.getKeys())).map(index -> index.getName()).collect(Collectors.toList());
            if (indexesToDrop.isEmpty()) {
                LOGGER.warn("Index not found with keys [" + arg.getKeys().stream().map(key -> '"' + key.getKeys().stream().collect(Collectors.joining(".")) + "\" :" + key.getType().getName()).collect(Collectors.joining(", ")) + "]. Ignoring the whole request", arg.getIndexToDrop());
                return Status.ok(new DropIndexesResult(indexesBefore));
            }
        }
    } else {
        indexesToDrop = trans.getIndexesInfo(req.getDatabase(), arg.getCollection()).filter(indexInfo -> !Constants.ID_INDEX.equals(indexInfo.getName())).map(indexInfo -> indexInfo.getName()).collect(Collectors.toList());
    }
    for (String indexToDrop : indexesToDrop) {
        LOGGER.info("Dropping index {} on collection {}.{}", req.getDatabase(), arg.getCollection(), indexToDrop);
        boolean dropped = trans.dropIndex(req.getDatabase(), arg.getCollection(), indexToDrop);
        if (!dropped) {
            LOGGER.info("Trying to drop index {}, but it has not been " + "found. This is normal since the index could have been filtered or " + "we are reapplying oplog during a recovery. Ignoring it", indexToDrop);
        }
    }
    return Status.ok(new DropIndexesResult(indexesBefore));
}
Also used : Request(com.eightkdata.mongowp.server.api.Request) SharedWriteTorodTransaction(com.torodb.torod.SharedWriteTorodTransaction) Arrays(java.util.Arrays) AttributeReference(com.torodb.core.language.AttributeReference) Constants(com.torodb.mongodb.language.Constants) Iterator(java.util.Iterator) DropIndexesResult(com.torodb.mongodb.commands.signatures.admin.DropIndexesCommand.DropIndexesResult) Command(com.eightkdata.mongowp.server.api.Command) Collectors(java.util.stream.Collectors) IndexFieldInfo(com.torodb.torod.IndexFieldInfo) List(java.util.List) Logger(org.apache.logging.log4j.Logger) Status(com.eightkdata.mongowp.Status) KnownType(com.torodb.mongodb.commands.pojos.index.IndexOptions.KnownType) IndexInfo(com.torodb.torod.IndexInfo) IndexOptions(com.torodb.mongodb.commands.pojos.index.IndexOptions) DropIndexesArgument(com.torodb.mongodb.commands.signatures.admin.DropIndexesCommand.DropIndexesArgument) LogManager(org.apache.logging.log4j.LogManager) DropIndexesResult(com.torodb.mongodb.commands.signatures.admin.DropIndexesCommand.DropIndexesResult)

Aggregations

SharedWriteTorodTransaction (com.torodb.torod.SharedWriteTorodTransaction)3 TorodConnection (com.torodb.torod.TorodConnection)2 OpTime (com.eightkdata.mongowp.OpTime)1 Status (com.eightkdata.mongowp.Status)1 MongoClient (com.eightkdata.mongowp.client.core.MongoClient)1 MongoConnection (com.eightkdata.mongowp.client.core.MongoConnection)1 UnreachableMongoServerException (com.eightkdata.mongowp.client.core.UnreachableMongoServerException)1 MongoException (com.eightkdata.mongowp.exceptions.MongoException)1 OplogOperationUnsupported (com.eightkdata.mongowp.exceptions.OplogOperationUnsupported)1 OplogStartMissingException (com.eightkdata.mongowp.exceptions.OplogStartMissingException)1 Command (com.eightkdata.mongowp.server.api.Command)1 Request (com.eightkdata.mongowp.server.api.Request)1 OplogOperation (com.eightkdata.mongowp.server.api.oplog.OplogOperation)1 HostAndPort (com.google.common.net.HostAndPort)1 UserException (com.torodb.core.exceptions.user.UserException)1 AttributeReference (com.torodb.core.language.AttributeReference)1 RollbackException (com.torodb.core.transaction.RollbackException)1 IndexOptions (com.torodb.mongodb.commands.pojos.index.IndexOptions)1 KnownType (com.torodb.mongodb.commands.pojos.index.IndexOptions.KnownType)1 DropIndexesArgument (com.torodb.mongodb.commands.signatures.admin.DropIndexesCommand.DropIndexesArgument)1