Various bug fixes and improvements to the checker code, from Grace Carpenter, Jim Downing and Nathan Sarr

git-svn-id: http://scm.dspace.org/svn/repo/trunk@1412 9c30dcfa-912a-0410-8fc2-9e0234be79fd
This commit is contained in:
Jim Downing
2006-01-30 13:22:55 +00:00
parent b8a54bbaa9
commit 6c35684c85
26 changed files with 503 additions and 437 deletions

View File

@@ -73,3 +73,12 @@ log4j.appender.A1.MaxBackupIndex=500
# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d %-5p %c @ %m%n
# A2 is the log for the Checker
log4j.category.org.dspace.checker=INFO, A2
log4j.appender.A2=org.apache.log4j.RollingFileAppender
log4j.appender.A2.File=@@log.dir@@/checker.log
log4j.appender.A2.layout=org.apache.log4j.PatternLayout
log4j.appender.A2.layout.ConversionPattern=%m%n
log4j.appender.A2.MaxFileSize=1048576
log4j.appender.A2.MaxBackupIndex=500

View File

@@ -49,6 +49,7 @@ import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.apache.log4j.Logger;
import org.dspace.checker.BitstreamDispatcher;
import org.dspace.checker.BitstreamInfoDAO;
import org.dspace.checker.CheckerCommand;
import org.dspace.checker.HandleDispatcher;
import org.dspace.checker.LimitedCountDispatcher;
@@ -113,14 +114,14 @@ public class ChecksumChecker
// create an options object and populate it
Options options = new Options();
options.addOption("l", "looping", false, "Loop through bitstreams");
options.addOption("l", "looping", false, "Loop once through bitstreams");
options.addOption("L", "continuous", false,
"Continuously loop through bitstreams");
"Loop continuously through bitstreams");
options.addOption("h", "help", false, "Help");
options.addOption("d", "duration", true, "Checking duration");
options.addOption("c", "count", true, "Check count");
options.addOption("a", "handle", true, "Specify a handle to check");
options.addOption("e", "errors", false, "Report Errors Only");
options.addOption("v", "verbose", false, "Report all processing");
OptionBuilder.withArgName("bitstream-ids").hasArgs().withDescription(
"Space separated list of bitstream ids");
@@ -176,88 +177,81 @@ public class ChecksumChecker
Date processStart = Calendar.getInstance().getTime();
BitstreamDispatcher dispatcher = null;
if (line.getOptions().length == 0)
// process should loop infinitely through
// most_recent_checksum table
if (line.hasOption('l'))
{
dispatcher = new LimitedCountDispatcher(new SimpleDispatcher(
processStart, false), 1);
dispatcher = new SimpleDispatcher(new BitstreamInfoDAO(), processStart, false);
}
else
else if (line.hasOption('L'))
{
// process should loop infinitely through
// most_recent_checksum table
if (line.hasOption('l'))
{
dispatcher = new SimpleDispatcher(processStart, false);
}
else if (line.hasOption('L'))
{
dispatcher = new SimpleDispatcher(processStart, true);
}
else if (line.hasOption('b'))
{
// check only specified bitstream(s)
String[] ids = line.getOptionValues('b');
List idList = new ArrayList(ids.length);
dispatcher = new SimpleDispatcher(new BitstreamInfoDAO(), processStart, true);
}
else if (line.hasOption('b'))
{
// check only specified bitstream(s)
String[] ids = line.getOptionValues('b');
List idList = new ArrayList(ids.length);
for (int i = 0; i < ids.length; i++)
{
try
{
idList.add(new Integer(ids[i]));
}
catch (NumberFormatException nfe)
{
System.err.println("The following argument: " + ids[i]
+ " is not an integer");
System.exit(0);
}
}
dispatcher = new ListDispatcher(idList);
}
else if (line.hasOption('a'))
for (int i = 0; i < ids.length; i++)
{
dispatcher = new HandleDispatcher(line.getOptionValue('a'));
}
else if (line.hasOption('d'))
{
// run checker process for specified duration
try
{
dispatcher = new LimitedDurationDispatcher(
new SimpleDispatcher(processStart, true), new Date(
System.currentTimeMillis()
+ Utils.parseDuration(line
.getOptionValue('d'))));
idList.add(new Integer(ids[i]));
}
catch (Exception e)
catch (NumberFormatException nfe)
{
LOG.fatal("Couldn't parse " + line.getOptionValue('d')
+ " as a duration: ", e);
System.err.println("The following argument: " + ids[i]
+ " is not an integer");
System.exit(0);
}
}
else if (line.hasOption('c'))
dispatcher = new ListDispatcher(idList);
}
else if (line.hasOption('a'))
{
dispatcher = new HandleDispatcher(new BitstreamInfoDAO(), line.getOptionValue('a'));
}
else if (line.hasOption('d'))
{
// run checker process for specified duration
try
{
// run checker process for specified number of bitstreams
dispatcher = new LimitedCountDispatcher(new SimpleDispatcher(
processStart, false));
dispatcher = new LimitedDurationDispatcher(
new SimpleDispatcher(new BitstreamInfoDAO(), processStart, true), new Date(
System.currentTimeMillis()
+ Utils.parseDuration(line
.getOptionValue('d'))));
}
catch (Exception e)
{
LOG.fatal("Couldn't parse " + line.getOptionValue('d')
+ " as a duration: ", e);
System.exit(0);
}
}
if (dispatcher == null)
else if (line.hasOption('c'))
{
System.out
.println("Error: insufficient option commands to run checker.");
printHelp(options);
int count = new Integer(line.getOptionValue('c')).intValue();
// run checker process for specified number of bitstreams
dispatcher = new LimitedCountDispatcher(new SimpleDispatcher(
new BitstreamInfoDAO(), processStart, false), count);
}
else
{
dispatcher = new LimitedCountDispatcher(new SimpleDispatcher(
new BitstreamInfoDAO(), processStart, false), 1);
}
ResultsLogger logger = new ResultsLogger(processStart);
CheckerCommand checker = new CheckerCommand();
// report errors only
if (line.hasOption('e'))
// verbose reporting
if (line.hasOption('v'))
{
checker.setReportErrorsOnly(true);
checker.setReportVerbose(true);
}
checker.configureLog();
checker.setProcessStartDate(processStart);
@@ -283,14 +277,14 @@ public class ChecksumChecker
+ " OR ChecksumChecker -d 2h");
System.out
.println("\nSpecify bitstream IDs: ChecksumChecker -b 13 15 17 20");
System.out.println("\nLoop through all bitstreams: "
System.out.println("\nLoop once through all bitstreams: "
+ "ChecksumChecker -l");
System.out
.println("\nLoop through all bitstreams continuously: ChecksumChecker -L");
.println("\nLoop continuously through all bitstreams: ChecksumChecker -L");
System.out
.println("\nCheck a defined number of bitstreams: ChecksumChecker -c 10");
System.out.println("Default (no arguments) is '-c 1'");
System.out.println("\nReport errors only in logs: ChecksumChecker -e");
System.out.println("\nReport all processing (verbose)(default reports only errors): ChecksumChecker -v");
System.out.println("\nDefault (no arguments) is equivalent to '-c 1'");
System.exit(0);
}

