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