mirror of
https://github.com/sjlongland/tornado-gallery.git
synced 2025-09-13 16:43:16 +10:00
84 lines
2.5 KiB
Python
84 lines
2.5 KiB
Python
#!/usr/bin/env python
|
|
|
|
from time import time
|
|
from .cache import Cache
|
|
from cachefs.node import Node
|
|
|
|
|
|
class MetadataFile(object):
|
|
"""
|
|
A representation of a metadata file.
|
|
"""
|
|
def __init__(self, fs_node):
|
|
self._fs_node = fs_node
|
|
self._last_mtime = None
|
|
self._root_data = None
|
|
self._children_data = None
|
|
|
|
def _refresh(self):
|
|
meta_mtime = self._fs_node.stat.st_mtime
|
|
if (self._last_mtime is None) or (meta_mtime > self._last_mtime):
|
|
child = None
|
|
root_data = {}
|
|
children_data = {}
|
|
for line in open(self._fs_node.abs_path, 'rt'):
|
|
if '\t' not in line:
|
|
continue
|
|
|
|
(key, value) = line.split('\t', 1)
|
|
if key.startswith('.'):
|
|
# Either belongs to the root, or the last child.
|
|
if child is None:
|
|
dest = root_data
|
|
else:
|
|
dest = children_data.setdefault(child, {})
|
|
else:
|
|
# Name of a child; anything starting with . here
|
|
# now belongs to the child.
|
|
dest = root_data
|
|
child = key
|
|
|
|
if key in dest:
|
|
dest[key] += value
|
|
else:
|
|
dest[key] = value
|
|
|
|
self._root_data = root_data
|
|
self._children_data = children_data
|
|
self._last_mtime = meta_mtime
|
|
|
|
def __getitem__(self, key):
|
|
# Refresh metadata if needed
|
|
self._refresh()
|
|
|
|
# If key is a tuple, then it names a specific child.
|
|
if isinstance(key, tuple):
|
|
(child, key) = key
|
|
else:
|
|
# We are referencing the root
|
|
child = None
|
|
|
|
if child is None:
|
|
return self._root_data[key]
|
|
else:
|
|
return self._children_data[child][key]
|
|
|
|
|
|
class MetadataCache(Cache):
|
|
"""
|
|
Store the metadata for lots of files and keep them cached.
|
|
"""
|
|
|
|
def __init__(self, fs_cache, cache_duration=300.0, log=None):
|
|
super(MetadataCache, self).__init__(cache_duration=cache_duration,
|
|
log=log)
|
|
self._fs_cache = fs_cache
|
|
|
|
def _fetch(self, filename):
|
|
return MetadataFile(self._fs_cache[filename])
|
|
|
|
def __getitem__(self, filename):
|
|
if isinstance(filename, Node):
|
|
filename = filename.abs_path
|
|
return super(MetadataCache, self).__getitem__(filename)
|