/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.jackrabbit.oak.plugins.document.mongo;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

import org.apache.jackrabbit.guava.common.base.Optional;
import org.apache.jackrabbit.guava.common.base.Stopwatch;
import org.apache.jackrabbit.guava.common.collect.ImmutableList;
import org.apache.jackrabbit.guava.common.collect.ImmutableMap;
import org.apache.jackrabbit.guava.common.collect.Iterables;
import org.apache.jackrabbit.guava.common.collect.Iterators;
import org.apache.jackrabbit.guava.common.collect.Lists;
import org.apache.jackrabbit.guava.common.io.Closeables;
import org.apache.jackrabbit.guava.common.util.concurrent.AtomicDouble;
import com.mongodb.Block;
import com.mongodb.DBObject;
import com.mongodb.MongoBulkWriteException;
import com.mongodb.MongoWriteException;
import com.mongodb.MongoCommandException;
import com.mongodb.WriteError;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
import com.mongodb.ReadPreference;

import com.mongodb.client.model.CreateCollectionOptions;

import org.apache.jackrabbit.guava.common.util.concurrent.UncheckedExecutionException;
import org.apache.jackrabbit.oak.cache.CacheStats;
import org.apache.jackrabbit.oak.cache.CacheValue;
import org.apache.jackrabbit.oak.plugins.document.Collection;
import org.apache.jackrabbit.oak.plugins.document.Document;
import org.apache.jackrabbit.oak.plugins.document.DocumentStore;
import org.apache.jackrabbit.oak.plugins.document.DocumentStoreException;
import org.apache.jackrabbit.oak.plugins.document.DocumentStoreStatsCollector;
import org.apache.jackrabbit.oak.plugins.document.JournalEntry;
import org.apache.jackrabbit.oak.plugins.document.NodeDocument;
import org.apache.jackrabbit.oak.plugins.document.Revision;
import org.apache.jackrabbit.oak.plugins.document.StableRevisionComparator;
import org.apache.jackrabbit.oak.plugins.document.UpdateOp;
import org.apache.jackrabbit.oak.plugins.document.Throttler;
import org.apache.jackrabbit.oak.plugins.document.UpdateOp.Condition;
import org.apache.jackrabbit.oak.plugins.document.UpdateOp.Key;
import org.apache.jackrabbit.oak.plugins.document.UpdateOp.Operation;
import org.apache.jackrabbit.oak.plugins.document.UpdateUtils;
import org.apache.jackrabbit.oak.plugins.document.cache.CacheChangesTracker;
import org.apache.jackrabbit.oak.plugins.document.cache.CacheInvalidationStats;
import org.apache.jackrabbit.oak.plugins.document.cache.ModificationStamp;
import org.apache.jackrabbit.oak.plugins.document.cache.NodeDocumentCache;
import org.apache.jackrabbit.oak.plugins.document.locks.NodeDocumentLocks;
import org.apache.jackrabbit.oak.plugins.document.locks.StripedNodeDocumentLocks;
import org.apache.jackrabbit.oak.plugins.document.util.Utils;
import org.apache.jackrabbit.oak.stats.Clock;
import org.apache.jackrabbit.oak.commons.PerfLogger;
import org.bson.BsonMaximumSizeExceededException;
import org.bson.conversions.Bson;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.jackrabbit.guava.common.base.Function;
import org.apache.jackrabbit.guava.common.collect.Maps;
import com.mongodb.BasicDBObject;
import com.mongodb.MongoException;
import com.mongodb.WriteConcern;
import com.mongodb.bulk.BulkWriteError;
import com.mongodb.bulk.BulkWriteResult;
import com.mongodb.bulk.BulkWriteUpsert;
import com.mongodb.client.ClientSession;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.BulkWriteOptions;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.FindOneAndUpdateOptions;
import com.mongodb.client.model.ReturnDocument;
import com.mongodb.client.model.UpdateOneModel;
import com.mongodb.client.model.UpdateOptions;
import com.mongodb.client.model.WriteModel;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;

import static java.util.Objects.isNull;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.stream.Collectors.toList;
import static org.apache.jackrabbit.guava.common.base.Predicates.in;
import static org.apache.jackrabbit.guava.common.base.Predicates.not;
import static org.apache.jackrabbit.guava.common.collect.Iterables.filter;
import static org.apache.jackrabbit.guava.common.collect.Maps.filterKeys;
import static org.apache.jackrabbit.guava.common.collect.Sets.difference;
import static com.mongodb.client.model.Projections.include;
import static java.lang.Integer.MAX_VALUE;
import static java.util.Collections.emptyList;
import static org.apache.jackrabbit.oak.plugins.document.Collection.NODES;
import static org.apache.jackrabbit.oak.plugins.document.DocumentStoreException.asDocumentStoreException;
import static org.apache.jackrabbit.oak.plugins.document.NodeDocument.DELETED_ONCE;
import static org.apache.jackrabbit.oak.plugins.document.NodeDocument.MODIFIED_IN_SECS;
import static org.apache.jackrabbit.oak.plugins.document.NodeDocument.NULL;
import static org.apache.jackrabbit.oak.plugins.document.NodeDocument.SD_MAX_REV_TIME_IN_SECS;
import static org.apache.jackrabbit.oak.plugins.document.NodeDocument.SD_TYPE;
import static org.apache.jackrabbit.oak.plugins.document.Throttler.NO_THROTTLING;
import static org.apache.jackrabbit.oak.plugins.document.UpdateOp.Condition.newEqualsCondition;
import static org.apache.jackrabbit.oak.plugins.document.mongo.MongoThrottlerFactory.exponentialThrottler;
import static org.apache.jackrabbit.oak.plugins.document.mongo.MongoUtils.createIndex;
import static org.apache.jackrabbit.oak.plugins.document.mongo.MongoUtils.createPartialIndex;
import static org.apache.jackrabbit.oak.plugins.document.mongo.MongoUtils.getDocumentStoreExceptionTypeFor;
import static org.apache.jackrabbit.oak.plugins.document.mongo.MongoUtils.hasIndex;
import static org.apache.jackrabbit.oak.plugins.document.util.Utils.isThrottlingEnabled;

/**
 * A document store that uses MongoDB as the backend.
 */
public class MongoDocumentStore implements DocumentStore {

    private static final Logger LOG = LoggerFactory.getLogger(MongoDocumentStore.class);
    private static final PerfLogger PERFLOG = new PerfLogger(
            LoggerFactory.getLogger(MongoDocumentStore.class.getName()
                    + ".perf"));

    private static final Bson BY_ID_ASC = new BasicDBObject(Document.ID, 1);

    private static final String OPLOG_RS = "oplog.rs";

    /**
     * The threshold value <b>(in hours)</b> after which the document store should start (if enabled) throttling.
     * Default is 2 hours.
     * <p>
     * For mongo based document store this value is threshold for the oplog replication window.
     */
    public static final int DEFAULT_THROTTLING_THRESHOLD = Integer.getInteger("oak.mongo.throttlingThreshold", 2);
    /**
     * The default throttling time (in millis) when throttling is enabled. This is the time for
     * which we block any data modification operation when system has been throttled.
     */
    public static final long DEFAULT_THROTTLING_TIME_MS = Long.getLong("oak.mongo.throttlingTime", 20);
    /**
     * nodeNameLimit for node name based on Mongo Version
     */
    private final int nodeNameLimit;

    /**
     * throttler for mongo document store
     */
    private Throttler throttler = NO_THROTTLING;

    enum DocumentReadPreference {
        PRIMARY,
        PREFER_PRIMARY,
        PREFER_SECONDARY,
        PREFER_SECONDARY_IF_OLD_ENOUGH
    }

    public static final int IN_CLAUSE_BATCH_SIZE = 500;

    /**
     * A conflicting ID assignment on insert. Used by
     * {@link #sendBulkUpdate(Collection, java.util.Collection, Map)} for
     * {@code UpdateOp} with {@code isNew == false}. An upsert with this
     * operation will always fail when there is no existing document.
     */
    private static final Map CONFLICT_ON_INSERT = new BasicDBObject(
            "$setOnInsert",
            new BasicDBObject(Document.ID, "a").append(Document.ID, "b")
    ).toMap();

    private MongoCollection<BasicDBObject> nodes;
    private final MongoCollection<BasicDBObject> clusterNodes;
    private final MongoCollection<BasicDBObject> settings;
    private final MongoCollection<BasicDBObject> journal;

    private final MongoDBConnection connection;
    private final MongoDBConnection clusterNodesConnection;
    private final Map<String, String> mongoStorageOptions = new HashMap<>();

    private final NodeDocumentCache nodesCache;

    private final NodeDocumentLocks nodeLocks;

    private Clock clock = Clock.SIMPLE;

    private final long maxReplicationLagMillis;

    /**
     * Duration in seconds under which queries would use index on _modified field
     * If set to -1 then modifiedTime index would not be used.
     * <p>
     * Default is 60 seconds.
     */
    private final long maxDeltaForModTimeIdxSecs =
            Long.getLong("oak.mongo.maxDeltaForModTimeIdxSecs", 60);

    /**
     * Disables the index hint sent to MongoDB.
     * This overrides {@link #maxDeltaForModTimeIdxSecs}.
     */
    private final boolean disableIndexHint =
            Boolean.getBoolean("oak.mongo.disableIndexHint");

    /**
     * Duration in milliseconds after which a mongo query will be terminated.
     * <p>
     * If this value is -1 no timeout is being set at all, if it is 1 or greater
     * this translated to MongoDB's maxTimeNS being set accordingly.
     * <p>
     * Default is 60'000 (one minute).
     * See: http://mongodb.github.io/node-mongodb-native/driver-articles/anintroductionto1_4_and_2_6.html#maxtimems
     */
    private final long maxQueryTimeMS =
            Long.getLong("oak.mongo.maxQueryTimeMS", TimeUnit.MINUTES.toMillis(1));

    /**
     * The number of documents to put into one bulk update.
     * <p>
     * Default is 30.
     */
    private int bulkSize =
            Integer.getInteger("oak.mongo.bulkSize", 30);

    /**
     * How many times should be the bulk update request retries in case of
     * a conflict.
     * <p>
     * Default is 0 (no retries).
     */
    private int bulkRetries =
            Integer.getInteger("oak.mongo.bulkRetries", 0);

    /**
     * How many times a query to MongoDB should be retried when it fails with a
     * MongoException.
     */
    private final int queryRetries =
            Integer.getInteger("oak.mongo.queryRetries", 2);

    /**
     * Acceptable replication lag of secondaries in milliseconds. Reads are
     * directed to the primary if the estimated replication lag is higher than
     * this value.
     */
    private final int acceptableLagMillis =
            Integer.getInteger("oak.mongo.acceptableLagMillis", 5000);

