/******************************************************************************* * Copyright (c) 2004, 2007 IBM Corporation and Cambridge Semantics Incorporated. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Cambridge Semantics Incorporated - Fork to Anzo *******************************************************************************/ package org.openanzo.jdbc.container; import java.util.HashSet; import java.util.Set; import java.util.concurrent.locks.ReentrantLock; import org.apache.commons.pool.impl.GenericObjectPool; import org.openanzo.exceptions.AnzoException; import org.openanzo.exceptions.AnzoRuntimeException; import org.openanzo.exceptions.ExceptionConstants; import org.openanzo.exceptions.LogUtils; import org.openanzo.jdbc.layout.indexer.LiteralIndexer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Manages a pool of RDBQuadStore objects. Database connections and SQL prepared statements are allocated for each RDBQuadStore according to the provided * configuration. * * @author Joe Betz */ class RDBQuadStorePool { private static final Logger log = LoggerFactory.getLogger(RDBQuadStorePool.class); /** Usage Count */ private int usageCount = 0; /** Max number of JDBC connections to open in pool */ private final int MAX_READ_CONNECTIONS = 15; /** Max number of JDBC connections to open in pool */ private int MAX_WRITE_CONNECTIONS = 1; /** Set of all RDBQuadStores */ protected final Set<RDBQuadStore> allStores; /** GenericObjectPool read RDBQuadStorePool */ private GenericObjectPool readPool = null; /** RDBQuadStoreFactory for READ QuadStores */ private RDBQuadStoreFactory factoryRead = null; /** GenericObjectPool rw RDBQuadStorePool */ private GenericObjectPool rwPool = null; /** RDBQuadStoreFactory for READ_WRITE QuadStores */ private RDBQuadStoreFactory factoryRw = null; /** Pool is started */ private boolean started = false; private final ReentrantLock startLock = new ReentrantLock(); private final CoreDBConfiguration configuration; private final LiteralIndexer literalIndexer; /** * Create new RDBQuadStorePool * * @param properties * Configuration properties * @param literalIndexer * optional literal indexer */ protected RDBQuadStorePool(CoreDBConfiguration configuration, LiteralIndexer literalIndexer) { if (configuration == null) { throw new AnzoRuntimeException(ExceptionConstants.SERVER.NO_SERVER_CONFIG); } this.literalIndexer = literalIndexer; this.configuration = configuration; allStores = new HashSet<RDBQuadStore>(); incrementUsageCount(); if (!configuration.getSupportsTableLocks()) { MAX_WRITE_CONNECTIONS = 1; } } /** * Start the connection pools * * @throws AnzoException */ protected void start() throws AnzoException { startLock.lock(); try { if (started) return; started = true; setupPools(); } finally { startLock.unlock(); } } /** * Determine if the pool is started * * @return true if pool is started * @throws AnzoException */ public boolean getIsStarted() throws AnzoException { return started; } /** * Stop the connection pools */ private void stop() { startLock.lock(); try { started = false; try { rwPool.close(); factoryRw.close(); rwPool = null; factoryRw = null; } catch (Exception e) { log.error(LogUtils.RDB_MARKER, "Error closing connection pool", e); } try { readPool.close(); factoryRead.close(); readPool = null; factoryRead = null; } catch (Exception e) { log.error(LogUtils.RDB_MARKER, "Error closing connection pool", e); } } finally { startLock.unlock(); } } private void setupPools() { readPool = new GenericObjectPool(); factoryRead = new RDBQuadStoreFactory(this, literalIndexer, false, MAX_READ_CONNECTIONS, configuration); setupPool(readPool, factoryRead, MAX_READ_CONNECTIONS, MAX_READ_CONNECTIONS / 2, 60000); rwPool = new GenericObjectPool(); factoryRw = new RDBQuadStoreFactory(this, literalIndexer, true, MAX_WRITE_CONNECTIONS, configuration); setupPool(rwPool, factoryRw, MAX_WRITE_CONNECTIONS, (MAX_WRITE_CONNECTIONS > 1) ? MAX_WRITE_CONNECTIONS / 2 : 1, 60000); } private void setupPool(GenericObjectPool pool, RDBQuadStoreFactory factory, int maxActive, int maxIdle, long blockWait) { pool.setFactory(factory); pool.setMaxActive(maxActive); pool.setMaxIdle(maxIdle); pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK); pool.setMaxWait(blockWait); } /** * Get a RDBQuadStore from the pool * * @param type * Type of RDBQuadStore to acquire * @return RDBQuadStore from the pool * @throws AnzoException */ protected synchronized RDBQuadStore acquireRDBQuadStore(boolean write) throws AnzoException { RDBQuadStore quadStore = null; try { if (write) { quadStore = (RDBQuadStore) rwPool.borrowObject(); } else { quadStore = (RDBQuadStore) readPool.borrowObject(); } } catch (Exception e) { log.error(LogUtils.RDB_MARKER, "Error error acquiring quad store", e); throw new RuntimeException(e); } allStores.add(quadStore); return quadStore; } private int incrementUsageCount() { return ++usageCount; } private int decrementUsageCount() { return --usageCount; } /** * Close a reference to the pool, and if last reference, close the pool */ protected void close() { int usage = decrementUsageCount(); if (usage == 0) { stop(); } } /** * Get the number of active stores in the read pool * * @return number of active stores in the read pool */ public int getReadStoresInUseSize() { return readPool.getNumActive(); } /** * Get the number of inactive stores in the read pool * * @return number of inactive stores in the read pool */ public int getReadStoresInactiveSize() { return readPool.getNumIdle(); } /** * Get the the max number of stores in the read pool * * @return the max number of stores in the read pool */ public int getReadStoreMaxPoolSize() { return readPool.getMaxActive(); } /** * Get the number of active stores in the write pool * * @return number of active stores in the write pool */ public int getWriteStoresInUseSize() { return rwPool.getNumActive(); } /** * Get the number of inactive stores in the write pool * * @return number of inactive stores in the write pool */ public int getWriteStoresInactiveSize() { return rwPool.getNumIdle(); } /** * Get the max number of stores in the write pool * * @return the max number of stores in the write pool */ public int getWriteStoresMaxPoolSize() { return rwPool.getMaxActive(); } /** * set the max size of the read pool * * @param size * max size of the read pool */ public void setReadStoresMaxPoolSize(int size) { readPool.setMaxActive(size); } /** * set the max size of the write pool * * @param size * max size of the write pool */ public void setWriteStoresMaxPoolSize(int size) { rwPool.setMaxActive(size); } /** * Get the max time to wait for a store in the read pool * * @return the max time to wait for a store in the read pool */ public long getReadStoresPoolMaxWaitTime() { return readPool.getMaxWait(); } /** * Get the max time to wait for a store in the write pool * * @return the max time to wait for a store in the write pool */ public long getWriteStoresPoolMaxWaitTime() { return rwPool.getMaxWait(); } /** * Set the max time to wait for a store in the read pool * * @param maxWait * time */ public void setReadStoresPoolMaxWaitTime(long maxWait) { readPool.setMaxWait(maxWait); } /** * Set the max time to wait for a stores in the write pool * * @param maxWait * time */ public void setWriteStoresPoolMaxWaitTime(long maxWait) { rwPool.setMaxWait(maxWait); } /** * Get the max idle stores in read pool * * @return the max idle stores in read pool */ public int getReadStoresPoolMaxIdle() { return readPool.getMaxIdle(); } /** * Get the min idle time for stores in read pool * * @return the min idle time for stores in read pool */ public long getReadStoresPoolMinIdleTime() { return readPool.getMinEvictableIdleTimeMillis(); } /** * Get the max idle stores in write pool * * @return the max idle stores in write pool */ public int getWriteStoresPoolMaxIdle() { return rwPool.getMaxIdle(); } /** * Get the min idle time for stores in write pool * * @return the min idle time for stores in write pool */ public long getWriteStoresPoolMinIdleTime() { return rwPool.getMinEvictableIdleTimeMillis(); } /** * Set the max number of idle stores in the read pool * * @param max * number of idle stores */ public void setReadStoresPoolMaxIdlexIdle(int max) { readPool.setMaxIdle(max); } /** * Set the minimum idle time for stores in the read pool * * @param minWait * idle time for stores in the read pool */ public void setReadStoresPoolMinIdleTime(long minWait) { readPool.setMinEvictableIdleTimeMillis(minWait); } /** * Set the max number of idle stores in the write pool * * @param max * number of idle stores */ public void setWriteStoresPoolMaxIdle(int max) { rwPool.setMaxIdle(max); } /** * Set the minimum idle time for stores in the write pool * * @param minWait * idle time for stores in the write pool */ public void setWriteStoresPoolMinIdleTime(long minWait) { rwPool.setMinEvictableIdleTimeMillis(minWait); } /** * Get the database store URL * * @return the database store URL */ public String getDatabaseUrl() { return configuration.getJdbcUrl(); } /** * Get the database username * * @return the database username */ public String getDatabaseUserName() { return configuration.getUser(); } /** * Set the database store URL * * @param jdbcUrl * for stores in the pool */ public void setDatabaseUrl(String jdbcUrl) { configuration.setJBDCUrl(jdbcUrl); } /** * Set the database username * * @param userName * for database stores */ public void setDatabaseUserName(String userName) { configuration.setUser(userName); } /** * Get the database password * * @return the database password */ public String getDatabasePassword() { return configuration.getPassword(); } /** * Set the database password * * @param password * for database stores */ public void setDatabasePassword(String password) { configuration.setPassword(password); } /** * Get the database driver's class name * * @return the database driver's class name */ public String getDatabaseDriver() { return configuration.getDriverClassName(); } /** * Set the name of the jdbc driver class * * @param dbDriver * classname of jdbc driver */ public void setDatabaseDriver(String dbDriver) { configuration.setDriverClassName(dbDriver); } /** * Get the filename for initialization and read file for database * * @return the filename for initialization and read file for database */ public String getRepositoryInitFile() { return configuration.getSqlFilename(); } /** * Set the filename of the initialization and read file for database * * @param dbInitFile * initialization and read file for database */ public void setRepositoryInitFile(String dbInitFile) { configuration.setSqlFilename(dbInitFile); } /** * @return the configuration */ public CoreDBConfiguration getConfiguration() { return configuration; } }