Search in sources :

Example 1 with PurgeOldMessages

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);
    }
}
Also used : PurgeOldMessages(com.zimbra.cs.redolog.op.PurgeOldMessages) RetentionPolicy(com.zimbra.soap.mail.type.RetentionPolicy) SetRetentionPolicy(com.zimbra.cs.redolog.op.SetRetentionPolicy) Policy(com.zimbra.soap.mail.type.Policy) Account(com.zimbra.cs.account.Account) CreateFolder(com.zimbra.cs.redolog.op.CreateFolder) ZFolder(com.zimbra.client.ZFolder) RetentionPolicy(com.zimbra.soap.mail.type.RetentionPolicy) SetRetentionPolicy(com.zimbra.cs.redolog.op.SetRetentionPolicy) TypedIdList(com.zimbra.cs.mailbox.util.TypedIdList) RefreshMountpoint(com.zimbra.cs.redolog.op.RefreshMountpoint) TargetConstraint(com.zimbra.cs.mailbox.MailItem.TargetConstraint) CreateMountpoint(com.zimbra.cs.redolog.op.CreateMountpoint) AccountServiceException(com.zimbra.cs.account.AccountServiceException) ServiceException(com.zimbra.common.service.ServiceException) AlterItemTag(com.zimbra.cs.redolog.op.AlterItemTag) CreateTag(com.zimbra.cs.redolog.op.CreateTag) DbTag(com.zimbra.cs.db.DbTag) PendingDelete(com.zimbra.cs.mailbox.MailItem.PendingDelete)

Aggregations

ZFolder (com.zimbra.client.ZFolder)1 ServiceException (com.zimbra.common.service.ServiceException)1 Account (com.zimbra.cs.account.Account)1 AccountServiceException (com.zimbra.cs.account.AccountServiceException)1 DbTag (com.zimbra.cs.db.DbTag)1 PendingDelete (com.zimbra.cs.mailbox.MailItem.PendingDelete)1 TargetConstraint (com.zimbra.cs.mailbox.MailItem.TargetConstraint)1 TypedIdList (com.zimbra.cs.mailbox.util.TypedIdList)1 AlterItemTag (com.zimbra.cs.redolog.op.AlterItemTag)1 CreateFolder (com.zimbra.cs.redolog.op.CreateFolder)1 CreateMountpoint (com.zimbra.cs.redolog.op.CreateMountpoint)1 CreateTag (com.zimbra.cs.redolog.op.CreateTag)1 PurgeOldMessages (com.zimbra.cs.redolog.op.PurgeOldMessages)1 RefreshMountpoint (com.zimbra.cs.redolog.op.RefreshMountpoint)1 SetRetentionPolicy (com.zimbra.cs.redolog.op.SetRetentionPolicy)1 Policy (com.zimbra.soap.mail.type.Policy)1 RetentionPolicy (com.zimbra.soap.mail.type.RetentionPolicy)1