Search in sources :

Example 1 with MongoException

use of com.eightkdata.mongowp.exceptions.MongoException in project torodb by torodb.

the class ContinuousOplogFetcher method fetch.

@Override
public OplogBatch fetch() throws StopReplicationException, RollbackReplicationException {
    if (state.isClosed()) {
        return FinishedOplogBatch.getInstance();
    }
    try {
        return retrier.retry(() -> {
            try {
                if (state.isClosed()) {
                    return FinishedOplogBatch.getInstance();
                }
                state.prepareToFetch();
                MongoCursor<OplogOperation> cursor = state.getLastUsedMongoCursor();
                Batch<OplogOperation> batch = cursor.tryFetchBatch();
                if (batch == null || !batch.hasNext()) {
                    Thread.sleep(1000);
                    batch = cursor.tryFetchBatch();
                    if (batch == null || !batch.hasNext()) {
                        return NotReadyForMoreOplogBatch.getInstance();
                    }
                }
                List<OplogOperation> fetchedOps = null;
                long fetchTime = 0;
                /*
           * As we already modify the cursor by fetching the batch, we cannot retry the whole block
           * (as the cursor would be reused and the previous batch will be discarted).
           *
           * Then, if we leave the following try section with an error, we need to discard the
           * cursor, so the next iteration starts from the last batch we returned. On the other
           * hand, if we finished successfully, then we need to update the state.
           */
                boolean successful = false;
                try {
                    fetchedOps = batch.asList();
                    fetchTime = batch.getFetchTime();
                    postBatchChecks(cursor, fetchedOps);
                    OplogBatch result = new NormalOplogBatch(fetchedOps, true);
                    successful = true;
                    return result;
                } finally {
                    if (!successful) {
                        cursor.close();
                    } else {
                        assert fetchedOps != null;
                        assert fetchTime != 0;
                        state.updateState(fetchedOps, fetchTime);
                    }
                }
            } catch (RestartFetchException ex) {
                //lets choose a new reader
                state.discardReader();
                //and then try again
                throw new RollbackException(ex);
            } catch (DeadCursorException ex) {
                //lets retry the whole block with the same reader
                throw new RollbackException(ex);
            } catch (StopReplicationException | RollbackReplicationException ex) {
                //do not try again
                throw new RetrierAbortException(ex);
            } catch (MongoServerException ex) {
                //TODO: Fix this violation on the abstraction!
                LOGGER.debug("Found an unwrapped MongodbServerException");
                //lets choose a new reader
                state.discardReader();
                //rollback and hopefully use another member
                throw new RollbackException(ex);
            } catch (MongoException | MongoRuntimeException ex) {
                LOGGER.warn("Catched an error while reading the remote " + "oplog: {}", ex.getLocalizedMessage());
                //lets choose a new reader
                state.discardReader();
                //rollback and hopefully use another member
                throw new RollbackException(ex);
            }
        }, Hint.CRITICAL, Hint.TIME_SENSIBLE);
    } catch (RetrierGiveUpException ex) {
        this.close();
        throw new StopReplicationException("Stopping replication after several attepts to " + "fetch the remote oplog", ex);
    } catch (RetrierAbortException ex) {
        this.close();
        Throwable cause = ex.getCause();
        if (cause != null) {
            if (cause instanceof StopReplicationException) {
                throw (StopReplicationException) cause;
            }
            if (cause instanceof RollbackReplicationException) {
                throw (RollbackReplicationException) cause;
            }
        }
        throw new StopReplicationException("Stopping replication after a unknown abort " + "exception", ex);
    }
}
Also used : DeadCursorException(com.eightkdata.mongowp.server.api.pojos.MongoCursor.DeadCursorException) MongoException(com.eightkdata.mongowp.exceptions.MongoException) MongoRuntimeException(com.eightkdata.mongowp.server.api.MongoRuntimeException) RollbackReplicationException(com.torodb.mongodb.repl.oplogreplier.RollbackReplicationException) RollbackException(com.torodb.core.transaction.RollbackException) RetrierGiveUpException(com.torodb.core.retrier.RetrierGiveUpException) NormalOplogBatch(com.torodb.mongodb.repl.oplogreplier.NormalOplogBatch) RetrierAbortException(com.torodb.core.retrier.RetrierAbortException) FinishedOplogBatch(com.torodb.mongodb.repl.oplogreplier.FinishedOplogBatch) OplogBatch(com.torodb.mongodb.repl.oplogreplier.OplogBatch) NotReadyForMoreOplogBatch(com.torodb.mongodb.repl.oplogreplier.NotReadyForMoreOplogBatch) NormalOplogBatch(com.torodb.mongodb.repl.oplogreplier.NormalOplogBatch) OplogOperation(com.eightkdata.mongowp.server.api.oplog.OplogOperation) MongoServerException(com.mongodb.MongoServerException) StopReplicationException(com.torodb.mongodb.repl.oplogreplier.StopReplicationException)

