/** * Add the event to the end of queue. * * @param event The event to add to the queue. * @exception FrameworkException Thrown on errors. */ public void add(Event event) throws FrameworkException { Debug.log(Debug.MSG_STATUS, "QUEUE OPERATION: Adding event to database queue ..."); Connection dbConn = null; PreparedStatement ps = null; long startTime = -1; if (Debug.isLevelEnabled(Debug.BENCHMARK)) startTime = System.currentTimeMillis(); try { event.id = PersistentSequence.getNextSequenceValue(SEQUENCE_NAME); dbConn = DBConnectionPool.getInstance().acquireConnection(); event.arrivalTime = new java.sql.Timestamp(System.currentTimeMillis()); if (Debug.isLevelEnabled(Debug.DB_DATA)) Debug.log(Debug.DB_DATA, "\n" + LINE + "\nExecuting SQL:\n" + INSERT_EVENT_SQL); if (Debug.isLevelEnabled(Debug.DB_DATA)) Debug.log(Debug.DB_DATA, "Event being inserted into database:\n" + event.describe()); if (Debug.isLevelEnabled(Debug.MSG_DATA)) Debug.log(Debug.MSG_DATA, "Event contents:\n" + event.message); ps = dbConn.prepareStatement(INSERT_EVENT_SQL); ps.setString(1, event.channelName); ps.setInt(2, event.id); DBLOBUtils.setCLOB(ps, 3, event.message); ps.setTimestamp(4, event.arrivalTime); int numRows = ps.executeUpdate(); if (numRows != 1) { String errMsg = "Execution of SQL statement [" + INSERT_EVENT_SQL + "] affected [" + numRows + "] rows."; Debug.error(errMsg); throw new FrameworkException(errMsg); } DBConnectionPool.getInstance().commit(dbConn); if (Debug.isLevelEnabled(Debug.DB_DATA)) Debug.log(Debug.DB_DATA, "Successfully committed SQL operation.\n" + LINE); // NOTE: We don't add the item just inserted into the database into the in-memory // queue, as we want it loaded by the separate dequeueing thread. } 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 insert event into PersistentEvent database table."); } } }
/** * Update the given event as indicated. * * @param event The event to update. * @param eventStatus The event delivery status. * @exception FrameworkException Thrown on errors. */ public void update(Event event, EventStatus eventStatus) throws FrameworkException { if (Debug.isLevelEnabled(Debug.MSG_STATUS)) Debug.log( Debug.MSG_STATUS, "QUEUE OPERATION: Updating database queue using event status [" + eventStatus.name + "] ..."); // If no consumers were available, the event delivery wasn't attempted so leave // the queue in its current state. if (eventStatus == EventStatus.NO_CONSUMERS_AVAILABLE) { Debug.log( Debug.MSG_STATUS, "Skipping queue update, as no consumers were available to process it."); return; } Connection dbConn = null; PreparedStatement ps = null; long startTime = -1; if (Debug.isLevelEnabled(Debug.BENCHMARK)) startTime = System.currentTimeMillis(); try { dbConn = DBConnectionPool.getInstance().acquireConnection(); if (eventStatus == EventStatus.DELIVERY_SUCCESSFUL) { // If the event was successfully delivered, update status in database to delivered. if (Debug.isLevelEnabled(Debug.DB_DATA)) Debug.log(Debug.DB_DATA, "\n" + LINE + "\nExecuting SQL:\n" + UPDATE_EVENT_SUCCESS_SQL); ps = dbConn.prepareStatement(UPDATE_EVENT_SUCCESS_SQL); java.sql.Timestamp ts = new java.sql.Timestamp(System.currentTimeMillis()); ps.setTimestamp(1, ts); ps.setString(2, event.channelName); ps.setInt(3, event.id); } else if (eventStatus == EventStatus.DELIVERY_FAILED) { // If the event delivery failed, we mark it as failed in the database. if (Debug.isLevelEnabled(Debug.DB_DATA)) Debug.log(Debug.DB_DATA, "\n" + LINE + "\nExecuting SQL:\n" + UPDATE_EVENT_ERROR_SQL); // Truncate error message if it's larger than database column. if ((event.lastErrorMessage != null) && (event.lastErrorMessage.length() > MAX_ERROR_MESSAGE_LENGTH)) event.lastErrorMessage = event.lastErrorMessage.substring(0, MAX_ERROR_MESSAGE_LENGTH); event.lastErrorTime = new java.sql.Timestamp(System.currentTimeMillis()); ps = dbConn.prepareStatement(UPDATE_EVENT_ERROR_SQL); ps.setTimestamp(1, event.lastErrorTime); ps.setString(2, event.lastErrorMessage); ps.setString(3, event.channelName); ps.setInt(4, event.id); } else { throw new FrameworkException( "ERROR: Invalid event update type [" + eventStatus.name + "]."); } if (Debug.isLevelEnabled(Debug.DB_DATA)) Debug.log(Debug.DB_DATA, "Event being operated on in database:\n" + event.describe()); int numRows = ps.executeUpdate(); if (numRows > 1) { String errMsg = "Execution of update SQL statement affected [" + numRows + "] rows."; Debug.error(errMsg); throw new FrameworkException(errMsg); } DBConnectionPool.getInstance().commit(dbConn); if (Debug.isLevelEnabled(Debug.DB_DATA)) Debug.log(Debug.DB_DATA, "Successfully committed SQL operation.\n" + LINE); // At this point, the event should be removed from the in-memory buffer of events as well, // irrespective of processing outcome. if (Debug.isLevelEnabled(Debug.MSG_STATUS)) Debug.log( Debug.MSG_STATUS, "Removing event [" + event.describe() + "] from in-memory queue buffer."); boolean removed = queue.remove(event); if (Debug.isLevelEnabled(Debug.MSG_STATUS)) Debug.log( Debug.MSG_STATUS, "Event removed? [" + removed + "]. In-memory queue buffer size [" + queue.size() + "]."); } 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 update event in PersistentEvent database table."); } } }