Search in sources :

Example 11 with Session

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

the class ImapSessionManager method closeFolder.

void closeFolder(ImapSession session, boolean isUnregistering) {
    // detach session from handler and jettison session state from folder
    if (session.isInteractive()) {
        session.inactivate();
    }
    // no fancy stuff for search folders since they're always recalculated on load
    if (session.isVirtual()) {
        session.detach();
        return;
    }
    // checkpoint the folder data if desired
    if (SERIALIZE_ON_CLOSE) {
        try {
            // could use session.serialize() if we want to leave it in memory...
            ZimbraLog.imap.debug("Paging session during close: %s", session);
            session.unload(false);
        } catch (MailboxInMaintenanceException miMe) {
            if (ZimbraLog.imap.isDebugEnabled()) {
                ZimbraLog.imap.info("Mailbox in maintenance detected during close - will detach %s", session, miMe);
            } else {
                ZimbraLog.imap.info("Mailbox in maintenance detected during close - will detach %s", session);
            }
            session.detach();
            return;
        } catch (Exception e) {
            ZimbraLog.imap.warn("Skipping error while trying to serialize during close %s", session, e);
        }
    }
    if (isUnregistering) {
        return;
    }
    // recognize if we're not configured to allow sessions to hang around after end of SELECT
    if (TERMINATE_ON_CLOSE) {
        session.detach();
        return;
    }
    // if there are still other listeners on this folder, this session is unnecessary
    Mailbox mbox = session.getMailbox();
    if (mbox != null) {
        mbox.lock.lock();
        try {
            for (Session listener : mbox.getListeners(Session.Type.IMAP)) {
                ImapSession i4listener = (ImapSession) listener;
                if (i4listener != session && i4listener.getFolderId() == session.getFolderId()) {
                    ZimbraLog.imap.trace("more recent listener exists for folder.  Detaching %s", session);
                    session.detach();
                    recordAccess(i4listener);
                    return;
                }
            }
        } finally {
            mbox.lock.release();
        }
    }
}
Also used : Mailbox(com.zimbra.cs.mailbox.Mailbox) MailboxInMaintenanceException(com.zimbra.cs.mailbox.MailServiceException.MailboxInMaintenanceException) ServiceException(com.zimbra.common.service.ServiceException) MailboxInMaintenanceException(com.zimbra.cs.mailbox.MailServiceException.MailboxInMaintenanceException) Session(com.zimbra.cs.session.Session)

Example 12 with Session

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

the class Mailbox method commitCache.