View File

@@ -46,6 +46,9 @@ import org.dspace.storage.bitstore.BitstreamStorageManager;
* </p>
*
* @author Jim Downing
* @author Grace Carpenter
* @author Nathan Sarr
*
*/
public class BitstreamDAO
{

View File

@@ -33,7 +33,6 @@
*/
package org.dspace.checker;
import java.sql.SQLException;
/**
* <p>
@@ -54,8 +53,10 @@ import java.sql.SQLException;
* </ol>
*
*
* @author Nate Sarr
* @author Jim Downing
* @author Grace Carpenter
* @author Nathan Sarr
*
*/
public interface BitstreamDispatcher
{
@@ -72,10 +73,6 @@ public interface BitstreamDispatcher
* @return the next bitstream id, or BitstreamDispatcher.SENTINEL if there
* isn't another value
*
* @throws SQLException
* if there is some problem querying a database
*
* @todo This should probably wrap the SQL exception
*/
public int next() throws SQLException;
public int next();
}

View File

@@ -42,7 +42,9 @@ import java.util.Date;
* </p>
*
* @author Jim Downing
* @author Nate Sarr
* @author Grace Carpenter
* @author Nathan Sarr
*
*/
public final class BitstreamInfo
{

View File

@@ -38,7 +38,9 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.log4j.Logger;
import org.dspace.storage.rdbms.DatabaseManager;
@@ -50,11 +52,19 @@ import org.dspace.storage.rdbms.DatabaseManager;
* checker.
* </p>
*
* @author Nate Sarr
* @author Jim Downing
* @author Grace Carpenter
* @author Nathan Sarr
*
*/
public final class BitstreamInfoDAO extends DAOSupport
{
/**
* This value should be returned by <code>next()</code> to indicate that
* there are no more values.
*/
public static int SENTINEL = -1;
/** Query that gets bitstream information for a specified ID. */
private static final String FIND_BY_BITSTREAM_ID = "select bitstream.deleted, bitstream.store_number, bitstream.size_bytes, "
+ "bitstreamformatregistry.short_description, bitstream.bitstream_id, "
@@ -88,27 +98,6 @@ public final class BitstreamInfoDAO extends DAOSupport
+ "select 'x' from most_recent_checksum "
+ "where most_recent_checksum.bitstream_id = bitstream.bitstream_id );";
/**
* Query that select a specified bitstream from bitstream table and inserts
* it into the most_recent_checksum table if it does not already exist.
*/
private static final String INSERT_MISSING_CHECKSUM_BITSTREAM = "insert into most_recent_checksum ( "
+ "bitstream_id, to_be_processed, expected_checksum, current_checksum, "
+ "last_process_start_date, last_process_end_date, "
+ "checksum_algorithm, matched_prev_checksum, result ) "
+ "select bitstream.bitstream_id, "
+ "true, "
+ "CASE WHEN bitstream.checksum IS NULL THEN '' ELSE bitstream.checksum END, "
+ "?, "
+ "?, "
+ "CASE WHEN bitstream.checksum_algorithm IS NULL "
+ "THEN 'MD5' ELSE bitstream.checksum_algorithm END, true, "
+ "CASE WHEN bitstream.deleted = true THEN 'BITSTREAM_MARKED_DELETED' else 'CHECKSUM_MATCH' END "
+ "from bitstream where bitstream.bitstream_id = ? "
+ "and not exists( "
+ "select 'x' from most_recent_checksum "
+ "where most_recent_checksum.bitstream_id = ? );";
/**
* Query that updates most_recent_checksum table with checksum result for
* specified bitstream ID.
@@ -123,6 +112,42 @@ public final class BitstreamInfoDAO extends DAOSupport
private static final String DELETE_BITSTREAM_INFO = "Delete from most_recent_checksum "
+ "where bitstream_id = ?";
/**
* This selects the next bitstream in order of last processing end date. The
* timestamp is truncated to milliseconds this is because the Date for java
* does not support nanoseconds and milliseconds were considered accurate
* enough
*/
public static final String GET_OLDEST_BITSTREAM = "select bitstream_id "
+ "from most_recent_checksum " + "where to_be_processed = true "
+ "order by date_trunc('milliseconds', last_process_end_date), "
+ "bitstream_id " + "ASC LIMIT 1";
/**
* Selects the next bitstream in order of last processing end date, ensuring
* that no bitstream is checked more than once since the date parameter
* used.
*/
public static final String GET_OLDEST_BITSTREAM_DATE = "select bitstream_id "
+ "from most_recent_checksum "
+ "where to_be_processed = true "
+ "and last_process_start_date < ? "
+ "order by date_trunc('milliseconds', last_process_end_date), "
+ "bitstream_id " + "ASC LIMIT 1";
/** SQL query to retrieve bitstreams for a given item. */
private static final String ITEM_BITSTREAMS = "SELECT b2b.bitstream_id "
+ "FROM bundle2bitstream b2b, item2bundle i2b WHERE "
+ "b2b.bundle_id=i2b.bundle_id AND i2b.item_id=?";
/** SQL query to retrieve bitstreams for a given collection. */
private static final String COLLECTION_BITSTREAMS = "SELECT b2b.bitstream_id "
+ "FROM bundle2bitstream b2b, item2bundle i2b, collection2item c2i WHERE "
+ "b2b.bundle_id=i2b.bundle_id AND c2i.item_id=i2b.item_id AND c2i.collection_id=?";
/** SQL query to retrieve bitstreams for a given community. */
private static final String COMMUNITY_BITSTREAMS = "SELECT b2b.bitstream_id FROM bundle2bitstream b2b, item2bundle i2b, collection2item c2i, community2collection c2c WHERE b2b.bundle_id=i2b.bundle_id AND c2i.item_id=i2b.item_id AND c2c.collection_id=c2i.collection_id AND c2c.community_id=?";
/** Standard Log4J logger. */
private static final Logger LOG = Logger.getLogger(BitstreamInfoDAO.class);
@@ -257,13 +282,12 @@ public final class BitstreamInfoDAO extends DAOSupport
try
{
LOG.debug("updateing missing bitstreams");
LOG.debug("updating missing bitstreams");
conn = DatabaseManager.getConnection();
stmt = conn.prepareStatement(INSERT_MISSING_CHECKSUM_BITSTREAMS);
stmt.setTimestamp(1, new java.sql.Timestamp(new Date().getTime()));
stmt.setTimestamp(2, new java.sql.Timestamp(new Date().getTime()));
stmt.executeUpdate();
LOG.debug("Committing update");
checksumHistoryDAO.updateMissingBitstreams(conn);
conn.commit();
@@ -327,64 +351,6 @@ public final class BitstreamInfoDAO extends DAOSupport
return numDeleted;
}
/**
* Queries the bitstream table for the specified bitstream ID and inserts it
* into the most_recent_checksum table if it does not already exist.
*
* @param id
* the bitstream id.
*
* @return true if the bitstream was found and updated
*/
public boolean updateMissingBitstream(int id)
{
Connection conn = null;
PreparedStatement stmt = null;
boolean bitstreamFound = false;
try
{
conn = DatabaseManager.getConnection();
stmt = conn.prepareStatement(INSERT_MISSING_CHECKSUM_BITSTREAM);
stmt.setTimestamp(1, new java.sql.Timestamp(new Date().getTime()));
stmt.setTimestamp(2, new java.sql.Timestamp(new Date().getTime()));
stmt.setInt(3, id);
stmt.setInt(4, id);
int rowsUpdated = stmt.executeUpdate();
if (rowsUpdated == 1)
{
bitstreamFound = true;
}
if (rowsUpdated > 1)
{
conn.rollback();
throw new IllegalStateException(
"Too many rows updated! Number of rows updated: "
+ rowsUpdated
+ " only one row should be updated for bitstream id "
+ id);
}
conn.commit();
}
catch (SQLException e)
{
LOG.error("Problem with inserting missing bitstream. "
+ e.getMessage(), e);
throw new RuntimeException("Problem inserting missing bitstream. "
+ e.getMessage(), e);
}
finally
{
cleanup(stmt, conn);
}
return bitstreamFound;
}
public int deleteBitstreamInfoWithHistory(int id)
{
Connection conn = null;
@@ -411,4 +377,219 @@ public final class BitstreamInfoDAO extends DAOSupport
return numDeleted;
}
/**
* Get the oldest bitstream in the most recent checksum table. If more than
* one found the first one in the result set is returned.
*
* @return the bitstream id or -1 if the no bitstreams are found
*
*/
public int getOldestBitstream()
{
Connection conn = null;
PreparedStatement prepStmt = null;
ResultSet rs = null;
try
{
conn = DatabaseManager.getConnection();
prepStmt = conn.prepareStatement(GET_OLDEST_BITSTREAM);
rs = prepStmt.executeQuery();
if (rs.next())
{
return rs.getInt(1);
}
else
{
return SENTINEL;
}
}
catch (SQLException e)
{
LOG.error("Problem with get oldest bitstream " + e.getMessage(), e);
throw new RuntimeException("Oldest bitstream error. "
+ e.getMessage(), e);
}
finally
{
cleanup(prepStmt, conn);
}
}
/**
* Returns the oldest bistream that in the set of bitstreams that are less
* than the specified date. If no bitstreams are found -1 is returned.
*
* @param lessThanDate
* @return id of olded bitstream or -1 if not bistreams are found
*/
public int getOldestBitstream(Timestamp lessThanDate)
{
Connection conn = null;
PreparedStatement prepStmt = null;
ResultSet rs = null;
try
{
conn = DatabaseManager.getConnection();
prepStmt = conn.prepareStatement(GET_OLDEST_BITSTREAM_DATE);
prepStmt.setTimestamp(1, lessThanDate);
rs = prepStmt.executeQuery();
if (rs.next())
{
return rs.getInt(1);
}
else
{
return SENTINEL;
}
}
catch (SQLException e)
{
LOG.error("get oldest bitstream less than date " + e.getMessage(),
e);
throw new RuntimeException("get oldest bitstream less than date. "
+ e.getMessage(), e);
}
finally
{
cleanup(prepStmt, conn);
}
}
/**
* Get the bitstream ids for a given Item
*
* @param itemId
* @return the list of bitstream ids for this item
*/
public List getItemBitstreams(int itemId)
{
List ids = new ArrayList();
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try
{
conn = DatabaseManager.getConnection();
ps = conn.prepareStatement(ITEM_BITSTREAMS);
ps.setInt(1, itemId);
rs = ps.executeQuery();
while (rs.next())
{
ids.add(new Integer(rs.getInt(1)));
}
}
catch (SQLException e)
{
LOG.error("get item bitstreams " + e.getMessage(), e);
throw new RuntimeException(
"get item bitstreams. " + e.getMessage(), e);
}
finally
{
cleanup(ps, conn, rs);
}
return ids;
}
/**
* Get the bitstream ids for a given collection
*
* @param itemId
* @return the list of bitstream ids for this item
*/
public List getCollectionBitstreams(int collectionId)
{
List ids = new ArrayList();
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try
{
conn = DatabaseManager.getConnection();
ps = conn.prepareStatement(COLLECTION_BITSTREAMS);
ps.setInt(1, collectionId);
rs = ps.executeQuery();
while (rs.next())
{
ids.add(new Integer(rs.getInt(1)));
}
}
catch (SQLException e)
{
LOG.error("get item bitstreams " + e.getMessage(), e);
throw new RuntimeException(
"get item bitstreams. " + e.getMessage(), e);
}
finally
{
cleanup(ps, conn, rs);
}
return ids;
}
/**
* Get the bitstream ids for a given community
*
* @param itemId
* @return the list of bitstream ids for this item
*/
public List getCommunityBitstreams(int communityId)
{
List ids = new ArrayList();
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try
{
conn = DatabaseManager.getConnection();
ps = conn.prepareStatement(COMMUNITY_BITSTREAMS);
ps.setInt(1, communityId);
rs = ps.executeQuery();
while (rs.next())
{
ids.add(new Integer(rs.getInt(1)));
}
}
catch (SQLException e)
{
LOG.error("get item bitstreams " + e.getMessage(), e);
throw new RuntimeException(
"get item bitstreams. " + e.getMessage(), e);
}
finally
{
cleanup(ps, conn, rs);
}
return ids;
}
}

View File

@@ -54,9 +54,10 @@ import org.dspace.core.Utils;
* against the last calculated checksum for that bitstream.
* </p>
*
* @author Nate Sarr
* @author Grace Carpenter
* @author Jim Downing
* @author Grace Carpenter
* @author Nathan Sarr
*
*
* @todo the accessor methods are currently unused - are they useful?
* @todo check for any existing resource problems
@@ -96,8 +97,8 @@ public final class CheckerCommand
*/
private ChecksumResultsCollector collector = null;
/** Report only errors */
private boolean reportErrorsOnly = false;
/** Report all processing */
private boolean reportVerbose = false;
/**
* Default constructor uses DSpace plugin manager to construct dependencies.
@@ -135,37 +136,25 @@ public final class CheckerCommand
collector = new ResultsLogger(processStartDate);
}
// loop through bitstreams and check
try
{
bitstreamInfoDAO.updateMissingBitstreams();
int id = dispatcher.next();
LOG.debug("Processing bitstream id = " + id);
while (id != BitstreamDispatcher.SENTINEL)
{
BitstreamInfo info = checkBitstream(id);
if (reportErrorsOnly
&& (info.getChecksumCheckResult() == ChecksumCheckResults.CHECKSUM_MATCH))
{
// NO-OP do not report good checksums
}
else
{
collector.collect(info);
}
id = dispatcher.next();
}
}
catch (SQLException e)
{
LOG.error("Next bitstream metadata could not be retrieved. ", e);
}
// update missing bitstreams that were entered into the
// bitstream table - this always done.
bitstreamInfoDAO.updateMissingBitstreams();
int id = dispatcher.next();
while (id != BitstreamDispatcher.SENTINEL)
{
LOG.debug("Processing bitstream id = " + id);
BitstreamInfo info = checkBitstream(id);
if (reportVerbose
|| (info.getChecksumCheckResult() != ChecksumCheckResults.CHECKSUM_MATCH))
{
collector.collect(info);
}
id = dispatcher.next();
}
}
/**
@@ -181,15 +170,6 @@ public final class CheckerCommand
// get bitstream info from bitstream table
BitstreamInfo info = bitstreamInfoDAO.findByBitstreamId(id);
// make sure bitstream and most_recent_checksum in sync for the id
if (info == null)
{
if (bitstreamInfoDAO.updateMissingBitstream(id))
{
info = bitstreamInfoDAO.findByBitstreamId(id);
}
}
// requested id was not found in bitstream
// or most_recent_checksum table
if (info == null)
@@ -480,9 +460,9 @@ public final class CheckerCommand
*
* @return true if only errors reported
*/
public boolean isReportErrorsOnly()
public boolean isReportVerbose()
{
return reportErrorsOnly;
return reportVerbose;
}
/**
@@ -491,8 +471,8 @@ public final class CheckerCommand
* @param reportErrorsOnly
* true to report only errors in the logs.
*/
public void setReportErrorsOnly(boolean reportErrorsOnly)
public void setReportVerbose(boolean reportVerbose)
{
this.reportErrorsOnly = reportErrorsOnly;
this.reportVerbose = reportVerbose;
}
}

View File

@@ -37,8 +37,10 @@ package org.dspace.checker;
* Enumeration of ChecksumCheckResults containing constants for checksum
* comparison result that must correspond to values in checksum_result table.
*
* @author Grace Carpenter
* @author Jim Downing
* @author Grace Carpenter
* @author Nathan Sarr
*
*
* @todo Refactor these as properties of ChecksumChecker?
*/

View File

@@ -40,7 +40,10 @@ import java.util.Date;
* Represents a history record for the bitstream.
* </p>
*
* @author Nate Sarr
* @author Jim Downing
* @author Grace Carpenter
* @author Nathan Sarr
*
*/
public class ChecksumHistory
{

View File

@@ -19,8 +19,10 @@ import org.dspace.storage.rdbms.DatabaseManager;
* </p>
*
* @author Jim Downing
* @author Grace Carpenter
* @author Nathan Sarr
*
*
*/
public class ChecksumHistoryDAO extends DAOSupport
{
@@ -149,7 +151,7 @@ public class ChecksumHistoryDAO extends DAOSupport
/**
* @param conn
*/
protected void updateMissingBitstreams(Connection conn)
protected void updateMissingBitstreams(Connection conn) throws SQLException
{
PreparedStatement stmt = null;
try
@@ -163,10 +165,9 @@ public class ChecksumHistoryDAO extends DAOSupport
throw new RuntimeException("Problem updating missing history. "
+ e.getMessage(), e);
}
finally
{
cleanup(stmt, conn);
cleanup(stmt);
}
}

View File

@@ -49,7 +49,10 @@ import org.dspace.storage.rdbms.DatabaseManager;
* Database Access for the checksum results information.
* </p>
*
* @author Nate Sarr
* @author Jim Downing
* @author Grace Carpenter
* @author Nathan Sarr
*
*/
public final class ChecksumResultDAO extends DAOSupport
{

View File

@@ -37,6 +37,9 @@ package org.dspace.checker;
* Component that receives BitstreamInfo results from a checker.
*
* @author Jim Downing
* @author Grace Carpenter
* @author Nathan Sarr
*
*/
public interface ChecksumResultsCollector
{

View File

@@ -8,6 +8,14 @@ import java.sql.Statement;
import org.apache.log4j.Logger;
import org.dspace.storage.rdbms.DatabaseManager;
/**
* Database Helper Class to cleanup database resources
*
* @author Jim Downing
* @author Grace Carpenter
* @author Nathan Sarr
*
*/
public class DAOSupport
{

View File

@@ -37,7 +37,10 @@ package org.dspace.checker;
* Value Object that holds bitstream information that will be used for dspace
* bitstream.
*
* @author Nate Sarr
* @author Jim Downing
* @author Grace Carpenter
* @author Nathan Sarr
*
*/
public final class DSpaceBitstreamInfo
{

View File

@@ -69,7 +69,10 @@ import org.dspace.core.ConfigurationManager;
* after the checksum checker has been run.
* </p>
*
* @author Nate Sarr
* @author Jim Downing
* @author Grace Carpenter
* @author Nathan Sarr
*
*
*/
public class DailyReportEmailer

View File

@@ -33,9 +33,6 @@
*/
package org.dspace.checker;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
@@ -51,21 +48,12 @@ import org.dspace.handle.HandleManager;
* item, collection or community referred to by Handle.
*
* @author Jim Downing
* @author Grace Carpenter
* @author Nathan Sarr
*
*/
public class HandleDispatcher implements BitstreamDispatcher
{
/** SQL query to retrieve bitstreams for a given item. */
private static final String ITEM_BITSTREAMS = "SELECT b2b.bitstream_id "
+ "FROM bundle2bitstream b2b, item2bundle i2b WHERE "
+ "b2b.bundle_id=i2b.bundle_id AND i2b.item_id=?";
/** SQL query to retrieve bitstreams for a given collection. */
private static final String COLLECTION_BITSTREAMS = "SELECT b2b.bitstream_id "
+ "FROM bundle2bitstream b2b, item2bundle i2b, collection2item c2i WHERE "
+ "b2b.bundle_id=i2b.bundle_id AND c2i.item_id=i2b.item_id AND c2i.collection_id=?";
/** SQL query to retrieve bitstreams for a given community. */
private static final String COMMUNITY_BITSTREAMS = "SELECT b2b.bitstream_id FROM bundle2bitstream b2b, item2bundle i2b, collection2item c2i, community2collection c2c WHERE b2b.bundle_id=i2b.bundle_id AND c2i.item_id=i2b.item_id AND c2c.collection_id=c2i.collection_id AND c2c.community_id=?";
/** Log 4j logger. */
private static final Logger LOG = Logger.getLogger(HandleDispatcher.class);
@@ -79,6 +67,11 @@ public class HandleDispatcher implements BitstreamDispatcher
/** the delegate to dispatch to. */
ListDispatcher delegate = null;
/**
* Database access for retrieving bitstreams
*/
BitstreamInfoDAO bitstreamInfoDAO;
/**
* Blanked off, no-op constructor.
*/
@@ -93,8 +86,9 @@ public class HandleDispatcher implements BitstreamDispatcher
* @param hdl
* the handle to get bitstreams from.
*/
public HandleDispatcher(String hdl)
public HandleDispatcher(BitstreamInfoDAO bitInfoDAO, String hdl)
{
bitstreamInfoDAO = bitInfoDAO;
handle = hdl;
}
@@ -104,41 +98,26 @@ public class HandleDispatcher implements BitstreamDispatcher
* @throws SQLException
* if database access fails.
*/
private void init() throws SQLException
private void init()
{
Context context = null;
int dsoType = -1;
int id = -1;
try
{
context = new Context();
DSpaceObject dso = HandleManager.resolveToObject(context, handle);
id = dso.getID();
dsoType = dso.getType();
context.abort();
List ids = new ArrayList();
}
catch (SQLException e)
{
LOG.error("init error " + e.getMessage(), e);
throw new RuntimeException("init error" + e.getMessage(), e);
switch (dso.getType())
{
case Constants.BITSTREAM:
ids.add(new Integer(dso.getID()));
break;
case Constants.ITEM:
ids = getItemIds(dso.getID());
break;
case Constants.COLLECTION:
ids = getCollectionIds(dso.getID());
break;
case Constants.COMMUNITY:
ids = getCommunityIds(dso.getID());
}
delegate = new ListDispatcher(ids);
init = Boolean.TRUE;
}
finally
{
@@ -148,6 +127,30 @@ public class HandleDispatcher implements BitstreamDispatcher
context.abort();
}
}
List ids = new ArrayList();
switch (dsoType)
{
case Constants.BITSTREAM:
ids.add(new Integer(id));
break;
case Constants.ITEM:
ids = bitstreamInfoDAO.getItemBitstreams(id);
break;
case Constants.COLLECTION:
ids = bitstreamInfoDAO.getCollectionBitstreams(id);
break;
case Constants.COMMUNITY:
ids = bitstreamInfoDAO.getCommunityBitstreams(id);
break;
}
delegate = new ListDispatcher(ids);
init = Boolean.TRUE;
}
/**
@@ -155,7 +158,7 @@ public class HandleDispatcher implements BitstreamDispatcher
*
* @see org.dspace.checker.BitstreamDispatcher#next()
*/
public int next() throws SQLException
public int next()
{
synchronized (init)
{
@@ -167,100 +170,4 @@ public class HandleDispatcher implements BitstreamDispatcher
return delegate.next();
}
/**
* Utility query method to get item ids.
*
* @param id
* the item id
* @return a list of bitstream ids for items.
* @throws SQLException
* if database access fails
*/
private List getItemIds(int id) throws SQLException
{
return getIdList(id, ITEM_BITSTREAMS);
}
/**
* Utility query method.
*
* @param id
* Collection id
* @return a list of bitstream ids for collection
* @throws SQLException
* if database access error occurs.
*/
private List getCollectionIds(int id) throws SQLException
{
return getIdList(id, COLLECTION_BITSTREAMS);
}
/**
* Utility query method.
*
* @param id
* the community id
* @return the bitstream ids.
* @throws SQLException
* if a database access error occurs.
*/
private List getCommunityIds(int id) throws SQLException
{
return getIdList(id, COMMUNITY_BITSTREAMS);
}
/**
* Utility query method.
*
* @param arg
* community/collection/item id.
* @param query
* query to be excuted
* @return list of bitstream ids.
* @throws SQLException
* if database access occurs.
*/
private List getIdList(int arg, String query) throws SQLException
{
List ids = new ArrayList();
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
Context ctx = new Context();
try
{
conn = ctx.getDBConnection();
ps = conn.prepareStatement(query);
ps.setInt(1, arg);
rs = ps.executeQuery();
while (rs.next())
{
ids.add(new Integer(rs.getInt(1)));
}
LOG.debug("Returned " + ids.size() + " ids for handle " + handle);
}
finally
{
if (rs != null)
{
rs.close();
}
if (ps != null)
{
ps.close();
}
ctx.complete();
}
return ids;
}
}

View File

@@ -42,6 +42,9 @@ import org.dspace.core.PluginManager;
* dispatcher.
*
* @author Jim Downing
* @author Grace Carpenter
* @author Nathan Sarr
*
*/
public class LimitedCountDispatcher implements BitstreamDispatcher
{
@@ -92,7 +95,7 @@ public class LimitedCountDispatcher implements BitstreamDispatcher
* @throws SQLException
* if database error occurs.
*/
public int next() throws SQLException
public int next()
{
if (remaining > 0)
{

View File

@@ -33,7 +33,6 @@
*/
package org.dspace.checker;
import java.sql.SQLException;
import java.util.Date;
/**
@@ -48,6 +47,9 @@ import java.util.Date;
* </p>
*
* @author Jim Downing
* @author Grace Carpenter
* @author Nathan Sarr
*
*/
public class LimitedDurationDispatcher implements BitstreamDispatcher
{
@@ -90,7 +92,7 @@ public class LimitedDurationDispatcher implements BitstreamDispatcher
/**
* @see org.dspace.checker.BitstreamDispatcher#next()
*/
public int next() throws SQLException
public int next()
{
return (System.currentTimeMillis() > end) ? SENTINEL : delegate.next();
}

View File

@@ -33,7 +33,6 @@
*/
package org.dspace.checker;
import java.sql.SQLException;
import java.util.Collections;
import java.util.EmptyStackException;
import java.util.List;
@@ -43,6 +42,9 @@ import java.util.Stack;
* Really simple dispatcher that just iterates over a pre-defined list of ids.
*
* @author Jim Downing
* @author Grace Carpenter
* @author Nathan Sarr
*
*/
public class ListDispatcher implements BitstreamDispatcher
{
@@ -74,7 +76,7 @@ public class ListDispatcher implements BitstreamDispatcher
/**
* @see org.dspace.checker.BitstreamDispatcher#next()
*/
public synchronized int next() throws SQLException
public synchronized int next()
{
try
{

View File

@@ -47,7 +47,10 @@ import org.dspace.storage.rdbms.DatabaseManager;
/**
* This class will report information on the checksum checker process.
*
* @author Nate Sarr
* @author Jim Downing
* @author Grace Carpenter
* @author Nathan Sarr
*
*
*/
public class ReporterDAO extends DAOSupport

View File

@@ -45,7 +45,10 @@ import org.dspace.core.I18N;
* </p>
*
*
* @author Jim Downing
* @author Grace Carpenter
* @author Nathan Sarr
*
*
*/
public class ResultsLogger implements ChecksumResultsCollector
@@ -131,7 +134,7 @@ public class ResultsLogger implements ChecksumResultsCollector
.info(msg("checksum-algorithm") + ": "
+ info.getChecksumAlgorithm());
LOG.info(msg("previous-checksum") + ": " + info.getStoredChecksum());
LOG.info(msg("previous-checksum-data")
LOG.info(msg("previous-checksum-date")
+ ": "
+ ((info.getProcessEndDate() != null) ? DATE_FORMAT.format(info
.getProcessEndDate()) : "unknown"));

View File

@@ -57,6 +57,9 @@ import org.dspace.core.Utils;
* and can use a different configuration file if it is passed in.
*
* @author Jim Downing
* @author Grace Carpenter
* @author Nathan Sarr
*
*
*/
public final class ResultsPruner

View File

@@ -33,45 +33,19 @@
*/
package org.dspace.checker;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import org.dspace.storage.rdbms.DatabaseManager;
/**
* An implementation of the selection strategy that selects bitstreams in the
* order that they were last checked, looping endlessly.
*
* @author Nate Sarr
* @author Jim Downing
* @author Grace Carpenter
* @author Nathan Sarr
*
*/
public class SimpleDispatcher implements BitstreamDispatcher
{
/**
* This selects the next bitstream that is to be processed, in order of last
* processing end date. The timestamp is truncated to milliseconds this is
* because the Date for java does not support nanoseconds and milliseconds
* were considered accurate enough
*/
public static final String FIND_BITSTREAMS_LOOP = "select bitstream_id "
+ "from most_recent_checksum " + "where to_be_processed = true "
+ "order by date_trunc('milliseconds', last_process_end_date), "
+ "bitstream_id " + "ASC LIMIT 1";
/**
* Selects the next bitstream in order of last processing end date, ensuring
* that no bitstream is checked more than once since the date parameter
* used.
*/
public static final String FIND_BITSTREAMS_NO_LOOP = "select bitstream_id "
+ "from most_recent_checksum "
+ "where to_be_processed = true "
+ "and last_process_start_date < ? "
+ "order by date_trunc('milliseconds', last_process_end_date), "
+ "bitstream_id " + "ASC LIMIT 1";
/**
* Should this dispatcher keep on dispatching around the collection?
@@ -89,6 +63,11 @@ public class SimpleDispatcher implements BitstreamDispatcher
*/
private int bitstreamId = -1;
/**
* Access for bitstream information
*/
private BitstreamInfoDAO bitstreamInfoDAO;
/**
* Creates a new SimpleDispatcher.
*
@@ -98,8 +77,10 @@ public class SimpleDispatcher implements BitstreamDispatcher
* indicates whether checker should loop infinitely through
* most_recent_checksum table
*/
public SimpleDispatcher(Date startTime, boolean looping)
public SimpleDispatcher(BitstreamInfoDAO bitstreamInfoDAO, Date startTime,
boolean looping)
{
this.bitstreamInfoDAO = bitstreamInfoDAO;
this.processStartTime = startTime;
this.loopContinuously = looping;
}
@@ -117,57 +98,19 @@ public class SimpleDispatcher implements BitstreamDispatcher
*
* @see org.dspace.checker.BitstreamDispatcher#next()
*/
public synchronized int next() throws SQLException
public synchronized int next()
{
Connection conn = null;
PreparedStatement prepStmt = null;
ResultSet rs = null;
try
// should process loop infinitely through the
// bitstreams in most_recent_checksum table?
if (!loopContinuously && (processStartTime != null))
{
// create the connection and execute the statement
conn = DatabaseManager.getConnection();
// should process loop infinitely through the
// bitstreams in most_recent_checksum table?
if (!loopContinuously && (processStartTime != null))
{
prepStmt = conn.prepareStatement(FIND_BITSTREAMS_NO_LOOP);
prepStmt.setTimestamp(1, new java.sql.Timestamp(
processStartTime.getTime()));
}
else
{
prepStmt = conn.prepareStatement(FIND_BITSTREAMS_LOOP);
}
rs = prepStmt.executeQuery();
if (rs.next())
{
return rs.getInt(1);
}
else
{
return SENTINEL;
}
return bitstreamInfoDAO.getOldestBitstream(new java.sql.Timestamp(
processStartTime.getTime()));
}
finally
else
{
if (rs != null)
{
rs.close();
}
if (prepStmt != null)
{
prepStmt.close();
}
if (conn != null)
{
DatabaseManager.freeConnection(conn);
}
return bitstreamInfoDAO.getOldestBitstream();
}
}
}

View File

@@ -41,7 +41,10 @@ import java.util.Date;
*
* Simple Reporting Class which can return several different reports.
*
* @author Nate Sarr
* @author Jim Downing
* @author Grace Carpenter
* @author Nathan Sarr
*
*/
public interface SimpleReporter
{

View File

@@ -47,7 +47,10 @@ import org.dspace.core.I18N;
*
* Simple Reporter implementation.
*
* @author Nate Sarr
* @author Jim Downing
* @author Grace Carpenter
* @author Nathan Sarr
*
* @todo estimate string buffer sizes.
*/
public class SimpleReporterImpl implements SimpleReporter

View File

@@ -135,7 +135,9 @@ public class I18N {
* @return Localized message
*/
public String getMessage(String msg, Class clazz) {
return getMessage(msg, clazz.getName());
String className = clazz.getName();
return messages.getString(new StringBuilder(50).append(className)
.append(".").append(msg).toString());
}
/**