001: package org.dspace.checker;
002:
003: import java.sql.Connection;
004: import java.sql.PreparedStatement;
005: import java.sql.SQLException;
006: import java.sql.Timestamp;
007: import java.util.Date;
008: import java.util.Iterator;
009: import java.util.Map;
010:
011: import org.apache.log4j.Logger;
012: import org.dspace.core.ConfigurationManager;
013: import org.dspace.storage.rdbms.DatabaseManager;
014:
015: /**
016: * <p>
017: * This is the data access for the checksum history information. All
018: * update,insert and delete database operations should go through this class for
019: * checksum history operations.
020: * </p>
021: *
022: * @author Jim Downing
023: * @author Grace Carpenter
024: * @author Nathan Sarr
025: *
026: *
027: */
028: public class ChecksumHistoryDAO extends DAOSupport {
029: /**
030: * Query that selects bitstream IDs from most_recent_checksum table that are
031: * not yet in the checksum_history table, and inserts them into
032: * checksum_history.
033: */
034: private static final String INSERT_MISSING_HISTORY_BITSTREAMS = "insert into checksum_history ( "
035: + "bitstream_id, process_start_date, "
036: + "process_end_date, checksum_expected, "
037: + "checksum_calculated, result ) "
038: + "select most_recent_checksum.bitstream_id, "
039: + "most_recent_checksum.last_process_start_date, "
040: + "most_recent_checksum.last_process_end_date, "
041: + "most_recent_checksum.expected_checksum, most_recent_checksum.expected_checksum, "
042: + "CASE WHEN bitstream.deleted = true THEN 'BITSTREAM_MARKED_DELETED' else 'CHECKSUM_MATCH' END "
043: + "from most_recent_checksum, bitstream where "
044: + "not exists( select 'x' from checksum_history where "
045: + "most_recent_checksum.bitstream_id = checksum_history.bitstream_id ) "
046: + "and most_recent_checksum.bitstream_id = bitstream.bitstream_id";
047:
048: private static final String INSERT_MISSING_HISTORY_BITSTREAMS_ORACLE = "insert into checksum_history ( "
049: + "check_id, bitstream_id, process_start_date, "
050: + "process_end_date, checksum_expected, "
051: + "checksum_calculated, result ) "
052: + "select checksum_history_seq.nextval, most_recent_checksum.bitstream_id, "
053: + "most_recent_checksum.last_process_start_date, "
054: + "most_recent_checksum.last_process_end_date, "
055: + "most_recent_checksum.expected_checksum, most_recent_checksum.expected_checksum, "
056: + "CASE WHEN bitstream.deleted = 1 THEN 'BITSTREAM_MARKED_DELETED' else 'CHECKSUM_MATCH' END "
057: + "from most_recent_checksum, bitstream where "
058: + "not exists( select 'x' from checksum_history where "
059: + "most_recent_checksum.bitstream_id = checksum_history.bitstream_id ) "
060: + "and most_recent_checksum.bitstream_id = bitstream.bitstream_id";
061:
062: /** Query that inserts results of recent check into the history table. */
063: private static final String INSERT_HISTORY = "insert into checksum_history ( bitstream_id, process_start_date, "
064: + " process_end_date, checksum_expected, checksum_calculated, result ) "
065: + " values ( ?, ?, ?, ?, ?, ?)";
066:
067: private static final String INSERT_HISTORY_ORACLE = "insert into checksum_history ( check_id, bitstream_id, process_start_date, "
068: + " process_end_date, checksum_expected, checksum_calculated, result ) "
069: + " values ( checksum_history_seq.nextval, ?, ?, ?, ?, ?, ?)";
070:
071: /**
072: * Deletes from the most_recent_checksum where the bitstream id is found
073: */
074: private static final String DELETE_BITSTREAM_HISTORY = "Delete from checksum_history "
075: + "where bitstream_id = ?";
076:
077: /**
078: * Logger for the checksum history DAO.
079: */
080: private static final Logger LOG = Logger
081: .getLogger(ChecksumHistoryDAO.class);
082:
083: /**
084: * Inserts results of checksum check into checksum_history table for a given
085: * bitstream.
086: *
087: * @param info
088: * the BitstreamInfo representing a checksum check.
089: *
090: * @throws IllegalArgumentException
091: * if the <code>BitstreamInfo</code> is null.
092: */
093: public void insertHistory(BitstreamInfo info) {
094: if (info == null) {
095: throw new IllegalArgumentException(
096: "BitstreamInfo parameter may not be null");
097: }
098:
099: Connection conn = null;
100: PreparedStatement stmt = null;
101:
102: try {
103: conn = DatabaseManager.getConnection();
104: if ("oracle".equals(ConfigurationManager
105: .getProperty("db.name")))
106: stmt = conn.prepareStatement(INSERT_HISTORY_ORACLE);
107: else
108: stmt = conn.prepareStatement(INSERT_HISTORY);
109: stmt.setInt(1, info.getBitstreamId());
110: stmt.setTimestamp(2, new java.sql.Timestamp(info
111: .getProcessStartDate().getTime()));
112: stmt.setTimestamp(3, new java.sql.Timestamp(info
113: .getProcessEndDate().getTime()));
114: stmt.setString(4, info.getStoredChecksum());
115: stmt.setString(5, info.getCalculatedChecksum());
116: stmt.setString(6, info.getChecksumCheckResult());
117: stmt.executeUpdate();
118: conn.commit();
119: } catch (SQLException e) {
120: LOG.error("Problem updating checksum row. "
121: + e.getMessage(), e);
122: throw new RuntimeException(
123: "Problem updating checksum row. " + e.getMessage(),
124: e);
125: } finally {
126: cleanup(stmt, conn);
127: }
128: }
129:
130: /**
131: * Deletes the bitstream from the bitstream_history table if it exist.
132: *
133: * @param id
134: * the bitstream id.
135: *
136: * @return number of records deleted
137: */
138: protected int deleteHistoryForBitstreamInfo(int id, Connection conn) {
139: PreparedStatement stmt = null;
140:
141: int numDeleted = 0;
142:
143: try {
144: conn = DatabaseManager.getConnection();
145: stmt = conn.prepareStatement(DELETE_BITSTREAM_HISTORY);
146: stmt.setInt(1, id);
147:
148: numDeleted = stmt.executeUpdate();
149: conn.commit();
150: } catch (SQLException e) {
151: LOG.error("Problem with inserting missing bitstream. "
152: + e.getMessage(), e);
153: throw new RuntimeException(
154: "Problem inserting missing bitstream. "
155: + e.getMessage(), e);
156: } finally {
157: cleanup(stmt, conn);
158: }
159:
160: return numDeleted;
161: }
162:
163: /**
164: * @param conn
165: */
166: protected void updateMissingBitstreams(Connection conn)
167: throws SQLException {
168: PreparedStatement stmt = null;
169: try {
170: if ("oracle".equals(ConfigurationManager
171: .getProperty("db.name")))
172: stmt = conn
173: .prepareStatement(INSERT_MISSING_HISTORY_BITSTREAMS_ORACLE);
174: else
175: stmt = conn
176: .prepareStatement(INSERT_MISSING_HISTORY_BITSTREAMS);
177: stmt.executeUpdate();
178: } catch (SQLException e) {
179: LOG.error("Problem updating missing history. "
180: + e.getMessage(), e);
181: throw new RuntimeException(
182: "Problem updating missing history. "
183: + e.getMessage(), e);
184: } finally {
185: cleanup(stmt);
186: }
187: }
188:
189: /**
190: * Delete the history records from the database.
191: *
192: * @param retentionDate
193: * any records older than this data are deleted.
194: * @param result
195: * result code records must have for them to be deleted.
196: * @param conn
197: * database connection.
198: * @return number of records deleted.
199: * @throws SQLException
200: * if database error occurs.
201: */
202: protected int deleteHistoryByDateAndCode(Date retentionDate,
203: String result, Connection conn) throws SQLException {
204: PreparedStatement update = null;
205:
206: try {
207: update = conn
208: .prepareStatement("DELETE FROM checksum_history WHERE process_end_date<? AND result=?");
209: update.setTimestamp(1, new Timestamp(retentionDate
210: .getTime()));
211: update.setString(2, result);
212: return update.executeUpdate();
213: } finally {
214: cleanup(update);
215: }
216:
217: }
218:
219: /**
220: * Prune the history records from the database.
221: *
222: * @param interests
223: * set of results and the duration of time before they are
224: * removed from the database
225: *
226: * @return number of bitstreams deleted
227: */
228: public int prune(Map interests) {
229: Connection conn = null;
230: try {
231: conn = DatabaseManager.getConnection();
232: long now = System.currentTimeMillis();
233: int count = 0;
234: for (Iterator iter = interests.keySet().iterator(); iter
235: .hasNext();) {
236: String result = (String) iter.next();
237: Long dur = (Long) interests.get(result);
238: count += deleteHistoryByDateAndCode(new Date(now
239: - dur.longValue()), result, conn);
240: conn.commit();
241: }
242: return count;
243: } catch (SQLException e) {
244: LOG.error("Problem pruning results: " + e.getMessage(), e);
245: throw new RuntimeException("Problem pruning results: "
246: + e.getMessage(), e);
247: } finally {
248: DatabaseManager.freeConnection(conn);
249: }
250: }
251: }
|