com.eightkdata.mongowp.mongoserver.api.QueryCommandProcessor Maven / Gradle / Ivy
/*
* This file is part of mongowp.
*
* mongowp 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.
*
* mongowp 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 mongowp. If not, see .
*
* Copyright (c) 2014, 8Kdata Technology
*
*/
package com.eightkdata.mongowp.mongoserver.api;
import com.eightkdata.mongowp.messages.request.RequestBaseMessage;
import com.eightkdata.mongowp.mongoserver.api.commands.*;
import com.eightkdata.mongowp.mongoserver.api.pojos.InsertResponse;
import com.eightkdata.mongowp.mongoserver.callback.MessageReplier;
import com.google.common.base.Preconditions;
import io.netty.util.AttributeMap;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
import org.bson.BsonDocument;
import org.bson.BsonValue;
/**
*
*/
public interface QueryCommandProcessor {
public enum QueryCommandGroup {
Aggregation(AggregationQueryCommand.values()),
Geospatial(GeospatialQueryCommand.values()),
QueryAndWriteOperations(QueryAndWriteOperationsQueryCommand.values()),
Authentication(AuthenticationQueryCommand.values()),
UserManagement(UserManagementQueryCommand.values()),
RoleManagement(RoleManagementQueryCommand.values()),
Replication(ReplicationQueryCommand.values()),
Sharding(ShardingQueryCommand.values()),
Administration(AdministrationQueryCommand.values()),
Diagnostic(DiagnosticQueryCommand.values()),
Internal(InternalQueryCommand.values()),
Testing(TestingQueryCommand.values()),
SystemEventsAuditing(SystemEventsAuditingQueryCommand.values());
private final QueryCommand[] queryCommands;
private QueryCommandGroup(QueryCommand[] queryCommands) {
this.queryCommands = queryCommands;
}
private static final Map COMMANDS_MAP = new HashMap();
static {
for(QueryCommandGroup commandGroup : values()) {
for(QueryCommand command : commandGroup.queryCommands) {
// Some driver use lower case version of the command so we must take it into account
String key = command.getKey().toLowerCase(Locale.ROOT);
if (COMMANDS_MAP.containsKey(key)) {
throw new RuntimeException("Key " + key + " is not unique, found in enum " +
COMMANDS_MAP.get(key).getClass().getName() + " and in enum " +
command.getClass().getName() + ". Fix it!");
}
COMMANDS_MAP.put(key, command);
}
}
}
/**
*
* @param queryDocument
* @return
* @throws IllegalArgumentException If queryDocument is null
*/
@Nullable
public static QueryCommand byQueryDocument(@Nonnull BsonDocument queryDocument) {
Preconditions.checkNotNull(queryDocument);
// TODO: if might be worth to improve searching taking into account the # of keys of the document,
// matching it with the # of args of the commands, which could be registered as enum fields
for(String possibleCommand : queryDocument.keySet()) {
// Some driver use lower case version of the command so we must take it into account
possibleCommand = possibleCommand.toLowerCase(Locale.ROOT);
if(COMMANDS_MAP.containsKey(possibleCommand)) {
return COMMANDS_MAP.get(possibleCommand);
}
}
return null;
}
}
public interface QueryCommand {
/**
*
* @param requestBaseMessage
* @param query
* @param caller
* @throws java.lang.Exception
* @throws java.lang.IllegalArgumentException If either query or caller are null
*/
public void call(@Nonnull RequestBaseMessage requestBaseMessage, @Nonnull BsonDocument query, @Nonnull ProcessorCaller caller) throws Exception;
public String getKey();
public boolean isAdminOnly();
}
public class ProcessorCaller extends QueryCommandProcessorCaller {
@Nonnull private final QueryCommandProcessor queryCommandProcessor;
@Nonnull private final MetaCommandProcessor metaQueryProcessor;
@Inject
public ProcessorCaller(
@Nonnull String database,
@Nonnull QueryCommandProcessor queryCommandProcessor,
@Nonnull MetaCommandProcessor metaQueryProcessor,
@Nonnull MessageReplier messageReplier) {
super(database, messageReplier);
this.queryCommandProcessor = queryCommandProcessor;
this.metaQueryProcessor = metaQueryProcessor;
}
public void count(@Nonnull BsonDocument document) throws Exception {
CountRequest.Builder requestBuilder = new CountRequest.Builder(
getDatabase(),
messageReplier.getAttributeMap()
);
String collection;
if (document.containsKey("count")) {
collection = document.get("count").asString().getValue();
}
else {
throw new RuntimeException("attribute count must be an String");
}
String hint = document.containsKey("hint") ? document.get("hint").asString().getValue() : null;
int limit = document.containsKey("limit") ? document.get("limit").asInt32().intValue() : 0;
int skip = document.containsKey("skip") ? document.get("skip").asInt32().intValue() : 0;
BsonDocument query = document.containsKey("query") ? document.get("query").asDocument() : null;
requestBuilder.setCollection(collection)
.setLimit(limit)
.setHint(hint)
.setQuery(query)
.setSkip(skip);
CountReply reply;
if (metaQueryProcessor.isMetaCollection(requestBuilder.getCollection())) {
reply = metaQueryProcessor.count(requestBuilder.build());
}
else {
reply = queryCommandProcessor.count(requestBuilder.build());
}
reply.reply(messageReplier);
}
public void collStats(BsonDocument query) throws Exception {
String collection = query.get("collstats").asString().getValue();
if (collection == null) { //Mongodb and its problems with capital letters
collection = query.get("collStats").asString().getValue();
}
Number scale;
if (!query.containsKey("scale")) {
scale = 1;
}
else {
BsonValue scaleBsonValue = query.get("scale");
if (scaleBsonValue.isNumber()) {
scale = scaleBsonValue.asNumber().longValue();
}
else if (scaleBsonValue.isDocument()) {
scale = scaleBsonValue.asDocument().get("scale").asNumber().longValue();
}
else {
throw new IllegalArgumentException("Scale must be a number or "
+ "an object that contains a key 'scale' whose value is "
+ "a number");
}
}
CollStatsRequest request = new CollStatsRequest(
getDatabase(),
messageReplier.getAttributeMap(),
collection,
scale
);
CollStatsReply reply;
if (metaQueryProcessor.isMetaCollection(collection)) {
reply = metaQueryProcessor.collStats(request);
}
else {
reply = queryCommandProcessor.collStats(request);
}
reply.reply(messageReplier);
}
public void insert(@Nonnull BsonDocument document) throws Exception {
String collection = document.get("insert").asString().getValue();
InsertResponse response;
if (metaQueryProcessor.isMetaCollection(collection)) {
response = metaQueryProcessor.insert(messageReplier.getAttributeMap(), collection, document).get();
}
else {
response = queryCommandProcessor.insert(document, messageReplier.getAttributeMap());
}
response.renderize(messageReplier);
}
public void update(@Nonnull BsonDocument document) throws Exception {
queryCommandProcessor.update(document, messageReplier);
}
public void delete(@Nonnull BsonDocument document) throws Exception {
queryCommandProcessor.delete(document, messageReplier);
}
public void createIndexes(@Nonnull BsonDocument document) throws Exception {
queryCommandProcessor.createIndexes(document, messageReplier);
}
public void create(@Nonnull BsonDocument document) throws Exception {
queryCommandProcessor.create(document, messageReplier);
}
public void drop(@Nonnull BsonDocument document) throws Exception {
queryCommandProcessor.drop(document, messageReplier);
}
public void deleteIndexes(BsonDocument query) throws Exception {
queryCommandProcessor.deleteIndexes(query, messageReplier);
}
public void getLastError(
@Nullable BsonValue w, boolean j, boolean fsync,
@Nonnegative @Nullable int wtimeout
) throws Exception {
queryCommandProcessor.getLastError(w, j, fsync, wtimeout, messageReplier);
}
public void validate(@Nonnull String database, @Nonnull BsonDocument document) throws Exception {
queryCommandProcessor.validate(database, document, messageReplier);
}
public void whatsmyuri(@Nonnull String host, @Nonnull int port) {
queryCommandProcessor.whatsmyuri(host, port, messageReplier);
}
public void isMaster() {
queryCommandProcessor.isMaster(messageReplier);
}
public void replSetGetStatus() {
queryCommandProcessor.replSetGetStatus(messageReplier);
}
public void buildInfo() {
queryCommandProcessor.buildInfo(messageReplier);
}
public void ping() {
queryCommandProcessor.ping(messageReplier);
}
public void getLog(@Nonnull GetLogType log) {
queryCommandProcessor.getLog(log, messageReplier);
}
public void unimplemented(@Nonnull QueryCommand userCommand) throws Exception {
queryCommandProcessor.unimplemented(userCommand, messageReplier);
}
public void listDatabases() throws Exception {
queryCommandProcessor.listDatabases(messageReplier);
}
public void getnonce() {
queryCommandProcessor.getnonce(messageReplier);
}
public void listCollections(BsonDocument query) throws Exception {
queryCommandProcessor.listCollections(messageReplier, query);
}
public void listIndexes(String collection) throws Exception {
queryCommandProcessor.listIndexes(messageReplier, collection);
}
}
@Nonnull
public CountReply count(@Nonnull CountRequest request) throws Exception;
public InsertResponse insert(@Nonnull BsonDocument document, @Nonnull AttributeMap attributeMap) throws Exception;
public void update(@Nonnull BsonDocument document, @Nonnull MessageReplier messageReplier) throws Exception;
public void delete(@Nonnull BsonDocument document, @Nonnull MessageReplier messageReplier) throws Exception;
public void drop(@Nonnull BsonDocument document, @Nonnull MessageReplier messageReplier) throws Exception;
public void deleteIndexes(BsonDocument query, MessageReplier messageReplier) throws Exception;
public void createIndexes(@Nonnull BsonDocument document, @Nonnull MessageReplier messageReplier) throws Exception;
public void create(@Nonnull BsonDocument document, @Nonnull MessageReplier messageReplier) throws Exception;
/**
* Either w or majority will be set, but not both at the same time.
* @param j
* @param w
* @param majority
* @param fsync
* @param wtimeout
* @param messageReplier
*/
public void getLastError(
@Nullable Object w, boolean j, boolean fsync,
@Nonnegative @Nullable int wtimeout, @Nonnull MessageReplier messageReplier
) throws Exception;
public void validate(@Nonnull String database, @Nonnull BsonDocument document, @Nonnull MessageReplier messageReplier) throws Exception;
public void ping(MessageReplier messageReplier);
public void listDatabases(MessageReplier messageReplier) throws Exception;
public void whatsmyuri(@Nonnull String host, @Nonnull int port, @Nonnull MessageReplier messageReplier);
public void replSetGetStatus(@Nonnull MessageReplier messageReplier);
public void listCollections(@Nonnull MessageReplier messageReplier, BsonDocument query) throws Exception;
public void listIndexes(MessageReplier messageReplier, String collection) throws Exception;
public enum GetLogType {
global("global"),
rs("rs"),
startupWarnings("startupWarnings"),
all("*");
private final String logFilter;
GetLogType(String logFilter) {
this.logFilter = logFilter;
}
public String getLogFilter() {
return logFilter;
}
private static final Map TYPES_MAP = new HashMap(values().length);
static {
for(GetLogType getLogType : values()) {
TYPES_MAP.put(getLogType.logFilter, getLogType);
}
}
@Nullable public static GetLogType getByLog(String log) {
return TYPES_MAP.get(log);
}
}
public void getLog(@Nonnull GetLogType log, @Nonnull MessageReplier messageReplier);
public void isMaster(@Nonnull MessageReplier messageReplier);
public void buildInfo(@Nonnull MessageReplier messageReplier);
public boolean handleError(@Nonnull QueryCommand userCommand, @Nonnull MessageReplier messageReplier, @Nonnull Throwable throwable)
throws Exception;
public void unimplemented(@Nonnull QueryCommand userCommand, @Nonnull MessageReplier messageReplier) throws Exception;
public CollStatsReply collStats(CollStatsRequest request) throws Exception ;
public void getnonce(MessageReplier messageReplier);
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy