Search in sources :

Example 1 with QueryParams

use of com.zimbra.cs.db.DbMailItem.QueryParams in project zm-mailbox by Zimbra.

the class Mailbox method purgeDumpster.

private int purgeDumpster(long olderThanMillis, int maxItems) throws ServiceException {
    QueryParams params = new QueryParams();
    params.setChangeDateBefore((int) (olderThanMillis / 1000)).setRowLimit(maxItems);
    Set<Integer> itemIds = DbMailItem.getIds(this, getOperationConnection(), params, true);
    if (!itemIds.isEmpty()) {
        return deleteFromDumpster(ArrayUtil.toIntArray(itemIds));
    } else {
        return 0;
    }
}
Also used : QueryParams(com.zimbra.cs.db.DbMailItem.QueryParams)

Example 2 with QueryParams

use of com.zimbra.cs.db.DbMailItem.QueryParams in project zm-mailbox by Zimbra.

the class Mailbox method emptyFolder.

/**
     * @param removeTopLevelFolder - delete folder after it has been emptied
     */
private void emptyFolder(OperationContext octxt, int folderId, boolean removeTopLevelFolder, boolean removeSubfolders, TargetConstraint tcon) throws ServiceException {
    try {
        if (emptyFolderOpLock.tryLock() || emptyFolderOpLock.tryLock(Provisioning.getInstance().getLocalServer().getEmptyFolderOpTimeout(), TimeUnit.SECONDS)) {
            int batchSize = Provisioning.getInstance().getLocalServer().getMailEmptyFolderBatchSize();
            ZimbraLog.mailbox.debug("Emptying folder %s, removeTopLevelFolder=%b, removeSubfolders=%b, batchSize=%d", folderId, removeTopLevelFolder, removeSubfolders, batchSize);
            List<Integer> folderIds = new ArrayList<Integer>();
            if (!removeSubfolders) {
                folderIds.add(folderId);
            } else {
                List<Folder> folders = getFolderById(octxt, folderId).getSubfolderHierarchy();
                for (Folder folder : folders) {
                    folderIds.add(folder.getId());
                }
            }
            // Make sure that the user has the delete permission for all folders in the hierarchy.
            for (int id : folderIds) {
                if ((getEffectivePermissions(octxt, id, MailItem.Type.FOLDER) & ACL.RIGHT_DELETE) == 0) {
                    throw ServiceException.PERM_DENIED("not authorized to empty folder " + getFolderById(octxt, id).getPath());
                }
            }
            int lastChangeID = octxt != null && octxt.change != -1 ? octxt.change : getLastChangeID();
            // Delete the items in batches.  (1000 items by default)
            QueryParams params = new QueryParams();
            params.setFolderIds(folderIds).setModifiedSequenceBefore(lastChangeID + 1).setRowLimit(batchSize);
            boolean firstTime = true;
            do {
                // Give other threads a chance to use the mailbox between deletion batches.
                if (firstTime) {
                    firstTime = false;
                } else {
                    long sleepMillis = LC.empty_folder_batch_sleep_ms.longValue();
                    try {
                        ZimbraLog.mailbox.debug("emptyLargeFolder() sleeping for %dms", sleepMillis);
                        Thread.sleep(sleepMillis);
                    } catch (InterruptedException e) {
                        ZimbraLog.mailbox.warn("Sleep was interrupted", e);
                    }
                }
            } while (deletedBatchOfItemsInFolder(octxt, params, tcon));
            if ((removeTopLevelFolder || removeSubfolders) && (!folderIds.isEmpty())) {
                if (!removeTopLevelFolder) {
                    // 0th position is the folder being emptied
                    folderIds.remove(0);
                }
                if (!folderIds.isEmpty()) {
                    lock.lock();
                    try {
                        delete(octxt, ArrayUtil.toIntArray(folderIds), MailItem.Type.FOLDER, tcon, false, /* don't useEmptyForFolders */
                        null);
                    } finally {
                        lock.release();
                    }
                }
            }
        } else {
            ZimbraLog.mailbox.info("Empty large folder operation canceled because previous empty folder operation is in progress");
            throw ServiceException.ALREADY_IN_PROGRESS("Empty Folder operation is in progress. Please wait for the operation to complete");
        }
    } catch (InterruptedException e) {
        ZimbraLog.mailbox.warn("Empty folder operation interupted while acquiring emptyFolderOpLock", e);
        throw ServiceException.ALREADY_IN_PROGRESS("Empty Folder operation is in progress. Please wait for the operation to complete");
    } finally {
        if (emptyFolderOpLock.isHeldByCurrentThread()) {
            emptyFolderOpLock.unlock();
        }
    }
}
Also used : CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) QueryParams(com.zimbra.cs.db.DbMailItem.QueryParams) CreateFolder(com.zimbra.cs.redolog.op.CreateFolder) ZFolder(com.zimbra.client.ZFolder) RefreshMountpoint(com.zimbra.cs.redolog.op.RefreshMountpoint) TargetConstraint(com.zimbra.cs.mailbox.MailItem.TargetConstraint) CreateMountpoint(com.zimbra.cs.redolog.op.CreateMountpoint)

