web/views/staticcontrollers.py
branchstable
changeset 9159 7a6ea3468765
parent 8694 d901c36bcfce
child 9229 739ae5366bed
equal deleted inserted replaced
9158:08d8fba05854 9159:7a6ea3468765
    25 
    25 
    26 import os
    26 import os
    27 import os.path as osp
    27 import os.path as osp
    28 import hashlib
    28 import hashlib
    29 import mimetypes
    29 import mimetypes
       
    30 import threading
    30 from time import mktime
    31 from time import mktime
    31 from datetime import datetime, timedelta
    32 from datetime import datetime, timedelta
    32 from logging import getLogger
    33 from logging import getLogger
    33 
    34 
    34 from cubicweb import Unauthorized
    35 from cubicweb import Unauthorized
   103 
   104 
   104     def __init__(self, config):
   105     def __init__(self, config):
   105         self._resources = {}
   106         self._resources = {}
   106         self.config = config
   107         self.config = config
   107         self.logger = getLogger('cubicweb.web')
   108         self.logger = getLogger('cubicweb.web')
       
   109         self.lock = threading.Lock()
   108 
   110 
   109     def _resource(self, path):
   111     def _resource(self, path):
   110         """get the resouce"""
   112         """get the resouce"""
   111         try:
   113         try:
   112             return self._resources[path]
   114             return self._resources[path]
   141         return osp.join(self.config.appdatahome, 'uicache', fname)
   143         return osp.join(self.config.appdatahome, 'uicache', fname)
   142 
   144 
   143     def concat_cached_filepath(self, paths):
   145     def concat_cached_filepath(self, paths):
   144         filepath = self.build_filepath(paths)
   146         filepath = self.build_filepath(paths)
   145         if not self._up_to_date(filepath, paths):
   147         if not self._up_to_date(filepath, paths):
   146             with open(filepath, 'wb') as f:
   148             tmpfile = filepath + '.tmp'
   147                 for path in paths:
   149             try:
   148                     dirpath, rid = self._resource(path)
   150                 with self.lock:
   149                     if rid is None:
   151                     if self._up_to_date(filepath, paths):
   150                         # In production mode log an error, do not return a 404
   152                         # first check could have raced with some other thread
   151                         # XXX the erroneous content is cached anyway
   153                         # updating the file
   152                         self.logger.error('concatenated data url error: %r file '
   154                         return filepath
   153                                           'does not exist', path)
   155                     with open(tmpfile, 'wb') as f:
   154                         if self.config.debugmode:
   156                         for path in paths:
   155                             raise NotFound(path)
   157                             dirpath, rid = self._resource(path)
   156                     else:
   158                             if rid is None:
   157                         with open(osp.join(dirpath, rid), 'rb') as source:
   159                                 # In production mode log an error, do not return a 404
   158                             for line in source:
   160                                 # XXX the erroneous content is cached anyway
   159                                 f.write(line)
   161                                 self.logger.error('concatenated data url error: %r file '
   160                         f.write('\n')
   162                                                   'does not exist', path)
       
   163                                 if self.config.debugmode:
       
   164                                     raise NotFound(path)
       
   165                             else:
       
   166                                 with open(osp.join(dirpath, rid), 'rb') as source:
       
   167                                     for line in source:
       
   168                                         f.write(line)
       
   169                                 f.write('\n')
       
   170                     os.rename(tmpfile, filepath)
       
   171             except:
       
   172                 os.remove(tmpfile)
       
   173                 raise
   161         return filepath
   174         return filepath
   162 
   175 
   163 
   176 
   164 class DataController(StaticFileController):
   177 class DataController(StaticFileController):
   165     """Controller in charge of serving static file in /data/
   178     """Controller in charge of serving static file in /data/