/* * 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.repl.oplogreplier.batch; import com.codahale.metrics.Histogram; import com.codahale.metrics.Timer; import com.eightkdata.mongowp.server.api.oplog.DbCmdOplogOperation; import com.eightkdata.mongowp.server.api.oplog.OplogOperation; import com.google.common.util.concurrent.Service; import com.torodb.core.exceptions.user.UserException; import com.torodb.core.metrics.MetricNameFactory; import com.torodb.core.metrics.ToroMetricRegistry; import com.torodb.core.retrier.RetrierAbortException; import com.torodb.core.retrier.RetrierGiveUpException; import com.torodb.core.transaction.RollbackException; import com.torodb.mongodb.repl.oplogreplier.ApplierContext; import com.torodb.mongodb.repl.oplogreplier.OplogOperationApplier.OplogApplyingException; import java.util.Locale; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import javax.annotation.Nonnull; import javax.annotation.concurrent.ThreadSafe; import javax.inject.Inject; /** * */ @ThreadSafe public interface AnalyzedOplogBatchExecutor extends Service, AnalyzedOplogBatchVisitor<OplogOperation, ApplierContext, RetrierGiveUpException> { public void execute(OplogOperation op, ApplierContext context) throws OplogApplyingException, RollbackException, UserException; public void execute(CudAnalyzedOplogBatch cudBatch, ApplierContext context) throws RollbackException, UserException, NamespaceJobExecutionException; public default OplogOperation apply(AnalyzedOplogBatch batch, ApplierContext replContext) throws RetrierGiveUpException, RetrierAbortException { return batch.accept(this, replContext); } public static class AnalyzedOplogBatchExecutorMetrics { protected static final MetricNameFactory NAME_FACTORY = new MetricNameFactory("OplogBatchExecutor"); private final ConcurrentMap<String, Timer> singleOpTimers = new ConcurrentHashMap<>(); private final ToroMetricRegistry metricRegistry; private final Histogram cudBatchSize; private final Timer cudBatchTimer; private final Timer namespaceBatchTimer; @Inject public AnalyzedOplogBatchExecutorMetrics(ToroMetricRegistry metricRegistry) { this.metricRegistry = metricRegistry; this.cudBatchSize = metricRegistry.histogram(NAME_FACTORY.createMetricName("batchSize")); this.cudBatchTimer = metricRegistry.timer(NAME_FACTORY.createMetricName("cudTimer")); this.namespaceBatchTimer = metricRegistry.timer(NAME_FACTORY .createMetricName("namespaceTimer")); } /** * Returns the timer associated with {@link SingleOpAnalyzedOplogBatch} that contains the given * operation. * * @param singleOplogOp * @return */ public Timer getSingleOpTimer(OplogOperation singleOplogOp) { String mapKey = getMapKey(singleOplogOp); return singleOpTimers.computeIfAbsent( mapKey, (key) -> createSingleTimer(singleOplogOp, key) ); } public Histogram getCudBatchSize() { return cudBatchSize; } public Timer getCudBatchTimer() { return cudBatchTimer; } public Timer getNamespaceBatchTimer() { return namespaceBatchTimer; } @Nonnull private String getMapKey(OplogOperation oplogOp) { if (oplogOp instanceof DbCmdOplogOperation) { DbCmdOplogOperation cmdOp = (DbCmdOplogOperation) oplogOp; return cmdOp.getCommandName().orElse("unknownCmd"); } return oplogOp.getType().name(); } private Timer createSingleTimer(OplogOperation oplogOp, String mapKey) { String prefix = "single-"; if (oplogOp instanceof DbCmdOplogOperation) { return metricRegistry.timer(NAME_FACTORY.createMetricName(prefix + mapKey)); } return metricRegistry.timer(prefix + mapKey.toLowerCase(Locale.ENGLISH)); } } }