Ejemplo n.º 1
0
  void _open() throws IOException {

    long sleepTime = 100;

    final long start = System.currentTimeMillis();
    while (true) {

      IOException lastError = null;

      try {
        _sock = SocketChannel.open();
        _socket = _sock.socket();
        _socket.connect(_addr, _options.connectTimeout);

        _socket.setTcpNoDelay(!USE_NAGLE);
        _socket.setSoTimeout(_options.socketTimeout);
        _in = _socket.getInputStream();
        return;
      } catch (IOException ioe) {
        //  TODO  - erh to fix                lastError = new IOException( "couldn't connect to [" +
        // _addr + "] bc:" + lastError , lastError );
        lastError = new IOException("couldn't connect to [" + _addr + "] bc:" + ioe);
        _logger.log(Level.INFO, "connect fail to : " + _addr, ioe);
      }

      if (!_options.autoConnectRetry || (_pool != null && !_pool._everWorked)) throw lastError;

      long sleptSoFar = System.currentTimeMillis() - start;

      if (sleptSoFar >= CONN_RETRY_TIME_MS) throw lastError;

      if (sleepTime + sleptSoFar > CONN_RETRY_TIME_MS) sleepTime = CONN_RETRY_TIME_MS - sleptSoFar;

      _logger.severe(
          "going to sleep and retry.  total sleep time after = "
              + (sleptSoFar + sleptSoFar)
              + "ms  this time:"
              + sleepTime
              + "ms");
      ThreadUtil.sleep(sleepTime);
      sleepTime *= 2;
    }
  }
Ejemplo n.º 2
0
class DBPortPool extends SimplePool<DBPort> {

  static class Holder {

    Holder(MongoOptions options) {
      _options = options;
    }

    DBPortPool get(InetSocketAddress addr) {

      DBPortPool p = _pools.get(addr);

      if (p != null) return p;

      synchronized (_pools) {
        p = _pools.get(addr);
        if (p != null) {
          return p;
        }

        p = new DBPortPool(addr, _options);
        _pools.put(addr, p);
        String name = "com.mongodb:type=ConnectionPool,host=" + addr.toString().replace(':', '_');

        try {
          ObjectName on = new ObjectName(name);
          if (_server.isRegistered(on)) {
            _server.unregisterMBean(on);
            Bytes.LOGGER.log(
                Level.INFO, "multiple Mongo instances for same host, jmx numbers might be off");
          }
          _server.registerMBean(p, on);
        } catch (JMException e) {
          Bytes.LOGGER.log(Level.WARNING, "jmx registration error, continuing", e);
        } catch (java.security.AccessControlException e) {
          Bytes.LOGGER.log(Level.WARNING, "jmx registration error, continuing", e);
        }
      }

      return p;
    }

    void close() {
      synchronized (_pools) {
        for (DBPortPool p : _pools.values()) {
          p.close();
        }
      }
    }

    final MongoOptions _options;
    final Map<InetSocketAddress, DBPortPool> _pools =
        Collections.synchronizedMap(new HashMap<InetSocketAddress, DBPortPool>());
    final MBeanServer _server = ManagementFactory.getPlatformMBeanServer();
  }

  // ----

  public static class NoMoreConnection extends MongoInternalException {
    NoMoreConnection(String msg) {
      super(msg);
    }
  }

  public static class SemaphoresOut extends NoMoreConnection {
    SemaphoresOut() {
      super("Out of semaphores to get db connection");
    }
  }

  public static class ConnectionWaitTimeOut extends NoMoreConnection {
    ConnectionWaitTimeOut(int timeout) {
      super("Connection wait timeout after " + timeout + " ms");
    }
  }

  // ----

  DBPortPool(InetSocketAddress addr, MongoOptions options) {
    super("DBPortPool-" + addr.toString(), options.connectionsPerHost, options.connectionsPerHost);
    _options = options;
    _addr = addr;
    _waitingSem =
        new Semaphore(
            _options.connectionsPerHost * _options.threadsAllowedToBlockForConnectionMultiplier);
  }

  protected long memSize(DBPort p) {
    return 0;
  }

  protected int pick(int iThink, boolean couldCreate) {
    final int id = Thread.currentThread().hashCode();
    final int s = _availSafe.size();
    for (int i = 0; i < s; i++) {
      DBPort p = _availSafe.get(i);
      if (p._lastThread == id) return i;
    }

    if (couldCreate) return -1;
    return iThink;
  }

  public DBPort get() {
    DBPort port = null;
    if (!_waitingSem.tryAcquire()) throw new SemaphoresOut();

    try {
      port = get(_options.maxWaitTime);
    } finally {
      _waitingSem.release();
    }

    if (port == null) throw new ConnectionWaitTimeOut(_options.maxWaitTime);

    port._lastThread = Thread.currentThread().hashCode();
    return port;
  }

  void gotError(Exception e) {
    if (e instanceof java.nio.channels.ClosedByInterruptException
        || e instanceof InterruptedException) {
      // this is probably a request that is taking too long
      // so usually doesn't mean there is a real db problem
      return;
    }

    if (e instanceof java.net.SocketTimeoutException && _options.socketTimeout > 0) {
      // we don't want to clear the port pool for 1 connection timing out
      return;
    }

    // We don't want to clear the entire pool for the occasional error.
    if (e instanceof SocketException) {
      if (recentFailures < ALLOWED_ERRORS_BEFORE_CLEAR) {
        return;
      }
    }

    Bytes.LOGGER.log(Level.INFO, "emptying DBPortPool b/c of error", e);
    clear();
  }

  void close() {
    clear();
  }

  public void cleanup(DBPort p) {
    p.close();
  }

  public boolean ok(DBPort t) {
    return _addr.equals(t._addr);
  }

  protected DBPort createNew() throws MongoInternalException {
    try {
      return new DBPort(_addr, this, _options);
    } catch (IOException ioe) {
      throw new MongoInternalException("can't create port to:" + _addr, ioe);
    }
  }

  public int getRecentFailures() {
    return recentFailures;
  }

  public void incrementRecentFailures() {
    _logger.warning("Failure recorded:" + _addr.toString());
    this.recentFailures++;
  }

  public void resetRecentFailures() {
    if (this.recentFailures > 0) {
      _logger.warning("Successful Request. Reseting recent failures:" + _addr.toString());
    }

    this.recentFailures = 0;
  }

  final MongoOptions _options;
  private final Semaphore _waitingSem;
  final InetSocketAddress _addr;
  boolean _everWorked = false;
  public static final Integer ALLOWED_ERRORS_BEFORE_CLEAR =
      Integer.valueOf(System.getProperty("MONGO.ERRORS_BEFORE_CLEAR", "5"));
  private Logger _logger = Logger.getLogger(DBPortPool.class.toString());

  /** The number of failures that this port pool has recently experienced. */
  private int recentFailures = 0;
}