create cache packages for caching tile servers

This commit is contained in:
Laura Klünder 2017-11-20 21:10:03 +01:00
parent 7b16be8041
commit 5498e9f84f
2 changed files with 64 additions and 3 deletions

View file

@ -3,6 +3,7 @@ import os
import pickle import pickle
import threading import threading
from collections import deque from collections import deque
from itertools import chain
import numpy as np import numpy as np
from django.conf import settings from django.conf import settings
@ -11,9 +12,10 @@ from shapely import prepared
from shapely.geometry import GeometryCollection from shapely.geometry import GeometryCollection
from shapely.ops import unary_union from shapely.ops import unary_union
from c3nav.mapdata.models import Level, MapUpdate from c3nav.mapdata.models import Level, MapUpdate, Source
from c3nav.mapdata.render.geometry import AltitudeAreaGeometries, LevelGeometries from c3nav.mapdata.render.geometry import AltitudeAreaGeometries, LevelGeometries
from c3nav.mapdata.utils.cache import AccessRestrictionAffected, MapHistory from c3nav.mapdata.utils.cache import AccessRestrictionAffected, MapHistory
from c3nav.mapdata.utils.cache.package import CachePackage
from c3nav.mapdata.utils.geometry import get_rings from c3nav.mapdata.utils.geometry import get_rings
empty_geometry_collection = GeometryCollection() empty_geometry_collection = GeometryCollection()
@ -43,6 +45,8 @@ class LevelRenderData:
'spaces__obstacles', 'spaces__lineobstacles', 'spaces__obstacles', 'spaces__lineobstacles',
'spaces__groups', 'spaces__ramps')) 'spaces__groups', 'spaces__ramps'))
package = CachePackage(bounds=tuple(chain(*Source.max_bounds())))
single_level_geoms = {} single_level_geoms = {}
interpolators = {} interpolators = {}
last_interpolator = None last_interpolator = None
@ -212,11 +216,16 @@ class LevelRenderData:
for access_restriction, areas in access_restriction_affected.items() for access_restriction, areas in access_restriction_affected.items()
} }
AccessRestrictionAffected.build(access_restriction_affected).save_level(level.pk, 'composite') access_restriction_affected = AccessRestrictionAffected.build(access_restriction_affected)
access_restriction_affected.save_level(level.pk, 'composite')
map_history.save_level(level.pk, 'composite')
package.add_level(level.pk, map_history, access_restriction_affected)
render_data.save(level.pk) render_data.save(level.pk)
map_history.save(MapHistory.level_filename(level.pk, 'composite')) package.save_all()
cached = {} cached = {}
cache_key = None cache_key = None

View file

@ -0,0 +1,52 @@
import os
import struct
from collections import namedtuple
from io import BytesIO
from tarfile import TarFile, TarInfo
from c3nav.mapdata.utils.cache import AccessRestrictionAffected, GeometryIndexed, MapHistory
CachePackageLevel = namedtuple('CachePackageLevel', ('history', 'restrictions'))
class CachePackage:
def __init__(self, bounds, levels=None):
self.bounds = bounds
self.levels = {} if levels is None else levels
def add_level(self, level_id: int, history: MapHistory, restrictions: AccessRestrictionAffected):
self.levels[level_id] = CachePackageLevel(history, restrictions)
def save(self, filename=None, compression=None):
if filename is None:
from django.conf import settings
filename = os.path.join(settings.CACHE_ROOT, 'package.tar')
if compression is not None:
filename += '.' + compression
filemode = 'w'
if compression is not None:
filemode += ':' + compression
with TarFile.open(filename, filemode) as f:
self._add_bytesio(f, 'bounds', BytesIO(struct.pack('<IIII', *(int(i*100) for i in self.bounds))))
for level_id, level_data in self.levels.items():
self._add_geometryindexed(f, 'history_%d' % level_id, level_data.history)
self._add_geometryindexed(f, 'restrictions_%d' % level_id, level_data.restrictions)
def _add_bytesio(self, f: TarFile, filename: str, data: BytesIO):
data.seek(0, os.SEEK_END)
tarinfo = TarInfo(name=filename)
tarinfo.size = data.tell()
data.seek(0)
f.addfile(tarinfo, data)
def _add_geometryindexed(self, f: TarFile, filename: str, obj: GeometryIndexed):
data = BytesIO()
obj.write(data)
self._add_bytesio(f, filename, data)
def save_all(self, filename=None):
for compression in (None, 'gz', 'xz'):
self.save(filename, compression)