forked from KEMT/zpwiki
137 lines
4.5 KiB
Python
137 lines
4.5 KiB
Python
import gzip
|
|
|
|
from diskcache import FanoutCache, Disk
|
|
from diskcache.core import BytesType, MODE_BINARY, BytesIO
|
|
|
|
from util.logconf import logging
|
|
log = logging.getLogger(__name__)
|
|
# log.setLevel(logging.WARN)
|
|
log.setLevel(logging.INFO)
|
|
# log.setLevel(logging.DEBUG)
|
|
|
|
|
|
class GzipDisk(Disk):
|
|
def store(self, value, read, key=None):
|
|
"""
|
|
Override from base class diskcache.Disk.
|
|
|
|
Chunking is due to needing to work on pythons < 2.7.13:
|
|
- Issue #27130: In the "zlib" module, fix handling of large buffers
|
|
(typically 2 or 4 GiB). Previously, inputs were limited to 2 GiB, and
|
|
compression and decompression operations did not properly handle results of
|
|
2 or 4 GiB.
|
|
|
|
:param value: value to convert
|
|
:param bool read: True when value is file-like object
|
|
:return: (size, mode, filename, value) tuple for Cache table
|
|
"""
|
|
# pylint: disable=unidiomatic-typecheck
|
|
if type(value) is BytesType:
|
|
if read:
|
|
value = value.read()
|
|
read = False
|
|
|
|
str_io = BytesIO()
|
|
gz_file = gzip.GzipFile(mode='wb', compresslevel=1, fileobj=str_io)
|
|
|
|
for offset in range(0, len(value), 2**30):
|
|
gz_file.write(value[offset:offset+2**30])
|
|
gz_file.close()
|
|
|
|
value = str_io.getvalue()
|
|
|
|
return super(GzipDisk, self).store(value, read)
|
|
|
|
|
|
def fetch(self, mode, filename, value, read):
|
|
"""
|
|
Override from base class diskcache.Disk.
|
|
|
|
Chunking is due to needing to work on pythons < 2.7.13:
|
|
- Issue #27130: In the "zlib" module, fix handling of large buffers
|
|
(typically 2 or 4 GiB). Previously, inputs were limited to 2 GiB, and
|
|
compression and decompression operations did not properly handle results of
|
|
2 or 4 GiB.
|
|
|
|
:param int mode: value mode raw, binary, text, or pickle
|
|
:param str filename: filename of corresponding value
|
|
:param value: database value
|
|
:param bool read: when True, return an open file handle
|
|
:return: corresponding Python value
|
|
"""
|
|
value = super(GzipDisk, self).fetch(mode, filename, value, read)
|
|
|
|
if mode == MODE_BINARY:
|
|
str_io = BytesIO(value)
|
|
gz_file = gzip.GzipFile(mode='rb', fileobj=str_io)
|
|
read_csio = BytesIO()
|
|
|
|
while True:
|
|
uncompressed_data = gz_file.read(2**30)
|
|
if uncompressed_data:
|
|
read_csio.write(uncompressed_data)
|
|
else:
|
|
break
|
|
|
|
value = read_csio.getvalue()
|
|
|
|
return value
|
|
|
|
def getCache(scope_str):
|
|
return FanoutCache('data-unversioned/cache/' + scope_str,
|
|
disk=GzipDisk,
|
|
shards=64,
|
|
timeout=1,
|
|
size_limit=3e11,
|
|
# disk_min_file_size=2**20,
|
|
)
|
|
|
|
# def disk_cache(base_path, memsize=2):
|
|
# def disk_cache_decorator(f):
|
|
# @functools.wraps(f)
|
|
# def wrapper(*args, **kwargs):
|
|
# args_str = repr(args) + repr(sorted(kwargs.items()))
|
|
# file_str = hashlib.md5(args_str.encode('utf8')).hexdigest()
|
|
#
|
|
# cache_path = os.path.join(base_path, f.__name__, file_str + '.pkl.gz')
|
|
#
|
|
# if not os.path.exists(os.path.dirname(cache_path)):
|
|
# os.makedirs(os.path.dirname(cache_path), exist_ok=True)
|
|
#
|
|
# if os.path.exists(cache_path):
|
|
# return pickle_loadgz(cache_path)
|
|
# else:
|
|
# ret = f(*args, **kwargs)
|
|
# pickle_dumpgz(cache_path, ret)
|
|
# return ret
|
|
#
|
|
# return wrapper
|
|
#
|
|
# return disk_cache_decorator
|
|
#
|
|
#
|
|
# def pickle_dumpgz(file_path, obj):
|
|
# log.debug("Writing {}".format(file_path))
|
|
# with open(file_path, 'wb') as file_obj:
|
|
# with gzip.GzipFile(mode='wb', compresslevel=1, fileobj=file_obj) as gz_file:
|
|
# pickle.dump(obj, gz_file, pickle.HIGHEST_PROTOCOL)
|
|
#
|
|
#
|
|
# def pickle_loadgz(file_path):
|
|
# log.debug("Reading {}".format(file_path))
|
|
# with open(file_path, 'rb') as file_obj:
|
|
# with gzip.GzipFile(mode='rb', fileobj=file_obj) as gz_file:
|
|
# return pickle.load(gz_file)
|
|
#
|
|
#
|
|
# def dtpath(dt=None):
|
|
# if dt is None:
|
|
# dt = datetime.datetime.now()
|
|
#
|
|
# return str(dt).rsplit('.', 1)[0].replace(' ', '--').replace(':', '.')
|
|
#
|
|
#
|
|
# def safepath(s):
|
|
# s = s.replace(' ', '_')
|
|
# return re.sub('[^A-Za-z0-9_.-]', '', s)
|