Java tutorial
/* * Copyright 2013 Robert Gacki <robert.gacki@cgi.com> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.otto.mongodb.profiler.op.analyze; import com.mongodb.BasicDBObject; import com.mongodb.DBObject; import de.otto.mongodb.profiler.op.CountProfile; import de.otto.mongodb.profiler.op.Explanation; import de.otto.mongodb.profiler.op.ProfileEntry; import de.otto.mongodb.profiler.op.ProfileIssue; import org.joda.time.DateTime; import java.util.Collection; import java.util.Iterator; import static de.otto.mongodb.profiler.util.MongoSupport.get; import static de.otto.mongodb.profiler.util.MongoSupport.require; /** * The analyzer of a count command. * * @author Robert Gacki */ public class CountCommandAnalyzer extends CommandAnalyzer { private static final BasicDBObject EMPTY_DBO = new BasicDBObject(); private static final String COUNT_COMMAND = "count"; @Override protected boolean analyzeCommand(DBObject dbo, AnalyzerContext context) { final DBObject command = require("command", DBObject.class, dbo); if (!command.containsField(COUNT_COMMAND)) { return false; } final String op = require("op", String.class, dbo); final String ns = require("ns", String.class, dbo) + "." + require(COUNT_COMMAND, String.class, command); final DBObject queryData = get("query", DBObject.class, command, EMPTY_DBO); final String hash = context.createQueryHash(ns, op + COUNT_COMMAND, queryData); DefaultCountProfile profile = context.findProfile(hash, DefaultCountProfile.class); if (profile == null) { profile = context.addProfile(hash, new DefaultCountProfile(hash, ns, context.getOutlierConfiguration(), queryData)); } if (context.shouldExplainQuery(profile)) { final Explanation explanation = context.explainQuery(require(COUNT_COMMAND, String.class, command), profile); if (explanation != null) { profile.add(explanation); } } profile.add(new ProfileEntry(dbo, DateTime.now())); return true; } private class DefaultCountProfile extends DefaultQueryProfile implements CountProfile { public DefaultCountProfile(String id, String ns, OutlierConfiguration outlierConfiguration, DBObject query) { super(id, ns, outlierConfiguration, query, false); } @Override public String getType() { return CountProfile.TYPE_VALUE; } @Override protected Collection<ProfileIssue> findIssuesInProfile(DBObject profile) { final Collection<ProfileIssue> issues = super.findIssuesInProfile(profile); // If the query is empty, the count will not scan the collection but return the document count meta-data. // So there is no issue here. if (issues != null && getQuery().keySet().isEmpty()) { final Iterator<ProfileIssue> issuesIterator = issues.iterator(); while (issuesIterator.hasNext()) { if (QueryProfileIssues.DOCS_SCANNED_DIFFERS_FROM_RETURNED.issue.getCode() .equals(issuesIterator.next().getCode())) { issuesIterator.remove(); } } } return issues; } } }