Search in sources :

Example 1 with AccountKey

use of com.zimbra.cs.mailbox.calendar.cache.AccountKey in project zm-mailbox by Zimbra.

the class DavServlet method checkCachedResponse.

private CacheStates checkCachedResponse(DavContext ctxt, Account authUser) throws IOException, DavException, ServiceException {
    CacheStates cache = new CacheStates();
    // Are we running with cache enabled, and is this a cachable CalDAV ctag request?
    if (cache.ctagCacheEnabled && isCtagRequest(ctxt)) {
        cache.ctagResponseCache = CalendarCacheManager.getInstance().getCtagResponseCache();
        cache.gzipAccepted = ctxt.isGzipAccepted();
        String targetUser = ctxt.getUser();
        Account targetAcct = Provisioning.getInstance().get(AccountBy.name, targetUser);
        boolean ownAcct = targetAcct != null && targetAcct.getId().equals(authUser.getId());
        String parentPath = ctxt.getPath();
        KnownUserAgent knownUA = ctxt.getKnownUserAgent();
        // Use cache only when requesting own account and User-Agent and path are well-defined.
        if (ownAcct && knownUA != null && parentPath != null) {
            AccountKey accountKey = new AccountKey(targetAcct.getId());
            AccountCtags allCtagsData = CalendarCacheManager.getInstance().getCtags(accountKey);
            // We can't use cache if it doesn't have data for this user.
            if (allCtagsData != null) {
                boolean validRoot = true;
                int rootFolderId = Mailbox.ID_FOLDER_USER_ROOT;
                if (!"/".equals(parentPath)) {
                    CtagInfo calInfoRoot = allCtagsData.getByPath(parentPath);
                    if (calInfoRoot != null)
                        rootFolderId = calInfoRoot.getId();
                    else
                        validRoot = false;
                }
                if (validRoot) {
                    // Is there a previously cached response?
                    cache.ctagCacheKey = new CtagResponseCacheKey(targetAcct.getId(), knownUA.toString(), rootFolderId);
                    CtagResponseCacheValue ctagResponse = cache.ctagResponseCache.get(cache.ctagCacheKey);
                    if (ctagResponse != null) {
                        // Found a cached response.  Let's check if it's stale.
                        // 1. If calendar list has been updated since, cached response is no good.
                        String currentCalListVer = allCtagsData.getVersion();
                        if (currentCalListVer.equals(ctagResponse.getVersion())) {
                            // 2. We have to examine ctags of individual calendars.
                            boolean cacheHit = true;
                            Map<Integer, String> oldCtags = ctagResponse.getCtags();
                            // We're good if ctags from before are unchanged.
                            for (Map.Entry<Integer, String> entry : oldCtags.entrySet()) {
                                int calFolderId = entry.getKey();
                                String ctag = entry.getValue();
                                CtagInfo calInfoCurr = allCtagsData.getById(calFolderId);
                                if (calInfoCurr == null) {
                                    // Just a sanity check.  The cal list version check should have
                                    // already taken care of added/removed calendars.
                                    cacheHit = false;
                                    break;
                                }
                                if (!ctag.equals(calInfoCurr.getCtag())) {
                                    // A calendar has been modified.  Stale!
                                    cacheHit = false;
                                    break;
                                }
                            }
                            if (cacheHit) {
                                ZimbraLog.dav.debug("CTAG REQUEST CACHE HIT");
                                // All good.  Send cached response.
                                ctxt.setStatus(DavProtocol.STATUS_MULTI_STATUS);
                                HttpServletResponse response = ctxt.getResponse();
                                response.setStatus(ctxt.getStatus());
                                response.setContentType(DavProtocol.DAV_CONTENT_TYPE);
                                byte[] respData = ctagResponse.getResponseBody();
                                response.setContentLength(ctagResponse.getRawLength());
                                byte[] unzipped = null;
                                if (ZimbraLog.dav.isDebugEnabled() || (ctagResponse.isGzipped() && !cache.gzipAccepted)) {
                                    if (ctagResponse.isGzipped()) {
                                        ByteArrayInputStream bais = new ByteArrayInputStream(respData);
                                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
                                        GZIPInputStream gzis = null;
                                        try {
                                            gzis = new GZIPInputStream(bais, respData.length);
                                            ByteUtil.copy(gzis, false, baos, true);
                                        } finally {
                                            ByteUtil.closeStream(gzis);
                                        }
                                        unzipped = baos.toByteArray();
                                    } else {
                                        unzipped = respData;
                                    }
                                    if (ZimbraLog.dav.isDebugEnabled()) {
                                        ZimbraLog.dav.debug("RESPONSE:\n" + new String(unzipped, "UTF-8"));
                                    }
                                }
                                if (!ctagResponse.isGzipped()) {
                                    response.getOutputStream().write(respData);
                                } else {
                                    if (cache.gzipAccepted) {
                                        response.addHeader(DavProtocol.HEADER_CONTENT_ENCODING, DavProtocol.ENCODING_GZIP);
                                        response.getOutputStream().write(respData);
                                    } else {
                                        assert (unzipped != null);
                                        response.getOutputStream().write(unzipped);
                                    }
                                }
                                // Tell the context the response has been sent.
                                ctxt.responseSent();
                            }
                        }
                    }
                    if (!ctxt.isResponseSent()) {
                        // Cache miss, or cached response is stale.  We're gonna have to generate the
                        // response the hard way.  Capture a snapshot of current state of calendars
                        // to attach to the response to be cached later.
                        cache.cacheThisCtagResponse = true;
                        cache.acctVerSnapshot = allCtagsData.getVersion();
                        cache.ctagsSnapshot = new HashMap<Integer, String>();
                        Collection<CtagInfo> childCals = allCtagsData.getChildren(rootFolderId);
                        if (rootFolderId != Mailbox.ID_FOLDER_USER_ROOT) {
                            CtagInfo ctagRoot = allCtagsData.getById(rootFolderId);
                            if (ctagRoot != null)
                                cache.ctagsSnapshot.put(rootFolderId, ctagRoot.getCtag());
                        }
                        for (CtagInfo calInfo : childCals) {
                            cache.ctagsSnapshot.put(calInfo.getId(), calInfo.getCtag());
                        }
                    }
                }
            }
            if (!ctxt.isResponseSent())
                ZimbraLog.dav.debug("CTAG REQUEST CACHE MISS");
        }
    }
    return cache;
}
Also used : Account(com.zimbra.cs.account.Account) AccountCtags(com.zimbra.cs.mailbox.calendar.cache.AccountCtags) HttpServletResponse(javax.servlet.http.HttpServletResponse) ByteArrayOutputStream(java.io.ByteArrayOutputStream) CtagResponseCacheKey(com.zimbra.cs.mailbox.calendar.cache.CtagResponseCache.CtagResponseCacheKey) Mountpoint(com.zimbra.cs.mailbox.Mountpoint) CtagInfo(com.zimbra.cs.mailbox.calendar.cache.CtagInfo) GZIPInputStream(java.util.zip.GZIPInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) KnownUserAgent(com.zimbra.cs.dav.DavContext.KnownUserAgent) AccountKey(com.zimbra.cs.mailbox.calendar.cache.AccountKey) Map(java.util.Map) HashMap(java.util.HashMap) CtagResponseCacheValue(com.zimbra.cs.mailbox.calendar.cache.CtagResponseCache.CtagResponseCacheValue)

Aggregations

Account (com.zimbra.cs.account.Account)1 KnownUserAgent (com.zimbra.cs.dav.DavContext.KnownUserAgent)1 Mountpoint (com.zimbra.cs.mailbox.Mountpoint)1 AccountCtags (com.zimbra.cs.mailbox.calendar.cache.AccountCtags)1 AccountKey (com.zimbra.cs.mailbox.calendar.cache.AccountKey)1 CtagInfo (com.zimbra.cs.mailbox.calendar.cache.CtagInfo)1 CtagResponseCacheKey (com.zimbra.cs.mailbox.calendar.cache.CtagResponseCache.CtagResponseCacheKey)1 CtagResponseCacheValue (com.zimbra.cs.mailbox.calendar.cache.CtagResponseCache.CtagResponseCacheValue)1 ByteArrayInputStream (java.io.ByteArrayInputStream)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 HashMap (java.util.HashMap)1 Map (java.util.Map)1 GZIPInputStream (java.util.zip.GZIPInputStream)1 HttpServletResponse (javax.servlet.http.HttpServletResponse)1