All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.mongodb.connection.DefaultServer Maven / Gradle / Ivy

Go to download

The MongoDB Java Driver uber-artifact, containing mongodb-driver, mongodb-driver-core, and bson

The newest version!
/*
 * Copyright (c) 2008-2015 MongoDB, Inc.
 *
 * 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 com.mongodb.connection;

import com.mongodb.MongoException;
import com.mongodb.MongoNodeIsRecoveringException;
import com.mongodb.MongoNotPrimaryException;
import com.mongodb.MongoSecurityException;
import com.mongodb.MongoSocketException;
import com.mongodb.MongoSocketReadTimeoutException;
import com.mongodb.ServerAddress;
import com.mongodb.async.SingleResultCallback;
import com.mongodb.event.CommandListener;

import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import static com.mongodb.assertions.Assertions.isTrue;
import static com.mongodb.assertions.Assertions.notNull;
import static com.mongodb.connection.ServerConnectionState.CONNECTING;
import static com.mongodb.internal.async.ErrorHandlingResultCallback.errorHandlingCallback;

class DefaultServer implements ClusterableServer {
    private final ServerAddress serverAddress;
    private final ConnectionPool connectionPool;
    private final ClusterConnectionMode clusterConnectionMode;
    private final ConnectionFactory connectionFactory;
    private final ServerMonitor serverMonitor;
    private final Set> changeListeners =
    Collections.newSetFromMap(new ConcurrentHashMap, Boolean>());
    private final ChangeListener serverStateListener;
    private final CommandListener commandListener;
    private volatile ServerDescription description;
    private volatile boolean isClosed;

    public DefaultServer(final ServerAddress serverAddress,
                         final ClusterConnectionMode clusterConnectionMode,
                         final ConnectionPool connectionPool,
                         final ConnectionFactory connectionFactory,
                         final ServerMonitorFactory serverMonitorFactory, final CommandListener commandListener) {
        this.commandListener = commandListener;
        notNull("serverMonitorFactory", serverMonitorFactory);
        this.clusterConnectionMode = notNull("clusterConnectionMode", clusterConnectionMode);
        this.connectionFactory = notNull("connectionFactory", connectionFactory);
        this.serverAddress = notNull("serverAddress", serverAddress);
        this.connectionPool = notNull("connectionPool", connectionPool);
        this.serverStateListener = new DefaultServerStateListener();
        description = ServerDescription.builder().state(CONNECTING).address(serverAddress).build();
        serverMonitor = serverMonitorFactory.create(serverStateListener);
        serverMonitor.start();
    }

    @Override
    public Connection getConnection() {
        isTrue("open", !isClosed());
        try {
            return connectionFactory.create(connectionPool.get(), new DefaultServerProtocolExecutor(), clusterConnectionMode);
        } catch (MongoSecurityException e) {
            invalidate();
            throw e;
        }
    }

    @Override
    public void getConnectionAsync(final SingleResultCallback callback) {
        isTrue("open", !isClosed());
        connectionPool.getAsync(new SingleResultCallback() {
            @Override
            public void onResult(final InternalConnection result, final Throwable t) {
                if (t instanceof MongoSecurityException) {
                    invalidate();
                }
                if (t != null) {
                    callback.onResult(null, t);
                } else {
                    callback.onResult(connectionFactory.createAsync(result, new DefaultServerProtocolExecutor(), clusterConnectionMode),
                                      null);
                }
            }
        });
    }

    @Override
    public ServerDescription getDescription() {
        isTrue("open", !isClosed());

        return description;
    }

    @Override
    public void addChangeListener(final ChangeListener changeListener) {
        isTrue("open", !isClosed());

        changeListeners.add(changeListener);
    }

    @Override
    public void invalidate() {
        isTrue("open", !isClosed());

        serverStateListener.stateChanged(new ChangeEvent(description, ServerDescription.builder()
                                                                                                          .state(CONNECTING)
                                                                                                          .address(serverAddress).build()));
        connectionPool.invalidate();
        serverMonitor.invalidate();
    }

    @Override
    public void close() {
        if (!isClosed()) {
            connectionPool.close();
            serverMonitor.close();
            isClosed = true;
        }
    }

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

    @Override
    public void connect() {
        serverMonitor.connect();
    }

    ConnectionPool getConnectionPool() {
        return connectionPool;
    }

    private void handleThrowable(final Throwable t) {
        if ((t instanceof MongoSocketException && !(t instanceof MongoSocketReadTimeoutException))
            || t instanceof MongoNotPrimaryException
            || t instanceof MongoNodeIsRecoveringException) {
            invalidate();
        }
    }

    private class DefaultServerProtocolExecutor implements ProtocolExecutor {
        @Override
        public  T execute(final Protocol protocol, final InternalConnection connection) {
            try {
                protocol.setCommandListener(commandListener);
                return protocol.execute(connection);
            } catch (MongoException e) {
                handleThrowable(e);
                throw e;
            }
        }

        @Override
        public  void executeAsync(final Protocol protocol, final InternalConnection connection,
                                     final SingleResultCallback callback) {
            protocol.executeAsync(connection, errorHandlingCallback(new SingleResultCallback() {
                @Override
                public void onResult(final T result, final Throwable t) {
                    if (t != null) {
                        handleThrowable(t);
                    }
                    callback.onResult(result, t);
                }
            }));
        }
    }

    private final class DefaultServerStateListener implements ChangeListener {
        @Override
        public void stateChanged(final ChangeEvent event) {
            description = event.getNewValue();
            for (ChangeListener listener : changeListeners) {
                listener.stateChanged(event);
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy