Package com.orientechnologies.orient.client.remote

Source Code of com.orientechnologies.orient.client.remote.ORemoteConnectionManager

/*
  *
  *  *  Copyright 2014 Orient Technologies LTD (info(at)orientechnologies.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.
  *  *
  *  * For more information: http://www.orientechnologies.com
  *
  */
package com.orientechnologies.orient.client.remote;

import com.orientechnologies.common.concur.resource.OResourcePool;
import com.orientechnologies.common.concur.resource.OResourcePoolListener;
import com.orientechnologies.common.io.OIOException;
import com.orientechnologies.common.log.OLogManager;
import com.orientechnologies.orient.core.config.OContextConfiguration;
import com.orientechnologies.orient.core.config.OGlobalConfiguration;
import com.orientechnologies.orient.enterprise.channel.OChannel;
import com.orientechnologies.orient.enterprise.channel.binary.OChannelBinaryAsynchClient;
import com.orientechnologies.orient.enterprise.channel.binary.OChannelBinaryProtocol;
import com.orientechnologies.orient.enterprise.channel.binary.OChannelListener;
import com.orientechnologies.orient.enterprise.channel.binary.ORemoteServerEventListener;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
* Manages network connections against OrientDB servers. All the connection pools are managed in a Map<url,pool>, but in the future
* we could have a unique pool per sever and manage database connections over the protocol.
*
* @author Luca Garulli (l.garulli--at--orientechnologies.com)
*/
public class ORemoteConnectionManager implements OChannelListener {
  public static final String                                                                   PARAM_MAX_POOL = "maxpool";

  protected final ConcurrentHashMap<String, OResourcePool<String, OChannelBinaryAsynchClient>> connections;
  protected final long                                                                         timeout;

  public ORemoteConnectionManager(final int iMaxConnectionPerURL, final long iTimeout) {
    connections = new ConcurrentHashMap<String, OResourcePool<String, OChannelBinaryAsynchClient>>();
    timeout = iTimeout;
  }

  public void close() {
    for (Map.Entry<String, OResourcePool<String, OChannelBinaryAsynchClient>> entry : connections.entrySet())
      entry.getValue().close();

    connections.clear();
  }

  public OChannelBinaryAsynchClient acquire(String iServerURL, final OContextConfiguration clientConfiguration,
      final Map<String, Object> iConfiguration, final ORemoteServerEventListener iListener) {
    OResourcePool<String, OChannelBinaryAsynchClient> pool = connections.get(iServerURL);
    if (pool == null) {
      int maxPool = OGlobalConfiguration.CLIENT_CHANNEL_MAX_POOL.getValueAsInteger();

      if (iConfiguration != null && iConfiguration.size() > 0) {
        if (iConfiguration.containsKey(PARAM_MAX_POOL))
          maxPool = Integer.parseInt(iConfiguration.get(PARAM_MAX_POOL).toString());
      }

      pool = new OResourcePool<String, OChannelBinaryAsynchClient>(maxPool,
          new OResourcePoolListener<String, OChannelBinaryAsynchClient>() {
            @Override
            public OChannelBinaryAsynchClient createNewResource(final String iKey, final Object... iAdditionalArgs) {
              return createNetworkConnection(iKey, (OContextConfiguration) iAdditionalArgs[0],
                  (Map<String, Object>) iAdditionalArgs[1], (ORemoteServerEventListener) iAdditionalArgs[2]);
            }

            @Override
            public boolean reuseResource(final String iKey, final Object[] iAdditionalArgs, final OChannelBinaryAsynchClient iValue) {
              return true;
            }
          });

      final OResourcePool<String, OChannelBinaryAsynchClient> prev = connections.putIfAbsent(iServerURL, pool);
      if (prev != null) {
        // ALREADY PRESENT, DESTROY IT AND GET THE ALREADY EXISTENT OBJ
        pool.close();
        pool = prev;
      }
    }

    try {
      // RETURN THE RESOURCE
      return pool.getResource(iServerURL, timeout, clientConfiguration, iConfiguration, iListener);

    } catch (RuntimeException e) {
      // ERROR ON RETRIEVING THE INSTANCE FROM THE POOL
      connections.remove(iServerURL);
      throw e;
    } catch (Exception e) {
      // ERROR ON RETRIEVING THE INSTANCE FROM THE POOL
      OLogManager.instance().error(this, "Error on retrieving the connection from pool: " + iServerURL, e);
      connections.remove(iServerURL);
    }
    return null;
  }

