Search in sources :

Example 11 with ModificationKey

use of com.zimbra.cs.session.PendingModifications.ModificationKey in project zm-mailbox by Zimbra.

the class CalListCache method notifyCommittedChanges.

void notifyCommittedChanges(PendingModifications mods, int changeId) {
    ChangeMap changeMap = new ChangeMap(1);
    if (mods.created != null) {
        for (Map.Entry<ModificationKey, MailItem> entry : mods.created.entrySet()) {
            MailItem item = entry.getValue();
            if (item instanceof Folder) {
                Folder folder = (Folder) item;
                MailItem.Type viewType = folder.getDefaultView();
                if (viewType == MailItem.Type.APPOINTMENT || viewType == MailItem.Type.TASK) {
                    ChangedFolders changedFolders = changeMap.getAccount(entry.getKey().getAccountId());
                    changedFolders.created.add(folder.getId());
                }
            }
        }
    }
    if (mods.modified != null) {
        for (Map.Entry<ModificationKey, Change> entry : mods.modified.entrySet()) {
            Change change = entry.getValue();
            Object whatChanged = change.what;
            if (whatChanged instanceof Folder) {
                Folder folder = (Folder) whatChanged;
                MailItem.Type viewType = folder.getDefaultView();
                if (viewType == MailItem.Type.APPOINTMENT || viewType == MailItem.Type.TASK) {
                    ChangedFolders changedFolders = changeMap.getAccount(entry.getKey().getAccountId());
                    int folderId = folder.getId();
                    if ((change.why & Change.FOLDER) != 0) {
                        // moving the calendar folder to another parent folder
                        int parentFolder = folder.getFolderId();
                        changedFolders.created.add(folderId);
                        if (parentFolder == Mailbox.ID_FOLDER_TRASH) {
                            changedFolders.deleted.add(folderId);
                        } else {
                            changedFolders.created.add(folderId);
                        }
                    } else {
                        // not a folder move, but something else changed, either calendar's metadata
                        // or a child item (appointment/task)
                        changedFolders.modified.add(folderId);
                    }
                }
            } else if (whatChanged instanceof Message) {
                Message msg = (Message) whatChanged;
                if (msg.hasCalendarItemInfos()) {
                    if (msg.getFolderId() == Mailbox.ID_FOLDER_INBOX || (change.why & Change.FOLDER) != 0) {
                        // If message was moved, we don't know which folder it was moved from.
                        // Just invalidate the Inbox because that's the only message folder we care
                        // about in calendaring.
                        ChangedFolders changedFolders = changeMap.getAccount(entry.getKey().getAccountId());
                        changedFolders.modified.add(Mailbox.ID_FOLDER_INBOX);
                    }
                }
            }
        }
    }
    if (mods.deleted != null) {
        for (Map.Entry<ModificationKey, Change> entry : mods.deleted.entrySet()) {
            MailItem.Type type = (MailItem.Type) entry.getValue().what;
            if (type == MailItem.Type.FOLDER) {
                // We only have item id.  Let's just assume it's a calendar folder id and check
                // against the cached list.
                ChangedFolders changedFolders = changeMap.getAccount(entry.getKey().getAccountId());
                changedFolders.deleted.add(entry.getKey().getItemId());
            }
        // Let's not worry about hard deletes of invite/reply emails.  It has no practical benefit.
        }
    }
    try {
        for (Map.Entry<String, ChangedFolders> entry : changeMap.entrySet()) {
            ChangedFolders changedFolders = entry.getValue();
            if (changedFolders.isEmpty())
                continue;
            String accountId = entry.getKey();
            AccountKey key = new AccountKey(accountId);
            CalList list = mMemcachedLookup.get(key);
            if (list != null) {
                boolean updated = false;
                CalList newList = new CalList(list);
                for (Integer folderId : changedFolders.created) {
                    if (!list.contains(folderId)) {
                        updated = true;
                        newList.add(folderId);
                    }
                }
                for (Integer folderId : changedFolders.modified) {
                    if (list.contains(folderId))
                        updated = true;
                }
                for (Integer folderId : changedFolders.deleted) {
                    if (list.contains(folderId)) {
                        updated = true;
                        newList.remove(folderId);
                    }
                }
                // There was a change.  Increment the version and put back to cache.
                if (updated) {
                    newList.incrementSeq();
                    mMemcachedLookup.put(key, newList);
                }
            }
        }
    } catch (ServiceException e) {
        ZimbraLog.calendar.warn("Unable to notify calendar list cache.  Some cached data may become stale.", e);
    }
}
Also used : Message(com.zimbra.cs.mailbox.Message) ModificationKey(com.zimbra.cs.session.PendingModifications.ModificationKey) Change(com.zimbra.cs.session.PendingModifications.Change) Folder(com.zimbra.cs.mailbox.Folder) MailItem(com.zimbra.cs.mailbox.MailItem) ServiceException(com.zimbra.common.service.ServiceException) HashMap(java.util.HashMap) Map(java.util.Map) MemcachedMap(com.zimbra.common.util.memcached.MemcachedMap)

Example 12 with ModificationKey

use of com.zimbra.cs.session.PendingModifications.ModificationKey in project zm-mailbox by Zimbra.

the class CtagInfoCache method notifyCommittedChanges.

void notifyCommittedChanges(PendingModifications mods, int changeId) {
    int inboxFolder = Mailbox.ID_FOLDER_INBOX;
    Set<CalendarKey> keysToInvalidate = new HashSet<CalendarKey>();
    if (mods.created != null) {
        for (Map.Entry<ModificationKey, MailItem> entry : mods.created.entrySet()) {
            MailItem item = entry.getValue();
            if (item instanceof Message) {
                Message msg = (Message) item;
                if (msg.hasCalendarItemInfos() && msg.getFolderId() == inboxFolder) {
                    CalendarKey key = new CalendarKey(msg.getMailbox().getAccountId(), inboxFolder);
                    keysToInvalidate.add(key);
                }
            }
        }
    }
    if (mods.modified != null) {
        for (Map.Entry<ModificationKey, Change> entry : mods.modified.entrySet()) {
            Change change = entry.getValue();
            Object whatChanged = change.what;
            if (whatChanged instanceof Folder) {
                Folder folder = (Folder) whatChanged;
                MailItem.Type viewType = folder.getDefaultView();
                if (viewType == MailItem.Type.APPOINTMENT || viewType == MailItem.Type.TASK) {
                    CalendarKey key = new CalendarKey(folder.getMailbox().getAccountId(), folder.getId());
                    keysToInvalidate.add(key);
                }
            } else if (whatChanged instanceof Message) {
                Message msg = (Message) whatChanged;
                if (msg.hasCalendarItemInfos()) {
                    if (msg.getFolderId() == inboxFolder || (change.why & Change.FOLDER) != 0) {
                        // If message was moved, we don't know which folder it was moved from.
                        // Just invalidate the Inbox because that's the only message folder we care
                        // about in calendaring.
                        CalendarKey key = new CalendarKey(msg.getMailbox().getAccountId(), inboxFolder);
                        keysToInvalidate.add(key);
                    }
                }
            }
        }
    }
    if (mods.deleted != null) {
        for (Entry<ModificationKey, Change> entry : mods.deleted.entrySet()) {
            Type type = (Type) entry.getValue().what;
            if (type == MailItem.Type.FOLDER) {
                // We only have item id.  Assume it's a folder id and issue a delete.
                String acctId = entry.getKey().getAccountId();
                if (acctId == null)
                    // just to be safe
                    continue;
                CalendarKey key = new CalendarKey(acctId, entry.getKey().getItemId());
                keysToInvalidate.add(key);
            }
        // Let's not worry about hard deletes of invite/reply emails.  It has no practical benefit.
        }
    }
    try {
        mMemcachedLookup.removeMulti(keysToInvalidate);
    } catch (ServiceException e) {
        ZimbraLog.calendar.warn("Unable to notify ctag info cache.  Some cached data may become stale.", e);
    }
}
Also used : Message(com.zimbra.cs.mailbox.Message) ModificationKey(com.zimbra.cs.session.PendingModifications.ModificationKey) Change(com.zimbra.cs.session.PendingModifications.Change) ZFolder(com.zimbra.client.ZFolder) Folder(com.zimbra.cs.mailbox.Folder) Type(com.zimbra.cs.mailbox.MailItem.Type) MailItem(com.zimbra.cs.mailbox.MailItem) Type(com.zimbra.cs.mailbox.MailItem.Type) ServiceException(com.zimbra.common.service.ServiceException) HashMap(java.util.HashMap) Map(java.util.Map) MemcachedMap(com.zimbra.common.util.memcached.MemcachedMap) HashSet(java.util.HashSet)

Example 13 with ModificationKey

use of com.zimbra.cs.session.PendingModifications.ModificationKey in project zm-mailbox by Zimbra.

the class ImapListener method notifyPendingChanges.

