Package flumotion :: Package component :: Package misc :: Package httpserver :: Package httpcached :: Module strategy_basic
[hide private]

Source Code for Module flumotion.component.misc.httpserver.httpcached.strategy_basic

  1  # -*- Mode: Python; test-case-name: flumotion.test.test_component_providers -*- 
  2  # vi:si:et:sw=4:sts=4:ts=4 
  3   
  4  # Flumotion - a streaming media server 
  5  # Copyright (C) 2004,2005,2006,2007,2008,2009 Fluendo, S.L. 
  6  # Copyright (C) 2010,2011 Flumotion Services, S.A. 
  7  # All rights reserved. 
  8  # 
  9  # This file may be distributed and/or modified under the terms of 
 10  # the GNU Lesser General Public License version 2.1 as published by 
 11  # the Free Software Foundation. 
 12  # This file is distributed without any warranty; without even the implied 
 13  # warranty of merchantability or fitness for a particular purpose. 
 14  # See "LICENSE.LGPL" in the source distribution for more information. 
 15  # 
 16  # Headers in this file shall remain intact. 
 17   
 18  import stat 
 19   
 20  from twisted.internet import defer 
 21   
 22  from flumotion.common import log 
 23   
 24  from flumotion.component.misc.httpserver import fileprovider 
 25  from flumotion.component.misc.httpserver import cachestats 
 26  from flumotion.component.misc.httpserver.httpcached import common 
 27  from flumotion.component.misc.httpserver.httpcached import strategy_base 
 28   
 29  LOG_CATEGORY = "basic-caching" 
 30   
 31  EXPIRE_CHECK_TTL = 3 
 32   
 33   
34 -class CachingStrategy(strategy_base.CachingStrategy):
35 """ 36 Simplistic caching strategy where all requested streams 37 are cached when requested. 38 39 On each cache-miss, a caching session is created and started right away. 40 41 When a cached file expire, a new session is created with the condition 42 that it has been modified. If not the cached file is used 43 and keep alive, if it succeed the cached file is deleted 44 and a new caching session is created and started. 45 46 Updates the caching statistics. 47 """ 48 49 logCategory = LOG_CATEGORY 50
51 - def __init__(self, cachemgr, reqmgr, ttl):
52 strategy_base.CachingStrategy.__init__(self, cachemgr, reqmgr, ttl)
53
54 - def _onCacheMiss(self, url, stats):
55 session = strategy_base.CachingSession(self, url, self.cachemgr.stats) 56 session.cache() 57 d = session.waitStarted() 58 d.addCallbacks(self._cbCreateSource, self._filterErrors, 59 callbackArgs=(stats, )) 60 return d
61
62 - def _onCacheOutdated(self, url, identifier, cachedFile, stats):
63 self.log("Checking if resource is outdated '%s'", url) 64 mtime = cachedFile.stat.st_mtime 65 sess = strategy_base.CachingSession(self, url, 66 self.cachemgr.stats, ifModifiedSince=mtime) 67 sess.cache() 68 sess.checkModified = True 69 d = sess.waitStarted() 70 args = (url, identifier, cachedFile, stats) 71 d.addCallbacks(self._reallyOutdated, self._maybeNotOutdated, 72 callbackArgs=args, errbackArgs=args) 73 return d
74
75 - def _reallyOutdated(self, session, url, identifier, cachedFile, stats):
76 self.debug("Resource outdated, caching the new one for '%s'", url) 77 session.checkModified = False 78 cachedFile.unlink() 79 cachedFile.close() 80 stats.onCacheOutdated() 81 stats.onStarted(session.size, cachestats.CACHE_MISS) 82 return strategy_base.RemoteSource(session, stats)
83
84 - def _maybeNotOutdated(self, failure, url, identifier, cachedFile, stats):
85 if failure.check(strategy_base.ConditionError): 86 # Not outdated, so we refresh the TTL 87 self.log("Resource not outdated, keep using " 88 "the cached one for '%s'", url) 89 self.keepCacheAlive(identifier) 90 stats.onStarted(cachedFile.stat[stat.ST_SIZE], 91 cachestats.CACHE_HIT) 92 return strategy_base.CachedSource(identifier, url, 93 cachedFile, stats) 94 95 if failure.check(fileprovider.NotFoundError, fileprovider.AccessError): 96 # The file has been deleted or its rights have been revoked 97 self.debug("Resource deleted or forbidden, removing cached file") 98 cachedFile.close() 99 return failure 100 101 if failure.check(fileprovider.FileError): 102 self.warning("Cached file expiration check fail, " 103 "using cached file anyway: %s", 104 failure.getErrorMessage()) 105 # Use a fixed small ttl to prevent doing an expiration check 106 # for all the files if the resource server is down. 107 self.keepCacheAlive(identifier, EXPIRE_CHECK_TTL) 108 stats.onStarted(cachedFile.stat[stat.ST_SIZE], 109 cachestats.CACHE_HIT) 110 return strategy_base.CachedSource(identifier, url, 111 cachedFile, stats) 112 113 cachedFile.close() 114 return failure
115
116 - def _filterErrors(self, failure):
117 if failure.check(strategy_base.ConditionError): 118 raise fileprovider.FileError(failure.getErrorMessage()) 119 return failure
120
121 - def _cbCreateSource(self, session, stats):
124