  public void release(final OChannelBinaryAsynchClient conn) {
    final OResourcePool<String, OChannelBinaryAsynchClient> pool = connections.get(conn.getServerURL());
    if (pool != null) {
      if (!conn.isConnected()) {
        OLogManager.instance().debug(this, "Network connection pool is receiving a closed connection to reuse: discard it");
        pool.remove(conn);
      } else
        pool.returnResource(conn);
    }
  }

  public void remove(final OChannelBinaryAsynchClient conn) {
    if (conn.isConnected()) {
      try {
        conn.unlock();
      } catch (Exception e) {
      }

      try {
        conn.close();
      } catch (Exception e) {
      }
    }

    final OResourcePool<String, OChannelBinaryAsynchClient> pool = connections.get(conn.getServerURL());
    if (pool == null)
      throw new IllegalStateException("Connection cannot be released because the pool doesn't exist anymore");

    pool.remove(conn);
  }

  @Override
  public void onChannelClose(final OChannel channel) {
    remove((OChannelBinaryAsynchClient) channel);
  }

  public Set<String> getURLs() {
    return connections.keySet();
  }

  public int getMaxResources(final String url) {
    final OResourcePool<String, OChannelBinaryAsynchClient> pool = connections.get(url);
    if (pool == null)
      return 0;

    return pool.getMaxResources();
  }

  public int getAvailableConnections(final String url) {
    final OResourcePool<String, OChannelBinaryAsynchClient> pool = connections.get(url);
    if (pool == null)
      return 0;

    return pool.getAvailableResources();
  }

  public int getCreatedInstancesInPool(final String url) {
    final OResourcePool<String, OChannelBinaryAsynchClient> pool = connections.get(url);
    if (pool == null)
      return 0;

    return pool.getCreatedInstancesInPool();
  }

  public void closePool(final String url) {
    final OResourcePool<String, OChannelBinaryAsynchClient> pool = connections.remove(url);
    if (pool == null)
      return;

    closePool(pool);
  }

  protected void closePool(final OResourcePool<String, OChannelBinaryAsynchClient> pool) {
    final List<OChannelBinaryAsynchClient> conns = new ArrayList<OChannelBinaryAsynchClient>(pool.getResources());
    for (OChannelBinaryAsynchClient c : conns)
      try {
        c.close();
      } catch (Exception e) {
      }
  }

  protected OChannelBinaryAsynchClient createNetworkConnection(String iServerURL, final OContextConfiguration clientConfiguration,
      Map<String, Object> iAdditionalArg, final ORemoteServerEventListener asynchEventListener) throws OIOException {
    if (iServerURL == null)
      throw new IllegalArgumentException("server url is null");

    // TRY WITH CURRENT URL IF ANY
    try {
      OLogManager.instance().debug(this, "Trying to connect to the remote host %s...", iServerURL);

      final String serverURL;
      final String databaseName;
      int sepPos = iServerURL.indexOf("/");
      if (sepPos > -1) {
        // REMOVE DATABASE NAME IF ANY
        serverURL = iServerURL.substring(0, sepPos);
        databaseName = iServerURL.substring(sepPos + 1);
      } else {
        serverURL = iServerURL;
        databaseName = null;
      }

      sepPos = serverURL.indexOf(":");
      final String remoteHost = serverURL.substring(0, sepPos);
      final int remotePort = Integer.parseInt(serverURL.substring(sepPos + 1));

      final OChannelBinaryAsynchClient ch = new OChannelBinaryAsynchClient(remoteHost, remotePort, databaseName,
          clientConfiguration, OChannelBinaryProtocol.CURRENT_PROTOCOL_VERSION, asynchEventListener);

      // REGISTER MYSELF AS LISTENER TO REMOVE THE CHANNEL FROM THE POOL IN CASE OF CLOSING
      ch.registerListener(this);

      return ch;

    } catch (OIOException e) {
      // RE-THROW IT
      throw e;
    } catch (Exception e) {
      OLogManager.instance().debug(this, "Error on connecting to %s", e, iServerURL);
      throw new OIOException("Error on connecting to " + iServerURL, e);
    }
  }
}
TOP

Related Classes of com.orientechnologies.orient.client.remote.ORemoteConnectionManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.