/**********************************************************************************
* $URL: https://source.sakaiproject.org/svn/search/trunk/search-impl/impl/src/test/org/sakaiproject/search/indexer/impl/test/TDataSource.java $
* $Id: TDataSource.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.indexer.impl.test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.apache.lucene.document.CompressionTools;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.sakaiproject.search.api.SearchService;
import org.sakaiproject.search.jdbc.WrappingConnection;
import org.sakaiproject.search.jdbc.WrappingDataSource;
import org.sakaiproject.search.model.SearchBuilderItem;
import org.sakaiproject.search.model.impl.SearchBuilderItemImpl;
/**
* @author ieb
*/
public class TDataSource
{
private static final Log log = LogFactory.getLog(TDataSource.class);
private SharedPoolDataSource tds;
private DataSource wds;
protected int nopen = 0;
private DriverAdapterCPDS cpds;
public TDataSource(int poolSize, final boolean logging) throws Exception {
super();
cpds = new DriverAdapterCPDS();
/*
* try { // can we test against mysql
* Class.forName("com.mysql.jdbc.Driver");
* cpds.setDriver("com.mysql.jdbc.Driver"); cpds
* .setUrl("jdbc:mysql://127.0.0.1:3306/sakai22?useUnicode=true&characterEncoding=UTF-8");
* cpds.setUser("sakai22"); cpds.setPassword("sakai22"); } catch
* (ClassNotFoundException cnfe) { }
*/
// we need to use derby db because HSQL only has read_uncommitted
// transaction
// isolation
log.info("Using Derby DB");
cpds.setDriver("org.apache.derby.jdbc.EmbeddedDriver");
cpds.setUrl("jdbc:derby:target/testdb;create=true");
cpds.setUser("sa");
cpds.setPassword("manager");
tds = new SharedPoolDataSource();
tds.setConnectionPoolDataSource(cpds);
tds.setMaxActive(poolSize);
tds.setMaxWait(5);
tds.setDefaultAutoCommit(false);
wds = new WrappingDataSource(tds) {
public Connection getConnection() throws SQLException {
final Connection c = super.getConnection();
nopen++;
if (logging) log.info("+++++++++++Opened " + nopen);
Exception ex = new Exception();
StackTraceElement[] ste = ex.getStackTrace();
log.debug("Stack Trace " + ste[1].toString());
return new WrappingConnection(c) {
public void close() throws SQLException
{
c.close();
nopen--;
if (logging) log.info("--------------Closed " + nopen);
}
};
}
};
Connection connection = tds.getConnection();
Statement s = connection.createStatement();
try
{
s.execute("DROP TABLE search_transaction");
}
catch (Exception ex)
{
log.warn("Drop Table Said :" + ex.getMessage());
}
try
{
s
.execute("create table search_transaction ( txname varchar(36), txid bigint )");
}
catch (Exception ex)
{
log.warn("Create Table Said :" + ex.getMessage());
}
try
{
s.execute("DROP TABLE searchbuilderitem");
}
catch (Exception ex)
{
log.warn("Drop Table Said :" + ex.getMessage());
}
try
{
s.execute("CREATE TABLE searchbuilderitem ( \n"
+ " id varchar(64) NOT NULL, \n" + " version timestamp NOT NULL, \n"
+ " name varchar(255) NOT NULL, \n"
+ " context varchar(255) NOT NULL, \n"
+ " searchaction int default NULL, \n"
+ " searchstate int default NULL, \n"
+ " itemscope int default NULL, \n" + " PRIMARY KEY (id), \n"
+ " UNIQUE (name) \n" + ")");
}
catch (Exception ex)
{
log.warn("Create Table Said :" + ex.getMessage());
}
try
{
s.execute("DROP TABLE search_journal");
}
catch (Exception ex)
{
log.warn("Drop 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(36) NOT NULL, "
+ " PRIMARY KEY (txid) )");
}
catch (Exception ex)
{
log.warn("Create Table Said :" + ex.getMessage());
}
try
{
s.execute("DROP TABLE search_node_status");
}
catch (Exception ex)
{
log.warn("Drop 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 List<SearchBuilderItem> populateDocuments(long targetItems, String prefix)
throws SQLException
{
int nitems = 0;
Connection connection = null;
PreparedStatement insertPST = null;
List<SearchBuilderItem> items = new ArrayList<SearchBuilderItem>();
try
{
connection = getDataSource().getConnection();
insertPST = connection
.prepareStatement("insert into searchbuilderitem "
+ "(id,version,name,context,searchaction,searchstate,itemscope) values "
+ "(?,?,?,?,?,?,?)");
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++;
}
SearchBuilderItemImpl sbi = new SearchBuilderItemImpl();
sbi.setContext("/" + name + prefix+"/at/a");
sbi.setName("/" + name + prefix +"/at/a/location/" + i);
sbi.setVersion(new Date(System.currentTimeMillis()));
sbi.setId(String.valueOf(System.currentTimeMillis()) + String.valueOf(i));
sbi.setItemscope(SearchBuilderItem.ITEM);
sbi.setSearchaction(action);
sbi.setSearchstate(state);
insertPST.clearParameters();
insertPST.setString(1, sbi.getId());
insertPST.setTimestamp(2, new Timestamp(sbi.getVersion().getTime()));
insertPST.setString(3, sbi.getName());
insertPST.setString(4, sbi.getContext());
insertPST.setInt(5, sbi.getSearchaction());
insertPST.setInt(6, sbi.getSearchstate());
insertPST.setInt(7, sbi.getItemscope());
insertPST.execute();
items.add(sbi);
}
connection.commit();
}
finally
{
try
{
insertPST.close();
}
catch (Exception ex2)
{
log.debug(ex2);
}
try
{
connection.close();
}
catch (Exception ex2)
{
log.debug(ex2);
}
}
return items;
}
/**
* @param items
* @param indexSearcher
* @return
*/
public int checkIndexContents(List<SearchBuilderItem> items,
IndexSearcher indexSearcher)
{
int errors = 0;
try
{
Map<String, SearchBuilderItem> finalState = new HashMap<String, SearchBuilderItem>();
for (SearchBuilderItem sbi : items)
{
if (sbi.getSearchstate().equals(SearchBuilderItem.STATE_PENDING)) {
finalState.put(sbi.getId(), sbi);
}
}
for (SearchBuilderItem sbi :finalState.values() )
{
TermQuery tq = new TermQuery(new Term(SearchService.FIELD_REFERENCE, sbi
.getName()));
TopDocs topDocs = indexSearcher.search(tq, 1000000);
if (sbi.getSearchaction().equals(SearchBuilderItem.ACTION_ADD))
{
log.info("====== ADD CHECKING =====");
if (topDocs.totalHits != 1)
{
log.error("Didnt find " + sbi.getName() + " got " + topDocs.totalHits);
errors++;
}
else
{
Document doc = indexSearcher.doc(topDocs.scoreDocs[0].doc);
byte[] binValue = doc.getBinaryValue(SearchService.FIELD_REFERENCE);
String value = null;
if (binValue == null)
{
log.warn("Binary Value not found!");
value = doc.get(SearchService.FIELD_REFERENCE);
} else {
value = CompressionTools.decompressString(binValue);
}
if (!sbi.getName().equals(value))
{
log.error("Ids Dont Match " + sbi.getName() + ":" + value);
errors++;
}
else
{
log.debug("Ok " + sbi.getName());
}
}
}
else
{
log.info("====== DELETE CHECKING =====");
if (topDocs.totalHits != 0)
{
Document doc = indexSearcher.doc(0);
String value = CompressionTools.decompressString(doc.getBinaryValue(SearchService.FIELD_REFERENCE));
log.error("Found " + sbi.getName() + " when should have not "
+ value + " "
+ SearchBuilderItem.actions[sbi.getSearchaction()] + " "
+ (sbi.isLocked()?"Locked to "+sbi.getLock():SearchBuilderItem.states[sbi.getSearchstate()]) + "");
errors++;
}
else
{
log.debug("Ok " + sbi.getName());
}
}
}
return errors;
}
catch (Exception ex)
{
log.error("Searching Exception ", ex);
return -1;
}
}
/**
* @param items
* @return
* @throws SQLException
*/
public List<SearchBuilderItem> deleteSomeItems(List<SearchBuilderItem> items) throws SQLException
{
int nitems = 0;
Connection connection = null;
PreparedStatement updatePST = null;
try
{
connection = getDataSource().getConnection();
updatePST = connection
.prepareStatement("update searchbuilderitem set searchaction = ?, searchstate = ? where id = ?");
int i = 0;
for (SearchBuilderItem sbi : items )
{
if ( sbi.getSearchaction().equals(SearchBuilderItem.ACTION_ADD)) {
i++;
if ( i%3 == 0 ) {
sbi.setSearchaction(SearchBuilderItem.ACTION_DELETE);
sbi.setSearchstate(SearchBuilderItem.STATE_PENDING);
updatePST.clearParameters();
updatePST.setInt(1, sbi.getSearchaction());
updatePST.setInt(2, sbi.getSearchstate());
updatePST.setString(3, sbi.getId());
if ( updatePST.executeUpdate() != 1) {
throw new SQLException("Failed to update for delete "+sbi.getId());
}
log.info("Marked "+sbi.getName()+" for deletion ");
}
}
}
connection.commit();
}
finally
{
try
{
updatePST.close();
}
catch (Exception ex2)
{
log.debug(ex2);
}
try
{
connection.close();
}
catch (Exception ex2)
{
log.debug(ex2);
}
}
return items;
}
}