/** * VMware Continuent Tungsten Replicator * Copyright (C) 2015 VMware, Inc. All rights reserved. * * 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. * * Initial developer(s): Edward Archibald * Contributor(s): Gilles Rayrat */ package com.continuent.tungsten.common.cluster.resource; import java.net.Socket; import java.sql.Connection; import java.sql.SQLException; import java.util.Date; import java.util.concurrent.atomic.AtomicBoolean; import com.continuent.tungsten.common.patterns.order.Sequence; import com.continuent.tungsten.common.utils.CLUtils; public class DatabaseConnection { public enum ConnectionType { DIRECT, CLUSTER, CONNECTOR, BRIDGED }; private ConnectionType type = ConnectionType.DIRECT; private String name; private Connection connection; private Sequence sequence = null; private DataSource ds = null; private Object context; /** Last time the connection was used */ private Date lastUsed = new Date(); /** Flag indicating if a connection is being used (processing query) */ private AtomicBoolean isConnectionInUse = new AtomicBoolean(false); public DatabaseConnection(ConnectionType type, String name, Connection connection, DataSource ds, Object context) { this.type = type; this.name = name; this.connection = connection; this.ds = ds; setContext(context); } public ConnectionType getType() { return type; } public void setType(ConnectionType type) { this.type = type; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Connection getConnection() { return connection; } public Object getContext() { return context; } public void setContext(Object context) { this.context = context; if (ds != null) this.sequence = ds.getSequence(); } public Sequence getSequence() { return sequence; } public void setSequence(Sequence sequence) { this.sequence = sequence; } public DataSource getDs() { return ds; } /** * Returns the lastUsed value. * * @return Returns the lastUsed. */ public Date getLastUsed() { return lastUsed; } /** * Updates the lastUsed value to the current Date/Time. * */ public void touch() { this.lastUsed = new Date(); } public AtomicBoolean getIsConnectionInUse() { return isConnectionInUse; } public String toString() { return toString(false); } public String toString(boolean detailed) { if (type == ConnectionType.DIRECT) { return String.format("%s(%s) DIRECT TO %s", name, liveness(), ds.toString()); } else if (type == ConnectionType.CLUSTER) { StringBuilder builder = new StringBuilder(); builder.append(name).append('(').append(liveness()) .append(") VIA CLUSTER TO ").append(connection.toString()); return builder.toString(); } else if (type == ConnectionType.CONNECTOR) { return String.format("%s(%s) CONNECTOR TO HOST %s", name, liveness(), getContext()); } else if (type == ConnectionType.BRIDGED) { return name + " BRIDGED to " + ds != null ? ds.getName() : "null"; } else { CLUtils.println(String.format( "no connection status logic for type %s", type)); return "UNKNOWN"; } } /** * Provides a string representation of whether this connection is closed or * not * * @return "CLOSED" if the wrapped JDBC connection is closed, "OPEN" * otherwise */ private String liveness() { boolean isClosed = false; try { if (isClosed()) { isClosed = true; } } catch (SQLException s) { isClosed = true; } if (isClosed) { return "CLOSED"; } return "OPEN"; } public boolean isClosed() throws SQLException { if (type == ConnectionType.BRIDGED) { return ((Socket) context).isClosed(); } return connection.isClosed(); } }