Example 2 with MongoException

use of com.eightkdata.mongowp.exceptions.MongoException in project torodb by torodb.

the class AkkaDbCloner method cloneIndex.

private void cloneIndex(MongodServer localServer, String fromDb, String dstDb, MongoConnection remoteConnection, CloneOptions opts, String fromCol, String toCol) throws CloningException {
    WriteMongodTransaction transaction = createWriteMongodTransaction(localServer);
    try {
        try {
            List<IndexOptions> indexesToClone = getIndexesToClone(Lists.newArrayList(ListIndexesRequester.getListCollections(remoteConnection, dstDb, fromCol).getFirstBatch()), dstDb, toCol, fromDb, fromCol, opts);
            if (indexesToClone.isEmpty()) {
                return;
            }
            Status<CreateIndexesResult> status = transaction.execute(new Request(dstDb, null, true, null), CreateIndexesCommand.INSTANCE, new CreateIndexesArgument(fromCol, indexesToClone));
            if (!status.isOk()) {
                throw new CloningException("Error while cloning indexes: " + status.getErrorMsg());
            }
            transaction.commit();
        } catch (UserException | MongoException ex) {
            throw new CloningException("Unexpected error while cloning indexes", ex);
        }
    } finally {
        transaction.close();
    }
}
Also used : CreateIndexesResult(com.torodb.mongodb.commands.signatures.admin.CreateIndexesCommand.CreateIndexesResult) WriteMongodTransaction(com.torodb.mongodb.core.WriteMongodTransaction) MongoException(com.eightkdata.mongowp.exceptions.MongoException) CreateIndexesArgument(com.torodb.mongodb.commands.signatures.admin.CreateIndexesCommand.CreateIndexesArgument) IndexOptions(com.torodb.mongodb.commands.pojos.index.IndexOptions) Request(com.eightkdata.mongowp.server.api.Request) UserException(com.torodb.core.exceptions.user.UserException)

Example 3 with MongoException

use of com.eightkdata.mongowp.exceptions.MongoException in project torodb by torodb.

the class TransactionalDbCloner method cloneIndex.

private void cloneIndex(String dstDb, MongoConnection remoteConnection, WriteMongodTransaction transaction, CloneOptions opts, String fromCol, CollectionOptions collOptions) throws CloningException {
    try {
        String fromDb = opts.getDbToClone();
        HostAndPort remoteAddress = remoteConnection.getClientOwner().getAddress();
        String remoteAddressString = remoteAddress != null ? remoteAddress.toString() : "local";
        LOGGER.info("copying indexes from {}.{} on {} to {}.{} on local server", fromDb, fromCol, remoteAddressString, dstDb, fromCol);
        Status<?> status;
        List<IndexOptions> indexes = Lists.newArrayList(ListIndexesRequester.getListCollections(remoteConnection, dstDb, fromCol).getFirstBatch());
        if (indexes.isEmpty()) {
            return;
        }
        status = transaction.execute(new Request(dstDb, null, true, null), CreateIndexesCommand.INSTANCE, new CreateIndexesArgument(fromCol, indexes));
        if (!status.isOk()) {
            throw new CloningException("Error while trying to fetch indexes from remote: " + status);
        }
    } catch (MongoException ex) {
        throw new CloningException("Error while trying to fetch indexes from remote", ex);
    }
}
Also used : HostAndPort(com.google.common.net.HostAndPort) MongoException(com.eightkdata.mongowp.exceptions.MongoException) CreateIndexesArgument(com.torodb.mongodb.commands.signatures.admin.CreateIndexesCommand.CreateIndexesArgument) IndexOptions(com.torodb.mongodb.commands.pojos.index.IndexOptions) Request(com.eightkdata.mongowp.server.api.Request)

Example 4 with MongoException

use of com.eightkdata.mongowp.exceptions.MongoException in project torodb by torodb.

the class TransactionalDbCloner method cloneDatabase.

/**
   *
   * @param dstDb
   * @param remoteConnection
   * @param transaction
   * @param opts
   * @throws CloningException
   * @throws NotMasterException if {@link CloneOptions#getWritePermissionSupplier()
   *                            opts.getWritePermissionSupplier().get()} is evaluated to false
   */
public void cloneDatabase(@Nonnull String dstDb, @Nonnull MongoConnection remoteConnection, @Nonnull WriteMongodTransaction transaction, @Nonnull CloneOptions opts) throws CloningException, NotMasterException, MongoException {
    if (!remoteConnection.isRemote() && opts.getDbToClone().equals(dstDb)) {
        LOGGER.warn("Trying to clone a database to itself! Ignoring it");
        return;
    }
    String fromDb = opts.getDbToClone();
    CursorResult<Entry> listCollections;
    try {
        listCollections = ListCollectionsRequester.getListCollections(remoteConnection, fromDb, null);
    } catch (MongoException ex) {
        throw new CloningException("It was impossible to get information from the remote server", ex);
    }
    if (!opts.getWritePermissionSupplier().get()) {
        throw new NotMasterException("Destiny database cannot be written");
    }
    Map<String, CollectionOptions> collsToClone = Maps.newHashMap();
    for (Iterator<Entry> iterator = listCollections.getFirstBatch(); iterator.hasNext(); ) {
        Entry collEntry = iterator.next();
        String collName = collEntry.getCollectionName();
        if (opts.getCollsToIgnore().contains(collName)) {
            LOGGER.debug("Not cloning {} because is marked as an ignored collection", collName);
            continue;
        }
        if (!NamespaceUtil.isUserWritable(fromDb, collName)) {
            LOGGER.info("Not cloning {} because is a not user writable", collName);
            continue;
        }
        if (NamespaceUtil.isNormal(fromDb, collName)) {
            LOGGER.info("Not cloning {} because it is not normal", collName);
            continue;
        }
        LOGGER.info("Collection {}.{} will be cloned", fromDb, collName);
        collsToClone.put(collName, collEntry.getCollectionOptions());
    }
    if (!opts.getWritePermissionSupplier().get()) {
        throw new NotMasterException("Destiny database cannot be written " + "after get collections info");
    }
    for (Map.Entry<String, CollectionOptions> entry : collsToClone.entrySet()) {
        dropCollection(transaction, dstDb, entry.getKey());
        createCollection(transaction, dstDb, entry.getKey(), entry.getValue());
    }
    if (opts.isCloneData()) {
        for (Map.Entry<String, CollectionOptions> entry : collsToClone.entrySet()) {
            cloneCollection(dstDb, remoteConnection, transaction, opts, entry.getKey(), entry.getValue());
        }
    }
    if (opts.isCloneIndexes()) {
        for (Map.Entry<String, CollectionOptions> entry : collsToClone.entrySet()) {
            cloneIndex(dstDb, remoteConnection, transaction, opts, entry.getKey(), entry.getValue());
        }
    }
}
Also used : Entry(com.torodb.mongodb.commands.signatures.admin.ListCollectionsCommand.ListCollectionsResult.Entry) MongoException(com.eightkdata.mongowp.exceptions.MongoException) CollectionOptions(com.torodb.mongodb.commands.pojos.CollectionOptions) NotMasterException(com.eightkdata.mongowp.exceptions.NotMasterException) Map(java.util.Map)

Example 5 with MongoException

use of com.eightkdata.mongowp.exceptions.MongoException in project torodb by torodb.

the class OplogManager method storeState.

