📄 dbwatchmanager.java
字号:
public void setWatchExpirable(User user, ForumThread thread, int watchType,
boolean expirable) throws UnauthorizedException
{
WatchList wList = getWatchList(user, watchType);
long threadID = thread.getID();
boolean isWatched = wList.isWatchedThread(threadID);
boolean isExpirable = wList.isWatchExpirable(threadID);
//Only change the entry if it exists and if it's a change from the
//current value.
if (isWatched && (isExpirable != expirable)) {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = ConnectionManager.getConnection();
pstmt = con.prepareStatement(UPDATE_WATCH_EXPIRATION);
pstmt.setInt(1, expirable?1:0);
pstmt.setLong(2, user.getID());
pstmt.setLong(3, thread.getID());
pstmt.setInt(4, watchType);
pstmt.executeUpdate();
}
catch( SQLException sqle ) {
sqle.printStackTrace();
}
finally {
try { pstmt.close(); }
catch (Exception e) { e.printStackTrace(); }
try { con.close(); }
catch (Exception e) { e.printStackTrace(); }
}
//Remove user's watch list from cache.
StringBuffer key = new StringBuffer(Long.toString(user.getID()));
key.append("-").append(watchType);
watchCache.remove(key.toString());
}
}
public Iterator getWatchedForumThreads(Forum forum, User user, int watchType)
{
return getWatchList(user, watchType).watchedThreads(forum);
}
public Iterator getWatchedForumThreads(User user, int watchType) {
return getWatchList(user, watchType).watchedThreads();
}
public int getWatchCount(Forum forum, User user, int watchType) {
return getWatchList(user, watchType).getWatchCount(forum);
}
public int getWatchCount(User user, int watchType) {
return getWatchList(user, watchType).getWatchCount();
}
public boolean isWatchedThread(User user, ForumThread thread, int watchType) {
return getWatchList(user, watchType).isWatchedThread(thread.getID());
}
/**
* Notifies watches that a thread has been updated. If there are email
* watches, email notifications are sent out.
*/
protected void notifyWatches(ForumThread thread) {
//If watches are turned on.
if (!emailNotifyEnabled) {
return;
}
//Create a new email watch update task that will send out emails to
//any users that have watches on the updated thread.
EmailWatchUpdateTask task = new EmailWatchUpdateTask(this, factory, thread);
TaskEngine.addTask(task);
}
/**
* Deletes all watches on a thread. Typically, this method is called when
* deleting a thread from the system. A Connection is passed in so that
* this method can participate in a transaction.
*
* @param thread the ForumThread to remove all watches from.
* @param con a database connection to perform work with.
*/
protected void deleteThreadWatches(ForumThread thread, Connection con)
throws SQLException
{
int numRows;
PreparedStatement pstmt = null;
try {
pstmt = con.prepareStatement(DELETE_THREAD_WATCHES);
pstmt.setLong(1,thread.getID());
numRows = pstmt.executeUpdate();
}
finally {
try { pstmt.close(); }
catch (Exception e) { e.printStackTrace(); }
}
//If any watches were deleted, expire the watch cache. This is
//potentially a "bad" thing if there is a huge number of active users
//looking at their watches, but is a good trade-off for now compared to
//trying to expire individual cache entries.
if (numRows > 0) {
watchCache.clear();
}
}
private WatchList getWatchList(User user, int watchType) {
//Remove user's watch list from cache.
StringBuffer key = new StringBuffer(Long.toString(user.getID()));
key.append("-").append(watchType);
WatchList watchList = (WatchList)watchCache.get(key.toString());
if (watchList != null) {
return watchList;
}
LongList threadsByDate = new LongList();
BooleanList expirableByDate = new BooleanList();
LongList forumsByDate = new LongList();
LongList threadsByForum = new LongList();
LongList forumsByForum = new LongList();
Connection con = null;
PreparedStatement pstmt = null;
try {
con = ConnectionManager.getConnection();
pstmt = con.prepareStatement(ALL_WATCHES);
pstmt.setLong(1, user.getID());
pstmt.setInt(2, watchType);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
threadsByDate.add(rs.getLong(1));
expirableByDate.add(rs.getBoolean(2));
forumsByDate.add(rs.getLong(3));
}
pstmt.close();
pstmt = con.prepareStatement(ALL_WATCHES_BY_FORUM);
pstmt.setLong(1, user.getID());
pstmt.setInt(2, watchType);
rs = pstmt.executeQuery();
while (rs.next()) {
threadsByForum.add(rs.getLong(1));
forumsByForum.add(rs.getLong(2));
}
}
catch( SQLException sqle ) {
sqle.printStackTrace();
}
finally {
try { pstmt.close(); }
catch (Exception e) { e.printStackTrace(); }
try { con.close(); }
catch (Exception e) { e.printStackTrace(); }
}
watchList = new WatchList(
threadsByDate.toArray(),
expirableByDate.toArray(),
forumsByDate.toArray(),
threadsByForum.toArray(),
forumsByForum.toArray(),
factory
);
//Add watch list to cache for next time, then return it.
watchCache.add(key.toString(), watchList);
return watchList;
}
/**
* A task the deletes all watches that are "delatable" and that are attached
* to threads older than a certain value.
*
* The class does not deal with watch cache expiration since that would
* require deletion of the entire cache. Instead, we just let the watch
* objects expire naturally.
*/
class DeleteWatchesTask implements Runnable {
public void run() {
long now = System.currentTimeMillis();
long deleteDays = JiveGlobals.DAY * getDeleteDays();
long oldestDate = now - deleteDays;
Connection con = null;
PreparedStatement pstmt = null;
boolean abortTransaction = false;
try {
con = ConnectionManager.getTransactionConnection();
//Simple case: database supports sub-selects. This query can be
//slow if many records are affected, but will at least work.
if (ConnectionManager.supportsSubqueries) {
pstmt = con.prepareStatement(EXPIRE_OLD_WATCHES);
pstmt.setLong(1, oldestDate);
pstmt.execute();
}
//Complicated case: db doesn't support sub-selects. So, build
//up the "IN" clause ourselves. We'll submit them 100 records
//at a time.
else {
pstmt = con.prepareStatement(GET_EXPIRED_WATCHES);
pstmt.setLong(1, oldestDate);
ResultSet rs = pstmt.executeQuery();
LongList expiredThreads = new LongList();
while (rs.next()) {
expiredThreads.add(rs.getLong(1));
}
pstmt.close();
int length = expiredThreads.size();
//Do nothing if there are no records to delete.
if (length == 0) {
return;
}
int numBlocks = length / 100;
for (int i=0; i <= numBlocks; i++) {
int blockNum = i*100;
//Build up "IN" SQL statement list.
StringBuffer buf = new StringBuffer();
buf.append(expiredThreads.get(blockNum));
int j=1;
while (j < 100 && blockNum+j < length) {
buf.append(",").append(expiredThreads.get(blockNum+j));
j++;
}
//Do db delete.
String sql = "DELETE FROM jiveWatch WHERE threadID IN (" +
buf.toString() + ")";
Statement stmt = con.createStatement();
stmt.execute(sql);
stmt.close();
}
}
}
catch( SQLException sqle ) {
abortTransaction = true;
sqle.printStackTrace();
}
finally {
try {
if (ConnectionManager.supportsSubqueries) { pstmt.close(); }
}
catch (Exception e) { e.printStackTrace(); }
try {
ConnectionManager.closeTransactionConnection(con, abortTransaction);
}
catch (Exception e) { e.printStackTrace(); }
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -