Search in sources :

Example 1 with ModificationKey

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

the class EffectiveACLCache method notifyCommittedChanges.

public void notifyCommittedChanges(PendingModifications mods, int changeId) {
    Set<EffectiveACLCacheKey> keysToInvalidate = new HashSet<EffectiveACLCacheKey>();
    if (mods.modified != null) {
        for (Map.Entry<ModificationKey, Change> entry : mods.modified.entrySet()) {
            Change change = entry.getValue();
            Object whatChanged = change.what;
            // permission change or move to a new parent folder.
            if (whatChanged instanceof Folder && (change.why & (Change.ACL | Change.FOLDER)) != 0) {
                Folder folder = (Folder) whatChanged;
                // Invalidate all child folders because their inherited ACL will need to be recomputed.
                String acctId = folder.getMailbox().getAccountId();
                // includes "folder" folder
                List<Folder> subfolders = folder.getSubfolderHierarchy();
                for (Folder subf : subfolders) {
                    EffectiveACLCacheKey key = new EffectiveACLCacheKey(acctId, subf.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) {
                String acctId = entry.getKey().getAccountId();
                if (acctId == null)
                    // just to be safe
                    continue;
                EffectiveACLCacheKey key = new EffectiveACLCacheKey(acctId, entry.getKey().getItemId());
                keysToInvalidate.add(key);
            }
        }
    }
    try {
        mMemcachedLookup.removeMulti(keysToInvalidate);
    } catch (ServiceException e) {
        ZimbraLog.calendar.warn("Unable to notify folder acl 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) MemcachedMap(com.zimbra.common.util.memcached.MemcachedMap) HashSet(java.util.HashSet)

Example 2 with ModificationKey

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

the class CalSummaryCache method notifyCommittedChanges.

void notifyCommittedChanges(PendingModifications mods, int changeId) {
    if (mods.created != null) {
        for (Map.Entry<ModificationKey, MailItem> entry : mods.created.entrySet()) {
            MailItem item = entry.getValue();
            if (item instanceof CalendarItem) {
                int folderId = item.getFolderId();
                invalidateItem(item.getMailbox(), folderId, item.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 CalendarItem) {
                CalendarItem item = (CalendarItem) whatChanged;
                Mailbox mbox = item.getMailbox();
                int folderId = item.getFolderId();
                int itemId = item.getId();
                invalidateItem(mbox, folderId, itemId);
                // If this is a folder move, invalidate the item from the old folder too.
                if ((change.why & Change.FOLDER) != 0) {
                    String accountId = mbox.getAccountId();
                    int prevFolderId;
                    synchronized (mSummaryCache) {
                        prevFolderId = mSummaryCache.getFolderForItem(accountId, itemId);
                    }
                    if (prevFolderId != folderId && prevFolderId != SummaryLRU.FOLDER_NOT_FOUND) {
                        invalidateItem(mbox, prevFolderId, itemId);
                    }
                }
            }
        }
    }
    if (mods.deleted != null) {
        String lastAcctId = null;
        Mailbox lastMbox = null;
        for (Map.Entry<ModificationKey, Change> entry : mods.deleted.entrySet()) {
            MailItem.Type type = (MailItem.Type) entry.getValue().what;
            if (type == MailItem.Type.APPOINTMENT || type == MailItem.Type.TASK) {
                // We only have item id.  Look up the folder id of the item in the cache.
                Mailbox mbox = null;
                String acctId = entry.getKey().getAccountId();
                // just to be safe
                if (acctId == null)
                    continue;
                if (acctId.equals(lastAcctId)) {
                    // Deletion by id list usually happens because of a folder getting emptied.
                    // It's highly likely the items all belong to the same mailbox, let alone folder.
                    mbox = lastMbox;
                } else {
                    try {
                        mbox = MailboxManager.getInstance().getMailboxByAccountId(acctId, FetchMode.DO_NOT_AUTOCREATE);
                    } catch (ServiceException e) {
                        ZimbraLog.calendar.error("Error looking up the mailbox of account in delete notification: account=" + acctId, e);
                        continue;
                    }
                }
                if (mbox != null) {
                    lastAcctId = acctId;
                    lastMbox = mbox;
                    int itemId = entry.getKey().getItemId();
                    String accountId = mbox.getAccountId();
                    int folderId;
                    synchronized (mSummaryCache) {
                        folderId = mSummaryCache.getFolderForItem(accountId, itemId);
                    }
                    if (folderId != SummaryLRU.FOLDER_NOT_FOUND) {
                        invalidateItem(mbox, folderId, itemId);
                    }
                }
            }
        }
    }
    if (MemcachedConnector.isConnected()) {
        mMemcachedCache.notifyCommittedChanges(mods, changeId);
    }
}
Also used : 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) Mailbox(com.zimbra.cs.mailbox.Mailbox) ServiceException(com.zimbra.common.service.ServiceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Example 3 with ModificationKey

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

the class CalSummaryMemcachedCache method notifyCommittedChanges.

void notifyCommittedChanges(PendingModifications 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)

Example 4 with ModificationKey

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

the class PendingRemoteNotificationsTest method testPendingRemoteNotifications.

@Test
public void testPendingRemoteNotifications() throws Exception {
    String acctId = "12aa345b-2b47-44e6-8cb8-7fdfa18c1a9f";
    ImapMessageInfo imapMsg1 = new ImapMessageInfo(123, 123, Type.MESSAGE.toString(), 0, null);
    BaseItemInfo msg1 = ModificationItem.itemUpdate(imapMsg1, Mailbox.ID_FOLDER_INBOX, acctId);
    ImapMessageInfo imapMsg2 = new ImapMessageInfo(456, 456, Type.MESSAGE.toString(), 0, null);
    BaseItemInfo msg2 = ModificationItem.itemUpdate(imapMsg2, Mailbox.ID_FOLDER_INBOX, acctId);
    PendingRemoteModifications prm = new PendingRemoteModifications();
    prm.recordCreated(msg1);
    assertTrue(!prm.created.isEmpty());
    BaseItemInfo newItem = prm.created.get(new ModificationKey(msg1));
    assertEquals(imapMsg1.getId(), newItem.getIdInMailbox());
    assertEquals(imapMsg1.getImapUid(), newItem.getImapUid());
    assertEquals(acctId, newItem.getAccountId());
    // rename a tag
    ZimbraTag tag = ModificationItem.tagRename(2, "tagname");
    prm.recordModified(tag, acctId, Change.NAME);
    Change tagChange = prm.modified.get(new ModificationKey(acctId, tag.getTagId()));
    assertNotNull(tagChange);
    assertEquals(Change.NAME, tagChange.why);
    assertEquals(tag, tagChange.what);
    // rename a folder
    ModificationItem folder = ModificationItem.folderRename(3, "/newpath", acctId);
    prm.recordModified(folder, Change.NAME);
    Change folderChange = prm.modified.get(new ModificationKey(folder));
    assertNotNull(folderChange);
    assertEquals(Change.NAME, folderChange.why);
    assertEquals(folder, folderChange.what);
    // modify an item
    BaseItemInfo updateItem = ModificationItem.itemUpdate(imapMsg2, Mailbox.ID_FOLDER_INBOX, acctId);
    prm.recordModified(updateItem, Change.FLAGS);
    Change itemChange = prm.modified.get(new ModificationKey(updateItem));
    assertNotNull(itemChange);
    assertEquals(Change.FLAGS, itemChange.why);
    assertEquals(updateItem, itemChange.what);
    // adding a delete notification for the previously added message
    // should remove it from the created map, and NOT add it to the deleted map
    prm.recordDeleted(Type.MESSAGE, acctId, imapMsg1.getId());
    assertTrue(prm.created.isEmpty());
    assertTrue(prm.deleted == null);
    // adding a delete notification for a previously modified message
    // should remove it from the modified map AND add it to the deleted map
    prm.recordDeleted(Type.MESSAGE, acctId, imapMsg2.getId());
    assertNull(prm.modified.get(new ModificationKey(msg2)));
    assertEquals(1, prm.deleted.size());
    Change deletionChange = prm.deleted.get(new ModificationKey(msg2));
    assertEquals(Change.NONE, deletionChange.why);
    assertEquals(MailItem.Type.MESSAGE, deletionChange.what);
}
Also used : ModificationItem(com.zimbra.cs.session.ModificationItem) BaseItemInfo(com.zimbra.common.mailbox.BaseItemInfo) PendingRemoteModifications(com.zimbra.cs.session.PendingRemoteModifications) ZimbraTag(com.zimbra.common.mailbox.ZimbraTag) ModificationKey(com.zimbra.cs.session.PendingModifications.ModificationKey) ImapMessageInfo(com.zimbra.soap.mail.type.ImapMessageInfo) Change(com.zimbra.cs.session.PendingModifications.Change) Test(org.junit.Test)

Example 5 with ModificationKey

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

the class FilterListener method notify.

@Override
public void notify(ChangeNotification notification) {
    if (notification.mods.modified != null && EVENTS.contains(notification.op)) {
        for (PendingModifications.Change change : notification.mods.modified.values()) {
            if (change.what instanceof Folder) {
                if ((change.why & Change.PARENT) == 0 && (change.why & Change.NAME) == 0) {
                    continue;
                }
                Folder folder = (Folder) change.what;
                Folder oldFolder = (Folder) change.preModifyObj;
                if (oldFolder == null) {
                    ZimbraLog.filter.warn("Cannot determine the old folder name for %s.", folder.getName());
                    continue;
                }
                updateFilterRules(notification.mailboxAccount, folder, oldFolder.getPath());
            } else if (change.what instanceof Tag) {
                if ((change.why & Change.NAME) == 0) {
                    continue;
                }
                Tag tag = (Tag) change.what;
                Tag oldTag = (Tag) change.preModifyObj;
                if (oldTag == null) {
                    ZimbraLog.filter.warn("Cannot determine the old tag name for %s.", tag.getName());
                    continue;
                }
                updateFilterRules(notification.mailboxAccount, tag, oldTag.getName());
            }
        }
    }
    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.FOLDER || type == MailItem.Type.MOUNTPOINT) {
                Folder oldFolder = (Folder) entry.getValue().preModifyObj;
                if (oldFolder == null) {
                    ZimbraLog.filter.warn("Cannot determine the old folder name for %s.", entry.getKey());
                    continue;
                }
                updateFilterRules(notification.mailboxAccount, (Folder) null, oldFolder.getPath());
            } else if (type == MailItem.Type.TAG) {
                Tag oldTag = (Tag) entry.getValue().preModifyObj;
                updateFilterRules(notification.mailboxAccount, oldTag);
            }
        }
    }
}
Also used : MailItem(com.zimbra.cs.mailbox.MailItem) PendingModifications(com.zimbra.cs.session.PendingModifications) ModificationKey(com.zimbra.cs.session.PendingModifications.ModificationKey) Change(com.zimbra.cs.session.PendingModifications.Change) Tag(com.zimbra.cs.mailbox.Tag) Change(com.zimbra.cs.session.PendingModifications.Change) Folder(com.zimbra.cs.mailbox.Folder) Map(java.util.Map)

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