@SuppressWarnings("rawtypes")
@Override
public void notifyPendingChanges(PendingModifications pnsIn, int changeId, Session source) {
    if (!pnsIn.hasNotifications()) {
        return;
    }
    if (changeId < lastChangeId) {
        ZimbraLog.imap.debug("ImapListener :: change %d is not higher than last change %d. Ignoring", changeId, lastChangeId);
        return;
    }
    ImapHandler i4handler = handler;
    try {
        synchronized (this) {
            AddedItems added = new AddedItems();
            if (pnsIn.deleted != null) {
                @SuppressWarnings("unchecked") Map<ModificationKey, Change> deleted = pnsIn.deleted;
                for (Map.Entry<ModificationKey, Change> entry : deleted.entrySet()) {
                    handleDelete(changeId, entry.getKey().getItemId(), entry.getValue());
                }
            }
            notifyPendingCreates(pnsIn, changeId, added);
            if (pnsIn.modified != null) {
                @SuppressWarnings("unchecked") Map<ModificationKey, Change> modified = pnsIn.modified;
                for (Change chg : modified.values()) {
                    handleModify(changeId, chg, added);
                }
            }
            // add new messages to the currently selected mailbox
            if (!added.isEmpty()) {
                mFolder.handleAddedMessages(changeId, added);
            }
            mFolder.finishNotification(changeId);
        }
        if (i4handler != null && i4handler.isIdle()) {
            i4handler.sendNotifications(true, true);
        }
    } catch (IOException e) {
        // which calls Session.doCleanup, which calls Mailbox.removeListener
        if (ZimbraLog.imap.isDebugEnabled()) {
            // with stack trace
            ZimbraLog.imap.debug("Failed to notify, closing %s", this, e);
        } else {
            // without stack trace
            ZimbraLog.imap.info("Failed to notify (%s), closing %s", e.toString(), this);
        }
        if (i4handler != null) {
            i4handler.close();
        }
    } finally {
        lastChangeId = changeId;
    }
}
Also used : ModificationKey(com.zimbra.cs.session.PendingModifications.ModificationKey) Change(com.zimbra.cs.session.PendingModifications.Change) IOException(java.io.IOException) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) TreeMap(java.util.TreeMap)

Example 14 with ModificationKey

use of com.zimbra.cs.session.PendingModifications.ModificationKey in project zm-mailbox by Zimbra.

the class CalItemReminderService method notify.

@Override
public void notify(ChangeNotification notification) {
    Account account = notification.mailboxAccount;
    if (notification.mods.created != null) {
        for (Map.Entry<ModificationKey, BaseItemInfo> entry : notification.mods.created.entrySet()) {
            BaseItemInfo item = entry.getValue();
            if (item instanceof CalendarItem) {
                CalendarItem calItem = (CalendarItem) item;
                ZimbraLog.scheduler.debug("Handling creation of calendar item (id=%s,mailboxId=%s)", calItem.getId(), calItem.getMailboxId());
                scheduleNextReminders((CalendarItem) item, true, true);
            }
        }
    }
    if (notification.mods.modified != null) {
        for (Map.Entry<ModificationKey, Change> entry : notification.mods.modified.entrySet()) {
            Change change = entry.getValue();
            if (change.what instanceof CalendarItem) {
                CalendarItem calItem = (CalendarItem) change.what;
                ZimbraLog.scheduler.debug("Handling modification of calendar item (id=%s,mailboxId=%s)", calItem.getId(), calItem.getMailboxId());
                boolean calItemCanceled = false;
                try {
                    if ((change.why & Change.FOLDER) != 0 && calItem.inTrash()) {
                        calItemCanceled = true;
                    }
                } catch (ServiceException e) {
                    ZimbraLog.scheduler.error("Error in fetching calendar item's folder", e);
                }
                // cancel any existing reminders and schedule new ones if cal item not canceled
                if (cancelExistingReminders(calItem) && !calItemCanceled)
                    scheduleNextReminders(calItem, true, true);
            }
        }
    }
    if (notification.mods.deleted != null) {
        for (Map.Entry<ModificationKey, Change> entry : notification.mods.deleted.entrySet()) {
            MailItem.Type type = (MailItem.Type) entry.getValue().what;
            if (type == MailItem.Type.APPOINTMENT || type == MailItem.Type.TASK) {
                Mailbox mbox = null;
                try {
                    mbox = MailboxManager.getInstance().getMailboxByAccount(account, MailboxManager.FetchMode.DO_NOT_AUTOCREATE);
                } catch (ServiceException e) {
                    ZimbraLog.scheduler.error("Error looking up the mailbox of account %s", account.getId(), e);
                }
                if (mbox != null) {
                    cancelExistingReminders(entry.getKey().getItemId(), mbox.getId());
                }
            }
        }
    }
}
Also used : Account(com.zimbra.cs.account.Account) BaseItemInfo(com.zimbra.common.mailbox.BaseItemInfo) ModificationKey(com.zimbra.cs.session.PendingModifications.ModificationKey) Change(com.zimbra.cs.session.PendingModifications.Change) CalendarItem(com.zimbra.cs.mailbox.CalendarItem) MailItem(com.zimbra.cs.mailbox.MailItem) ServiceException(com.zimbra.common.service.ServiceException) Mailbox(com.zimbra.cs.mailbox.Mailbox) Map(java.util.Map)

Example 15 with ModificationKey

use of com.zimbra.cs.session.PendingModifications.ModificationKey in project zm-mailbox by Zimbra.

the class CalSummaryMemcachedCache method notifyCommittedChanges.

void notifyCommittedChanges(PendingLocalModifications mods, int changeId) {
    Set<CalSummaryKey> keysToInvalidate = new HashSet<CalSummaryKey>();
    if (mods.modified != null) {
        for (Map.Entry<ModificationKey, Change> entry : mods.modified.entrySet()) {
            Change change = entry.getValue();
            Object whatChanged = change.what;
            if (whatChanged instanceof Folder) {
                Folder folder = (Folder) whatChanged;
                MailItem.Type viewType = folder.getDefaultView();
                if (viewType == MailItem.Type.APPOINTMENT || viewType == MailItem.Type.TASK) {
                    CalSummaryKey key = new CalSummaryKey(folder.getMailbox().getAccountId(), folder.getId());
                    keysToInvalidate.add(key);
                }
            }
        }
    }
    if (mods.deleted != null) {
        for (Map.Entry<ModificationKey, Change> entry : mods.deleted.entrySet()) {
            MailItem.Type type = (MailItem.Type) entry.getValue().what;
            if (type == MailItem.Type.FOLDER) {
                // We only have item id.  Assume it's a folder id and issue a delete.
                String acctId = entry.getKey().getAccountId();
                if (acctId == null)
                    // just to be safe
                    continue;
                CalSummaryKey key = new CalSummaryKey(acctId, entry.getKey().getItemId());
                keysToInvalidate.add(key);
            }
        // Let's not worry about hard deletes of invite/reply emails.  It has no practical benefit.
        }
    }
    try {
        mMemcachedLookup.removeMulti(keysToInvalidate);
    } catch (ServiceException e) {
        ZimbraLog.calendar.warn("Unable to notify ctag info cache.  Some cached data may become stale.", e);
    }
}
Also used : ModificationKey(com.zimbra.cs.session.PendingModifications.ModificationKey) Change(com.zimbra.cs.session.PendingModifications.Change) Folder(com.zimbra.cs.mailbox.Folder) MailItem(com.zimbra.cs.mailbox.MailItem) ServiceException(com.zimbra.common.service.ServiceException) Map(java.util.Map) BigByteArrayMemcachedMap(com.zimbra.common.util.memcached.BigByteArrayMemcachedMap) HashSet(java.util.HashSet)

Aggregations

ModificationKey (com.zimbra.cs.session.PendingModifications.ModificationKey)18 Change (com.zimbra.cs.session.PendingModifications.Change)17 MailItem (com.zimbra.cs.mailbox.MailItem)15 Map (java.util.Map)15 ServiceException (com.zimbra.common.service.ServiceException)13 Folder (com.zimbra.cs.mailbox.Folder)10 HashMap (java.util.HashMap)7 BaseItemInfo (com.zimbra.common.mailbox.BaseItemInfo)6 MemcachedMap (com.zimbra.common.util.memcached.MemcachedMap)6 HashSet (java.util.HashSet)6 Mailbox (com.zimbra.cs.mailbox.Mailbox)4 Message (com.zimbra.cs.mailbox.Message)4 Account (com.zimbra.cs.account.Account)3 CalendarItem (com.zimbra.cs.mailbox.CalendarItem)3 ZFolder (com.zimbra.client.ZFolder)2 BigByteArrayMemcachedMap (com.zimbra.common.util.memcached.BigByteArrayMemcachedMap)2 Type (com.zimbra.cs.mailbox.MailItem.Type)2 MailServiceException (com.zimbra.cs.mailbox.MailServiceException)2 PendingModifications (com.zimbra.cs.session.PendingModifications)2 IOException (java.io.IOException)2