use of com.zimbra.cs.mailbox.MailItem.PendingDelete in project zm-mailbox by Zimbra.
the class DbMailItem method getLeafNodes.
public static PendingDelete getLeafNodes(Mailbox mbox, QueryParams params) throws ServiceException {
DbConnection conn = mbox.getOperationConnection();
PreparedStatement stmt = null;
ResultSet rs = null;
try {
StringBuilder buf = new StringBuilder();
buf.append("SELECT " + LEAF_NODE_FIELDS + " FROM " + getMailItemTableName(mbox) + " WHERE " + IN_THIS_MAILBOX_AND + "type NOT IN " + FOLDER_TYPES);
String whereClause = params.getWhereClause();
if (!StringUtil.isNullOrEmpty(whereClause)) {
buf.append(" AND ").append(whereClause);
}
String limitClause = params.getLimitClause();
if (!StringUtil.isNullOrEmpty(limitClause)) {
buf.append(" ").append(limitClause);
}
stmt = conn.prepareStatement(buf.toString());
// Assume we're dealing with a very large result set.
Db.getInstance().enableStreaming(stmt);
int pos = 1;
pos = setMailboxId(stmt, mbox, pos);
PendingDelete info = accumulateDeletionInfo(mbox, stmt);
stmt = null;
return info;
} catch (SQLException e) {
throw ServiceException.FAILURE("fetching list of items to delete", e);
} finally {
DbPool.closeResults(rs);
DbPool.closeStatement(stmt);
}
}
use of com.zimbra.cs.mailbox.MailItem.PendingDelete in project zm-mailbox by Zimbra.
the class DbMailItem method getLeafNodes.
public static PendingDelete getLeafNodes(Folder folder) throws ServiceException {
Mailbox mbox = folder.getMailbox();
int folderId = folder.getId();
QueryParams params = new QueryParams();
params.setFolderIds(Collections.singletonList(folderId));
PendingDelete info = getLeafNodes(mbox, params);
// make sure that the folder is in the list of deleted items
info.itemIds.add(folder.getType(), folderId, folder.getUuid());
return info;
}
use of com.zimbra.cs.mailbox.MailItem.PendingDelete in project zm-mailbox by Zimbra.
the class Mailbox method deletedBatchOfItemsInFolder.
private boolean deletedBatchOfItemsInFolder(OperationContext octxt, QueryParams params, TargetConstraint tcon) throws ServiceException {
// Lock this mailbox to make sure that no one modifies the items we're about to delete.
lock.lock();
try {
DeleteItem redoRecorder = new DeleteItem(mId, MailItem.Type.UNKNOWN, tcon);
boolean success = false;
try {
beginTransaction("delete", octxt, redoRecorder);
setOperationTargetConstraint(tcon);
PendingDelete info = DbMailItem.getLeafNodes(this, params);
if (info.itemIds.isEmpty()) {
return false;
}
redoRecorder.setIds(ArrayUtil.toIntArray(info.itemIds.getAllIds()));
MailItem.delete(this, info, null, true, /* writeTombstones */
false);
success = true;
} finally {
endTransaction(success);
}
} finally {
lock.release();
}
return true;
}
use of com.zimbra.cs.mailbox.MailItem.PendingDelete 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);
}
}
use of com.zimbra.cs.mailbox.MailItem.PendingDelete in project zm-mailbox by Zimbra.
the class DbTag method getLeafNodes.
public static PendingDelete getLeafNodes(Mailbox mbox, Tag tag, int before, Integer maxItems) throws ServiceException {
DbConnection conn = mbox.getOperationConnection();
PreparedStatement stmt = null;
ResultSet rs = null;
try {
String orderByLimit = "";
if (maxItems != null && Db.supports(Db.Capability.LIMIT_CLAUSE)) {
orderByLimit = " ORDER BY date " + Db.getInstance().limit(maxItems);
}
String mailboxesMatchAnd = DebugConfig.disableMailboxGroups ? "" : "mi.mailbox_id = ti.mailbox_id AND ";
stmt = conn.prepareStatement("SELECT " + DbMailItem.LEAF_NODE_FIELDS + " FROM " + DbMailItem.getMailItemTableName(mbox, "mi") + " INNER JOIN " + getTaggedItemTableName(mbox, "ti") + " ON " + mailboxesMatchAnd + "ti.item_id = mi.id" + " WHERE " + inThisMailboxAnd("ti") + "ti.tag_id = ? AND date < ? AND type NOT IN " + DbMailItem.NON_SEARCHABLE_TYPES + orderByLimit);
int pos = 1;
pos = DbMailItem.setMailboxId(stmt, mbox, pos);
stmt.setInt(pos++, tag.getId());
stmt.setInt(pos++, before);
PendingDelete info = DbMailItem.accumulateDeletionInfo(mbox, stmt);
stmt = null;
return info;
} catch (SQLException e) {
throw ServiceException.FAILURE("fetching list of items for purge", e);
} finally {
DbPool.closeResults(rs);
DbPool.closeStatement(stmt);
}
}
Aggregations