    /**
     * The minimal number of documents to prefetch.
     */
    private final int minPrefetch =
            Integer.getInteger("oak.mongo.minPrefetch", 5);

    /**
     * Feature flag for use of MongoDB client sessions.
     */
    private final boolean useClientSession;

    private String lastReadWriteMode;

    private final Map<String, String> metadata;

    private DocumentStoreStatsCollector stats;

    /**
     * An updater instance to periodically updates mongo oplog window
     */
    private MongoDocumentStoreThrottlingMetricsUpdater throttlingMetricsUpdater;

    private boolean hasModifiedIdCompoundIndex = true;

    private static final Key KEY_MODIFIED = new Key(MODIFIED_IN_SECS, null);

    private final boolean readOnly;

    @Override
    public int getNodeNameLimit() {
        return nodeNameLimit;
    }

    /**
     * Return the {@link Throttler} for the underlying store
     * Default is no throttling
     *
     * @return throttler for document store
     */
    @Override
    public Throttler throttler() {
        return throttler;
    }

    public MongoDocumentStore(MongoClient connection, MongoDatabase db,
                              MongoDocumentNodeStoreBuilderBase<?> builder) {
        this.readOnly = builder.getReadOnlyMode();
        MongoStatus status = builder.getMongoStatus();
        if (status == null) {
            status = new MongoStatus(connection, db.getName());
        }
        status.checkVersion();
        metadata = ImmutableMap.<String,String>builder()
                .put("type", "mongo")
                .put("version", status.getVersion())
                .build();

        this.nodeNameLimit = MongoUtils.getNodeNameLimit(status);
        this.connection = new MongoDBConnection(connection, db, status, builder.getMongoClock());
        this.clusterNodesConnection = getOrCreateClusterNodesConnection(builder);
        stats = builder.getDocumentStoreStatsCollector();
        nodes = this.connection.getCollection(Collection.NODES.toString());
        clusterNodes = this.clusterNodesConnection.getCollection(Collection.CLUSTER_NODES.toString());
        settings = this.connection.getCollection(Collection.SETTINGS.toString());
        journal = this.connection.getCollection(Collection.JOURNAL.toString());
        initializeMongoStorageOptions(builder);

        maxReplicationLagMillis = builder.getMaxReplicationLagMillis();

        useClientSession = !builder.isClientSessionDisabled()
                && Boolean.parseBoolean(System.getProperty("oak.mongo.clientSession", "true"));

        if (!readOnly) {
            ensureIndexes(db, status);
        }

        this.nodeLocks = new StripedNodeDocumentLocks();
        this.nodesCache = builder.buildNodeDocumentCache(this, nodeLocks);

        // if throttling is enabled
        final boolean throttlingEnabled = isThrottlingEnabled(builder);
        if (throttlingEnabled) {
            MongoDatabase localDb = connection.getDatabase("local");
            Optional<String> ol = Iterables.tryFind(localDb.listCollectionNames(), s -> Objects.equals(OPLOG_RS, s));

            if (ol.isPresent()) {
                // oplog window based on current oplog filling rate
                final AtomicDouble oplogWindow = new AtomicDouble(MAX_VALUE);
                throttler = exponentialThrottler(DEFAULT_THROTTLING_THRESHOLD, oplogWindow, DEFAULT_THROTTLING_TIME_MS);
                throttlingMetricsUpdater = new MongoDocumentStoreThrottlingMetricsUpdater(localDb, oplogWindow);
                throttlingMetricsUpdater.scheduleUpdateMetrics();
                LOG.info("Started MongoDB throttling metrics with threshold {}, throttling time {}",
                        DEFAULT_THROTTLING_THRESHOLD, DEFAULT_THROTTLING_TIME_MS);
            } else {
                LOG.warn("Connected to MongoDB with replication not detected and hence oplog based throttling is not supported");
            }
        }

        LOG.info("Connected to MongoDB {} with maxReplicationLagMillis {}, " +
                "maxDeltaForModTimeIdxSecs {}, disableIndexHint {}, " +
                "leaseSocketTimeout {}, clientSessionSupported {}, " +
                "clientSessionInUse {}, {}, serverStatus {}, throttlingSupported {}",
                status.getVersion(), maxReplicationLagMillis,
                maxDeltaForModTimeIdxSecs, disableIndexHint,
                builder.getLeaseSocketTimeout(),
                status.isClientSessionSupported(), useClientSession,
                db.getWriteConcern(), status.getServerDetails(), throttlingEnabled);
    }

    // constructs storage options from config
    private void initializeMongoStorageOptions(MongoDocumentNodeStoreBuilderBase<?> builder) {
        if (builder.getCollectionCompressionType() != null) {
            this.mongoStorageOptions.put(MongoDBConfig.COLLECTION_COMPRESSION_TYPE, builder.getCollectionCompressionType());
        }
    }

    @NotNull
    private MongoDBConnection getOrCreateClusterNodesConnection(@NotNull MongoDocumentNodeStoreBuilderBase<?> builder) {
        MongoDBConnection mc;
        int leaseSocketTimeout = builder.getLeaseSocketTimeout();
        if (leaseSocketTimeout > 0) {
            mc = builder.createMongoDBClient(leaseSocketTimeout);
        } else {
            // use same connection
            mc = connection;
        }
        return mc;
    }

    private void ensureIndexes(@NotNull MongoDatabase db, @NotNull MongoStatus mongoStatus) {
        // reading documents in the nodes collection and checking
        // existing indexes is performed against the MongoDB primary
        // this ensures the information is up-to-date and accurate
        boolean emptyNodesCollection = execute(session -> MongoUtils.isCollectionEmpty(nodes, session), Collection.NODES);
        createCollection(db, Collection.NODES.toString(), mongoStatus);
        // compound index on _modified and _id
        if (emptyNodesCollection) {
            // this is an empty store, create a compound index
            // on _modified and _id (OAK-3071)

            createIndex(nodes, new String[]{NodeDocument.MODIFIED_IN_SECS, Document.ID},
                    new boolean[]{true, true}, false, false);
        } else if (!hasIndex(nodes.withReadPreference(ReadPreference.primary()),
                NodeDocument.MODIFIED_IN_SECS, Document.ID)) {
            hasModifiedIdCompoundIndex = false;
            LOG.warn("Detected an upgrade from Oak version <= 1.2. For optimal " +
                    "performance it is recommended to create a compound index " +
                    "for the 'nodes' collection on {_modified:1, _id:1}.");
        }

        // index on the _bin flag to faster access nodes with binaries for GC
        createIndex(nodes, NodeDocument.HAS_BINARY_FLAG, true, false, true);

        // index on _deleted for fast lookup of potentially garbage
        // depending on the MongoDB version, create a partial index
        if (emptyNodesCollection) {
            if (mongoStatus.isVersion(3, 2)) {
                createPartialIndex(nodes, new String[]{DELETED_ONCE, MODIFIED_IN_SECS},
                        new boolean[]{true, true}, "{" + DELETED_ONCE + ":true}");
            } else {
                createIndex(nodes, NodeDocument.DELETED_ONCE, true, false, true);
            }
        } else if (!hasIndex(nodes.withReadPreference(ReadPreference.primary()),
                DELETED_ONCE, MODIFIED_IN_SECS)) {
            LOG.warn("Detected an upgrade from Oak version <= 1.6. For optimal " +
                    "Revision GC performance it is recommended to create a " +
                    "partial index for the 'nodes' collection on " +
                    "{_deletedOnce:1, _modified:1} with a partialFilterExpression " +
                    "{_deletedOnce:true}. Partial indexes require MongoDB 3.2 " +
                    "or higher.");
        }

        // compound index on _sdType and _sdMaxRevTime
        if (emptyNodesCollection) {
            // this is an empty store, create compound index
            // on _sdType and _sdMaxRevTime (OAK-6129)
            createIndex(nodes, new String[]{SD_TYPE, SD_MAX_REV_TIME_IN_SECS},
                    new boolean[]{true, true}, false, true);
        } else if (!hasIndex(nodes.withReadPreference(ReadPreference.primary()),
                SD_TYPE, SD_MAX_REV_TIME_IN_SECS)) {
            LOG.warn("Detected an upgrade from Oak version <= 1.6. For optimal " +
                    "Revision GC performance it is recommended to create a " +
                    "sparse compound index for the 'nodes' collection on " +
                    "{_sdType:1, _sdMaxRevTime:1}.");
        }

        // index on _modified for journal entries
        createIndex(journal, JournalEntry.MODIFIED, true, false, false);
    }

    private void createCollection(MongoDatabase db, String collectionName, MongoStatus mongoStatus) {
        CreateCollectionOptions options = new CreateCollectionOptions();

        if (mongoStatus.isVersion(4, 2)) {
            options.storageEngineOptions(MongoDBConfig.getCollectionStorageOptions(mongoStorageOptions));
            if (!Iterables.tryFind(db.listCollectionNames(), s -> Objects.equals(collectionName, s)).isPresent()) {
                db.createCollection(collectionName, options);
                LOG.info("Creating Collection {}, with collection storage options", collectionName);
            }
        }
    }

    public boolean isReadOnly() {
        return readOnly;
    }

    @Override
    public void finalize() throws Throwable {
        super.finalize();
        // TODO should not be needed, but it seems
        // oak-jcr doesn't call dispose()
        dispose();
    }

    @Override
    public CacheInvalidationStats invalidateCache() {
        InvalidationResult result = new InvalidationResult();
        for (CacheValue key : nodesCache.keys()) {
            result.invalidationCount++;
            invalidateCache(Collection.NODES, key.toString());
        }
        return result;
    }

    @Override
    public CacheInvalidationStats invalidateCache(Iterable<String> keys) {
        LOG.debug("invalidateCache: start");
        final InvalidationResult result = new InvalidationResult();
        int size  = 0;

        final Iterator<String> it = keys.iterator();
        while(it.hasNext()) {
            // read chunks of documents only
            final List<String> ids = new ArrayList<String>(IN_CLAUSE_BATCH_SIZE);
            while(it.hasNext() && ids.size() < IN_CLAUSE_BATCH_SIZE) {
                final String id = it.next();
                if (nodesCache.getIfPresent(id) != null) {
                    // only add those that we actually do have cached
                    ids.add(id);
                }
            }
            size += ids.size();
            if (LOG.isTraceEnabled()) {
                LOG.trace("invalidateCache: batch size: {} of total so far {}",
                        ids.size(), size);
            }

            Map<String, ModificationStamp> modStamps = getModStamps(ids);
            result.queryCount++;

            int invalidated = nodesCache.invalidateOutdated(modStamps);
            for (String id : filter(ids, not(in(modStamps.keySet())))) {
                nodesCache.invalidate(id);
                invalidated++;
            }
            result.cacheEntriesProcessedCount += ids.size();
            result.invalidationCount += invalidated;
            result.upToDateCount += ids.size() - invalidated;
        }

        result.cacheSize = size;
        LOG.trace("invalidateCache: end. total: {}", size);
        return result;
    }

