2021SC@SDUSC
lock_storage.py:为“LockManager”实现两个存储提供程序。 这里定义了两种可选的锁存储类:一种是内存中的 (基于 dict),以及一种使用搁置的持久性低性能变体。
文件由LockStorageDict、LockStorageShelve两个类组成。
类LockStorageDict
使用字典的内存中锁管理器存储实现。 R/W 访问由 thread.lock 对象保护。 此外,为了使其与搁置字典一起使用,修改字典 成员通过重新分配完成,我们调用 _flush() 方法。 这显然不是持久的,但在某些情况下应该足够了。
类中函数get(self,token)负责返回一个令牌的锁字典。 如果锁不存在或已过期,则返回 None。 副作用:如果锁已过期,则会清除它并返回 None。
主要代码
def get(self, token):
self._lock.acquire_read()
try:
lock = self._dict.get(token)
if lock is None:
# Lock not found: purge dangling URL2TOKEN entries
_logger.debug("Lock purged dangling: {}".format(token))
self.delete(token)
return None
expire = float(lock["expire"])
if expire >= 0 and expire < time.time():
_logger.debug(
"Lock timed-out({}): {}".format(expire, lock_string(lock))
)
self.delete(token)
return None
return lock
finally:
self._lock.release()
函数create(self, path, lock):为资源路径创建直接锁。返回: 新的唯一锁定令牌。
注意:返回时可能会修改锁字典:
- lock['root'] 被忽略并设置为规范化的 <path>
- lock['timeout'] 可能被标准化并且比请求的短
代码
def create(self, path, lock):
"""Create a direct lock for a resource path.
path:
Normalized path (utf8 encoded string, no trailing '/')
lock:
lock dictionary, without a token entry
Returns:
New unique lock token.: <lock
**Note:** the lock dictionary may be modified on return:
- lock['root'] is ignored and set to the normalized <path>
- lock['timeout'] may be normalized and shorter than requested
- lock['token'] is added
"""
self._lock.acquire_write()
try:
# We expect only a lock definition, not an existing lock
assert lock.get("token") is None
assert lock.get("expire") is None, "Use timeout instead of expire"
assert path and "/" in path
# Normalize root: /foo/bar
org_path = path
path = normalize_lock_root(path)
lock["root"] = path
# Normalize timeout from ttl to expire-date
timeout = float(lock.get("timeout"))
if timeout is None:
timeout = LockStorageDict.LOCK_TIME_OUT_DEFAULT
elif timeout < 0 or timeout > LockStorageDict.LOCK_TIME_OUT_MAX:
timeout = LockStorageDict.LOCK_TIME_OUT_MAX
lock["timeout"] = timeout
lock["expire"] = time.time() + timeout
validate_lock(lock)
token = generate_lock_token()
lock["token"] = token
# Store lock
self._dict[token] = lock
# Store locked path reference
key = "URL2TOKEN:{}".format(path)
if key not in self._dict:
self._dict[key] = [token]
else:
# Note: Shelve dictionary returns copies, so we must reassign
# values:
tokList = self._dict[key]
tokList.append(token)
self._dict[key] = tokList
self._flush()
_logger.debug(
"LockStorageDict.set({!r}): {}".format(org_path, lock_string(lock))
)
return lock
finally:
self._lock.release()
函数refresh(self, token, timeout):修改现有锁的超时。 token: 有效的锁定令牌。 timeout: 以秒为单位的建议生命周期(-1 表示无限)。 实际到期时间可能比要求的要短! 返回: 锁字典。 如果令牌无效,则引发 ValueError
代码
assert token in self._dict, "Lock must exist"
assert timeout == -1 or timeout > 0
if timeout < 0 or timeout > LockStorageDict.LOCK_TIME_OUT_MAX:
timeout = LockStorageDict.LOCK_TIME_OUT_MAX
self._lock.acquire_write()
try:
# Note: shelve dictionary returns copies, so we must reassign
# values:
lock = self._dict[token]
lock["timeout"] = timeout
lock["expire"] = time.time() + timeout
self._dict[token] = lock
self._flush()
finally:
self._lock.release()
return lock
函数get_lock_list(self, path, include_root, include_children, token_only):返回 <path> 的直接锁列表。 过期的锁*不会*返回(但可能会被清除)。
path: 规范化路径(utf8 编码字符串,没有尾随 '/')
include_root: 错误:不要添加 <path> 锁(只有在 include_children 时才有意义 是真的)。
include_children: True:还要检查现有锁的所有子路径。
token_only: True:仅返回令牌列表。 这可能会实施 一些供应商更有效。
返回: 有效锁字典列表(可能为空)
类LockStorageShelve使用搁置的低性能锁管理器实现。
主要代码
def _flush(self):
"""Write persistent dictionary to disc."""
_logger.debug("_flush()")
self._lock.acquire_write() # TODO: read access is enough?
try:
self._dict.sync()
finally:
self._lock.release()
def clear(self):
"""Delete all entries."""
self._lock.acquire_write() # TODO: read access is enough?
try:
was_closed = self._dict is None
if was_closed:
self.open()
if len(self._dict):
self._dict.clear()
self._dict.sync()
if was_closed:
self.close()
finally:
self._lock.release()
文件lock_storage_redis.py由类LockStorageRedis组成。
类LockStorageRedis使用 redis 的锁管理器实现!
函数refresh(self, token, timeout)修改现有锁的超时。 token: 有效的锁定令牌。 timeout: 以秒为单位的建议生命周期(-1 表示无限)。 实际到期时间可能比要求的要短! 返回: 锁字典。 如果令牌无效,则引发 ValueError。
代码
def refresh(self, token, timeout):
"""Modify an existing lock's timeout.
token:
Valid lock token.
timeout:
Suggested lifetime in seconds (-1 for infinite).
The real expiration time may be shorter than requested!
Returns:
Lock dictionary.
Raises ValueError, if token is invalid.
"""
assert self._redis.exists(self._redis_lock_prefix.format(token))
assert timeout == -1 or timeout > 0
if timeout < 0 or timeout > LockStorageRedis.LOCK_TIME_OUT_MAX:
timeout = LockStorageRedis.LOCK_TIME_OUT_MAX
# Note: shelve dictionary returns copies, so we must reassign
# values:
lock = pickle.loads(self._redis.get(self._redis_lock_prefix.format(token)))
lock["timeout"] = timeout
lock["expire"] = time.time() + timeout
self._redis.set(
self._redis_lock_prefix.format(token), pickle.dumps(lock), ex=int(timeout)
)
self._flush()
return lock
文件middleware.py:抽象基础中间件类(可选使用)
由类BaseMiddleware组成。抽象基中间件类(可选)。 注意:这是一个方便的类,*可能*用于实现 WsgiDAV 中间件。这不是一个要求:任何实现 WSGI 规范可以添加到堆栈中。
WsgiDAV 中的派生类包括: wsgidav.dir_browser.WsgiDavDirBrowser wsgidav.debug_filter.WsgiDavDebugFilter
wsgidav.error_printer.ErrorPrinter
wsgidav.http_authenticator.HTTPAuthenticator
wsgidav.request_resolver.RequestResolver