View Javadoc
1   /*
2    * #%L
3    * SimpleReconnectStrategy.java - mongodb-async-driver - Allanbank Consulting, Inc.
4    * %%
5    * Copyright (C) 2011 - 2014 Allanbank Consulting, Inc.
6    * %%
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   * 
11   *      http://www.apache.org/licenses/LICENSE-2.0
12   * 
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   * #L%
19   */
20  package com.allanbank.mongodb.client.state;
21  
22  import java.io.IOException;
23  import java.util.List;
24  
25  import com.allanbank.mongodb.client.connection.Connection;
26  import com.allanbank.mongodb.util.IOUtils;
27  import com.allanbank.mongodb.util.log.Log;
28  import com.allanbank.mongodb.util.log.LogFactory;
29  
30  /**
31   * SimpleReconnectStrategy provides a reconnection strategy to simply attempt to
32   * connect to the server again.
33   * 
34   * @api.no This class is <b>NOT</b> part of the drivers API. This class may be
35   *         mutated in incompatible ways between any two releases of the driver.
36   * @copyright 2012-2013, Allanbank Consulting, Inc., All Rights Reserved
37   */
38  public class SimpleReconnectStrategy extends AbstractReconnectStrategy {
39  
40      /** The logger for the {@link SimpleReconnectStrategy}. */
41      protected static final Log LOG = LogFactory
42              .getLog(SimpleReconnectStrategy.class);
43  
44      /**
45       * Creates a new SimpleReconnectStrategy.
46       */
47      public SimpleReconnectStrategy() {
48          super();
49      }
50  
51      /**
52       * {@inheritDoc}
53       * <p>
54       * Overridden to try and connect to every server selected by the
55       * ServerSelector until one of the connections is successful.
56       * </p>
57       */
58      @Override
59      public Connection reconnect(final Connection oldConnection) {
60  
61          // Clear the interrupt state for the thread.
62          final boolean wasInterrupted = Thread.interrupted();
63          try {
64              // First try and connect back to the original server. This will
65              // hopefully re-enable the state.
66              final Server origServer = myState
67                      .get(oldConnection.getServerName());
68              Connection newConn = tryConnect(origServer);
69              if (newConn != null) {
70                  return newConn;
71              }
72  
73              final List<Server> servers = getSelector().pickServers();
74              for (final Server server : servers) {
75                  newConn = tryConnect(server);
76                  if (newConn != null) {
77                      return newConn;
78                  }
79              }
80  
81              LOG.info("Reconnect attempt failed for all {} servers: {}",
82                      servers.size(), servers);
83          }
84          finally {
85              // Reset the interrupt state.
86              if (wasInterrupted) {
87                  Thread.currentThread().interrupt();
88              }
89          }
90  
91          return null;
92      }
93  
94      /**
95       * Tries to connect to the server.
96       * 
97       * @param server
98       *            The server to connect to.
99       * @return The connection to the server.
100      */
101     private Connection tryConnect(final Server server) {
102         Connection newConn = null;
103         try {
104 
105             newConn = getConnectionFactory().connect(server, getConfig());
106             if (isConnected(server, newConn)) {
107                 LOG.info("Reconnected to {}", server);
108 
109                 // Make sure we don't close the connection.
110                 final Connection result = newConn;
111                 newConn = null;
112 
113                 return result;
114             }
115         }
116         catch (final IOException error) {
117             // Connection failed. Try the next one.
118             LOG.debug("Reconnect to {} failed: {}", server, error.getMessage());
119         }
120         finally {
121             IOUtils.close(newConn);
122         }
123         return null;
124     }
125 }