Search in sources :

Example 16 with TypedIdList

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);
    }
}
Also used : TypedIdList(com.zimbra.cs.mailbox.util.TypedIdList)

Example 17 with TypedIdList

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();
    }
}
Also used : CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) LinkedList(java.util.LinkedList) ArrayList(java.util.ArrayList) List(java.util.List) TypedIdList(com.zimbra.cs.mailbox.util.TypedIdList) TypedIdList(com.zimbra.cs.mailbox.util.TypedIdList) Pair(com.zimbra.common.util.Pair)

Example 18 with TypedIdList

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);
    }
}
Also used : CreateFolder(com.zimbra.cs.redolog.op.CreateFolder) ZFolder(com.zimbra.client.ZFolder) TypedIdList(com.zimbra.cs.mailbox.util.TypedIdList)

Example 19 with TypedIdList

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();
}
Also used : PagedDelete(com.zimbra.cs.mailbox.util.PagedDelete) Element(com.zimbra.common.soap.Element) Folder(com.zimbra.cs.mailbox.Folder) TypedIdList(com.zimbra.cs.mailbox.util.TypedIdList) SyncToken(com.zimbra.cs.service.util.SyncToken) MailItem(com.zimbra.cs.mailbox.MailItem) TypedIdList(com.zimbra.cs.mailbox.util.TypedIdList) List(java.util.List) Tag(com.zimbra.cs.mailbox.Tag) HashSet(java.util.HashSet)

Example 20 with TypedIdList

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);
    }
}
Also used : MailItem(com.zimbra.cs.mailbox.MailItem) Mailbox(com.zimbra.cs.mailbox.Mailbox) SQLException(java.sql.SQLException) ResultSet(java.sql.ResultSet) PreparedStatement(java.sql.PreparedStatement) TypedIdList(com.zimbra.cs.mailbox.util.TypedIdList) DbConnection(com.zimbra.cs.db.DbPool.DbConnection)

Aggregations

TypedIdList (com.zimbra.cs.mailbox.util.TypedIdList)25 ResultSet (java.sql.ResultSet)7 DbConnection (com.zimbra.cs.db.DbPool.DbConnection)6 PreparedStatement (java.sql.PreparedStatement)6 SQLException (java.sql.SQLException)6 Test (org.junit.Test)6 MailItem (com.zimbra.cs.mailbox.MailItem)5 PagedDelete (com.zimbra.cs.mailbox.util.PagedDelete)5 ZFolder (com.zimbra.client.ZFolder)4 CreateFolder (com.zimbra.cs.redolog.op.CreateFolder)4 ArrayList (java.util.ArrayList)4 List (java.util.List)4 Pair (com.zimbra.common.util.Pair)3 Folder (com.zimbra.cs.mailbox.Folder)3 Type (com.zimbra.cs.mailbox.MailItem.Type)3 Mailbox (com.zimbra.cs.mailbox.Mailbox)3 Element (com.zimbra.common.soap.Element)2 DbTag (com.zimbra.cs.db.DbTag)2 TargetConstraint (com.zimbra.cs.mailbox.MailItem.TargetConstraint)2 AlterItemTag (com.zimbra.cs.redolog.op.AlterItemTag)2