private void commitCache(MailboxChange change) {
    if (change == null) {
        return;
    }
    ChangeNotification notification = null;
    // save for notifications (below)
    PendingModifications dirty = null;
    if (change.dirty != null && change.dirty.hasNotifications()) {
        assert (lock.isWriteLockedByCurrentThread());
        assert (currentChange().writeChange);
        dirty = change.dirty;
        change.dirty = new PendingModifications();
    }
    Session source = change.octxt == null ? null : change.octxt.getSession();
    assert (!change.hasChanges() || lock.isWriteLockedByCurrentThread());
    try {
        // the mailbox data has changed, so commit the changes
        if (change.sync != null) {
            mData.trackSync = change.sync;
        }
        if (change.imap != null) {
            mData.trackImap = change.imap;
        }
        if (change.size != MailboxChange.NO_CHANGE) {
            mData.size = change.size;
        }
        if (change.itemId != MailboxChange.NO_CHANGE) {
            mData.lastItemId = change.itemId;
        }
        if (change.contacts != MailboxChange.NO_CHANGE) {
            mData.contacts = change.contacts;
        }
        if (change.changeId != MailboxChange.NO_CHANGE && change.changeId > mData.lastChangeId) {
            mData.lastChangeId = change.changeId;
            mData.lastChangeDate = change.timestamp;
        }
        if (change.accessed != MailboxChange.NO_CHANGE) {
            mData.lastWriteDate = change.accessed;
        }
        if (change.recent != MailboxChange.NO_CHANGE) {
            mData.recentMessages = change.recent;
        }
        if (change.config != null) {
            if (change.config.getSecond() == null) {
                if (mData.configKeys != null) {
                    mData.configKeys.remove(change.config.getFirst());
                }
            } else {
                if (mData.configKeys == null) {
                    mData.configKeys = new HashSet<String>(1);
                }
                mData.configKeys.add(change.config.getFirst());
            }
        }
        if (change.deletes != null && change.deletes.blobs != null) {
            // remove cached messages
            for (String digest : change.deletes.blobDigests) {
                MessageCache.purge(digest);
            }
        }
        // committed changes, so notify any listeners
        if (dirty != null && dirty.hasNotifications()) {
            try {
                // try to get a copy of the changeset that *isn't* live
                dirty = snapshotModifications(dirty);
            } catch (ServiceException e) {
                ZimbraLog.mailbox.warn("error copying notifications; will notify with live set", e);
            }
            try {
                notification = new ChangeNotification(getAccount(), dirty, change.octxt, mData.lastChangeId, change.getOperation(), change.timestamp);
            } catch (ServiceException e) {
                ZimbraLog.mailbox.warn("error getting account for the mailbox", e);
            }
        }
    } catch (RuntimeException e) {
        ZimbraLog.mailbox.error("ignoring error during cache commit", e);
    } finally {
        // keep our MailItem cache at a reasonable size
        trimItemCache();
        // make sure we're ready for the next change
        change.reset();
    }
    if (notification != null) {
        for (Session session : mListeners) {
            try {
                session.notifyPendingChanges(notification.mods, notification.lastChangeId, source);
            } catch (RuntimeException e) {
                ZimbraLog.mailbox.error("ignoring error during notification", e);
            }
        }
        // send to the message channel
        DbConnection conn = null;
        try {
            if (Zimbra.isAlwaysOn()) {
                conn = DbPool.getConnection();
                List<String> serverids = DbSession.get(conn, getId());
                for (String serverid : serverids) {
                    Server server = Provisioning.getInstance().getServerById(serverid);
                    if (server.isLocalServer()) {
                        continue;
                    }
                    MailboxNotification ntfn = MailboxNotification.create(getAccountId(), mData.lastChangeId, dirty.getSerializedBytes());
                    MessageChannel.getInstance().sendMessage(server, ntfn);
                }
            }
        } catch (ServiceException e) {
            ZimbraLog.session.warn("unable to get target server", e);
        } catch (MessageChannelException e) {
            ZimbraLog.session.warn("unable to create MailboxNotification", e);
            return;
        } catch (IOException e) {
            ZimbraLog.session.warn("unable to create MailboxNotification", e);
            return;
        } finally {
            if (conn != null) {
                conn.closeQuietly();
            }
        }
        MailboxListener.notifyListeners(notification);
    }
}
Also used : MessageChannelException(com.zimbra.cs.iochannel.MessageChannelException) Server(com.zimbra.cs.account.Server) MailboxNotification(com.zimbra.cs.iochannel.MailboxNotification) ChangeNotification(com.zimbra.cs.mailbox.MailboxListener.ChangeNotification) IOException(java.io.IOException) DbConnection(com.zimbra.cs.db.DbPool.DbConnection) PendingModifications(com.zimbra.cs.session.PendingModifications) AccountServiceException(com.zimbra.cs.account.AccountServiceException) ServiceException(com.zimbra.common.service.ServiceException) DbSession(com.zimbra.cs.db.DbSession) Session(com.zimbra.cs.session.Session) SoapSession(com.zimbra.cs.session.SoapSession)

Example 13 with Session

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

the class CrossServerNotification method getHandler.

@Override
public MessageHandler getHandler() {
    return new MessageHandler() {

        @Override
        public void handle(Message m, String clientId) {
            if (!(m instanceof CrossServerNotification)) {
                return;
            }
            CrossServerNotification message = (CrossServerNotification) m;
            Collection<Session> sessions = SessionCache.getSoapSessions(m.getRecipientAccountId());
            if (sessions == null) {
                log.warn("no active sessions for account %s", m.getRecipientAccountId());
                return;
            }
            RemoteNotifications soapNtfn = null, jsonNtfn = null;
            try {
                org.dom4j.Document dom = org.dom4j.DocumentHelper.parseText(message.getPayload());
                soapNtfn = new RemoteNotifications(Element.convertDOM(dom.getRootElement(), XMLElement.mFactory));
                jsonNtfn = new RemoteNotifications(Element.convertDOM(dom.getRootElement(), JSONElement.mFactory));
            } catch (DocumentException e) {
                log.warn("cannot parse notification from %s", clientId, e);
                return;
            }
            for (Session session : sessions) {
                log.debug("notifying session %s", session.toString());
                SoapSession ss = (SoapSession) session;
                SoapProtocol responseProtocol = ss.getResponseProtocol();
                if (responseProtocol == SoapProtocol.Soap11 || responseProtocol == SoapProtocol.Soap12) {
                    ss.addRemoteNotifications(soapNtfn);
                } else if (responseProtocol == SoapProtocol.SoapJS) {
                    ss.addRemoteNotifications(jsonNtfn);
                }
                ss.forcePush();
            }
        }
    };
}
Also used : SoapSession(com.zimbra.cs.session.SoapSession) RemoteNotifications(com.zimbra.cs.session.SoapSession.RemoteNotifications) DocumentException(org.dom4j.DocumentException) SoapProtocol(com.zimbra.common.soap.SoapProtocol) SoapSession(com.zimbra.cs.session.SoapSession) Session(com.zimbra.cs.session.Session)

