/* * ToroDB * Copyright © 2014 8Kdata Technology (www.8kdata.com) * * This program 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. * * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */ package com.torodb.mongodb.commands.signatures.diagnostic; import com.eightkdata.mongowp.bson.BsonArray; import com.eightkdata.mongowp.bson.BsonDocument; import com.eightkdata.mongowp.bson.BsonValue; import com.eightkdata.mongowp.exceptions.BadValueException; import com.eightkdata.mongowp.exceptions.FailedToParseException; import com.eightkdata.mongowp.exceptions.MongoException; import com.eightkdata.mongowp.exceptions.NoSuchKeyException; import com.eightkdata.mongowp.exceptions.TypesMismatchException; import com.eightkdata.mongowp.fields.ArrayField; import com.eightkdata.mongowp.fields.DoubleField; import com.eightkdata.mongowp.fields.StringField; import com.eightkdata.mongowp.server.api.MarshalException; import com.eightkdata.mongowp.server.api.impl.AbstractNotAliasableCommand; import com.eightkdata.mongowp.utils.BsonArrayBuilder; import com.eightkdata.mongowp.utils.BsonDocumentBuilder; import com.eightkdata.mongowp.utils.BsonReaderTool; import com.torodb.mongodb.commands.signatures.diagnostic.GetLogCommand.GetLogArgument; import com.torodb.mongodb.commands.signatures.diagnostic.GetLogCommand.GetLogReply; import java.util.ArrayList; import java.util.List; import javax.annotation.Nonnull; public class GetLogCommand extends AbstractNotAliasableCommand<GetLogArgument, GetLogReply> { private static final String COMMAND_NAME = "getLog"; public static final GetLogCommand INSTANCE = new GetLogCommand(); public GetLogCommand() { super(COMMAND_NAME); } @Override public boolean isAdminOnly() { return true; } @Override public boolean isSlaveOk() { return true; } @Override public Class<? extends GetLogArgument> getArgClass() { return GetLogArgument.class; } @Override public GetLogArgument unmarshallArg(BsonDocument requestDoc) throws BadValueException, TypesMismatchException, NoSuchKeyException, FailedToParseException { return GetLogArgument.unmarshall(requestDoc); } @Override public BsonDocument marshallArg(GetLogArgument request) throws MarshalException { return request.marshall(); } @Override public Class<? extends GetLogReply> getResultClass() { return GetLogReply.class; } @Override public GetLogReply unmarshallResult(BsonDocument resultDoc) throws BadValueException, TypesMismatchException, NoSuchKeyException, FailedToParseException, MongoException { try { return LogGetLogReply.unmarshall(resultDoc); } catch (NoSuchKeyException ex) { return AsteriskGetLogReply.unmarshall(resultDoc); } } @Override public BsonDocument marshallResult(GetLogReply result) throws MarshalException { return result.marshall(); } public static class GetLogArgument { private static final StringField COMMAND_NAME_FIELD = new StringField(COMMAND_NAME); private final boolean isAsterisk; private final String logName; public GetLogArgument(boolean isAsterisk, String logName) { this.isAsterisk = isAsterisk; this.logName = logName; } public boolean isIsAsterisk() { return isAsterisk; } @Nonnull public String getLogName() { return logName; } private static GetLogArgument unmarshall(BsonDocument resultDoc) throws TypesMismatchException, NoSuchKeyException, BadValueException { String logName = BsonReaderTool.getString(resultDoc, COMMAND_NAME_FIELD); return new GetLogArgument(logName.equals("*"), logName); } BsonDocument marshall() { return new BsonDocumentBuilder(1) .append(COMMAND_NAME_FIELD, logName) .build(); } } public abstract static class GetLogReply { abstract BsonDocument marshall(); } public static class LogGetLogReply extends GetLogReply { private final int totalLines; private final Iterable<String> lines; private static final DoubleField TOTAL_LINES_FIELD = new DoubleField("totalLinesWritten"); private static final ArrayField LOG_FIELD = new ArrayField("log"); public LogGetLogReply(int totalLines, Iterable<String> lines) { this.totalLines = totalLines; this.lines = lines; } private static GetLogReply unmarshall(BsonDocument resultDoc) throws TypesMismatchException, NoSuchKeyException, BadValueException { int totalLines = BsonReaderTool.getNumeric(resultDoc, TOTAL_LINES_FIELD).intValue(); BsonArray array = BsonReaderTool.getArray(resultDoc, LOG_FIELD); List<String> lines = new ArrayList<>(array.size()); for (BsonValue<?> bsonValue : array) { if (!bsonValue.isString()) { throw new BadValueException("The argument " + LOG_FIELD.getFieldName() + " should only contain strings, but a " + bsonValue.getValue() + " was found"); } lines.add(bsonValue.asString().getValue()); } return new LogGetLogReply(totalLines, lines); } public int getTotalLines() { return totalLines; } public Iterable<String> getLines() { return lines; } @Override BsonDocument marshall() { BsonDocumentBuilder builder = new BsonDocumentBuilder(2); builder.append(TOTAL_LINES_FIELD, totalLines); BsonArrayBuilder arrayBuilder = new BsonArrayBuilder(totalLines); for (String line : lines) { arrayBuilder.add(line); } builder.append(LOG_FIELD, arrayBuilder.build()); return builder.build(); } } public static class AsteriskGetLogReply extends GetLogReply { public static final ArrayField NAMES_FIELD = new ArrayField("names"); private final List<String> names; public AsteriskGetLogReply(List<String> names) { this.names = names; } private static GetLogReply unmarshall(BsonDocument resultDoc) throws TypesMismatchException, NoSuchKeyException, BadValueException { BsonArray array = BsonReaderTool.getArray(resultDoc, NAMES_FIELD); List<String> names = new ArrayList<>(array.size()); for (BsonValue<?> bsonValue : array) { if (!bsonValue.isString()) { throw new BadValueException("The argument " + NAMES_FIELD.getFieldName() + " should only contain strings, but a " + bsonValue.getValue() + " was found"); } names.add(bsonValue.asString().getValue()); } return new AsteriskGetLogReply(names); } @Override BsonDocument marshall() { BsonArrayBuilder arrayBuilder = new BsonArrayBuilder(names.size()); for (String name : names) { arrayBuilder.add(name); } return new BsonDocumentBuilder(1) .append(NAMES_FIELD, arrayBuilder.build()) .build(); } } }