@Locked(exclusive = true)
private void storeState(long hash, OpTime opTime) throws OplogManagerPersistException {
    Preconditions.checkState(isRunning(), "The service is not running");
    try {
        retrier.retry(() -> {
            try (WriteMongodTransaction transaction = connection.openWriteTransaction()) {
                Status<Long> deleteResult = transaction.execute(new Request(OPLOG_DB, null, true, null), DeleteCommand.INSTANCE, new DeleteArgument.Builder(OPLOG_COL).addStatement(new DeleteStatement(DOC_QUERY, false)).build());
                if (!deleteResult.isOk()) {
                    throw new RetrierAbortException(new MongoException(deleteResult));
                }
                //TODO: This should be stored as timestamp once TORODB-189 is resolved
                long optimeAsLong = opTime.toOldBson().getMillisFromUnix();
                Status<InsertResult> insertResult = transaction.execute(new Request(OPLOG_DB, null, true, null), InsertCommand.INSTANCE, new InsertArgument.Builder(OPLOG_COL).addDocument(new BsonDocumentBuilder().appendUnsafe(KEY, new BsonDocumentBuilder().appendUnsafe("hash", newLong(hash)).appendUnsafe("optime_i", DefaultBsonValues.newLong(optimeAsLong)).appendUnsafe("optime_t", newLong(opTime.getTerm())).build()).build()).build());
                if (insertResult.isOk() && insertResult.getResult().getN() != 1) {
                    throw new RetrierAbortException(new MongoException(ErrorCode.OPERATION_FAILED, "More than one element inserted"));
                }
                if (!insertResult.isOk()) {
                    throw new RetrierAbortException(new MongoException(insertResult));
                }
                transaction.commit();
                return Empty.getInstance();
            } catch (UserException ex) {
                throw new RetrierAbortException(ex);
            }
        }, Hint.INFREQUENT_ROLLBACK);
    } catch (RetrierGiveUpException ex) {
        throw new OplogManagerPersistException(ex);
    }
}
Also used : DeleteArgument(com.torodb.mongodb.commands.signatures.general.DeleteCommand.DeleteArgument) InsertResult(com.torodb.mongodb.commands.signatures.general.InsertCommand.InsertResult) WriteMongodTransaction(com.torodb.mongodb.core.WriteMongodTransaction) MongoException(com.eightkdata.mongowp.exceptions.MongoException) Request(com.eightkdata.mongowp.server.api.Request) RetrierGiveUpException(com.torodb.core.retrier.RetrierGiveUpException) DeleteStatement(com.torodb.mongodb.commands.signatures.general.DeleteCommand.DeleteStatement) BsonDocumentBuilder(com.eightkdata.mongowp.utils.BsonDocumentBuilder) RetrierAbortException(com.torodb.core.retrier.RetrierAbortException) InsertArgument(com.torodb.mongodb.commands.signatures.general.InsertCommand.InsertArgument) DefaultBsonValues.newLong(com.eightkdata.mongowp.bson.utils.DefaultBsonValues.newLong) UserException(com.torodb.core.exceptions.user.UserException) Locked(com.torodb.mongodb.annotations.Locked)

Aggregations

MongoException (com.eightkdata.mongowp.exceptions.MongoException)18 OplogOperation (com.eightkdata.mongowp.server.api.oplog.OplogOperation)6 Request (com.eightkdata.mongowp.server.api.Request)4 UserException (com.torodb.core.exceptions.user.UserException)4 RetrierAbortException (com.torodb.core.retrier.RetrierAbortException)4 RetrierGiveUpException (com.torodb.core.retrier.RetrierGiveUpException)4 RollbackException (com.torodb.core.transaction.RollbackException)4 OpTime (com.eightkdata.mongowp.OpTime)3 Status (com.eightkdata.mongowp.Status)3 BsonDocument (com.eightkdata.mongowp.bson.BsonDocument)3 MongoConnection (com.eightkdata.mongowp.client.core.MongoConnection)3 UnreachableMongoServerException (com.eightkdata.mongowp.client.core.UnreachableMongoServerException)3 BsonDocumentBuilder (com.eightkdata.mongowp.utils.BsonDocumentBuilder)3 HostAndPort (com.google.common.net.HostAndPort)3 WriteMongodTransaction (com.torodb.mongodb.core.WriteMongodTransaction)3 ErrorCode (com.eightkdata.mongowp.ErrorCode)2 DefaultBsonValues (com.eightkdata.mongowp.bson.utils.DefaultBsonValues)2 MongoClient (com.eightkdata.mongowp.client.core.MongoClient)2 NotMasterException (com.eightkdata.mongowp.exceptions.NotMasterException)2 OplogOperationUnsupported (com.eightkdata.mongowp.exceptions.OplogOperationUnsupported)2