Example 14 with Session

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

the class Mailbox method snapshotCounts.

void snapshotCounts() throws ServiceException {
    // for write ops, update the "new messages" count in the DB appropriately
    OperationContext octxt = currentChange().octxt;
    RedoableOp player = currentChange().getRedoPlayer();
    RedoableOp recorder = currentChange().recorder;
    if (recorder != null && (player == null || (octxt != null && !octxt.isRedo()))) {
        assert (currentChange().writeChange);
        boolean isNewMessage = recorder.getOperation() == MailboxOperation.CreateMessage;
        if (isNewMessage) {
            CreateMessage cm = (CreateMessage) recorder;
            if (cm.getFolderId() == ID_FOLDER_SPAM || cm.getFolderId() == ID_FOLDER_TRASH) {
                isNewMessage = false;
            } else if ((cm.getFlags() & NON_DELIVERY_FLAGS) != 0) {
                isNewMessage = false;
            } else if (octxt != null && octxt.getSession() != null && !octxt.isDelegatedRequest(this)) {
                isNewMessage = false;
            }
            if (isNewMessage) {
                String folderList = getAccount().getPrefMailFoldersCheckedForNewMsgIndicator();
                if (folderList != null) {
                    String[] folderIds = folderList.split(",");
                    isNewMessage = false;
                    for (int i = 0; i < folderIds.length; i++) {
                        if (cm.getFolderId() == Integer.parseInt(folderIds[i])) {
                            isNewMessage = true;
                            break;
                        }
                    }
                }
            }
        }
        if (isNewMessage) {
            currentChange().recent = mData.recentMessages + 1;
        } else if (octxt != null && mData.recentMessages != 0) {
            Session s = octxt.getSession();
            if (s instanceof SoapSession || (s instanceof SoapSession.DelegateSession && ((SoapSession.DelegateSession) s).getParentSession().isOfflineSoapSession())) {
                currentChange().recent = 0;
            }
        }
    }
    if (currentChange().isMailboxRowDirty(mData)) {
        assert (currentChange().writeChange);
        if (currentChange().recent != MailboxChange.NO_CHANGE) {
            ZimbraLog.mailbox.debug("setting recent count to %d", currentChange().recent);
        }
        DbMailbox.updateMailboxStats(this);
    }
    boolean foldersTagsDirty = false;
    if (currentChange().dirty != null && currentChange().dirty.hasNotifications()) {
        assert (currentChange().writeChange);
        if (currentChange().dirty.created != null) {
            for (MailItem item : currentChange().dirty.created.values()) {
                if (item instanceof Folder) {
                    foldersTagsDirty = true;
                    if (item.getSize() != 0) {
                        ((Folder) item).saveFolderCounts(false);
                    }
                } else if (item instanceof Tag) {
                    foldersTagsDirty = true;
                    if (item.isUnread()) {
                        ((Tag) item).saveTagCounts();
                    }
                }
            }
        }
        if (currentChange().dirty.modified != null) {
            for (Change change : currentChange().dirty.modified.values()) {
                if (change.what instanceof Folder) {
                    foldersTagsDirty = true;
                    if ((change.why & (Change.UNREAD | Change.SIZE)) != 0) {
                        ((Folder) change.what).saveFolderCounts(false);
                    }
                } else if (change.what instanceof Tag) {
                    foldersTagsDirty = true;
                    if ((change.why & Change.UNREAD | Change.SIZE) != 0) {
                        ((Tag) change.what).saveTagCounts();
                    }
                } else if ((change.what instanceof MailItem)) {
                    if (change.what instanceof Conversation) {
                        uncache((MailItem) change.what);
                    } else {
                        cache((MailItem) change.what);
                    }
                }
            }
        }
        if (currentChange().dirty.deleted != null) {
            for (Change change : currentChange().dirty.deleted.values()) {
                if (change.what instanceof Folder || change.what instanceof Tag) {
                    foldersTagsDirty = true;
                    break;
                }
            }
        }
        if (foldersTagsDirty) {
            cacheFoldersTagsToMemcached();
        }
    }
    if (DebugConfig.checkMailboxCacheConsistency && currentChange().dirty != null && currentChange().dirty.hasNotifications()) {
        if (currentChange().dirty.created != null) {
            for (MailItem item : currentChange().dirty.created.values()) {
                DbMailItem.consistencyCheck(item, item.mData, item.encodeMetadata().toString());
            }
        }
        if (currentChange().dirty.modified != null) {
            for (Change change : currentChange().dirty.modified.values()) {
                if (change.what instanceof MailItem) {
                    MailItem item = (MailItem) change.what;
                    DbMailItem.consistencyCheck(item, item.mData, item.encodeMetadata().toString());
                }
            }
        }
    }
}
Also used : Change(com.zimbra.cs.session.PendingModifications.Change) CreateFolder(com.zimbra.cs.redolog.op.CreateFolder) ZFolder(com.zimbra.client.ZFolder) RefreshMountpoint(com.zimbra.cs.redolog.op.RefreshMountpoint) TargetConstraint(com.zimbra.cs.mailbox.MailItem.TargetConstraint) CreateMountpoint(com.zimbra.cs.redolog.op.CreateMountpoint) DbMailItem(com.zimbra.cs.db.DbMailItem) SoapSession(com.zimbra.cs.session.SoapSession) RedoableOp(com.zimbra.cs.redolog.op.RedoableOp) CreateMessage(com.zimbra.cs.redolog.op.CreateMessage) AlterItemTag(com.zimbra.cs.redolog.op.AlterItemTag) CreateTag(com.zimbra.cs.redolog.op.CreateTag) DbTag(com.zimbra.cs.db.DbTag) DbSession(com.zimbra.cs.db.DbSession) Session(com.zimbra.cs.session.Session) SoapSession(com.zimbra.cs.session.SoapSession)

