Search in sources :

Example 1 with Status

use of com.eightkdata.mongowp.Status in project torodb by torodb.

the class TorodbSafeRequestProcessor method execute.

@Override
public <A, R> Status<R> execute(Request req, Command<? super A, ? super R> command, A arg, MongodConnection connection) {
    mongodMetrics.getCommands().mark();
    Timer timer = mongodMetrics.getTimer(command);
    try (Timer.Context ctx = timer.time()) {
        Callable<Status<R>> callable;
        RequiredTransaction commandType = commandsLibrary.getCommandType(command);
        switch(commandType) {
            case NO_TRANSACTION:
                callable = () -> {
                    return connection.getCommandsExecutor().execute(req, command, arg, connection);
                };
                break;
            case READ_TRANSACTION:
                callable = () -> {
                    try (ReadOnlyMongodTransaction trans = connection.openReadOnlyTransaction()) {
                        return trans.execute(req, command, arg);
                    }
                };
                break;
            case WRITE_TRANSACTION:
                callable = () -> {
                    try (WriteMongodTransaction trans = connection.openWriteTransaction(true)) {
                        Status<R> result = trans.execute(req, command, arg);
                        if (result.isOk()) {
                            trans.commit();
                        }
                        return result;
                    }
                };
                break;
            case EXCLUSIVE_WRITE_TRANSACTION:
                callable = () -> {
                    try (ExclusiveWriteMongodTransaction trans = connection.openExclusiveWriteTransaction(true)) {
                        Status<R> result = trans.execute(req, command, arg);
                        if (result.isOk()) {
                            trans.commit();
                        }
                        return result;
                    }
                };
                break;
            default:
                throw new AssertionError("Unexpected command type" + commandType);
        }
        try {
            return retrier.retry(callable);
        } catch (RetrierGiveUpException ex) {
            return Status.from(ErrorCode.CONFLICTING_OPERATION_IN_PROGRESS, "It was impossible to execute " + command.getCommandName() + " after several attempts");
        }
    }
}
Also used : Status(com.eightkdata.mongowp.Status) ExclusiveWriteMongodTransaction(com.torodb.mongodb.core.ExclusiveWriteMongodTransaction) WriteMongodTransaction(com.torodb.mongodb.core.WriteMongodTransaction) Timer(com.codahale.metrics.Timer) RequiredTransaction(com.torodb.mongodb.commands.TorodbCommandsLibrary.RequiredTransaction) ReadOnlyMongodTransaction(com.torodb.mongodb.core.ReadOnlyMongodTransaction) ExclusiveWriteMongodTransaction(com.torodb.mongodb.core.ExclusiveWriteMongodTransaction) RetrierGiveUpException(com.torodb.core.retrier.RetrierGiveUpException)

Example 2 with Status

use of com.eightkdata.mongowp.Status in project torodb by torodb.

the class FindImplementation method apply.