    @Override
    public <T extends Document> void invalidateCache(Collection<T> collection, String key) {
        if (collection == Collection.NODES) {
            nodesCache.invalidate(key);
        }
    }

    @Override
    public <T extends Document> T find(Collection<T> collection, String key) {
        final long start = PERFLOG.start();
        final T result = find(collection, key, true, -1);
        PERFLOG.end(start, 1, "find: preferCached=true, key={}", key);
        return result;
    }

    @Override
    public <T extends Document> T find(final Collection<T> collection,
                                       final String key,
                                       int maxCacheAge) {
        final long start = PERFLOG.start();
        final T result = find(collection, key, false, maxCacheAge);
        PERFLOG.end(start, 1, "find: preferCached=false, key={}", key);
        return result;
    }

    @SuppressWarnings("unchecked")
    private <T extends Document> T find(final Collection<T> collection,
                                       final String key,
                                       boolean preferCached,
                                       final int maxCacheAge) {
        if (collection != Collection.NODES) {
            DocumentReadPreference readPref = DocumentReadPreference.PRIMARY;
            if (withClientSession()) {
                readPref = getDefaultReadPreference(collection);
            }
            return findUncachedWithRetry(collection, key, readPref);
        }
        NodeDocument doc;
        if (maxCacheAge > 0 || preferCached) {
            // first try without lock
            doc = nodesCache.getIfPresent(key);
            if (doc != null) {
                if (preferCached ||
                        getTime() - doc.getCreated() < maxCacheAge) {
                    stats.doneFindCached(collection, key);
                    if (doc == NodeDocument.NULL) {
                        return null;
                    }
                    return (T) doc;
                }
            }
        }
        Throwable t;
        try {
            Lock lock = nodeLocks.acquire(key);
            try {
                if (maxCacheAge > 0 || preferCached) {
                    // try again some other thread may have populated
                    // the cache by now
                    doc = nodesCache.getIfPresent(key);
                    if (doc != null) {
                        if (preferCached ||
                                getTime() - doc.getCreated() < maxCacheAge) {
                            stats.doneFindCached(collection, key);
                            if (doc == NodeDocument.NULL) {
                                return null;
                            }
                            return (T) doc;
                        }
                    }
                }
                final NodeDocument d = (NodeDocument) findUncachedWithRetry(
                        collection, key,
                        getReadPreference(maxCacheAge));
                invalidateCache(collection, key);
                doc = nodesCache.get(key, new Callable<NodeDocument>() {
                    @Override
                    public NodeDocument call() throws Exception {
                        return d == null ? NodeDocument.NULL : d;
                    }
                });
            } finally {
                lock.unlock();
            }
            if (doc == NodeDocument.NULL) {
                return null;
            } else {
                return (T) doc;
            }
        } catch (UncheckedExecutionException | com.google.common.util.concurrent.UncheckedExecutionException e) {
            t = e.getCause();
        } catch (ExecutionException e) {
            t = e.getCause();
        } catch (RuntimeException e) {
            t = e;
        }
        throw handleException(t, collection, key);
    }

    /**
     * Finds a document and performs a number of retries if the read fails with
     * an exception.
     *
     * @param collection the collection to read from.
     * @param key the key of the document to find.
     * @param docReadPref the read preference.
     * @param <T> the document type of the given collection.
     * @return the document or {@code null} if the document doesn't exist.
     */
    @Nullable
    private <T extends Document> T findUncachedWithRetry(
            Collection<T> collection, String key,
            DocumentReadPreference docReadPref) {
        if (key.equals("0:/")) {
            LOG.trace("root node");
        }
        int numAttempts = queryRetries + 1;
        MongoException ex = null;
        for (int i = 0; i < numAttempts; i++) {
            if (i > 0) {
                LOG.warn("Retrying read of " + key);
            }
            try {
                return findUncached(collection, key, docReadPref);
            } catch (MongoException e) {
                ex = e;
                LOG.warn("findUncachedWithRetry : read fails with an exception" + e, e);
            }
        }
        if (ex != null) {
            throw handleException(ex, collection, key);
        } else {
            // impossible to get here
            throw new IllegalStateException();
        }
    }

    @Nullable
    protected <T extends Document> T findUncached(Collection<T> collection, String key, DocumentReadPreference docReadPref) {
        log("findUncached", key, docReadPref);
        final Stopwatch watch = startWatch();
        boolean isSlaveOk = false;
        boolean docFound = true;
        try {
            ReadPreference readPreference = getMongoReadPreference(collection, null, docReadPref);
            MongoCollection<BasicDBObject> dbCollection = getDBCollection(collection, readPreference);

            if(readPreference.isSlaveOk()){
                LOG.trace("Routing call to secondary for fetching [{}]", key);
                isSlaveOk = true;
            }

            List<BasicDBObject> result = new ArrayList<>(1);
            execute(session -> {
                if (session != null) {
                    dbCollection.find(session, getByKeyQuery(key)).into(result);
                } else {
                    dbCollection.find(getByKeyQuery(key)).into(result);
                }
                return null;
            }, collection);

            if(result.isEmpty()) {
                docFound = false;
                return null;
            }
            T doc = convertFromDBObject(collection, result.get(0));
            if (doc != null) {
                doc.seal();
            }
            return doc;
        } finally {
            stats.doneFindUncached(watch.elapsed(TimeUnit.NANOSECONDS), collection, key, docFound, isSlaveOk);
        }
    }

    @NotNull
    @Override
    public <T extends Document> List<T> query(Collection<T> collection,
                                String fromKey,
                                String toKey,
                                int limit) {
        return query(collection, fromKey, toKey, null, 0, limit);
    }

    @NotNull
    @Override
    public <T extends Document> List<T> query(Collection<T> collection,
                                              String fromKey,
                                              String toKey,
                                              String indexedProperty,
                                              long startValue,
                                              int limit) {
        return query(collection, fromKey, toKey, indexedProperty, startValue, limit, emptyList());
    }

    @NotNull
    @Override
    public <T extends Document> List<T> query(final Collection<T> collection,
                                              final String fromKey,
                                              final String toKey,
                                              final String indexedProperty,
                                              final long startValue,
                                              final int limit,
                                              final List<String> projection) throws DocumentStoreException {
        return queryWithRetry(collection, fromKey, toKey, indexedProperty, startValue, limit, projection, maxQueryTimeMS);
    }

    /**
     * Queries for documents and performs a number of retries if the read fails
     * with an exception.
     */
    @NotNull
    private <T extends Document> List<T> queryWithRetry(Collection<T> collection,
                                                        String fromKey,
                                                        String toKey,
                                                        String indexedProperty,
                                                        long startValue,
                                                        int limit,
                                                        List<String> projection,
                                                        long maxQueryTime) {
        int numAttempts = queryRetries + 1;
        MongoException ex = null;
        for (int i = 0; i < numAttempts; i++) {
            if (i > 0) {
                LOG.warn("Retrying query, fromKey={}, toKey={}", fromKey, toKey);
            }
            try {
                return queryInternal(collection, fromKey, toKey,
                        indexedProperty, startValue, limit, projection, maxQueryTime);
            } catch (MongoException e) {
                ex = e;
            }
        }
        if (ex != null) {
            throw handleException(ex, collection, Lists.newArrayList(fromKey, toKey));
        } else {
            // impossible to get here
            throw new IllegalStateException();
        }
    }

    @SuppressWarnings("unchecked")
    @NotNull
    protected <T extends Document> List<T> queryInternal(Collection<T> collection,
                                                         String fromKey,
                                                         String toKey,
                                                         String indexedProperty,
                                                         long startValue,
                                                         int limit,
                                                         List<String> projection,
                                                         long maxQueryTime) {
        log("query", fromKey, toKey, indexedProperty, startValue, limit);

        List<Bson> clauses = new ArrayList<>();
        clauses.add(Filters.gt(Document.ID, fromKey));
        clauses.add(Filters.lt(Document.ID, toKey));

        Bson hint;
        if (NodeDocument.MODIFIED_IN_SECS.equals(indexedProperty)
                && canUseModifiedTimeIdx(startValue)) {
            hint = new BasicDBObject(NodeDocument.MODIFIED_IN_SECS, 1);
        } else {
            hint = new BasicDBObject(NodeDocument.ID, 1);
        }

        if (indexedProperty != null) {
            if (NodeDocument.DELETED_ONCE.equals(indexedProperty)) {
                if (startValue != 1) {
                    throw new DocumentStoreException(
                            "unsupported value for property " + 
                                    NodeDocument.DELETED_ONCE);
                }
                clauses.add(Filters.eq(indexedProperty, true));
            } else {
                clauses.add(Filters.gte(indexedProperty, startValue));
            }
        }
        Bson query = Filters.and(clauses);
        String parentId = Utils.getParentIdFromLowerLimit(fromKey);
        long lockTime = -1;
        final Stopwatch watch = startWatch();

        boolean isSlaveOk = false;
        int resultSize = 0;
        CacheChangesTracker cacheChangesTracker = null;
        if (parentId != null && collection == Collection.NODES && (projection == null || projection.isEmpty())) {
            cacheChangesTracker = nodesCache.registerTracker(fromKey, toKey);
        }
        try {
            ReadPreference readPreference =
                    getMongoReadPreference(collection, parentId, getDefaultReadPreference(collection));

            if(readPreference.isSlaveOk()){
                isSlaveOk = true;
                LOG.trace("Routing call to secondary for fetching children from [{}] to [{}]", fromKey, toKey);
            }

            List<T> list = new ArrayList<T>();
            MongoCollection<BasicDBObject> dbCollection = getDBCollection(collection, readPreference);
            execute(session -> {
                FindIterable<BasicDBObject> result;
                if (session != null) {
                    result = dbCollection.find(session, query);
                } else {
                    result = dbCollection.find(query);
                }

                if (projection != null && !projection.isEmpty()) {
                    result.projection(include(projection));
                }

                result.sort(BY_ID_ASC);
                if (limit >= 0) {
                    result.limit(limit);
                }
                if (!disableIndexHint && !hasModifiedIdCompoundIndex) {
                    result.hint(hint);
                }
                if (maxQueryTime > 0) {
                    // OAK-2614: set maxTime if maxQueryTimeMS > 0
                    result.maxTime(maxQueryTime, TimeUnit.MILLISECONDS);
                }

                try (MongoCursor<BasicDBObject> cursor = result.iterator()) {
                    for (int i = 0; i < limit && cursor.hasNext(); i++) {
                        BasicDBObject o = cursor.next();
                        T doc = convertFromDBObject(collection, o);
                        list.add(doc);
                    }
                }
                return null;
            }, collection);
            resultSize = list.size();

            if (cacheChangesTracker != null) {
                nodesCache.putNonConflictingDocs(cacheChangesTracker, (List<NodeDocument>) list);
            }

            return list;
        } finally {
            if (cacheChangesTracker != null) {
                cacheChangesTracker.close();
            }
            stats.doneQuery(watch.elapsed(TimeUnit.NANOSECONDS), collection, fromKey, toKey,
                    indexedProperty != null , resultSize, lockTime, isSlaveOk);
        }
    }