Example 15 with Session

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

the class EndSession method handle.

@Override
public Element handle(Element request, Map<String, Object> context) throws ServiceException {
    ZimbraSoapContext zsc = getZimbraSoapContext(context);
    if (zsc.hasSession()) {
        Session s = getSession(zsc);
        endSession(s);
    }
    boolean clearCookies = request.getAttributeBool(AccountConstants.A_LOG_OFF, false);
    if (clearCookies || getAuthenticatedAccount(zsc).isForceClearCookies()) {
        context.put(SoapServlet.INVALIDATE_COOKIES, true);
        try {
            zsc.getAuthToken().deRegister();
        } catch (AuthTokenException e) {
            throw ServiceException.FAILURE("Failed to de-register an auth token", e);
        }
    }
    Element response = zsc.createElement(AccountConstants.END_SESSION_RESPONSE);
    return response;
}
Also used : ZimbraSoapContext(com.zimbra.soap.ZimbraSoapContext) AuthTokenException(com.zimbra.cs.account.AuthTokenException) Element(com.zimbra.common.soap.Element) Session(com.zimbra.cs.session.Session)

Aggregations

Session (com.zimbra.cs.session.Session)21 SoapSession (com.zimbra.cs.session.SoapSession)11 ServiceException (com.zimbra.common.service.ServiceException)9 Element (com.zimbra.common.soap.Element)7 Mailbox (com.zimbra.cs.mailbox.Mailbox)5 AccountServiceException (com.zimbra.cs.account.AccountServiceException)4 Server (com.zimbra.cs.account.Server)4 AdminSession (com.zimbra.cs.session.AdminSession)4 AuthToken (com.zimbra.cs.account.AuthToken)3 Provisioning (com.zimbra.cs.account.Provisioning)3 DbSession (com.zimbra.cs.db.DbSession)3 ZFolder (com.zimbra.client.ZFolder)2 Account (com.zimbra.cs.account.Account)2 AuthTokenException (com.zimbra.cs.account.AuthTokenException)2 Folder (com.zimbra.cs.mailbox.Folder)2 TargetConstraint (com.zimbra.cs.mailbox.MailItem.TargetConstraint)2 ZimbraSoapContext (com.zimbra.soap.ZimbraSoapContext)2 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 HttpServletRequest (javax.servlet.http.HttpServletRequest)2