use of com.zimbra.cs.mailbox.util.TypedIdList in project zm-mailbox by Zimbra.
the class Mailbox method listCalendarItemsForRange.
/**
* @param start start time of range, in milliseconds. {@code -1} means to leave the start time unconstrained.
* @param end end time of range, in milliseconds. {@code -1} means to leave the end time unconstrained.
*/
public TypedIdList listCalendarItemsForRange(OperationContext octxt, MailItem.Type type, long start, long end, int folderId) throws ServiceException {
if (folderId == ID_AUTO_INCREMENT) {
return new TypedIdList();
}
boolean success = false;
try {
beginReadTransaction("listCalendarItemsForRange", octxt);
// if they specified a folder, make sure it actually exists
getFolderById(folderId);
// get the list of all visible calendar items in the specified folder
TypedIdList ids = DbMailItem.listCalendarItems(this, type, start, end, folderId, null);
success = true;
return ids;
} finally {
endTransaction(success);
}
}
use of com.zimbra.cs.mailbox.util.TypedIdList in project zm-mailbox by Zimbra.
the class Mailbox method getModifiedItems.
/**
* Returns all of the modified items since a given change number, newly added or modified
* items within given folderIds will be returned as the First field of Pair.
* Be noted that deleted items within folderIds as well as items that have been altered outside of given folderIds
* will be returned as "deleted" (second part of Pair) in order to handle item moves
* @param octxt The context for this request.
* @param lastSync We return items with change ID larger than this value.
* @param sinceDate We return items with date larger than this value.
* @param type The type of MailItems to return.
* @param folderIds folders from which add/change items are returned
* @params limit We limit the number rows returned by the limit value
* @return
* @throws ServiceException
*/
public Pair<List<Integer>, TypedIdList> getModifiedItems(OperationContext octxt, int lastSync, int sinceDate, MailItem.Type type, Set<Integer> folderIds, int lastDeleteSync, int limit) throws ServiceException {
lock.lock(false);
try {
if (lastSync >= getLastChangeID()) {
return new Pair<List<Integer>, TypedIdList>(Collections.<Integer>emptyList(), new TypedIdList());
}
boolean success = false;
try {
beginReadTransaction("getModifiedItems", octxt);
Set<Integer> visible = Folder.toId(getAccessibleFolders(ACL.RIGHT_READ));
if (folderIds == null) {
folderIds = visible;
} else if (visible != null) {
folderIds = SetUtil.intersect(folderIds, visible);
}
Pair<List<Integer>, TypedIdList> dataList = DbMailItem.getModifiedItems(this, type, lastSync, sinceDate, folderIds, lastDeleteSync, limit);
if (dataList == null) {
return null;
}
success = true;
return dataList;
} finally {
endTransaction(success);
}
} finally {
lock.release();
}
}
use of com.zimbra.cs.mailbox.util.TypedIdList in project zm-mailbox by Zimbra.
the class Mailbox method getItemIds.
public TypedIdList getItemIds(OperationContext octxt, int folderId) throws ServiceException {
boolean success = false;
try {
beginReadTransaction("listAllItemIds", octxt);
Folder folder = getFolderById(folderId);
TypedIdList ids = DbMailItem.listByFolder(folder, true);
success = true;
return ids;
} finally {
endTransaction(success);
}
}
use of com.zimbra.cs.mailbox.util.TypedIdList in project zm-mailbox by Zimbra.
the class Sync method deltaSync.
private static String deltaSync(Element response, OperationContext octxt, ItemIdFormatter ifmt, Mailbox mbox, SyncToken syncToken, int deleteLimit, int changeLimit, boolean typedDeletes, Folder root, Set<Folder> visible, int messageSyncStart) throws ServiceException {
int begin = syncToken.getChangeId();
int deleteModSeqCutoff = syncToken.getDeleteModSeq();
deleteModSeqCutoff = deleteModSeqCutoff <= 0 ? begin : deleteModSeqCutoff;
int mboxLastChangeId = mbox.getLastChangeID();
SyncToken newSyncToken = new SyncToken(mboxLastChangeId);
if (begin >= mboxLastChangeId && deleteModSeqCutoff >= mboxLastChangeId) {
return newSyncToken.toString();
}
int changeItemIdCutoff = syncToken.getOffsetInNext();
int deleteItemIdCutoff = syncToken.getDeleteOffsetInNext();
// first, fetch deleted items
TypedIdList tombstones = mbox.getTombstones(deleteModSeqCutoff);
Element eDeleted = response.addElement(MailConstants.E_DELETED);
// then, put together the requested folder hierarchy in 2 different flavors
List<Folder> hierarchy = (root == null || root.getId() == Mailbox.ID_FOLDER_USER_ROOT ? null : root.getSubfolderHierarchy());
Set<Integer> targetIds = (root != null && root.getId() == Mailbox.ID_FOLDER_USER_ROOT ? null : new HashSet<Integer>(hierarchy == null ? 0 : hierarchy.size()));
if (hierarchy != null) {
for (Folder folder : hierarchy) {
targetIds.add(folder.getId());
}
}
// then, handle created/modified folders
if (octxt.isDelegatedRequest(mbox)) {
// first, make sure that something changed...
if (!mbox.getModifiedFolders(begin).isEmpty() || !Collections.disjoint(tombstones.types(), FOLDER_TYPES)) {
// special-case the folder hierarchy for delegated delta sync
boolean anyFolders = folderSync(response, octxt, ifmt, mbox, root, visible, -1, messageSyncStart, SyncPhase.DELTA);
// if no folders are visible, add an empty "<folder/>" as a hint
if (!anyFolders) {
response.addElement(MailConstants.E_FOLDER);
}
}
} else {
for (Folder folder : mbox.getModifiedFolders(begin)) {
// no case of "synthetic tombstone" (item falling out of the tree being synced)
if (targetIds == null || targetIds.contains(folder.getId())) {
ToXML.encodeFolder(response, ifmt, octxt, folder, Change.ALL_FIELDS);
} else {
tombstones.add(folder.getType(), folder.getId(), folder.getUuid(), folder.getModifiedSequence());
}
}
}
// next, handle created/modified tags
for (Tag tag : mbox.getModifiedTags(octxt, begin)) {
ToXML.encodeTag(response, ifmt, octxt, tag, Change.ALL_FIELDS);
}
// finally, handle created/modified "other items"
int itemCount = 0;
Pair<List<Integer>, TypedIdList> changed = mbox.getModifiedItems(octxt, Math.min(begin, deleteModSeqCutoff), messageSyncStart, MailItem.Type.UNKNOWN, targetIds, deleteModSeqCutoff);
List<Integer> modified = changed.getFirst();
// items that have been altered in non-visible folders will be returned as "deleted" in order to handle moves
if (changed.getSecond() != null) {
tombstones.addAll(changed.getSecond());
}
delta: while (!modified.isEmpty()) {
List<Integer> batch = modified.subList(0, Math.min(modified.size(), FETCH_BATCH_SIZE));
for (MailItem item : mbox.getItemById(octxt, batch, MailItem.Type.UNKNOWN)) {
// detect interrupted sync and resume from the appropriate place
if ((item.getModifiedSequence() == begin + 1 && item.getId() < changeItemIdCutoff) || item.getModifiedSequence() <= begin) {
//if interrupted delete and un-interrupted modifications.
continue;
}
// if we've overflowed this sync response, set things up so that a subsequent sync starts from where we're cutting off
if (itemCount >= changeLimit) {
response.addAttribute(MailConstants.A_QUERY_MORE, true);
newSyncToken.setChangeModSeq((item.getModifiedSequence() - 1));
newSyncToken.setChangeItemId(item.getId());
newSyncToken.setDeleteModSeq(mboxLastChangeId);
break delta;
}
// For items in the system, if the content has changed since the user last sync'ed
// (because it was edited or created), just send back the folder ID and saved date --
// the client will request the whole object out of band -- potentially using the
// content servlet's "include metadata in headers" hack.
// If it's just the metadata that changed, send back the set of mutable attributes.
boolean created = item.getSavedSequence() > begin;
ToXML.encodeItem(response, ifmt, octxt, item, created ? Change.FOLDER | Change.CONFLICT | Change.DATE | Change.PARENT : MUTABLE_FIELDS);
itemCount++;
}
batch.clear();
}
// cleanup: only return a <deleted> element if we're sending back deleted item ids
if ((deleteLimit > 0 && tombstones.size() > deleteLimit) || deleteItemIdCutoff > 0) {
PagedDelete pgDel = new PagedDelete(tombstones, typedDeletes);
pgDel.removeBeforeCutoff(deleteItemIdCutoff, deleteModSeqCutoff);
if (deleteLimit > 0) {
pgDel.trimDeletesTillPageLimit(deleteLimit);
}
encodePagedDelete(eDeleted, pgDel, newSyncToken, tombstones, typedDeletes);
if (pgDel.isDeleteOverFlow()) {
response.addAttribute(MailConstants.A_QUERY_MORE, true);
response.addAttribute(MailConstants.A_QUERY_MORE, true);
}
} else {
encodeUnpagedDelete(eDeleted, tombstones, typedDeletes);
}
return newSyncToken.toString();
}
use of com.zimbra.cs.mailbox.util.TypedIdList in project zm-mailbox by Zimbra.
the class DbMailItem method listItems.
public static TypedIdList listItems(Folder folder, long messageSyncStart, MailItem.Type type, boolean descending, boolean older) throws ServiceException {
Mailbox mbox = folder.getMailbox();
assert Db.supports(Db.Capability.ROW_LEVEL_LOCKING) || Thread.holdsLock(mbox);
TypedIdList result = new TypedIdList();
DbConnection conn = mbox.getOperationConnection();
PreparedStatement stmt = null;
ResultSet rs = null;
try {
if (older) {
stmt = conn.prepareStatement("SELECT id, type, uuid FROM " + getMailItemTableName(folder) + " WHERE " + IN_THIS_MAILBOX_AND + " type = ? AND folder_id = ? AND date < ?" + " ORDER BY date" + (descending ? " DESC" : ""));
} else {
stmt = conn.prepareStatement("SELECT id, type, uuid FROM " + getMailItemTableName(folder) + " WHERE " + IN_THIS_MAILBOX_AND + " type = ? AND folder_id = ? AND date >= ?" + " ORDER BY date" + (descending ? " DESC" : ""));
}
int pos = 1;
pos = setMailboxId(stmt, mbox, pos);
stmt.setByte(pos++, type.toByte());
stmt.setInt(pos++, folder.getId());
stmt.setLong(pos++, messageSyncStart);
rs = stmt.executeQuery();
while (rs.next()) {
MailItem.Type dataType = MailItem.Type.of(rs.getByte(2));
result.add(dataType, rs.getInt(1), rs.getString(3));
}
return result;
} catch (SQLException e) {
throw ServiceException.FAILURE("fetching item list for folder " + folder.getId(), e);
} finally {
DbPool.closeResults(rs);
DbPool.closeStatement(stmt);
}
}
Aggregations