    boolean canUseModifiedTimeIdx(long modifiedTimeInSecs) {
        if (maxDeltaForModTimeIdxSecs < 0) {
            return false;
        }
        return (NodeDocument.getModifiedInSecs(getTime()) - modifiedTimeInSecs) <= maxDeltaForModTimeIdxSecs;
    }

    @Override
    public <T extends Document> void remove(Collection<T> collection, String key) {
        log("remove", key);
        MongoCollection<BasicDBObject> dbCollection = getDBCollection(collection);
        Stopwatch watch = startWatch();
        try {
            execute(session -> {
                Bson filter = getByKeyQuery(key);
                if (session != null) {
                    dbCollection.deleteOne(session, filter);
                } else {
                    dbCollection.deleteOne(filter);
                }
                return null;
            }, collection);
        } catch (Exception e) {
            throw DocumentStoreException.convert(e, "Remove failed for " + key);
        } finally {
            invalidateCache(collection, key);
            stats.doneRemove(watch.elapsed(TimeUnit.NANOSECONDS), collection, 1);
        }
    }

    @Override
    public <T extends Document> void remove(Collection<T> collection, List<String> keys) {
        log("remove", keys);
        MongoCollection<BasicDBObject> dbCollection = getDBCollection(collection);
        Stopwatch watch = startWatch();
        try {
            for(List<String> keyBatch : Lists.partition(keys, IN_CLAUSE_BATCH_SIZE)){
                Bson query = Filters.in(Document.ID, keyBatch);
                try {
                    execute(session -> {
                        if (session != null) {
                            dbCollection.deleteMany(session, query);
                        } else {
                            dbCollection.deleteMany(query);
                        }
                        return null;
                    }, collection);
                } catch (Exception e) {
                    throw DocumentStoreException.convert(e, "Remove failed for " + keyBatch);
                } finally {
                    if (collection == Collection.NODES) {
                        for (String key : keyBatch) {
                            invalidateCache(collection, key);
                        }
                    }
                }
            }
        } finally {
            stats.doneRemove(watch.elapsed(TimeUnit.NANOSECONDS), collection, keys.size());
        }
    }

    @Override
    public <T extends Document> int remove(Collection<T> collection, Map<String, Long> toRemove) {
        log("remove", toRemove);
        int num = 0;
        MongoCollection<BasicDBObject> dbCollection = getDBCollection(collection);
        Stopwatch watch = startWatch();
        try {
            List<String> batchIds = Lists.newArrayList();
            List<Bson> batch = Lists.newArrayList();
            Iterator<Entry<String, Long>> it = toRemove.entrySet().iterator();
            while (it.hasNext()) {
                Entry<String, Long> entry = it.next();
                Condition c = newEqualsCondition(entry.getValue());
                Bson clause = createQueryForUpdate(entry.getKey(),
                        Collections.singletonMap(KEY_MODIFIED, c));
                batchIds.add(entry.getKey());
                batch.add(clause);
                if (!it.hasNext() || batch.size() == IN_CLAUSE_BATCH_SIZE) {
                    Bson query = Filters.or(batch);
                    try {
                        num += execute(session -> {
                            DeleteResult result;
                            if (session != null) {
                                result = dbCollection.deleteMany(session, query);
                            } else {
                                result = dbCollection.deleteMany(query);
                            }
                            return result.getDeletedCount();
                        }, collection);
                    } catch (Exception e) {
                        throw DocumentStoreException.convert(e, "Remove failed for " + batch);
                    } finally {
                        if (collection == Collection.NODES) {
                            invalidateCache(batchIds);
                        }
                    }
                    batchIds.clear();
                    batch.clear();
                }
            }
        } finally {
            stats.doneRemove(watch.elapsed(TimeUnit.NANOSECONDS), collection, num);
        }
        return num;
    }

    @Override
    public <T extends Document> int remove(Collection<T> collection,
                                    String indexedProperty, long startValue, long endValue)
            throws DocumentStoreException {
        log("remove", collection, indexedProperty, startValue, endValue);
        int num = 0;
        MongoCollection<BasicDBObject> dbCollection = getDBCollection(collection);
        Stopwatch watch = startWatch();
        try {
            Bson query = Filters.and(
                    Filters.gt(indexedProperty, startValue),
                    Filters.lt(indexedProperty, endValue)
            );
            try {
                num = (int) Math.min(execute((DocumentStoreCallable<Long>) session -> {
                    DeleteResult result;
                    if (session != null) {
                        result = dbCollection.deleteMany(session, query);
                    } else {
                        result = dbCollection.deleteMany(query);
                    }
                    return result.getDeletedCount();
                }, collection), MAX_VALUE);
            } catch (Exception e) {
                throw DocumentStoreException.convert(e, "Remove failed for " + collection + ": " +
                    indexedProperty + " in (" + startValue + ", " + endValue + ")");
            } finally {
                if (collection == Collection.NODES) {
                    // this method is currently being used only for Journal collection while GC.
                    // But, to keep sanctity of the API, we need to acknowledge that Nodes collection
                    // could've been used. But, in this signature, there's no useful way to invalidate
                    // cache.
                    // So, we use the hammer for this task
                    invalidateCache();
                }
            }
        } finally {
            stats.doneRemove(watch.elapsed(TimeUnit.NANOSECONDS), collection, num);
        }
        return num;
    }

    @SuppressWarnings("unchecked")
    @Nullable
    private <T extends Document> T findAndModify(Collection<T> collection,
                                                 UpdateOp updateOp,
                                                 boolean upsert,
                                                 boolean checkConditions) {
        MongoCollection<BasicDBObject> dbCollection = getDBCollection(collection);
        // make sure we don't modify the original updateOp
        updateOp = updateOp.copy();
        Bson update = createUpdate(updateOp, !upsert);

        Lock lock = null;
        if (collection == Collection.NODES) {
            lock = nodeLocks.acquire(updateOp.getId());
        }
        final Stopwatch watch = startWatch();
        boolean newEntry = false;
        try {
            // get modCount of cached document
            Long modCount = null;
            T cachedDoc = null;
            if (collection == Collection.NODES) {
                cachedDoc = (T) nodesCache.getIfPresent(updateOp.getId());
                if (cachedDoc != null) {
                    modCount = cachedDoc.getModCount();
                }
            }

            // perform a conditional update with limited result
            // if we have a matching modCount
            if (modCount != null) {
                // only perform the conditional update when there are
                // no conditions and the check is OK. this avoid an
                // unnecessary call when the conditions do not match
                if (!checkConditions || UpdateUtils.checkConditions(cachedDoc, updateOp.getConditions())) {
                    // below condition may overwrite a user supplied condition
                    // on _modCount. This is fine, because the conditions were
                    // already checked against the cached document with the
                    // matching _modCount value. There is no need to check the
                    // user supplied condition on _modCount again on the server
                    Bson query = Filters.and(
                            createQueryForUpdate(updateOp.getId(), updateOp.getConditions()),
                            Filters.eq(Document.MOD_COUNT, modCount)
                    );

                    UpdateResult result = execute(session -> {
                        if (session != null) {
                            return dbCollection.updateOne(session, query, update);
                        } else {
                            return dbCollection.updateOne(query, update);
                        }
                    }, collection);
                    if (result.getModifiedCount() > 0) {
                        // success, update cached document
                        if (collection == Collection.NODES) {
                            NodeDocument newDoc = (NodeDocument) applyChanges(collection, cachedDoc, updateOp);
                            nodesCache.put(newDoc);
                        }
                        // return previously cached document
                        return cachedDoc;
                    }
                }
            }

            // conditional update failed or not possible
            // perform operation and get complete document
            Bson query = createQueryForUpdate(updateOp.getId(), updateOp.getConditions());
            FindOneAndUpdateOptions options = new FindOneAndUpdateOptions()
                    .returnDocument(ReturnDocument.BEFORE).upsert(upsert);
            BasicDBObject oldNode = execute(session -> {
                if (session != null) {
                    return dbCollection.findOneAndUpdate(session, query, update, options);
                } else {
                    return dbCollection.findOneAndUpdate(query, update, options);
                }
            }, collection);

            if (oldNode == null && upsert) {
                newEntry = true;
            }

            if (checkConditions && oldNode == null) {
                return null;
            }
            T oldDoc = convertFromDBObject(collection, oldNode);
            if (oldDoc != null) {
                if (collection == Collection.NODES) {
                    NodeDocument newDoc = (NodeDocument) applyChanges(collection, oldDoc, updateOp);
                    nodesCache.put(newDoc);
                }
                oldDoc.seal();
            } else if (upsert) {
                if (collection == Collection.NODES) {
                    NodeDocument doc = (NodeDocument) collection.newDocument(this);
                    UpdateUtils.applyChanges(doc, updateOp);
                    nodesCache.putIfAbsent(doc);
                }
            } else {
                // updateOp without conditions and not an upsert
                // this means the document does not exist
                if (collection == Collection.NODES) {
                    nodesCache.invalidate(updateOp.getId());
                }
            }
            return oldDoc;
        } catch (MongoWriteException e) {
            WriteError werr = e.getError();
            LOG.error("Failed to update the document with Id={} with MongoWriteException message = '{}'.",
                    updateOp.getId(), werr.getMessage());
            throw handleException(e, collection, updateOp.getId());
        } catch (MongoCommandException e) {
            LOG.error("Failed to update the document with Id={} with MongoCommandException message ='{}'. ",
                    updateOp.getId(), e.getMessage());
            throw handleException(e, collection, updateOp.getId());
        } catch (Exception e) {
            throw handleException(e, collection, updateOp.getId());
        } finally {
            if (lock != null) {
                lock.unlock();
            }
            stats.doneFindAndModify(watch.elapsed(TimeUnit.NANOSECONDS), collection, updateOp.getId(),
                    newEntry, true, 0);
        }
    }