@Override
public Status<FindResult> apply(Request req, Command<? super FindArgument, ? super FindResult> command, FindArgument arg, MongodTransaction context) {
    logFindCommand(arg);
    BsonDocument filter = arg.getFilter();
    Cursor<BsonDocument> cursor;
    switch(filter.size()) {
        case 0:
            {
                cursor = context.getTorodTransaction().findAll(req.getDatabase(), arg.getCollection()).asDocCursor().transform(t -> t.getRoot()).transform(ToBsonDocumentTranslator.getInstance());
                break;
            }
        case 1:
            {
                try {
                    cursor = getByAttributeCursor(context.getTorodTransaction(), req.getDatabase(), arg.getCollection(), filter).transform(ToBsonDocumentTranslator.getInstance());
                } catch (CommandFailed ex) {
                    return Status.from(ex);
                }
                break;
            }
        default:
            {
                return Status.from(ErrorCode.COMMAND_FAILED, "The given query is not supported right now");
            }
    }
    if (Long.valueOf(arg.getBatchSize()) > (long) Integer.MAX_VALUE) {
        return Status.from(ErrorCode.COMMAND_FAILED, "Only batchSize equals or lower than " + Integer.MAX_VALUE + " is supported");
    }
    OptionalLong batchSize = arg.getEffectiveBatchSize();
    List<BsonDocument> batch = cursor.getNextBatch(batchSize.isPresent() ? (int) batchSize.getAsLong() : 101);
    cursor.close();
    return Status.ok(new FindResult(CursorResult.createSingleBatchCursor(req.getDatabase(), arg.getCollection(), batch.iterator())));
}
Also used : Request(com.eightkdata.mongowp.server.api.Request) FindResult(com.torodb.mongodb.commands.signatures.general.FindCommand.FindResult) AttributeReference(com.torodb.core.language.AttributeReference) Cursor(com.torodb.core.cursors.Cursor) KvDocument(com.torodb.kvdocument.values.KvDocument) BsonDocument(com.eightkdata.mongowp.bson.BsonDocument) Command(com.eightkdata.mongowp.server.api.Command) ToBsonDocumentTranslator(com.torodb.kvdocument.conversion.mongowp.ToBsonDocumentTranslator) Singleton(javax.inject.Singleton) CursorResult(com.torodb.mongodb.commands.pojos.CursorResult) MongodTransaction(com.torodb.mongodb.core.MongodTransaction) OptionalLong(java.util.OptionalLong) KvValue(com.torodb.kvdocument.values.KvValue) List(java.util.List) Logger(org.apache.logging.log4j.Logger) Status(com.eightkdata.mongowp.Status) FindArgument(com.torodb.mongodb.commands.signatures.general.FindCommand.FindArgument) TorodTransaction(com.torodb.torod.TorodTransaction) Builder(com.torodb.core.language.AttributeReference.Builder) ErrorCode(com.eightkdata.mongowp.ErrorCode) ReadTorodbCommandImpl(com.torodb.mongodb.commands.impl.ReadTorodbCommandImpl) CommandFailed(com.eightkdata.mongowp.exceptions.CommandFailed) LogManager(org.apache.logging.log4j.LogManager) BsonDocument(com.eightkdata.mongowp.bson.BsonDocument) CommandFailed(com.eightkdata.mongowp.exceptions.CommandFailed) OptionalLong(java.util.OptionalLong) FindResult(com.torodb.mongodb.commands.signatures.general.FindCommand.FindResult)

Example 3 with Status

use of com.eightkdata.mongowp.Status in project torodb by torodb.

the class UpdateImplementation method apply.

