/** * Initialize the event queue. * * @param props A container of configuration properties. * @exception FrameworkException Thrown if configuration is invalid. */ public void initialize(Map props) throws FrameworkException { String temp = (String) props.get(LOAD_EVENT_BATCH_SIZE_PROP); if (StringUtils.hasValue(temp)) { maxDatabaseEventLoadSize = StringUtils.getInteger(temp); if (Debug.isLevelEnabled(Debug.SYSTEM_CONFIG)) Debug.log( Debug.SYSTEM_CONFIG, "QUEUE OPERATION: Initializing: Maximum-database-event-batch-load-size is [" + maxDatabaseEventLoadSize + "] rows."); } }
/** Constructor. */ public DatabaseEventQueue() { if (Debug.isLevelEnabled(Debug.OBJECT_LIFECYCLE)) Debug.log( Debug.OBJECT_LIFECYCLE, "QUEUE OPERATION: Creating event queue of type [" + StringUtils.getClassName(this) + "] ..."); queue = Collections.synchronizedList(new LinkedList()); }
/** * Get a human-readable description of the event queue. * * @return A description of the event queue. */ public String describe() { StringBuffer sb = new StringBuffer(); sb.append("Database event queue ["); sb.append(StringUtils.getClassName(this)); sb.append("], in-memory-event-count ["); sb.append(queue.size()); sb.append("], Event-load-batch-size ["); sb.append(maxDatabaseEventLoadSize); sb.append("]"); return (sb.toString()); }
/** * Reset any events meeting the given criteria so that they can be retried. * * @param criteria An event containing the event-selection criteria. * @return The number of events reset. * @exception FrameworkException Thrown on errors. */ protected static int reset(Event criteria) throws FrameworkException { Debug.log( Debug.MSG_STATUS, "QUEUE OPERATION: Resetting events in database for database queue ..."); if (!StringUtils.hasValue(criteria.channelName)) { throw new FrameworkException( "ERROR: Event channel name is a required queue search criteria."); } Connection dbConn = null; PreparedStatement ps = null; long startTime = -1; if (Debug.isLevelEnabled(Debug.BENCHMARK)) startTime = System.currentTimeMillis(); try { dbConn = DBConnectionPool.getInstance().acquireConnection(); if (Debug.isLevelEnabled(Debug.DB_DATA)) Debug.log( Debug.DB_DATA, "Criteria used to reset events in database:\n" + criteria.describe()); // If no identifier was given that uniquely identifies a single event ... if (criteria.id == 0) { // Use last error time and error count, if available. if (Debug.isLevelEnabled(Debug.DB_DATA)) Debug.log(Debug.DB_DATA, "\n" + LINE + "\nExecuting SQL:\n" + UPDATE_EVENT_RETRY_SQL); ps = dbConn.prepareStatement(UPDATE_EVENT_RETRY_SQL); ps.setString(1, criteria.channelName); if (criteria.lastErrorTime == null) ps.setNull(2, Types.DATE); else ps.setTimestamp(2, criteria.lastErrorTime); if (criteria.errorCount < 1) ps.setNull(3, Types.INTEGER); else ps.setInt(3, criteria.errorCount); } else { // An Id was given which should uniquely identify a single event, so we should // skip using any other qualifying criteria, if present. if (Debug.isLevelEnabled(Debug.DB_DATA)) Debug.log( Debug.DB_DATA, "\n" + LINE + "\nExecuting SQL:\n" + UPDATE_EVENT_RETRY_BY_ID_SQL); ps = dbConn.prepareStatement(UPDATE_EVENT_RETRY_BY_ID_SQL); ps.setString(1, criteria.channelName); ps.setInt(2, criteria.id); } int numRows = ps.executeUpdate(); DBConnectionPool.getInstance().commit(dbConn); if (Debug.isLevelEnabled(Debug.DB_DATA)) Debug.log( Debug.DB_DATA, "Committed SQL execution affected [" + numRows + "] rows.\n" + LINE); return numRows; } catch (SQLException sqle) { throw new DatabaseException( "ERROR: Could not execute SQL statement:\n" + DBInterface.getSQLErrorMessage(sqle)); } catch (Exception e) { throw new DatabaseException("ERROR: Could not execute SQL statement:\n" + e.toString()); } finally { releaseDatabaseResources(dbConn, ps); if (Debug.isLevelEnabled(Debug.BENCHMARK) && (startTime > 0)) { long stopTime = System.currentTimeMillis(); Debug.log( Debug.BENCHMARK, "ELAPSED TIME [" + (stopTime - startTime) + "] msec: " + "SQL: Time to reset event(s) in PersistentEvent database table."); } } }
/** * Load any available events from the database up to the configured maximum. * * @param criteria An event containing the event-selection criteria. * @return The next available event on the queue. * @exception FrameworkException Thrown on errors. */ private void loadFromDatabase(Event criteria) throws FrameworkException { Debug.log(Debug.MSG_STATUS, "QUEUE OPERATION: Loading events from database into queue ..."); if (!StringUtils.hasValue(criteria.channelName)) { throw new FrameworkException( "ERROR: Event channel name is a required queue search criteria."); } Connection dbConn = null; PreparedStatement ps = null; long startTime = -1; if (Debug.isLevelEnabled(Debug.BENCHMARK)) startTime = System.currentTimeMillis(); try { dbConn = DBConnectionPool.getInstance().acquireConnection(); if (Debug.isLevelEnabled(Debug.DB_DATA)) Debug.log(Debug.DB_DATA, "\n" + LINE + "\nExecuting SQL:\n" + QUERY_EVENT_SQL); if (Debug.isLevelEnabled(Debug.DB_DATA)) Debug.log( Debug.DB_DATA, "Criteria used in query against database:\n" + criteria.describe()); ps = dbConn.prepareStatement(QUERY_EVENT_SQL); ps.setString(1, criteria.channelName); ResultSet rs = ps.executeQuery(); for (int counter = 0; (counter < maxDatabaseEventLoadSize) && rs.next(); counter++) { Event event = new Event(); event.channelName = rs.getString(CHANNEL_NAME_COL); event.id = rs.getInt(ID_COL); event.message = DBLOBUtils.getCLOB(rs, MESSAGE_COL); if (Debug.isLevelEnabled(Debug.MSG_LIFECYCLE)) Debug.log(Debug.MSG_LIFECYCLE, "Event contents:\n" + event.message); event.arrivalTime = rs.getTimestamp(ARRIVAL_TIME_COL); event.errorStatus = rs.getString(ERROR_STATUS_COL); event.errorCount = rs.getInt(ERROR_COUNT_COL); event.lastErrorMessage = rs.getString(LAST_ERROR_MESSAGE_COL); event.lastErrorTime = rs.getTimestamp(LAST_ERROR_TIME_COL); // Add item to in-memory buffer. if (Debug.isLevelEnabled(Debug.MSG_STATUS)) Debug.log( Debug.MSG_STATUS, "Adding event [" + event.describe() + "] to in-memory queue buffer."); queue.add(event); if (Debug.isLevelEnabled(Debug.MSG_STATUS)) Debug.log(Debug.MSG_STATUS, "In-memory queue buffer size [" + queue.size() + "]."); } if (Debug.isLevelEnabled(Debug.DB_DATA)) Debug.log(Debug.DB_DATA, "\n" + LINE); } catch (SQLException sqle) { throw new DatabaseException( "ERROR: Could not execute SQL statement:\n" + DBInterface.getSQLErrorMessage(sqle)); } catch (Exception e) { throw new DatabaseException("ERROR: Could not execute SQL statement:\n" + e.toString()); } finally { releaseDatabaseResources(dbConn, ps); if (Debug.isLevelEnabled(Debug.BENCHMARK) && (startTime > 0)) { long stopTime = System.currentTimeMillis(); Debug.log( Debug.BENCHMARK, "ELAPSED TIME [" + (stopTime - startTime) + "] msec: " + "SQL: Time to load event(s) from PersistentEvent database table."); } } }