    /**
     * Try to apply all the {@link UpdateOp}s with at least MongoDB requests as
     * possible. The return value is the list of the old documents (before
     * applying changes). The mechanism is as follows:
     *
     * <ol>
     * <li>For each UpdateOp try to read the assigned document from the cache.
     *     Add them to {@code oldDocs}.</li>
     * <li>Prepare a list of all UpdateOps that doesn't have their documents and
     *     read them in one find() call. Add results to {@code oldDocs}.</li>
     * <li>Prepare a bulk update. For each remaining UpdateOp add following
     *     operation:
     *   <ul>
     *   <li>Find document with the same id and the same mod_count as in the
     *       {@code oldDocs}.</li>
     *   <li>Apply changes from the UpdateOps.</li>
     *   </ul>
     * </li>
     * <li>Execute the bulk update.</li>
     * </ol>
     *
     * If some other process modifies the target documents between points 2 and
     * 3, the mod_count will be increased as well and the bulk update will fail
     * for the concurrently modified docs. The method will then remove the
     * failed documents from the {@code oldDocs} and restart the process from
     * point 2. It will stop after 3rd iteration.
     *
     * @see #createOrUpdate(Collection, List)
     */
    @Override
    @NotNull
    public <T extends Document> List<T> findAndUpdate(final @NotNull Collection<T> collection, final @NotNull List<UpdateOp> updateOps) {
        log("findAndUpdate", updateOps);
        final Map<String, UpdateOp> operationsToCover = new LinkedHashMap<>(updateOps.size());
        final List<UpdateOp> duplicates = new ArrayList<>();
        final Map<UpdateOp, T> results = new LinkedHashMap<>(updateOps.size());

        final Stopwatch watch = startWatch();
        int retryCount = 0;
        try {
            for (UpdateOp updateOp : updateOps) {
                UpdateOp clone = updateOp.copy();
                if (operationsToCover.containsKey(updateOp.getId())) {
                    duplicates.add(clone);
                } else {
                    operationsToCover.put(updateOp.getId(), clone);
                }
                results.put(clone, null);
            }

            Map<String, T> oldDocs = new HashMap<>(updateOps.size());
            if (collection == NODES) {
                oldDocs.putAll((Map<String, T>) getCachedNodes(operationsToCover.keySet()));
            }

            for (int i = 0; i <= bulkRetries; i++) {
                retryCount = i;
                if (operationsToCover.size() <= 2) {
                    // bulkUpdate() method invokes Mongo twice, so sending 2 updates
                    // in bulk mode wouldn't result in any performance gain
                    break;
                }
                for (List<UpdateOp> partition : Lists.partition(new ArrayList<>(operationsToCover.values()), bulkSize)) {
                    Map<UpdateOp, T> successfulUpdates = bulkModify(collection, partition, oldDocs);
                    results.putAll(successfulUpdates);
                    operationsToCover.values().removeAll(successfulUpdates.keySet());
                }
            }

            // if there are some changes left, we'll apply them one after another i.e. failed ones
            final Iterator<UpdateOp> it = Iterators.concat(operationsToCover.values().iterator(), duplicates.iterator());
            while (it.hasNext()) {
                UpdateOp op = it.next();
                it.remove();
                results.put(op, findAndUpdate(collection, op));
            }
        } catch (MongoException e) {
            throw handleException(e, collection, Iterables.transform(updateOps, UpdateOp::getId));
        } finally {
            stats.doneFindAndModify(watch.elapsed(NANOSECONDS), collection, updateOps.stream().map(UpdateOp::getId).collect(toList()),
                    true, retryCount);
        }
        final List<T> resultList = new ArrayList<>(results.values());
        log("findAndUpdate returns", resultList);
        return resultList;
    }

    @Nullable
    @Override
    public <T extends Document> T createOrUpdate(Collection<T> collection, UpdateOp update)
            throws DocumentStoreException {
        log("createOrUpdate", update);
        UpdateUtils.assertUnconditional(update);
        T doc = findAndModify(collection, update, update.isNew(), false);
        log("createOrUpdate returns ", doc);
        return doc;
    }

    /**
     * Try to apply all the {@link UpdateOp}s with at least MongoDB requests as
     * possible. The return value is the list of the old documents (before
     * applying changes). The mechanism is as follows:
     *
     * <ol>
     * <li>For each UpdateOp try to read the assigned document from the cache.
     *     Add them to {@code oldDocs}.</li>
     * <li>Prepare a list of all UpdateOps that doesn't have their documents and
     *     read them in one find() call. Add results to {@code oldDocs}.</li>
     * <li>Prepare a bulk update. For each remaining UpdateOp add following
     *     operation:
     *   <ul>
     *   <li>Find document with the same id and the same mod_count as in the
     *       {@code oldDocs}.</li>
     *   <li>Apply changes from the UpdateOps.</li>
     *   </ul>
     * </li>
     * <li>Execute the bulk update.</li>
     * </ol>
     *
     * If some other process modifies the target documents between points 2 and
     * 3, the mod_count will be increased as well and the bulk update will fail
     * for the concurrently modified docs. The method will then remove the
     * failed documents from the {@code oldDocs} and restart the process from
     * point 2. It will stop after 3rd iteration.
     */
    @SuppressWarnings("unchecked")
    @Nullable
    @Override
    public <T extends Document> List<T> createOrUpdate(Collection<T> collection,
                                                       List<UpdateOp> updateOps) {
        log("createOrUpdate", updateOps);

        Map<String, UpdateOp> operationsToCover = new LinkedHashMap<String, UpdateOp>();
        List<UpdateOp> duplicates = new ArrayList<UpdateOp>();
        Map<UpdateOp, T> results = new LinkedHashMap<UpdateOp, T>();

        final Stopwatch watch = startWatch();
        try {
            for (UpdateOp updateOp : updateOps) {
                UpdateUtils.assertUnconditional(updateOp);
                UpdateOp clone = updateOp.copy();
                if (operationsToCover.containsKey(updateOp.getId())) {
                    duplicates.add(clone);
                } else {
                    operationsToCover.put(updateOp.getId(), clone);
                }
                results.put(clone, null);
            }

            Map<String, T> oldDocs = new HashMap<String, T>();
            if (collection == Collection.NODES) {
                oldDocs.putAll((Map<String, T>) getCachedNodes(operationsToCover.keySet()));
            }

            for (int i = 0; i <= bulkRetries; i++) {
                if (operationsToCover.size() <= 2) {
                    // bulkUpdate() method invokes Mongo twice, so sending 2 updates
                    // in bulk mode wouldn't result in any performance gain
                    break;
                }
                for (List<UpdateOp> partition : Lists.partition(Lists.newArrayList(operationsToCover.values()), bulkSize)) {
                    Map<UpdateOp, T> successfulUpdates = bulkUpdate(collection, partition, oldDocs);
                    results.putAll(successfulUpdates);
                    operationsToCover.values().removeAll(successfulUpdates.keySet());
                }
            }

            // if there are some changes left, we'll apply them one after another
            Iterator<UpdateOp> it = Iterators.concat(operationsToCover.values().iterator(), duplicates.iterator());
            while (it.hasNext()) {
                UpdateOp op = it.next();
                it.remove();
                T oldDoc = createOrUpdate(collection, op);
                if (oldDoc != null) {
                    results.put(op, oldDoc);
                }
            }
        } catch (MongoException e) {
            throw handleException(e, collection, Iterables.transform(updateOps,
                    new Function<UpdateOp, String>() {
                @Override
                public String apply(UpdateOp input) {
                    return input.getId();
                }
            }));
        } finally {
            stats.doneCreateOrUpdate(watch.elapsed(TimeUnit.NANOSECONDS),
                    collection, Lists.transform(updateOps, new Function<UpdateOp, String>() {
                @Override
                public String apply(UpdateOp input) {
                    return input.getId();
                }
            }));
        }
        List<T> resultList = new ArrayList<T>(results.values());
        log("createOrUpdate returns", resultList);
        return resultList;
    }

    private Map<String, NodeDocument> getCachedNodes(Set<String> keys) {
        Map<String, NodeDocument> nodes = new HashMap<String, NodeDocument>();
        for (String key : keys) {
            NodeDocument cached = nodesCache.getIfPresent(key);
            if (cached != null) {
                nodes.put(key, cached);
            }
        }
        return nodes;
    }

    @NotNull
    private <T extends Document> Map<UpdateOp, T> bulkModify(final Collection<T> collection, final List<UpdateOp> updateOps,
                                                             final Map<String, T> oldDocs) {
        Map<String, UpdateOp> bulkOperations = createMap(updateOps);
        Set<String> lackingDocs = difference(bulkOperations.keySet(), oldDocs.keySet());
        oldDocs.putAll(findDocuments(collection, lackingDocs));

        CacheChangesTracker tracker = null;
        if (collection == NODES) {
            tracker = nodesCache.registerTracker(bulkOperations.keySet());
        }

        try {
            final BulkRequestResult bulkResult = sendBulkRequest(collection, bulkOperations.values(), oldDocs, false);
            final Set<String> potentiallyUpdatedDocsSet = difference(bulkOperations.keySet(), bulkResult.failedUpdates);

            final Map<String, T> updatedDocsMap = new HashMap<>(potentiallyUpdatedDocsSet.size());

            final List<NodeDocument> docsToCache = new ArrayList<>();

            if (bulkResult.modifiedCount == potentiallyUpdatedDocsSet.size()) {
                // all documents had been updated, now we can simply
                // apply the update op on oldDocs and update the cache
                potentiallyUpdatedDocsSet.forEach(key -> {
                    T oldDoc = oldDocs.get(key);
                    if (isNull(oldDoc) || oldDoc == NULL) {
                        log("Skipping updating doc cache for ", key);
                        return;
                    }
                    T newDoc = applyChanges(collection, oldDoc, bulkOperations.get(key));
                    updatedDocsMap.put(newDoc.getId(), newDoc);
                    if (collection == NODES) {
                        docsToCache.add((NodeDocument) newDoc);
                    }
                });
            } else {
                // some documents might have not been updated, lets fetch them from database
                // and found out which had not been updated
                updatedDocsMap.putAll(findDocuments(collection, potentiallyUpdatedDocsSet));

                updatedDocsMap.forEach((key, value) -> {
                    T oldDoc = oldDocs.get(key);
                    if (isNull(oldDoc) || oldDoc == NULL || Objects.equals(oldDoc.getModCount(), value.getModCount())) {
                        // simply ignore updating the document cache in case
                        // 1. oldDoc is null
                        // 2. document didn't get updated i.e. modCount is same after update operation
                        log("Skipping updating doc cache for ", key);
                        return;
                    }
                    if (collection == NODES) {
                        docsToCache.add((NodeDocument) applyChanges(collection, oldDoc, bulkOperations.get(key)));
                    }
                });
            }

            // updates nodesCache if
            if (collection == NODES && docsToCache.size() > 0) {
                nodesCache.putNonConflictingDocs(tracker, docsToCache);
            }
            oldDocs.keySet().removeAll(bulkResult.failedUpdates);

            final Map<UpdateOp, T> result = new HashMap<>(oldDocs.size());

            // document might have been updated, if updated then add oldDoc else add null to result
            bulkOperations.entrySet().stream().filter(e -> !bulkResult.failedUpdates.contains(e.getKey())).forEach(e -> {
                T updated = updatedDocsMap.get(e.getKey());
                T oldDoc = oldDocs.get(e.getKey());
                if (oldDoc == null || oldDoc == NULL || Objects.equals(oldDoc.getModCount(), updated.getModCount())) {
                    // add null value in result cause, either this document didn't exist
                    // at time of modify operation, and we didn't anything for it
                    // or oldDoc is present and modCount is same,
                    // so document had not been updated.
                    log(" didn't get updated, returning null.", e.getKey());
                    result.put(e.getValue(), null);
                } else {
                    // document had been updated, seal the document and add in the result map
                    oldDoc.seal();
                    result.put(e.getValue(), oldDoc);
                }
            });
            return result;
        } finally {
            if (tracker != null) {
                tracker.close();
            }
        }
    }