Example 3 with QueryParams

use of com.zimbra.cs.db.DbMailItem.QueryParams in project zm-mailbox by Zimbra.

the class Mailbox method emptyDumpster.

public int emptyDumpster(OperationContext octxt) throws ServiceException {
    if (!hasFullAdminAccess(octxt)) {
        throw ServiceException.PERM_DENIED("only admins can delete from dumpster");
    }
    int numDeleted = 0;
    int batchSize = Provisioning.getInstance().getLocalServer().getMailEmptyFolderBatchSize();
    ZimbraLog.mailbox.info("Emptying dumpster with batchSize=" + batchSize);
    QueryParams params = new QueryParams();
    // +1 to catch items put into dumpster in the same second
    params.setChangeDateBefore((int) (System.currentTimeMillis() / 1000 + 1)).setRowLimit(batchSize);
    while (true) {
        lock.lock();
        try {
            Set<Integer> itemIds = null;
            // XXX: should we be in a txn and using getOperationConnection() instead?
            DbConnection conn = DbPool.getConnection(this);
            try {
                itemIds = DbMailItem.getIds(this, conn, params, true);
            } finally {
                conn.closeQuietly();
            }
            if (itemIds.isEmpty()) {
                break;
            }
            numDeleted += deleteFromDumpster(octxt, ArrayUtil.toIntArray(itemIds));
        } finally {
            lock.release();
        }
    }
    return numDeleted;
}
Also used : QueryParams(com.zimbra.cs.db.DbMailItem.QueryParams) RefreshMountpoint(com.zimbra.cs.redolog.op.RefreshMountpoint) TargetConstraint(com.zimbra.cs.mailbox.MailItem.TargetConstraint) CreateMountpoint(com.zimbra.cs.redolog.op.CreateMountpoint) DbConnection(com.zimbra.cs.db.DbPool.DbConnection)

Example 4 with QueryParams

use of com.zimbra.cs.db.DbMailItem.QueryParams in project zm-mailbox by Zimbra.

the class DbMailItemTest method getIds.

