/*
 * Copyright (c) 2008 - 2013 10gen, Inc. <http://10gen.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.mongodb.session;

import org.mongodb.annotations.NotThreadSafe;
import org.mongodb.connection.Cluster;
import org.mongodb.connection.ServerConnection;
import org.mongodb.connection.ServerSelector;

import static org.mongodb.assertions.Assertions.isTrue;
import static org.mongodb.assertions.Assertions.notNull;

/**
 * @since 3.0
 */
@NotThreadSafe
public class MonotonicSession implements ServerSelectingSession {
    private ServerSelector lastRequestedServerSelector;
    private ServerConnection connectionForReads;
    private ServerConnection connectionForWrites;
    private Cluster cluster;
    private boolean isClosed;

    public MonotonicSession(final Cluster cluster) {
        this.cluster = notNull("cluster", cluster);
    }

    @Override
    public ServerConnection getConnection(final ServerSelector serverSelector) {
        isTrue("open", !isClosed());
        notNull("serverSelector", serverSelector);
        synchronized (this) {
            ServerConnection connectionToUse;
            if (connectionForWrites != null) {
                connectionToUse = connectionForWrites;
            }
            else if (connectionForReads == null || !serverSelector.equals(lastRequestedServerSelector)) {
                lastRequestedServerSelector = serverSelector;
                if (connectionForReads != null) {
                    connectionForReads.close();
                }
                connectionForReads = cluster.getServer(serverSelector).getConnection();

                connectionToUse = connectionForReads;
            }
            else {
                connectionToUse = connectionForReads;
            }
            return new DelayedCloseConnection(connectionToUse);
        }
    }

    @Override
    public ServerConnection getConnection() {
        isTrue("open", !isClosed());
        synchronized (this) {
            if (connectionForWrites == null) {
                connectionForWrites = cluster.getServer(new PrimaryServerSelector()).getConnection();
                if (connectionForReads != null) {
                    connectionForReads.close();
                    connectionForReads = null;
                }
            }
            return new DelayedCloseConnection(connectionForWrites);
        }
    }

    @Override
    public Session getBoundSession(final ServerSelector serverSelector, final SessionBindingType sessionBindingType) {
        isTrue("open", !isClosed());
        return new SingleConnectionSession(getConnection(serverSelector));
    }

    @Override
    public void close() {
        if (!isClosed()) {
            if (connectionForReads != null) {
                connectionForReads.close();
                connectionForReads = null;
            }
            if (connectionForWrites != null) {
                connectionForWrites.close();
                connectionForWrites = null;
            }
            isClosed = true;
        }
    }

    @Override
    public boolean isClosed() {
        return isClosed;
    }
}

@@ -3208,24 +3208,62 @@
 Closed()) %7B%0A
+            synchronized (this) %7B%0A    
             
@@ -3288,32 +3288,36 @@
 eads != null) %7B%0A
+    
                 
@@ -3352,32 +3352,36 @@
                 
+    
 connectionForRea
@@ -3395,34 +3395,41 @@
 ll;%0A            
-%7D%0A
+    %7D%0A   
             if (
@@ -3416,32 +3416,33 @@
 %0A               
+ 
 if (connectionFo
@@ -3452,32 +3452,36 @@
 ites != null) %7B%0A
+    
                 
@@ -3517,32 +3517,36 @@
                 
+    
 connectionForWri
@@ -3561,34 +3561,42 @@
 ll;%0A            
+ 
-%7D%0A
+   %7D%0A    
             isCl
@@ -3608,16 +3608,30 @@
 = true;%0A
+            %7D%0A
         

Synchronize close method in MonotonicSession.