@Override
public Status<UpdateResult> apply(Request req, Command<? super UpdateArgument, ? super UpdateResult> command, UpdateArgument arg, WriteMongodTransaction context) {
    UpdateStatus updateStatus = new UpdateStatus();
    try {
        if (!context.getTorodTransaction().existsCollection(req.getDatabase(), arg.getCollection())) {
            context.getTorodTransaction().createIndex(req.getDatabase(), arg.getCollection(), Constants.ID_INDEX, ImmutableList.<IndexFieldInfo>of(new IndexFieldInfo(new AttributeReference(Arrays.asList(new Key[] { new ObjectKey(Constants.ID) })), FieldIndexOrdering.ASC.isAscending())), true);
        }
        for (UpdateStatement updateStatement : arg.getStatements()) {
            BsonDocument query = updateStatement.getQuery();
            UpdateAction updateAction = UpdateActionTranslator.translate(updateStatement.getUpdate());
            Cursor<ToroDocument> candidatesCursor;
            switch(query.size()) {
                case 0:
                    {
                        candidatesCursor = context.getTorodTransaction().findAll(req.getDatabase(), arg.getCollection()).asDocCursor();
                        break;
                    }
                case 1:
                    {
                        try {
                            candidatesCursor = findByAttribute(context.getTorodTransaction(), req.getDatabase(), arg.getCollection(), query);
                        } catch (CommandFailed ex) {
                            return Status.from(ex);
                        }
                        break;
                    }
                default:
                    {
                        return Status.from(ErrorCode.COMMAND_FAILED, "The given query is not supported right now");
                    }
            }
            if (candidatesCursor.hasNext()) {
                try {
                    Stream<List<ToroDocument>> candidatesbatchStream;
                    if (updateStatement.isMulti()) {
                        candidatesbatchStream = StreamSupport.stream(Spliterators.spliteratorUnknownSize(candidatesCursor.batch(100), Spliterator.ORDERED), false);
                    } else {
                        candidatesbatchStream = Stream.of(ImmutableList.of(candidatesCursor.next()));
                    }
                    Stream<KvDocument> updatedCandidates = candidatesbatchStream.map(candidates -> {
                        updateStatus.increaseCandidates(candidates.size());
                        context.getTorodTransaction().delete(req.getDatabase(), arg.getCollection(), candidates);
                        return candidates;
                    }).flatMap(l -> l.stream()).map(candidate -> {
                        try {
                            updateStatus.increaseUpdated();
                            return update(updateAction, candidate);
                        } catch (UserException userException) {
                            throw new UserWrappedException(userException);
                        }
                    });
                    context.getTorodTransaction().insert(req.getDatabase(), arg.getCollection(), updatedCandidates);
                } catch (UserWrappedException userWrappedException) {
                    throw userWrappedException.getCause();
                }
            } else if (updateStatement.isUpsert()) {
                KvDocument toInsertCandidate;
                if (updateAction instanceof SetDocumentUpdateAction) {
                    toInsertCandidate = ((SetDocumentUpdateAction) updateAction).getNewValue();
                } else {
                    toInsertCandidate = update(updateAction, new ToroDocument(-1, (KvDocument) MongoWpConverter.translate(query)));
                }
                if (!toInsertCandidate.containsKey(Constants.ID)) {
                    KvDocument.Builder builder = new KvDocument.Builder();
                    for (DocEntry<?> entry : toInsertCandidate) {
                        builder.putValue(entry.getKey(), entry.getValue());
                    }
                    builder.putValue(Constants.ID, MongoWpConverter.translate(objectIdFactory.consumeObjectId()));
                    toInsertCandidate = builder.build();
                }
                updateStatus.increaseCandidates(1);
                updateStatus.increaseCreated(toInsertCandidate.get(Constants.ID));
                Stream<KvDocument> toInsertCandidates = Stream.of(toInsertCandidate);
                context.getTorodTransaction().insert(req.getDatabase(), arg.getCollection(), toInsertCandidates);
            }
        }
    } catch (UserException ex) {
        //TODO: Improve error reporting
        return Status.from(ErrorCode.COMMAND_FAILED, ex.getLocalizedMessage());
    }
    mongodMetrics.getUpdateModified().mark(updateStatus.updated);
    mongodMetrics.getUpdateMatched().mark(updateStatus.candidates);
    mongodMetrics.getUpdateUpserted().mark(updateStatus.upsertResults.size());
    return Status.ok(new UpdateResult(updateStatus.updated, updateStatus.candidates, ImmutableList.copyOf(updateStatus.upsertResults)));
}
Also used : Request(com.eightkdata.mongowp.server.api.Request) UpdateActionTranslator(com.torodb.mongodb.language.UpdateActionTranslator) Arrays(java.util.Arrays) UpdatedToroDocumentBuilder(com.torodb.mongodb.language.update.UpdatedToroDocumentBuilder) FieldIndexOrdering(com.torodb.core.transaction.metainf.FieldIndexOrdering) Spliterators(java.util.Spliterators) BsonDocument(com.eightkdata.mongowp.bson.BsonDocument) WriteTorodbCommandImpl(com.torodb.mongodb.commands.impl.WriteTorodbCommandImpl) UpdateAction(com.torodb.mongodb.language.update.UpdateAction) UpdateStatement(com.torodb.mongodb.commands.signatures.general.UpdateCommand.UpdateStatement) Singleton(javax.inject.Singleton) ToroDocument(com.torodb.core.document.ToroDocument) UpdateResult(com.torodb.mongodb.commands.signatures.general.UpdateCommand.UpdateResult) ArrayList(java.util.ArrayList) ObjectKey(com.torodb.core.language.AttributeReference.ObjectKey) IndexFieldInfo(com.torodb.torod.IndexFieldInfo) Inject(javax.inject.Inject) KvValue(com.torodb.kvdocument.values.KvValue) ImmutableList(com.google.common.collect.ImmutableList) MongoWpConverter(com.torodb.kvdocument.conversion.mongowp.MongoWpConverter) StreamSupport(java.util.stream.StreamSupport) Builder(com.torodb.core.language.AttributeReference.Builder) ErrorCode(com.eightkdata.mongowp.ErrorCode) CommandFailed(com.eightkdata.mongowp.exceptions.CommandFailed) UpdateException(com.torodb.core.exceptions.user.UpdateException) SharedWriteTorodTransaction(com.torodb.torod.SharedWriteTorodTransaction) AttributeReference(com.torodb.core.language.AttributeReference) Constants(com.torodb.mongodb.language.Constants) Cursor(com.torodb.core.cursors.Cursor) KvDocument(com.torodb.kvdocument.values.KvDocument) UpsertResult(com.torodb.mongodb.commands.signatures.general.UpdateCommand.UpsertResult) Command(com.eightkdata.mongowp.server.api.Command) UserException(com.torodb.core.exceptions.user.UserException) SetDocumentUpdateAction(com.torodb.mongodb.language.update.SetDocumentUpdateAction) ObjectIdFactory(com.torodb.mongodb.language.ObjectIdFactory) DocEntry(com.torodb.kvdocument.values.KvDocument.DocEntry) MongodMetrics(com.torodb.mongodb.core.MongodMetrics) WriteMongodTransaction(com.torodb.mongodb.core.WriteMongodTransaction) List(java.util.List) Stream(java.util.stream.Stream) Status(com.eightkdata.mongowp.Status) UserWrappedException(com.torodb.core.exceptions.UserWrappedException) UpdateArgument(com.torodb.mongodb.commands.signatures.general.UpdateCommand.UpdateArgument) Spliterator(java.util.Spliterator) Key(com.torodb.core.language.AttributeReference.Key) KvDocument(com.torodb.kvdocument.values.KvDocument) UpdateStatement(com.torodb.mongodb.commands.signatures.general.UpdateCommand.UpdateStatement) UpdateAction(com.torodb.mongodb.language.update.UpdateAction) SetDocumentUpdateAction(com.torodb.mongodb.language.update.SetDocumentUpdateAction) AttributeReference(com.torodb.core.language.AttributeReference) UpdatedToroDocumentBuilder(com.torodb.mongodb.language.update.UpdatedToroDocumentBuilder) Builder(com.torodb.core.language.AttributeReference.Builder) ObjectKey(com.torodb.core.language.AttributeReference.ObjectKey) DocEntry(com.torodb.kvdocument.values.KvDocument.DocEntry) BsonDocument(com.eightkdata.mongowp.bson.BsonDocument) UserWrappedException(com.torodb.core.exceptions.UserWrappedException) ToroDocument(com.torodb.core.document.ToroDocument) CommandFailed(com.eightkdata.mongowp.exceptions.CommandFailed) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) List(java.util.List) Stream(java.util.stream.Stream) IndexFieldInfo(com.torodb.torod.IndexFieldInfo) UserException(com.torodb.core.exceptions.user.UserException) UpdateResult(com.torodb.mongodb.commands.signatures.general.UpdateCommand.UpdateResult) SetDocumentUpdateAction(com.torodb.mongodb.language.update.SetDocumentUpdateAction)

