use of com.torodb.core.transaction.RollbackException in project torodb by torodb.
the class ReplSyncApplier method runProtected.
@Override
protected void runProtected() {
runThread = Thread.currentThread();
/*
* TODO: In general, the replication context can be set as not reaplying. But it is not frequent
* but possible to stop the replication after some oplog ops have been apply but not marked as
* executed on the oplog manager. For that reason, all oplog ops betwen the last operation that
* have been marked as applyed and the current last operation on the remote oplog must be
* executed as replying operations. As it is not possible to do that yet, we have to always
* apply operations as replying to be safe.
*/
ApplierContext applierContext = new ApplierContext.Builder().setReapplying(true).setUpdatesAsUpserts(true).build();
while (isRunning()) {
OplogOperation lastOperation = null;
ExclusiveWriteMongodTransaction trans = connection.openExclusiveWriteTransaction();
try (ExclusiveWriteMongodTransaction transaction = trans) {
try {
for (OplogOperation opToApply : callback.takeOps()) {
lastOperation = opToApply;
LOGGER.trace("Executing {}", opToApply);
try {
boolean done = false;
while (!done) {
try {
oplogOpApplier.apply(opToApply, transaction, applierContext);
transaction.commit();
done = true;
} catch (RollbackException ex) {
LOGGER.debug("Recived a rollback exception while applying an oplog op", ex);
}
}
} catch (OplogApplyingException ex) {
if (!callback.failedToApply(opToApply, ex)) {
LOGGER.error(serviceName() + " stopped because one operation " + "cannot be executed", ex);
break;
}
} catch (UserException ex) {
if (callback.failedToApply(opToApply, ex)) {
LOGGER.error(serviceName() + " stopped because one operation " + "cannot be executed", ex);
break;
}
} catch (Throwable ex) {
if (callback.failedToApply(opToApply, ex)) {
LOGGER.error(serviceName() + " stopped because " + "an unknown error", ex);
break;
}
}
callback.markAsApplied(opToApply);
}
} catch (InterruptedException ex) {
LOGGER.debug("Interrupted applier thread while applying an operator");
}
}
if (lastOperation != null) {
try (WriteOplogTransaction oplogTransaction = oplogManager.createWriteTransaction()) {
oplogTransaction.addOperation(lastOperation);
} catch (OplogManagerPersistException ex) {
if (callback.failedToApply(lastOperation, ex)) {
LOGGER.error(serviceName() + " stopped because " + "the last applied operation couldn't " + "be persisted", ex);
break;
}
}
}
}
}
use of com.torodb.core.transaction.RollbackException in project torodb by torodb.
the class SimpleAnalyzedOplogBatchExecutor method visit.
@Override
public OplogOperation visit(CudAnalyzedOplogBatch batch, ApplierContext arg) throws RetrierGiveUpException {
metrics.getCudBatchSize().update(batch.getOriginalBatch().size());
try (Context context = metrics.getCudBatchTimer().time()) {
try {
execute(batch, arg);
} catch (UserException | NamespaceJobExecutionException ex) {
throw new RetrierGiveUpException("Unexpected exception while replying", ex);
} catch (RollbackException ex) {
ApplierContext retryingReplingContext = new ApplierContext.Builder().setReapplying(true).setUpdatesAsUpserts(true).build();
retrier.retry(() -> {
try {
execute(batch, retryingReplingContext);
return Empty.getInstance();
} catch (UserException | NamespaceJobExecutionException ex2) {
throw new RetrierAbortException("Unexpected user exception while applying " + "the batch " + batch, ex2);
}
}, Hint.CRITICAL, Hint.TIME_SENSIBLE);
}
}
List<OplogOperation> originalBatch = batch.getOriginalBatch();
return originalBatch.get(originalBatch.size() - 1);
}
use of com.torodb.core.transaction.RollbackException in project torodb by torodb.
the class AkkaDbCloner method cloneDatabase.
@Override
public void cloneDatabase(String dstDb, MongoClient remoteClient, MongodServer localServer, CloneOptions opts) throws CloningException, NotMasterException, MongoException {
Preconditions.checkState(isRunning(), "This db cloner is not running");
if (!remoteClient.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 (MongoConnection remoteConnection = remoteClient.openConnection()) {
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");
}
List<Entry> collsToClone = getCollsToClone(listCollections, fromDb, opts);
if (!opts.getWritePermissionSupplier().get()) {
throw new NotMasterException("Destiny database cannot be written " + "after get collections info");
}
try {
for (Entry entry : collsToClone) {
prepareCollection(localServer, dstDb, entry);
}
} catch (RollbackException ex) {
throw new AssertionError("Unexpected rollback exception", ex);
}
Materializer materializer = ActorMaterializer.create(getActorSystem());
try (MongoConnection remoteConnection = remoteClient.openConnection()) {
if (opts.isCloneData()) {
for (Entry entry : collsToClone) {
LOGGER.info("Cloning collection data {}.{} into {}.{}", fromDb, entry.getCollectionName(), dstDb, entry.getCollectionName());
try {
cloneCollection(localServer, remoteConnection, dstDb, opts, materializer, entry);
} catch (CompletionException completionException) {
Throwable cause = completionException.getCause();
if (cause instanceof RollbackException) {
throw (RollbackException) cause;
}
throw completionException;
}
}
}
if (opts.isCloneIndexes()) {
for (Entry entry : collsToClone) {
LOGGER.info("Cloning collection indexes {}.{} into {}.{}", fromDb, entry.getCollectionName(), dstDb, entry.getCollectionName());
try {
cloneIndex(localServer, dstDb, dstDb, remoteConnection, opts, entry.getCollectionName(), entry.getCollectionName());
} catch (CompletionException completionException) {
Throwable cause = completionException.getCause();
if (cause instanceof RollbackException) {
throw (RollbackException) cause;
}
throw completionException;
}
}
}
}
}
use of com.torodb.core.transaction.RollbackException in project torodb by torodb.
the class SameThreadInsertPipeline method insert.
@Override
public void insert(Stream<KvDocument> docs) throws RollbackException, UserException {
D2RTranslationBatchFunction d2rFun = new D2RTranslationBatchFunction(translatorFactory, metaDb, mutableMetaCollection);
DefaultToBackendFunction r2BackendFun = new DefaultToBackendFunction(jobFactory, metaDb, mutableMetaCollection);
try {
Iterators.partition(docs.iterator(), docBatchSize).forEachRemaining(list -> {
CollectionData collData = d2rFun.apply(list);
Iterable<BackendTransactionJob> jobs = r2BackendFun.apply(collData);
jobs.forEach(Unchecked.consumer(job -> job.execute(backendConnection)));
});
} catch (UncheckedException ex) {
Throwable cause = ex.getCause();
if (cause != null && cause instanceof UserException) {
throw (UserException) cause;
}
throw ex;
}
}
Aggregations