    private <T extends Document> Map<UpdateOp, T> bulkUpdate(Collection<T> collection,
                                                             List<UpdateOp> updateOperations,
                                                             Map<String, T> oldDocs) {
        Map<String, UpdateOp> bulkOperations = createMap(updateOperations);
        Set<String> lackingDocs = difference(bulkOperations.keySet(), oldDocs.keySet());
        oldDocs.putAll(findDocuments(collection, lackingDocs));

        CacheChangesTracker tracker = null;
        if (collection == Collection.NODES) {
            tracker = nodesCache.registerTracker(bulkOperations.keySet());
        }

        try {
            BulkRequestResult bulkResult = sendBulkRequest(collection, bulkOperations.values(), oldDocs, true);

            if (collection == Collection.NODES) {
                List<NodeDocument> docsToCache = new ArrayList<NodeDocument>();
                for (UpdateOp op : filterKeys(bulkOperations, in(bulkResult.upserts)).values()) {
                    NodeDocument doc = Collection.NODES.newDocument(this);
                    UpdateUtils.applyChanges(doc, op);
                    docsToCache.add(doc);
                }

                for (String key : difference(bulkOperations.keySet(), bulkResult.failedUpdates)) {
                    T oldDoc = oldDocs.get(key);
                    if (oldDoc != null && oldDoc != NodeDocument.NULL) {
                        NodeDocument newDoc = (NodeDocument) applyChanges(collection, oldDoc, bulkOperations.get(key));
                        docsToCache.add(newDoc);
                    }
                }

                nodesCache.putNonConflictingDocs(tracker, docsToCache);
            }
            oldDocs.keySet().removeAll(bulkResult.failedUpdates);

            Map<UpdateOp, T> result = new HashMap<UpdateOp, T>();
            for (Entry<String, UpdateOp> entry : bulkOperations.entrySet()) {
                if (bulkResult.failedUpdates.contains(entry.getKey())) {
                    continue;
                } else if (bulkResult.upserts.contains(entry.getKey())) {
                    result.put(entry.getValue(), null);
                } else {
                    result.put(entry.getValue(), oldDocs.get(entry.getKey()));
                }
            }
            return result;
        } finally {
            if (tracker != null) {
                tracker.close();
            }
        }
    }

    private static Map<String, UpdateOp> createMap(List<UpdateOp> updateOps) {
        return Maps.uniqueIndex(updateOps, new Function<UpdateOp, String>() {
            @Override
            public String apply(UpdateOp input) {
                return input.getId();
            }
        });
    }

    private <T extends Document> Map<String, T> findDocuments(Collection<T> collection, Set<String> keys) {
        Map<String, T> docs = new HashMap<String, T>();
        if (!keys.isEmpty()) {
            List<Bson> conditions = new ArrayList<>(keys.size());
            for (String key : keys) {
                conditions.add(getByKeyQuery(key));
            }
            MongoCollection<BasicDBObject> dbCollection;
            if (secondariesWithinAcceptableLag()) {
                dbCollection = getDBCollection(collection);
            } else {
                lagTooHigh();
                dbCollection = getDBCollection(collection).withReadPreference(ReadPreference.primary());
            }
            execute(session -> {
                FindIterable<BasicDBObject> cursor;
                if (session != null) {
                    cursor = dbCollection.find(session, Filters.or(conditions));
                } else {
                    cursor = dbCollection.find(Filters.or(conditions));
                }
                for (BasicDBObject doc : cursor) {
                    T foundDoc = convertFromDBObject(collection, doc);
                    docs.put(foundDoc.getId(), foundDoc);
                }
                return null;
            }, collection);
        }
        return docs;
    }

    @NotNull
    private <T extends Document> BulkRequestResult sendBulkRequest(final Collection<T> collection,
                                                                   final java.util.Collection<UpdateOp> updateOps,
                                                                   final Map<String, T> oldDocs,
                                                                   final boolean isUpsert) {
        MongoCollection<BasicDBObject> dbCollection = getDBCollection(collection);
        List<WriteModel<BasicDBObject>> writes = new ArrayList<>(updateOps.size());
        String[] bulkIds = new String[updateOps.size()];
        int i = 0;
        for (UpdateOp updateOp : updateOps) {
            String id = updateOp.getId();
            Bson query = createQueryForUpdate(id, updateOp.getConditions());
            // fail on insert when isNew == false OR isUpsert == false
            boolean failInsert = !(isUpsert && updateOp.isNew());
            T oldDoc = oldDocs.get(id);
            if (oldDoc == null || oldDoc == NodeDocument.NULL) {
                query = Filters.and(query, Filters.exists(Document.MOD_COUNT, false));
            } else {
                query = Filters.and(query, Filters.eq(Document.MOD_COUNT, oldDoc.getModCount()));
            }
            writes.add(new UpdateOneModel<>(query, createUpdate(updateOp, failInsert), new UpdateOptions().upsert(isUpsert))
            );
            bulkIds[i++] = id;
        }

        BulkWriteResult bulkResult;
        Set<String> failedUpdates = new HashSet<String>();
        Set<String> upserts = new HashSet<String>();
        BulkWriteOptions options = new BulkWriteOptions().ordered(false);
        try {
            bulkResult = execute(session -> {
                if (session != null) {
                    return dbCollection.bulkWrite(session, writes, options);
                } else {
                    return dbCollection.bulkWrite(writes, options);
                }
            }, collection);
        } catch (MongoBulkWriteException e) {
            bulkResult = e.getWriteResult();
            for (BulkWriteError err : e.getWriteErrors()) {
                failedUpdates.add(bulkIds[err.getIndex()]);
            }
        }
        for (BulkWriteUpsert upsert : bulkResult.getUpserts()) {
            upserts.add(bulkIds[upsert.getIndex()]);
        }
        return new BulkRequestResult(failedUpdates, upserts, bulkResult.getModifiedCount());
    }

    @Override
    public <T extends Document> T findAndUpdate(Collection<T> collection, UpdateOp update)
            throws DocumentStoreException {
        log("findAndUpdate", update);
        T doc = findAndModify(collection, update, false, true);
        log("findAndUpdate returns ", doc);
        return doc;
    }