Example 4 with Status

use of com.eightkdata.mongowp.Status in project torodb by torodb.

the class DropIndexesImplementation method apply.

@Override
public Status<DropIndexesResult> apply(Request req, Command<? super DropIndexesArgument, ? super DropIndexesResult> command, DropIndexesArgument arg, WriteMongodTransaction context) {
    int indexesBefore = (int) context.getTorodTransaction().getIndexesInfo(req.getDatabase(), arg.getCollection()).count();
    List<String> indexesToDrop;
    if (!arg.isDropAllIndexes()) {
        if (!arg.isDropByKeys()) {
            if (Constants.ID_INDEX.equals(arg.getIndexToDrop())) {
                return Status.from(ErrorCode.INVALID_OPTIONS, "cannot drop _id index");
            }
            indexesToDrop = Arrays.asList(arg.getIndexToDrop());
        } else {
            if (arg.getKeys().stream().anyMatch(key -> !(KnownType.contains(key.getType())) || (key.getType() != KnownType.asc.getIndexType() && key.getType() != KnownType.desc.getIndexType()))) {
                return getStatusForIndexNotFoundWithKeys(arg);
            }
            indexesToDrop = context.getTorodTransaction().getIndexesInfo(req.getDatabase(), arg.getCollection()).filter(index -> indexFieldsMatchKeys(index, arg.getKeys())).map(index -> index.getName()).collect(Collectors.toList());
            if (indexesToDrop.isEmpty()) {
                return getStatusForIndexNotFoundWithKeys(arg);
            }
        }
    } else {
        indexesToDrop = context.getTorodTransaction().getIndexesInfo(req.getDatabase(), arg.getCollection()).filter(indexInfo -> !Constants.ID_INDEX.equals(indexInfo.getName())).map(indexInfo -> indexInfo.getName()).collect(Collectors.toList());
    }
    for (String indexToDrop : indexesToDrop) {
        boolean dropped = context.getTorodTransaction().dropIndex(req.getDatabase(), arg.getCollection(), indexToDrop);
        if (!dropped) {
            return Status.from(ErrorCode.INDEX_NOT_FOUND, "index not found with name [" + indexToDrop + "]");
        }
    }
    return Status.ok(new DropIndexesResult(indexesBefore));
}
Also used : Request(com.eightkdata.mongowp.server.api.Request) 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) WriteTorodbCommandImpl(com.torodb.mongodb.commands.impl.WriteTorodbCommandImpl) Collectors(java.util.stream.Collectors) WriteMongodTransaction(com.torodb.mongodb.core.WriteMongodTransaction) IndexFieldInfo(com.torodb.torod.IndexFieldInfo) List(java.util.List) Status(com.eightkdata.mongowp.Status) KnownType(com.torodb.mongodb.commands.pojos.index.IndexOptions.KnownType) ErrorCode(com.eightkdata.mongowp.ErrorCode) IndexInfo(com.torodb.torod.IndexInfo) IndexOptions(com.torodb.mongodb.commands.pojos.index.IndexOptions) DropIndexesArgument(com.torodb.mongodb.commands.signatures.admin.DropIndexesCommand.DropIndexesArgument) DropIndexesResult(com.torodb.mongodb.commands.signatures.admin.DropIndexesCommand.DropIndexesResult)

