SF bug #130306: statcache.py full of thread problems.

Fixed the thread races.  Function forget_dir was also utterly Unix-specific.
This commit is contained in:
Tim Peters 2001-01-28 05:07:00 +00:00
parent 64d42c5bb1
commit 0149e84af2
2 changed files with 40 additions and 40 deletions

View File

@ -3,73 +3,72 @@
There are functions to reset the cache or to selectively remove items.
"""
import os
import os as _os
from stat import *
# The cache.
# Keys are pathnames, values are `os.stat' outcomes.
#
cache = {}
# The cache. Keys are pathnames, values are os.stat outcomes.
# Remember that multiple threads may be calling this! So, e.g., that
# cache.has_key(path) returns 1 doesn't mean the cache will still contain
# path on the next line. Code defensively.
cache = {}
def stat(path):
"""Stat a file, possibly out of the cache."""
if cache.has_key(path):
return cache[path]
cache[path] = ret = os.stat(path)
ret = cache.get(path, None)
if ret is None:
cache[path] = ret = _os.stat(path)
return ret
def reset():
"""Reset the cache completely."""
global cache
cache = {}
"""Clear the cache."""
cache.clear()
# For thread saftey, always use forget() internally too.
def forget(path):
"""Remove a given item from the cache, if it exists."""
if cache.has_key(path):
try:
del cache[path]
except KeyError:
pass
def forget_prefix(prefix):
"""Remove all pathnames with a given prefix."""
n = len(prefix)
for path in cache.keys():
if path[:n] == prefix:
del cache[path]
if path.startswith(prefix):
forget(path)
def forget_dir(prefix):
"""Forget about a directory and all entries in it, but not about
entries in subdirectories."""
if prefix[-1:] == '/' and prefix != '/':
prefix = prefix[:-1]
forget(prefix)
if prefix[-1:] != '/':
prefix = prefix + '/'
n = len(prefix)
for path in cache.keys():
if path[:n] == prefix:
rest = path[n:]
if rest[-1:] == '/': rest = rest[:-1]
if '/' not in rest:
del cache[path]
"""Forget a directory and all entries except for entries in subdirs."""
# Remove trailing separator, if any. This is tricky to do in a
# x-platform way. For example, Windows accepts both / and \ as
# separators, and if there's nothing *but* a separator we want to
# preserve that this is the root. Only os.path has the platform
# knowledge we need.
from os.path import split, join
prefix = split(join(prefix, "xxx"))[0]
forget(prefix)
for path in cache.keys():
# First check that the path at least starts with the prefix, so
# that when it doesn't we can avoid paying for split().
if path.startswith(prefix) and split(path)[0] == prefix:
forget(path)
def forget_except_prefix(prefix):
"""Remove all pathnames except with a given prefix.
Normally used with prefix = '/' after a chdir()."""
n = len(prefix)
for path in cache.keys():
if path[:n] != prefix:
del cache[path]
Normally used with prefix = '/' after a chdir().
"""
for path in cache.keys():
if not path.startswith(prefix):
forget(path)
def isdir(path):
"""Check for directory."""
"""Return 1 if directory, else 0."""
try:
st = stat(path)
except os.error:
except _os.error:
return 0
return S_ISDIR(st[ST_MODE])

View File

@ -197,6 +197,7 @@ Andreas Jung
Bob Kahn
Tamito Kajiyama
Lou Kates
Randall Kern
Magnus Kessler
Lawrence Kesteloot
Vivek Khera