use of com.zimbra.cs.redolog.op.PurgeOldMessages in project zm-mailbox by Zimbra.
the class Mailbox method purgeMessages.
/**
* Purges messages in system folders based on user- and admin-level purge settings on the account.
* Returns {@code true} if all messages that meet the purge criteria were purged, {@code false} if the number of
* messages to purge in any folder exceeded {@code maxItemsPerFolder}.
*/
public boolean purgeMessages(OperationContext octxt) throws ServiceException {
Account acct = getAccount();
int maxItemsPerFolder = Provisioning.getInstance().getLocalServer().getMailPurgeBatchSize();
if (ZimbraLog.purge.isDebugEnabled()) {
ZimbraLog.purge.debug("System retention policy: Trash=%s, Junk=%s, All messages=%s, Dumpster=%s", acct.getMailTrashLifetimeAsString(), acct.getMailSpamLifetimeAsString(), acct.getMailMessageLifetimeAsString(), acct.getMailDumpsterLifetimeAsString());
ZimbraLog.purge.debug("User-specified retention policy: Inbox read=%s, Inbox unread=%s, Sent=%s, Junk=%s, Trash=%s, Versions=%s, VersionsEnabled=%s", acct.getPrefInboxReadLifetimeAsString(), acct.getPrefInboxUnreadLifetimeAsString(), acct.getPrefSentLifetimeAsString(), acct.getPrefJunkLifetimeAsString(), acct.getPrefTrashLifetimeAsString(), acct.getFileVersionLifetimeAsString(), acct.isFileVersioningEnabled());
}
long globalTimeout = acct.getMailMessageLifetime();
long systemTrashTimeout = acct.getMailTrashLifetime();
long systemJunkTimeout = acct.getMailSpamLifetime();
boolean dumpsterPurgeEnabled = acct.isDumpsterPurgeEnabled();
long systemDumpsterTimeoutMillis = dumpsterPurgeEnabled ? acct.getMailDumpsterLifetime() : 0;
long userInboxReadTimeout = acct.getPrefInboxReadLifetime();
long userInboxUnreadTimeout = acct.getPrefInboxUnreadLifetime();
long userTrashTimeout = acct.getPrefTrashLifetime();
long userJunkTimeout = acct.getPrefJunkLifetime();
long userSentTimeout = acct.getPrefSentLifetime();
long trashTimeout = pickTimeout(systemTrashTimeout, userTrashTimeout);
long spamTimeout = pickTimeout(systemJunkTimeout, userJunkTimeout);
boolean userFileVersioningEnabled = acct.isFileVersioningEnabled();
long userFileVersionLifeTime = acct.getFileVersionLifetime();
if (globalTimeout <= 0 && trashTimeout <= 0 && spamTimeout <= 0 && userInboxReadTimeout <= 0 && userInboxReadTimeout <= 0 && userInboxUnreadTimeout <= 0 && userSentTimeout <= 0 && systemDumpsterTimeoutMillis <= 0 && (!userFileVersioningEnabled || userFileVersionLifeTime <= 0)) {
ZimbraLog.purge.debug("Retention policy does not require purge.");
return true;
}
ZimbraLog.purge.info("Purging messages.");
// sanity-check the really dangerous value...
if (globalTimeout > 0 && globalTimeout < Constants.MILLIS_PER_MONTH) {
// this min is also used by POP3 EXPIRE command. update Pop3Handler.MIN_EPXIRE_DAYS if it changes.
ZimbraLog.purge.warn("global message timeout < 1 month; defaulting to 31 days");
globalTimeout = Constants.MILLIS_PER_MONTH;
}
// call to purge expired messages with IMAP \Deleted flag
// for expiration check, used zimbraMailTrashLifetime
purgeExpiredIMAPDeletedMessages(trashTimeout);
PurgeOldMessages redoRecorder = new PurgeOldMessages(mId);
boolean success = false;
try {
beginTransaction("purgeMessages", octxt, redoRecorder);
// get the folders we're going to be purging
Folder trash = getFolderById(ID_FOLDER_TRASH);
Folder spam = getFolderById(ID_FOLDER_SPAM);
Folder sent = getFolderById(ID_FOLDER_SENT);
Folder inbox = getFolderById(ID_FOLDER_INBOX);
boolean purgedAll = true;
if (globalTimeout > 0) {
int numPurged = Folder.purgeMessages(this, null, getOperationTimestampMillis() - globalTimeout, null, false, false, maxItemsPerFolder);
ZimbraLog.purge.debug("Purged %d messages from All Folders", numPurged);
purgedAll = updatePurgedAll(purgedAll, numPurged, maxItemsPerFolder);
}
if (trashTimeout > 0) {
boolean useChangeDate = acct.getBooleanAttr(Provisioning.A_zimbraMailPurgeUseChangeDateForTrash, true);
int numPurged = Folder.purgeMessages(this, trash, getOperationTimestampMillis() - trashTimeout, null, useChangeDate, true, maxItemsPerFolder);
ZimbraLog.purge.debug("Purged %d messages from Trash", numPurged);
purgedAll = updatePurgedAll(purgedAll, numPurged, maxItemsPerFolder);
}
if (spamTimeout > 0) {
boolean useChangeDate = acct.isMailPurgeUseChangeDateForSpam();
int numPurged = Folder.purgeMessages(this, spam, getOperationTimestampMillis() - spamTimeout, null, useChangeDate, false, maxItemsPerFolder);
purgedAll = updatePurgedAll(purgedAll, numPurged, maxItemsPerFolder);
ZimbraLog.purge.debug("Purged %d messages from Spam", numPurged);
}
if (userInboxReadTimeout > 0) {
int numPurged = Folder.purgeMessages(this, inbox, getOperationTimestampMillis() - userInboxReadTimeout, false, false, false, maxItemsPerFolder);
purgedAll = updatePurgedAll(purgedAll, numPurged, maxItemsPerFolder);
ZimbraLog.purge.debug("Purged %d read messages from Inbox", numPurged);
}
if (userInboxUnreadTimeout > 0) {
int numPurged = Folder.purgeMessages(this, inbox, getOperationTimestampMillis() - userInboxUnreadTimeout, true, false, false, maxItemsPerFolder);
purgedAll = updatePurgedAll(purgedAll, numPurged, maxItemsPerFolder);
ZimbraLog.purge.debug("Purged %d unread messages from Inbox", numPurged);
}
if (userSentTimeout > 0) {
int numPurged = Folder.purgeMessages(this, sent, getOperationTimestampMillis() - userSentTimeout, null, false, false, maxItemsPerFolder);
purgedAll = updatePurgedAll(purgedAll, numPurged, maxItemsPerFolder);
ZimbraLog.purge.debug("Purged %d messages from Sent", numPurged);
}
if (systemDumpsterTimeoutMillis > 0) {
int numPurged = purgeDumpster(getOperationTimestampMillis() - systemDumpsterTimeoutMillis, maxItemsPerFolder);
ZimbraLog.purge.debug("Purged %d messages from Dumpster", numPurged);
purgedAll = updatePurgedAll(purgedAll, numPurged, maxItemsPerFolder);
}
if (userFileVersioningEnabled && userFileVersionLifeTime > 0) {
int numPurged = MailItem.purgeRevisions(this, getOperationTimestampMillis() - userFileVersionLifeTime);
ZimbraLog.purge.debug("Purged %d revisions", numPurged);
}
// Process any folders that have retention policy set.
for (Folder folder : getFolderList(octxt, SortBy.NONE)) {
RetentionPolicy rp = RetentionPolicyManager.getInstance().getCompleteRetentionPolicy(acct, folder.getRetentionPolicy());
for (Policy policy : rp.getPurgePolicy()) {
long folderLifetime;
try {
folderLifetime = DateUtil.getTimeInterval(policy.getLifetime());
} catch (ServiceException e) {
ZimbraLog.purge.error("Invalid purge lifetime set for folder %s.", folder.getPath(), e);
continue;
}
long folderTimeout = getOperationTimestampMillis() - folderLifetime;
int numPurged = Folder.purgeMessages(this, folder, folderTimeout, null, false, false, maxItemsPerFolder);
purgedAll = updatePurgedAll(purgedAll, numPurged, maxItemsPerFolder);
}
}
// Process any tags that have retention policy set.
for (Tag tag : getTagList(octxt)) {
RetentionPolicy rp = RetentionPolicyManager.getInstance().getCompleteRetentionPolicy(acct, tag.getRetentionPolicy());
for (Policy policy : rp.getPurgePolicy()) {
long tagLifetime;
try {
tagLifetime = DateUtil.getTimeInterval(policy.getLifetime());
} catch (ServiceException e) {
ZimbraLog.purge.error("Invalid purge lifetime set for tag %s.", tag.getName(), e);
continue;
}
long tagTimeout = getOperationTimestampMillis() - tagLifetime;
PendingDelete info = DbTag.getLeafNodes(this, tag, (int) (tagTimeout / 1000), maxItemsPerFolder);
MailItem.delete(this, info, null, false, false);
List<Integer> ids = info.itemIds.getIds(MailItem.Type.MESSAGE);
int numPurged = (ids == null ? 0 : ids.size());
purgedAll = updatePurgedAll(purgedAll, numPurged, maxItemsPerFolder);
}
}
// deletes have already been collected, so fetch the tombstones and write once
TypedIdList tombstones = collectPendingTombstones();
if (tombstones != null && !tombstones.isEmpty()) {
DbMailItem.writeTombstones(this, tombstones);
}
if (Threader.isHashPurgeAllowed(acct)) {
int convTimeoutSecs = (int) (LC.conversation_max_age_ms.longValue() / Constants.MILLIS_PER_SECOND);
DbMailItem.closeOldConversations(this, getOperationTimestamp() - convTimeoutSecs);
}
if (isTrackingSync()) {
int tombstoneTimeoutSecs = (int) (LC.tombstone_max_age_ms.longValue() / Constants.MILLIS_PER_SECOND);
int largestTrimmed = DbMailItem.purgeTombstones(this, getOperationTimestamp() - tombstoneTimeoutSecs);
if (largestTrimmed > getSyncCutoff()) {
currentChange().sync = largestTrimmed;
DbMailbox.setSyncCutoff(this, currentChange().sync);
}
}
// record the purge time.
if (purgedAll) {
DbMailbox.updateLastPurgeAt(this, System.currentTimeMillis());
}
success = true;
ZimbraLog.purge.debug("purgedAll=%b", purgedAll);
return purgedAll;
} finally {
endTransaction(success);
}
}
Aggregations