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();
}
}
}
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);
}
}
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();
}
}
};
}
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());
}
}
}
}
}
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;
}
Aggregations