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;
}
}
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();
}
}
}
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;
}
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);
}
Aggregations