Example 5 with Status

use of com.eightkdata.mongowp.Status 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

Status (com.eightkdata.mongowp.Status)7 Command (com.eightkdata.mongowp.server.api.Command)5 Request (com.eightkdata.mongowp.server.api.Request)4 AttributeReference (com.torodb.core.language.AttributeReference)4 List (java.util.List)4 ErrorCode (com.eightkdata.mongowp.ErrorCode)3 BsonDocument (com.eightkdata.mongowp.bson.BsonDocument)3 IndexOptions (com.torodb.mongodb.commands.pojos.index.IndexOptions)3 WriteMongodTransaction (com.torodb.mongodb.core.WriteMongodTransaction)3 Constants (com.torodb.mongodb.language.Constants)3 IndexFieldInfo (com.torodb.torod.IndexFieldInfo)3 Arrays (java.util.Arrays)3 CommandFailed (com.eightkdata.mongowp.exceptions.CommandFailed)2 MongoException (com.eightkdata.mongowp.exceptions.MongoException)2 Cursor (com.torodb.core.cursors.Cursor)2 Builder (com.torodb.core.language.AttributeReference.Builder)2 KvDocument (com.torodb.kvdocument.values.KvDocument)2 KvValue (com.torodb.kvdocument.values.KvValue)2 WriteTorodbCommandImpl (com.torodb.mongodb.commands.impl.WriteTorodbCommandImpl)2 KnownType (com.torodb.mongodb.commands.pojos.index.IndexOptions.KnownType)2