    @Override
    public <T extends Document> boolean create(Collection<T> collection, List<UpdateOp> updateOps) {
        log("create", updateOps);
        List<T> docs = new ArrayList<T>();
        List<BasicDBObject> inserts = new ArrayList<>(updateOps.size());
        List<String> ids = new ArrayList<>(updateOps.size());

        for (UpdateOp update : updateOps) {
            BasicDBObject doc = new BasicDBObject();
            inserts.add(doc);
            doc.put(Document.ID, update.getId());
            UpdateUtils.assertUnconditional(update);
            T target = collection.newDocument(this);
            UpdateUtils.applyChanges(target, update);
            docs.add(target);
            ids.add(update.getId());
            for (Entry<Key, Operation> entry : update.getChanges().entrySet()) {
                Key k = entry.getKey();
                Operation op = entry.getValue();
                switch (op.type) {
                    case SET:
                    case MAX:
                    case INCREMENT: {
                        doc.put(k.toString(), op.value);
                        break;
                    }
                    case SET_MAP_ENTRY: {
                        Revision r = k.getRevision();
                        if (r == null) {
                            throw new IllegalStateException("SET_MAP_ENTRY must not have null revision");
                        }
                        BasicDBObject value = (BasicDBObject) doc.get(k.getName());
                        if (value == null) {
                            value = new BasicDBObject();
                            doc.put(k.getName(), value);
                        }
                        value.put(r.toString(), op.value);
                        break;
                    }
                    case REMOVE:
                    case REMOVE_MAP_ENTRY:
                        // nothing to do for new entries
                        break;
                }
            }
            if (!doc.containsField(Document.MOD_COUNT)) {
                doc.put(Document.MOD_COUNT, 1L);
                target.put(Document.MOD_COUNT, 1L);
            }
        }

        MongoCollection<BasicDBObject> dbCollection = getDBCollection(collection);
        final Stopwatch watch = startWatch();
        boolean insertSuccess = false;
        try {
            try {
                execute(session -> {
                    if (session != null) {
                        dbCollection.insertMany(session, inserts);
                    } else {
                        dbCollection.insertMany(inserts);
                    }
                    return null;
                }, collection);
                if (collection == Collection.NODES) {
                    for (T doc : docs) {
                        nodesCache.putIfAbsent((NodeDocument) doc);
                    }
                }
                insertSuccess = true;
                return true;
            } catch (BsonMaximumSizeExceededException e) {
                for (T doc : docs) {
                    LOG.error("Failed to create one of the documents " +
                                    "with BsonMaximumSizeExceededException message = '{}'. " +
                                    "The document id={} has estimated size={} in VM.",
                                    e.getMessage(), doc.getId(), doc.getMemory());
                }
                return false;
            } catch (MongoException e) {
                return false;
            }
        } finally {
            stats.doneCreate(watch.elapsed(TimeUnit.NANOSECONDS), collection, ids, insertSuccess);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T extends Document> void prefetch(Collection<T> collection,
                                              Iterable<String> keysToPrefetch) {
        log("prefetch", keysToPrefetch);

        Set<String> keys = new HashSet<>();
        for (String k : keysToPrefetch) {
            if (nodesCache.getIfPresent(k) == null) {
                keys.add(k);
            }
        }
        if (keys.size() < minPrefetch) {
            return;
        }

        final Stopwatch watch = startWatch();
        List<String> resultKeys = new ArrayList<>(keys.size());
        CacheChangesTracker tracker = null;
        if (collection == Collection.NODES) {
            // keys set is modified later. create a copy of the keys set
            // owned by the cache changes tracker.
            tracker = nodesCache.registerTracker(new HashSet<>(keys));
        }
        Throwable t;
        try {
            ReadPreference readPreference = getMongoReadPreference(collection, null, getDefaultReadPreference(collection));
            MongoCollection<BasicDBObject> dbCollection = getDBCollection(collection, readPreference);

            if (readPreference.isSlaveOk()) {
                LOG.trace("Routing call to secondary for prefetching [{}]", keys);
            }

            List<BasicDBObject> result = new ArrayList<>(keys.size());
            execute(session -> {
                final Bson query = Filters.in(Document.ID, keys);
                if (session != null) {
                    dbCollection.find(session, query).into(result);
                } else {
                    dbCollection.find(query).into(result);
                }
                return null;
            }, collection);

            List<T> docs = new ArrayList<>(keys.size());
            for (BasicDBObject dbObject : result) {
                final T d = convertFromDBObject(collection, dbObject);
                if (d == null) {
                    continue;
                }
                d.seal();
                String key = String.valueOf(d.get(Document.ID));
                resultKeys.add(key);
                keys.remove(key);
                docs.add(d);
            }

            if (tracker != null) {
                nodesCache.putNonConflictingDocs(tracker, (List<NodeDocument>) docs);

                // documents for remaining ids in keys do not exist
                for (String id : keys) {
                    Lock lock = nodeLocks.acquire(id);
                    try {
                        // load NULL document into cache unless it may have
                        // been affected by another concurrent operation
                        if (!tracker.mightBeenAffected(id)) {
                            nodesCache.get(id, () -> NULL);
                        }
                    } finally {
                        lock.unlock();
                    }
                }
            }
            return;
        } catch (UncheckedExecutionException | com.google.common.util.concurrent.UncheckedExecutionException | ExecutionException e) {
            t = e.getCause();
        } catch (RuntimeException e) {
            t = e;
        } finally {
            if (tracker != null) {
                tracker.close();
            }
            stats.donePrefetch(watch.elapsed(TimeUnit.NANOSECONDS), collection, resultKeys);
        }
        throw handleException(t, collection, keysToPrefetch);
    }

    /**
     * Returns the {@link Document#MOD_COUNT} and
     * {@link NodeDocument#MODIFIED_IN_SECS} values of the documents with the
     * given {@code keys}. The returned map will only contain entries for
     * existing documents. The default value is -1 if the document does not have
     * a modCount field. The same applies to the modified field.
     *
     * @param keys the keys of the documents.
     * @return map with key to modification stamp mapping.
     * @throws MongoException if the call fails
     */
    @NotNull
    private Map<String, ModificationStamp> getModStamps(Iterable<String> keys)
            throws MongoException {
        // Fetch only the modCount and id
        final BasicDBObject fields = new BasicDBObject(Document.ID, 1);
        fields.put(Document.MOD_COUNT, 1);
        fields.put(NodeDocument.MODIFIED_IN_SECS, 1);

        Map<String, ModificationStamp> modCounts = Maps.newHashMap();

        nodes.withReadPreference(ReadPreference.primary())
                .find(Filters.in(Document.ID, keys)).projection(fields)
                .forEach((Block<BasicDBObject>) obj -> {
                    String id = (String) obj.get(Document.ID);
                    Long modCount = Utils.asLong((Number) obj.get(Document.MOD_COUNT));
                    if (modCount == null) {
                        modCount = -1L;
                    }
                    Long modified = Utils.asLong((Number) obj.get(NodeDocument.MODIFIED_IN_SECS));
                    if (modified == null) {
                        modified = -1L;
                    }
                    modCounts.put(id, new ModificationStamp(modCount, modified));
                });
        return modCounts;
    }

    DocumentReadPreference getReadPreference(int maxCacheAge) {
        if (withClientSession()) {
            return DocumentReadPreference.PREFER_SECONDARY;
        } else if(maxCacheAge >= 0 && maxCacheAge < maxReplicationLagMillis) {
            return DocumentReadPreference.PRIMARY;
        } else if(maxCacheAge == MAX_VALUE){
            return DocumentReadPreference.PREFER_SECONDARY;
        } else {
           return DocumentReadPreference.PREFER_SECONDARY_IF_OLD_ENOUGH;
        }
    }

    DocumentReadPreference getDefaultReadPreference(Collection col) {
        DocumentReadPreference preference = DocumentReadPreference.PRIMARY;
        if (withClientSession()) {
            preference = DocumentReadPreference.PREFER_SECONDARY;
        } else if (col == Collection.NODES) {
            preference = DocumentReadPreference.PREFER_SECONDARY_IF_OLD_ENOUGH;
        }
        return preference;
    }

    <T extends Document> ReadPreference getMongoReadPreference(@NotNull Collection<T> collection,
                                                               @Nullable String parentId,
                                                               @NotNull DocumentReadPreference preference) {
        switch(preference){
            case PRIMARY:
                return ReadPreference.primary();
            case PREFER_PRIMARY :
                return ReadPreference.primaryPreferred();
            case PREFER_SECONDARY :
                if (!withClientSession() || secondariesWithinAcceptableLag()) {
                    return getConfiguredReadPreference(collection);
                } else {
                    lagTooHigh();
                    return ReadPreference.primary();
                }
            case PREFER_SECONDARY_IF_OLD_ENOUGH:
                if(collection != Collection.NODES){
                    return ReadPreference.primary();
                }

                boolean secondarySafe;
                if (withClientSession() && secondariesWithinAcceptableLag()) {
                    secondarySafe = true;
                } else {
                   // This is not quite accurate, because ancestors
                    // are updated in a background thread (_lastRev). We
                    // will need to revise this for low maxReplicationLagMillis
                    // values
                    long replicationSafeLimit = getTime() - maxReplicationLagMillis;

                    if (parentId == null) {
                        secondarySafe = false;
                    } else {
                        //If parent has been modified loooong time back then there children
                        //would also have not be modified. In that case we can read from secondary
                        NodeDocument cachedDoc = getIfCached(Collection.NODES, parentId);
                        secondarySafe = cachedDoc != null && !cachedDoc.hasBeenModifiedSince(replicationSafeLimit);
                    }
                }

                ReadPreference readPreference;
                if (secondarySafe) {
                    readPreference = getConfiguredReadPreference(collection);
                } else {
                    readPreference = ReadPreference.primary();
                }

                return readPreference;
            default:
                throw new IllegalArgumentException("Unsupported usage " + preference);
        }
    }

    /**
     * Retrieves the ReadPreference specified for the Mongo DB in use irrespective of
     * DBCollection. Depending on deployments the user can tweak the default references
     * to read from secondary and in that also tag secondaries
     *
     * @return db level ReadPreference
     */
    <T extends Document> ReadPreference getConfiguredReadPreference(Collection<T> collection){
        return getDBCollection(collection).getReadPreference();
    }

    @Nullable
    protected <T extends Document> T convertFromDBObject(@NotNull Collection<T> collection,
                                                         @Nullable DBObject n) {
        T copy = null;
        if (n != null) {
            copy = collection.newDocument(this);
            for (String key : n.keySet()) {
                Object o = n.get(key);
                if (o instanceof String) {
                    copy.put(key, o);
                } else if (o instanceof Number &&
                        (NodeDocument.MODIFIED_IN_SECS.equals(key) || Document.MOD_COUNT.equals(key))) {
                    copy.put(key, Utils.asLong((Number) o));
                } else if (o instanceof Long) {
                    copy.put(key, o);
                } else if (o instanceof Integer) {
                    copy.put(key, o);
                } else if (o instanceof Boolean) {
                    copy.put(key, o);
                } else if (o instanceof BasicDBObject) {
                    copy.put(key, convertMongoMap((BasicDBObject) o));
                }
            }
        }
        return copy;
    }

    @NotNull
    private Map<Revision, Object> convertMongoMap(@NotNull BasicDBObject obj) {
        Map<Revision, Object> map = new TreeMap<Revision, Object>(StableRevisionComparator.REVERSE);
        for (Map.Entry<String, Object> entry : obj.entrySet()) {
            map.put(Revision.fromString(entry.getKey()), entry.getValue());
        }
        return map;
    }

    <T extends Document> MongoCollection<BasicDBObject> getDBCollection(Collection<T> collection) {
        if (collection == Collection.NODES) {
            return nodes;
        } else if (collection == Collection.CLUSTER_NODES) {
            return clusterNodes;
        } else if (collection == Collection.SETTINGS) {
            return settings;
        } else if (collection == Collection.JOURNAL) {
            return journal;
        } else {
            throw new IllegalArgumentException(
                    "Unknown collection: " + collection.toString());
        }
    }

    <T extends Document> MongoCollection<BasicDBObject> getDBCollection(Collection<T> collection,
                                                                        ReadPreference readPreference) {
        return getDBCollection(collection).withReadPreference(readPreference);
    }

    MongoDatabase getDatabase() {
        return connection.getDatabase();
    }

    MongoClient getClient() {
        return connection.getClient();
    }

    private static Bson getByKeyQuery(String key) {
        return Filters.eq(Document.ID, key);
    }

    @Override
    public void dispose() {
        connection.close();
        if (clusterNodesConnection != connection) {
            clusterNodesConnection.close();
        }
        try {
            Closeables.close(throttlingMetricsUpdater, false);
        } catch (IOException e) {
            LOG.warn("Error occurred while closing throttlingMetricsUpdater", e);
        }
        try {
            nodesCache.close();
        } catch (IOException e) {
            LOG.warn("Error occurred while closing nodes cache", e);
        }
    }

    @Override
    public Iterable<CacheStats> getCacheStats() {
        return nodesCache.getCacheStats();
    }

    @Override
    public Map<String, String> getMetadata() {
        return metadata;
    }

    @NotNull
    @Override
    public Map<String, String> getStats() {
        ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
        List<MongoCollection<?>> all = ImmutableList.of(nodes, clusterNodes, settings, journal);
        all.forEach(c -> toMapBuilder(builder,
                connection.getDatabase().runCommand(
                    new BasicDBObject("collStats", c.getNamespace().getCollectionName()),
                        BasicDBObject.class),
                c.getNamespace().getCollectionName()));
        return builder.build();
    }

    long getMaxDeltaForModTimeIdxSecs() {
        return maxDeltaForModTimeIdxSecs;
    }

    boolean getDisableIndexHint() {
        return disableIndexHint;
    }

    private static void log(String message, Object... args) {
        if (LOG.isDebugEnabled()) {
            String argList = Arrays.toString(args);
            if (argList.length() > 10000) {
                argList = argList.length() + ": " + argList;
            }
            LOG.debug(message + argList);
        }
    }

    @Override
    public <T extends Document> T getIfCached(Collection<T> collection, String key) {
        if (collection != Collection.NODES) {
            return null;
        }
        @SuppressWarnings("unchecked")
        T doc = (T) nodesCache.getIfPresent(key);
        if (doc == NodeDocument.NULL) {
            doc = null;
        }
        return doc;
    }

    @NotNull
    private static Bson createQueryForUpdate(String key,
                                             Map<Key, Condition> conditions) {
        Bson query = getByKeyQuery(key);
        if (conditions.isEmpty()) {
            // special case when there are no conditions
            return query;
        }
        List<Bson> conditionList = new ArrayList<>(conditions.size() + 1);
        conditionList.add(query);
        for (Entry<Key, Condition> entry : conditions.entrySet()) {
            Key k = entry.getKey();
            Condition c = entry.getValue();
            switch (c.type) {
                case EXISTS:
                    conditionList.add(Filters.exists(k.toString(), Boolean.TRUE.equals(c.value)));
                    break;
                case EQUALS:
                    conditionList.add(Filters.eq(k.toString(), c.value));
                    break;
                case NOTEQUALS:
                    conditionList.add(Filters.ne(k.toString(), c.value));
                    break;
            }
        }
        return Filters.and(conditionList);
    }

    /**
     * Creates a MongoDB update object from the given UpdateOp.
     *
     * @param updateOp the update op.
     * @param failOnInsert whether to create an update that will fail on insert.
     * @return the DBObject.
     */
    private static BasicDBObject createUpdate(UpdateOp updateOp,
                                              boolean failOnInsert) {
        BasicDBObject setUpdates = new BasicDBObject();
        BasicDBObject maxUpdates = new BasicDBObject();
        BasicDBObject incUpdates = new BasicDBObject();
        BasicDBObject unsetUpdates = new BasicDBObject();
        // always increment modCount
        updateOp.increment(Document.MOD_COUNT, 1);

        // other updates
        for (Entry<Key, Operation> entry : updateOp.getChanges().entrySet()) {
            Key k = entry.getKey();
            Operation op = entry.getValue();
            switch (op.type) {
                case SET:
                case SET_MAP_ENTRY: {
                    setUpdates.append(k.toString(), op.value);
                    break;
                }
                case MAX: {
                    maxUpdates.append(k.toString(), op.value);
                    break;
                }
                case INCREMENT: {
                    incUpdates.append(k.toString(), op.value);
                    break;
                }
                case REMOVE:
                case REMOVE_MAP_ENTRY: {
                    unsetUpdates.append(k.toString(), "1");
                    break;
                }
            }
        }

        BasicDBObject update = new BasicDBObject();
        if (!setUpdates.isEmpty()) {
            update.append("$set", setUpdates);
        }
        if (!maxUpdates.isEmpty()) {
            update.append("$max", maxUpdates);
        }
        if (!incUpdates.isEmpty()) {
            update.append("$inc", incUpdates);
        }
        if (!unsetUpdates.isEmpty()) {
            update.append("$unset", unsetUpdates);
        }

        if (failOnInsert) {
            update.putAll(CONFLICT_ON_INSERT);
        }

        return update;
    }

    @NotNull
    private <T extends Document> T applyChanges(Collection<T> collection, T oldDoc, UpdateOp update) {
        T doc = collection.newDocument(this);
        oldDoc.deepCopy(doc);
        UpdateUtils.applyChanges(doc, update);
        doc.seal();
        return doc;
    }

    private Stopwatch startWatch() {
        return Stopwatch.createStarted();
    }


    @Override
    public void setReadWriteMode(String readWriteMode) {
        if (readWriteMode == null || readWriteMode.equals(lastReadWriteMode)) {
            return;
        }
        lastReadWriteMode = readWriteMode;
        try {
            String rwModeUri = readWriteMode;
            if(!readWriteMode.startsWith("mongodb://")){
                rwModeUri = String.format("mongodb://localhost/?%s", readWriteMode);
            }
            MongoClientURI uri = new MongoClientURI(rwModeUri);
            ReadPreference readPref = uri.getOptions().getReadPreference();

            if (!readPref.equals(nodes.getReadPreference())) {
                nodes = nodes.withReadPreference(readPref);
                LOG.info("Using ReadPreference {} ", readPref);
            }

            WriteConcern writeConcern = uri.getOptions().getWriteConcern();
            if (!writeConcern.equals(nodes.getWriteConcern())) {
                nodes = nodes.withWriteConcern(writeConcern);
                LOG.info("Using WriteConcern " + writeConcern);
            }
        } catch (Exception e) {
            LOG.error("Error setting readWriteMode " + readWriteMode, e);
        }
    }

    private long getTime() {
        return clock.getTime();
    }

    void setClock(Clock clock) {
        this.clock = clock;
    }

    NodeDocumentCache getNodeDocumentCache() {
        return nodesCache;
    }

    public void setStatsCollector(DocumentStoreStatsCollector stats) {
        this.stats = stats;
    }

    @Override
    public long determineServerTimeDifferenceMillis() {
        // the assumption is that the network delay from this instance
        // to the server, and from the server back to this instance
        // are (more or less) equal.
        // taking this assumption into account allows to remove
        // the network delays from the picture: the difference
        // between end and start time is exactly this network
        // delay (plus some server time, but that's neglected).
        // so if the clocks are in perfect sync and the above
        // mentioned assumption holds, then the server time should
        // be exactly at the midPoint between start and end.
        // this should allow a more accurate picture of the diff.
        final long start = System.currentTimeMillis();
        // assumption here: server returns UTC - ie the returned
        // date object is correctly taking care of time zones.
        final BasicDBObject isMaster;
        try {
            isMaster = getDatabase().runCommand(new BasicDBObject("isMaster", 1), BasicDBObject.class);
            if (isMaster == null) {
                // OAK-4107 / OAK-4515 : extra safety
                LOG.warn("determineServerTimeDifferenceMillis: db.isMaster returned null - cannot determine time difference - assuming 0ms.");
                return 0;
            }
            final Date serverLocalTime = isMaster.getDate("localTime");
            if (serverLocalTime == null) {
                // OAK-4107 / OAK-4515 : looks like this can happen - at least
                // has been seen once on mongo 3.0.9
                // let's handle this gently and issue a log.warn
                // instead of throwing a NPE
                LOG.warn("determineServerTimeDifferenceMillis: db.isMaster.localTime returned null - cannot determine time difference - assuming 0ms.");
                return 0;
            }
            final long end = System.currentTimeMillis();

            final long midPoint = (start + end) / 2;
            final long serverLocalTimeMillis = serverLocalTime.getTime();

            // the difference should be
            // * positive when local instance is ahead
            // * and negative when the local instance is behind
            final long diff = midPoint - serverLocalTimeMillis;

            return diff;
        } catch (Exception e) {
            LOG.warn("determineServerTimeDifferenceMillis: db.isMaster failed with exception - assuming 0ms. "
                            + "(Result details: server exception=" + e + ", server error message=" + e.getMessage() + ")", e);
        }
        return 0;
    }

    private <T extends Document> DocumentStoreException handleException(Throwable ex,
                                                                        Collection<T> collection,
                                                                        Iterable<String> ids) {
        if (collection == Collection.NODES) {
            for (String id : ids) {
                invalidateCache(collection, id);
            }
        }
        return asDocumentStoreException(ex.getMessage(), ex,
                getDocumentStoreExceptionTypeFor(ex), ids);
    }

    private <T extends Document> DocumentStoreException handleException(Throwable ex,
                                                                        Collection<T> collection,
                                                                        String id) {
        return handleException(ex, collection, Collections.singleton(id));
    }

    private static void toMapBuilder(ImmutableMap.Builder<String, String> builder,
                                     BasicDBObject stats,
                                     String prefix) {
        stats.forEach((k, v) -> {
            // exclude some verbose internals and status
            if (!k.equals("wiredTiger") && !k.equals("indexDetails") && !k.equals("ok")) {
                String key = prefix + "." + k;
                if (v instanceof BasicDBObject) {
                    toMapBuilder(builder, (BasicDBObject) v, key);
                } else {
                    builder.put(key, String.valueOf(v));
                }
            }
        });
    }

    private boolean withClientSession() {
        return connection.getStatus().isClientSessionSupported() && useClientSession;
    }

    private boolean secondariesWithinAcceptableLag() {
        return getClient().getReplicaSetStatus() == null
                || connection.getStatus().getReplicaSetLagEstimate() < acceptableLagMillis;
    }

    private void lagTooHigh() {
        LOG.debug("Read from secondary is preferred but replication lag is too high. Directing read to primary.");
    }

    /**
     * Execute a callable with an optional {@link ClientSession}. A client
     * session is passed to {@link DocumentStoreCallable#call(ClientSession)} if
     * the connected MongoDB servers support client sessions, otherwise the
     * session is {@code null}. The client session must only be used within
     * the scope of the {@link DocumentStoreCallable#call(ClientSession)}.
     * 
     * @param callable the callable.
     * @param collection the collection this callable operates on.
     * @param <T> the return type of the callable.
     * @return the result of the callable.
     * @throws DocumentStoreException if the callable throws an exception.
     */
    private <T> T execute(@NotNull DocumentStoreCallable<T> callable,
                          @NotNull Collection<?> collection)
            throws DocumentStoreException {
        T result;
        if (withClientSession()) {
            try (ClientSession session = createClientSession(collection)) {
                result = callable.call(session);
            }
        } else {
            result = callable.call(null);
        }
        return result;
    }

    private ClientSession createClientSession(Collection<?> collection) {
        MongoDBConnection dbConnection;
        if (Collection.CLUSTER_NODES == collection) {
            dbConnection = clusterNodesConnection;
        } else {
            dbConnection = connection;
        }
        return dbConnection.createClientSession();
    }

    interface DocumentStoreCallable<T> {

        T call(@Nullable ClientSession session) throws DocumentStoreException;
    }

    private static class BulkRequestResult {

        private final Set<String> failedUpdates;

        private final Set<String> upserts;
        private final int modifiedCount;

        private BulkRequestResult(Set<String> failedUpdates, Set<String> upserts, int modifiedCount) {
            this.failedUpdates = failedUpdates;
            this.upserts = upserts;
            this.modifiedCount = modifiedCount;
        }
    }

    private static class InvalidationResult implements CacheInvalidationStats {
        int invalidationCount;
        int upToDateCount;
        int cacheSize;
        int queryCount;
        int cacheEntriesProcessedCount;

        @Override
        public String toString() {
            return "InvalidationResult{" +
                    "invalidationCount=" + invalidationCount +
                    ", upToDateCount=" + upToDateCount +
                    ", cacheSize=" + cacheSize +
                    ", queryCount=" + queryCount +
                    ", cacheEntriesProcessedCount=" + cacheEntriesProcessedCount +
                    '}';
        }

        @Override
        public String summaryReport() {
            return toString();
        }
    }
}