@Test
public void getIds() throws Exception {
    int now = (int) (System.currentTimeMillis() / 1000);
    int beforeNow = now - 1000;
    int afterNow = now + 1000;
    int deleteNow = now + 2000;
    final int beforeNowCount = 9;
    final int afterNowCount = 13;
    final int notDeleteCount = 7;
    final int deleteCount = 17;
    int id = 100;
    Set<Integer> ids = DbMailItem.getIds(mbox, conn, new QueryParams(), false);
    QueryParams params = new QueryParams();
    params.setChangeDateBefore(now);
    Set<Integer> idsInitBeforeNow = DbMailItem.getIds(mbox, conn, params, false);
    params = new QueryParams();
    params.setChangeDateAfter(now);
    Set<Integer> idsInitAftereNow = DbMailItem.getIds(mbox, conn, params, false);
    int idsInit = ids.size();
    for (int i = 0; i < beforeNowCount; i++) {
        DbUtil.executeUpdate(conn, "INSERT INTO mboxgroup1.mail_item " + "(mailbox_id, id, type, index_id, date, size, flags, tags, mod_metadata, change_date, mod_content) " + "VALUES(?, ?, ?, 0, 0, 0, 0, 0, 0, ?, 0)", mbox.getId(), id++, MailItem.Type.MESSAGE.toByte(), beforeNow);
    }
    id = 200;
    Set<Integer> idsAddBeforeNow = DbMailItem.getIds(mbox, conn, new QueryParams(), false);
    Assert.assertTrue(beforeNowCount == idsAddBeforeNow.size() - idsInit);
    for (int i = 0; i < afterNowCount; i++) {
        DbUtil.executeUpdate(conn, "INSERT INTO mboxgroup1.mail_item " + "(mailbox_id, id, type, index_id, date, size, flags, tags, mod_metadata, change_date, mod_content) " + "VALUES(?, ?, ?, 0, 0, 0, 0, 0, 0, ?, 0)", mbox.getId(), id++, MailItem.Type.MESSAGE.toByte(), afterNow);
    }
    Set<Integer> idsAddAfterNow = DbMailItem.getIds(mbox, conn, new QueryParams(), false);
    Assert.assertTrue(afterNowCount == idsAddAfterNow.size() - idsAddBeforeNow.size());
    params = new QueryParams();
    params.setChangeDateBefore(now);
    Set<Integer> idsBeforeNow = DbMailItem.getIds(mbox, conn, params, false);
    Assert.assertTrue((idsBeforeNow.size() - idsInitBeforeNow.size()) == beforeNowCount);
    params = new QueryParams();
    params.setChangeDateAfter(now);
    Set<Integer> idsAfterNow = DbMailItem.getIds(mbox, conn, params, false);
    Assert.assertTrue((idsAfterNow.size() - idsInitAftereNow.size()) == afterNowCount);
    id = 300;
    for (int i = 0; i < notDeleteCount; i++) {
        DbUtil.executeUpdate(conn, "INSERT INTO mboxgroup1.mail_item " + "(mailbox_id, id, type, index_id, date, size, flags, tags, mod_metadata, change_date, mod_content) " + "VALUES(?, ?, ?, 0, 0, 0, 0, 0, 0, ?, 0)", mbox.getId(), id++, MailItem.Type.MESSAGE.toByte(), deleteNow);
    }
    for (int i = 0; i < deleteCount; i++) {
        DbUtil.executeUpdate(conn, "INSERT INTO mboxgroup1.mail_item " + "(mailbox_id, id, type, index_id, date, size, flags, tags, mod_metadata, change_date, mod_content) " + "VALUES(?, ?, ?, 0, 0, 0, 128, 0, 0, ?, 0)", mbox.getId(), id++, MailItem.Type.MESSAGE.toByte(), deleteNow);
    }
    params = new QueryParams();
    params.setChangeDateAfter(deleteNow - 1);
    Set<Integer> idsForDelete = DbMailItem.getIds(mbox, conn, params, false);
    Assert.assertTrue(idsForDelete.size() == (deleteCount + notDeleteCount));
    params.setFlagToExclude(FlagInfo.DELETED);
    idsForDelete = DbMailItem.getIds(mbox, conn, params, false);
    Assert.assertTrue(idsForDelete.size() == notDeleteCount);
}
Also used : QueryParams(com.zimbra.cs.db.DbMailItem.QueryParams) Test(org.junit.Test)

Aggregations

QueryParams (com.zimbra.cs.db.DbMailItem.QueryParams)4 TargetConstraint (com.zimbra.cs.mailbox.MailItem.TargetConstraint)2 CreateMountpoint (com.zimbra.cs.redolog.op.CreateMountpoint)2 RefreshMountpoint (com.zimbra.cs.redolog.op.RefreshMountpoint)2 ZFolder (com.zimbra.client.ZFolder)1 DbConnection (com.zimbra.cs.db.DbPool.DbConnection)1 CreateFolder (com.zimbra.cs.redolog.op.CreateFolder)1 ArrayList (java.util.ArrayList)1 CopyOnWriteArrayList (java.util.concurrent.CopyOnWriteArrayList)1 Test (org.junit.Test)1