/********************************************************************************** * $URL: https://source.sakaiproject.org/svn/search/trunk/search-impl/impl/src/test/org/sakaiproject/search/index/soaktest/SharedTestDataSource.java $ * $Id: SharedTestDataSource.java 105078 2012-02-24 23:00:38Z ottenhoff@longsight.com $ *********************************************************************************** * * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008 The Sakai Foundation * * Licensed under the Educational Community 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.opensource.org/licenses/ECL-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. * **********************************************************************************/ package org.sakaiproject.search.index.soaktest; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Statement; import java.sql.Timestamp; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import javax.sql.DataSource; import org.apache.commons.dbcp.cpdsadapter.DriverAdapterCPDS; import org.apache.commons.dbcp.datasources.SharedPoolDataSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.sakaiproject.search.jdbc.WrappingConnection; import org.sakaiproject.search.jdbc.WrappingDataSource; import org.sakaiproject.search.model.SearchBuilderItem; /** * @author ieb */ public class SharedTestDataSource { /** * @author ieb * */ public class ConnectionMeta { private StackTraceElement location; private long created; private Connection connection; /** * @param string */ public ConnectionMeta(Connection c, StackTraceElement location) { created = System.currentTimeMillis(); this.location = location; this.connection = c; } /* (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { return "["+connection+"] Created By "+location.toString()+" age "+(System.currentTimeMillis()-created); } /** * @return */ public boolean isOld() { return (System.currentTimeMillis()-created) > 10000; } } private static final Log log = LogFactory.getLog(SharedTestDataSource.class); private SharedPoolDataSource tds; private DataSource wds; protected int nopen = 0; private int docid = 0; private int ldoc = 0; private Map<Connection, ConnectionMeta> connections = new ConcurrentHashMap<Connection, ConnectionMeta>(); public SharedTestDataSource(String dblocation, int pool, final boolean poolLogging, String driver, String dburl, String user, String password) throws Exception { log.info("Using Derby DB"); DriverAdapterCPDS cpds = new DriverAdapterCPDS(); cpds.setDriver("org.apache.derby.jdbc.EmbeddedDriver"); cpds.setUrl("jdbc:derby:" + dblocation + ";create=true"); cpds.setUser("sa"); cpds.setPassword("manager"); tds = new SharedPoolDataSource(); tds.setConnectionPoolDataSource(cpds); tds.setMaxActive(pool); tds.setMaxWait(5); tds.setDefaultAutoCommit(false); wds = new WrappingDataSource(tds) { public Connection getConnection() throws SQLException { final Connection c = tds.getConnection(); nopen++; Exception ex = new Exception(); StackTraceElement[] ste = ex.getStackTrace(); log.debug("Stack Trace " + ste[1].toString()); if (poolLogging) log.info("++++++++++++Opened " + nopen + " from " + ste[1].toString()); connections.put(c,new ConnectionMeta(c,ste[1])); StringBuilder sb = new StringBuilder(); for( ConnectionMeta cm : connections.values() ) { if ( cm.isOld() ) { sb.append("\n ").append(cm); } } if ( sb.length() > 0 ) { log.warn("Older Connections found, possible connection leak "+sb.toString()+"\n"); } return new WrappingConnection(c) { public void close() throws SQLException { connections.remove(c); c.close(); nopen--; Exception ex = new Exception(); StackTraceElement[] ste = ex.getStackTrace(); log.debug("Stack Trace " + ste[1].toString()); if (poolLogging) log.info("------------Closed " + nopen + " from " + ste[1].toString()); } }; } }; Connection connection = tds.getConnection(); Statement s = connection.createStatement(); try { s .execute("create table search_transaction ( txname varchar(64), txid bigint )"); } catch (Exception ex) { log.warn("Create Table Said :" + ex.getMessage()); } try { s.execute("CREATE TABLE searchbuilderitem ( id varchar(64) NOT NULL, " + " version timestamp NOT NULL, " + " name varchar(255) NOT NULL, " + " context varchar(255) NOT NULL, " + " searchaction int default NULL, " + " searchstate int default NULL, " + " itemscope int default NULL, " + " PRIMARY KEY (id), " + " UNIQUE (name) )"); } catch (Exception ex) { log.warn("Create Table Said :" + ex.getMessage()); } try { s.execute("CREATE TABLE search_journal ( " + " txid bigint NOT NULL, " + " txts bigint NOT NULL, " + " indexwriter varchar(255) NOT NULL, status varchar(32) NOT NULL, " + " PRIMARY KEY (txid) )"); } catch (Exception ex) { log.warn("Create Table Said :" + ex.getMessage()); } try { s.execute("CREATE TABLE search_node_status ( " + " jid bigint NOT NULL, " + " jidts bigint NOT NULL, " + " serverid varchar(255) NOT NULL, " + " PRIMARY KEY (serverid) )"); } catch (Exception ex) { log.warn("Create Table Said :" + ex.getMessage()); } s.close(); connection.commit(); connection.close(); } /** * @return */ public DataSource getDataSource() { return wds; } /** * @throws Exception */ public void close() throws Exception { tds.close(); } public int populateDocuments(long targetItems, String instanceName) throws SQLException { int nitems = 0; Connection connection = null; PreparedStatement insertPST = null; PreparedStatement deletePST = null; try { connection = getDataSource().getConnection(); insertPST = connection .prepareStatement("insert into searchbuilderitem " + "(id,version,name,context,searchaction,searchstate,itemscope) values " + "(?,?,?,?,?,?,?)"); deletePST = connection .prepareStatement("delete from searchbuilderitem where name = ? "); for (int i = 0; i < targetItems; i++) { int state = i % SearchBuilderItem.states.length; String name = SearchBuilderItem.states[state]; int action = i % 3; if (state == SearchBuilderItem.STATE_PENDING && action == SearchBuilderItem.ACTION_ADD) { nitems++; } String reference = "/" + instanceName + "/" + name + "/at/a/location/" + (ldoc++); deletePST.clearParameters(); deletePST.setString(1,reference); deletePST.executeUpdate(); insertPST.clearParameters(); insertPST.setString(1, String.valueOf(instanceName + System.currentTimeMillis()) + String.valueOf(i) + ":" + String.valueOf(docid++)); insertPST.setTimestamp(2, new Timestamp(System.currentTimeMillis())); insertPST.setString(3, reference); insertPST.setString(4, "/" + name + "/at/a"); insertPST.setInt(5, action); insertPST.setInt(6, state); insertPST.setInt(7, SearchBuilderItem.ITEM); insertPST.execute(); } connection.commit(); } finally { try { insertPST.close(); } catch (Exception ex2) { log.debug(ex2); } try { deletePST.close(); } catch (Exception e) { log.debug(e); } try { connection.close(); } catch (Exception ex2) { log.debug(ex2); } } return nitems; } /** * @param i */ public void resetAfter(int i) { if ( ldoc > i ) { ldoc = 0; } } }