Public Member Functions | Static Public Member Functions | Public Attributes | Private Member Functions | Private Attributes | List of all members
fabricate.AtimesRunner Class Reference
Inheritance diagram for fabricate.AtimesRunner:
fabricate.Runner object

Public Member Functions

def __init__ (self, builder)
 
def file_times (self)
 
def __call__ (self, args, kwargs)
 
def actual_runner (self)
 
def ignore (self, name)
 

Static Public Member Functions

def file_has_atimes (filename)
 
def exists (path)
 
def has_atimes (paths)
 

Public Attributes

 atimes
 
short int type
 
short int number
 
char name [SIZE_OF_OBJ_NAME]
 
cat_entry star
 

Private Member Functions

def _file_times (self, path, depth)
 
def _utime (self, filename, atime, mtime)
 
def _age_atimes (self, filetimes)
 

Private Attributes

 _builder
 

Detailed Description

Definition at line 266 of file fabricate.py.

Constructor & Destructor Documentation

def fabricate.AtimesRunner.__init__ (   self,
  builder 
)

Definition at line 267 of file fabricate.py.

Referenced by PandAna.core.core.spectrum.fill().

267  def __init__(self, builder):
268  self._builder = builder
269  self.atimes = AtimesRunner.has_atimes(self._builder.dirs)
270  if self.atimes == 0:
272  'atimes are not supported on this platform')
273 
def __init__(self, builder)
Definition: fabricate.py:267

Member Function Documentation

def fabricate.AtimesRunner.__call__ (   self,
  args,
  kwargs 
)
Run command and return its dependencies and outputs, using before
    and after access times to determine dependencies. 

Definition at line 421 of file fabricate.py.

References fabricate.AtimesRunner._age_atimes(), fabricate.AtimesRunner._utime(), fabricate.AtimesRunner.atimes, fabricate.AtimesRunner.file_times(), fabricate.Runner.ignore(), fabricate.Builder.ignore, and fabricate.shell().

421  def __call__(self, *args, **kwargs):
422  """ Run command and return its dependencies and outputs, using before
423  and after access times to determine dependencies. """
424 
425  # For Python pre-2.5, ensure os.stat() returns float atimes
426  old_stat_float = os.stat_float_times()
427  os.stat_float_times(True)
428 
429  originals = self.file_times()
430  if self.atimes == 2:
431  befores = originals
432  atime_resolution = 0
433  mtime_resolution = 0
434  else:
435  befores = self._age_atimes(originals)
436  atime_resolution = FAT_atime_resolution
437  mtime_resolution = FAT_mtime_resolution
438  shell_keywords = dict(silent=False)
439  shell_keywords.update(kwargs)
440  shell(*args, **shell_keywords)
441  afters = self.file_times()
442  deps = []
443  outputs = []
444  for name in afters:
445  if name in befores:
446  # if file exists before+after && mtime changed, add to outputs
447  # Note: Can't just check that atimes > than we think they were
448  # before because os might have rounded them to a later
449  # date than what we think we set them to in befores.
450  # So we make sure they're > by at least 1/2 the
451  # resolution. This will work for anything with a
452  # resolution better than FAT.
453  if afters[name][1]-mtime_resolution/2 > befores[name][1]:
454  if not self.ignore(name):
455  outputs.append(name)
456  elif afters[name][0]-atime_resolution/2 > befores[name][0]:
457  # otherwise add to deps if atime changed
458  if not self.ignore(name):
459  deps.append(name)
460  else:
461  # file created (in afters but not befores), add as output
462  if not self.ignore(name):
463  outputs.append(name)
464 
465  if self.atimes < 2:
466  # Restore atimes of files we didn't access: not for any functional
467  # reason -- it's just to preserve the access time for the user's info
468  for name in deps:
469  originals.pop(name)
470  for name in originals:
471  original = originals[name]
472  if original != afters.get(name, None):
473  self._utime(name, original[0], original[1])
474 
475  os.stat_float_times(old_stat_float) # restore stat_float_times value
476  return deps, outputs
477 
def shell(args, kwargs)
Definition: fabricate.py:143
def ignore(self, name)
Definition: fabricate.py:263
def _age_atimes(self, filetimes)
Definition: fabricate.py:408
def _utime(self, filename, atime, mtime)
Definition: fabricate.py:398
def __call__(self, args, kwargs)
Definition: fabricate.py:421
def fabricate.AtimesRunner._age_atimes (   self,
  filetimes 
)
private
Age files' atimes and mtimes to be at least FAT_xx_resolution old.
    Only adjust if the given filetimes dict says it isn't that old,
    and return a new dict of filetimes with the ages adjusted. 

Definition at line 408 of file fabricate.py.

References fabricate.AtimesRunner._utime().

Referenced by fabricate.AtimesRunner.__call__().

408  def _age_atimes(self, filetimes):
409  """ Age files' atimes and mtimes to be at least FAT_xx_resolution old.
410  Only adjust if the given filetimes dict says it isn't that old,
411  and return a new dict of filetimes with the ages adjusted. """
412  adjusted = {}
413  now = time.time()
414  for filename, entry in filetimes.items():
415  if now-entry[0] < FAT_atime_resolution or now-entry[1] < FAT_mtime_resolution:
416  entry = entry[0] - FAT_atime_resolution, entry[1] - FAT_mtime_resolution
417  self._utime(filename, entry[0], entry[1])
418  adjusted[filename] = entry
419  return adjusted
420 
def _age_atimes(self, filetimes)
Definition: fabricate.py:408
def _utime(self, filename, atime, mtime)
Definition: fabricate.py:398
def fabricate.AtimesRunner._file_times (   self,
  path,
  depth 
)
private
Helper function for file_times().
    Return a dict of file times, recursing directories that don't
    start with self._builder.ignoreprefix 

Definition at line 361 of file fabricate.py.

References fabricate.AtimesRunner._file_times().

Referenced by fabricate.AtimesRunner._file_times(), and fabricate.AtimesRunner.file_times().

361  def _file_times(self, path, depth):
362  """ Helper function for file_times().
363  Return a dict of file times, recursing directories that don't
364  start with self._builder.ignoreprefix """
365 
366  AtimesRunner.exists(path)
367  names = os.listdir(path)
368  times = {}
369  ignoreprefix = self._builder.ignoreprefix
370  for name in names:
371  if ignoreprefix and name.startswith(ignoreprefix):
372  continue
373  if path == '.':
374  fullname = name
375  else:
376  fullname = os.path.join(path, name)
377  st = os.stat(fullname)
378  if stat.S_ISDIR(st.st_mode):
379  if depth > 1:
380  times.update(self._file_times(fullname, depth-1))
381  elif stat.S_ISREG(st.st_mode):
382  times[fullname] = st.st_atime, st.st_mtime
383  return times
384 
def _file_times(self, path, depth)
Definition: fabricate.py:361
def fabricate.AtimesRunner._utime (   self,
  filename,
  atime,
  mtime 
)
private
Call os.utime but ignore permission errors 

Definition at line 398 of file fabricate.py.

Referenced by fabricate.AtimesRunner.__call__(), and fabricate.AtimesRunner._age_atimes().

398  def _utime(self, filename, atime, mtime):
399  """ Call os.utime but ignore permission errors """
400  try:
401  os.utime(filename, (atime, mtime))
402  except OSError as e:
403  # ignore permission errors -- we can't build with files
404  # that we can't access anyway
405  if e.errno != 1:
406  raise
407 
def _utime(self, filename, atime, mtime)
Definition: fabricate.py:398
def fabricate.Runner.actual_runner (   self)
inherited
Return the actual runner object (overriden in SmartRunner). 

Definition at line 259 of file fabricate.py.

259  def actual_runner(self):
260  """ Return the actual runner object (overriden in SmartRunner). """
261  return self
262 
def actual_runner(self)
Definition: fabricate.py:259
def fabricate.AtimesRunner.exists (   path)
static

Definition at line 327 of file fabricate.py.

327  def exists(path):
328  if not os.path.exists(path):
329  # Note: in linux, error may not occur: strace runner doesn't check
330  raise PathError("build dirs specified a non-existant path '%s'" % path)
331 
def fabricate.AtimesRunner.file_has_atimes (   filename)
static
Return whether the given filesystem supports access time updates for
    this file. Return:
      - 0 if no a/mtimes not updated
      - 1 if the atime resolution is at least one day and
the mtime resolution at least 2 seconds (as on FAT filesystems)
      - 2 if the atime and mtime resolutions are both < ms
(NTFS filesystem has 100 ns resolution). 

Definition at line 275 of file fabricate.py.

References open().

275  def file_has_atimes(filename):
276  """ Return whether the given filesystem supports access time updates for
277  this file. Return:
278  - 0 if no a/mtimes not updated
279  - 1 if the atime resolution is at least one day and
280  the mtime resolution at least 2 seconds (as on FAT filesystems)
281  - 2 if the atime and mtime resolutions are both < ms
282  (NTFS filesystem has 100 ns resolution). """
283 
284  def access_file(filename):
285  """ Access (read a byte from) file to try to update its access time. """
286  f = open(filename)
287  f.read(1)
288  f.close()
289 
290  initial = os.stat(filename)
291  os.utime(filename, (
292  initial.st_atime-FAT_atime_resolution,
293  initial.st_mtime-FAT_mtime_resolution))
294 
295  adjusted = os.stat(filename)
296  access_file(filename)
297  after = os.stat(filename)
298 
299  # Check that a/mtimes actually moved back by at least resolution and
300  # updated by a file access.
301  # add NTFS_atime_resolution to account for float resolution factors
302  # Comment on resolution/2 in atimes_runner()
303  if initial.st_atime-adjusted.st_atime > FAT_atime_resolution+NTFS_atime_resolution or \
304  initial.st_mtime-adjusted.st_mtime > FAT_mtime_resolution+NTFS_atime_resolution or \
305  initial.st_atime==adjusted.st_atime or \
306  initial.st_mtime==adjusted.st_mtime or \
307  not after.st_atime-FAT_atime_resolution/2 > adjusted.st_atime:
308  return 0
309 
310  os.utime(filename, (
311  initial.st_atime-NTFS_atime_resolution,
312  initial.st_mtime-NTFS_mtime_resolution))
313  adjusted = os.stat(filename)
314 
315  # Check that a/mtimes actually moved back by at least resolution
316  # Note: != comparison here fails due to float rounding error
317  # double NTFS_atime_resolution to account for float resolution factors
318  if initial.st_atime-adjusted.st_atime > NTFS_atime_resolution*2 or \
319  initial.st_mtime-adjusted.st_mtime > NTFS_mtime_resolution*2 or \
320  initial.st_atime==adjusted.st_atime or \
321  initial.st_mtime==adjusted.st_mtime:
322  return 1
323 
324  return 2
325 
def file_has_atimes(filename)
Definition: fabricate.py:275
procfile open("FD_BRL_v0.txt")
def fabricate.AtimesRunner.file_times (   self)
Return a dict of "filepath: (atime, mtime)" entries for each file
    in self._builder.dirs. "filepath" is the absolute path, "atime" is
    the access time, "mtime" the modification time.
    Recurse directories that don't start with
    self._builder.ignoreprefix and have depth less than
    self._builder.dirdepth. 

Definition at line 385 of file fabricate.py.

References fabricate.AtimesRunner._file_times().

Referenced by fabricate.AtimesRunner.__call__().

385  def file_times(self):
386  """ Return a dict of "filepath: (atime, mtime)" entries for each file
387  in self._builder.dirs. "filepath" is the absolute path, "atime" is
388  the access time, "mtime" the modification time.
389  Recurse directories that don't start with
390  self._builder.ignoreprefix and have depth less than
391  self._builder.dirdepth. """
392 
393  times = {}
394  for path in self._builder.dirs:
395  times.update(self._file_times(path, self._builder.dirdepth))
396  return times
397 
def _file_times(self, path, depth)
Definition: fabricate.py:361
def fabricate.AtimesRunner.has_atimes (   paths)
static
Return whether a file created in each path supports atimes and mtimes.
    Return value is the same as used by file_has_atimes
    Note: for speed, this only tests files created at the top directory
    of each path. A safe assumption in most build environments.
    In the unusual case that any sub-directories are mounted
    on alternate file systems that don't support atimes, the build may
    fail to identify a dependency 

Definition at line 333 of file fabricate.py.

References min().

333  def has_atimes(paths):
334  """ Return whether a file created in each path supports atimes and mtimes.
335  Return value is the same as used by file_has_atimes
336  Note: for speed, this only tests files created at the top directory
337  of each path. A safe assumption in most build environments.
338  In the unusual case that any sub-directories are mounted
339  on alternate file systems that don't support atimes, the build may
340  fail to identify a dependency """
341 
342  atimes = 2 # start by assuming we have best atimes
343  for path in paths:
344  AtimesRunner.exists(path)
345  handle, filename = tempfile.mkstemp(dir=path)
346  try:
347  try:
348  f = os.fdopen(handle, 'wb')
349  except:
350  os.close(handle)
351  raise
352  try:
353  f.write(b'x') # need a byte in the file for access test
354  finally:
355  f.close()
356  atimes = min(atimes, AtimesRunner.file_has_atimes(filename))
357  finally:
358  os.remove(filename)
359  return atimes
360 
def has_atimes(paths)
Definition: fabricate.py:333
static float min(const float a, const float b, const float c)
Definition: absgeo.cxx:45
def fabricate.Runner.ignore (   self,
  name 
)
inherited

Definition at line 263 of file fabricate.py.

Referenced by fabricate.AtimesRunner.__call__(), and fabricate.StraceRunner._match_line().

263  def ignore(self, name):
264  return self._builder.ignore.search(name)
265 
def ignore(self, name)
Definition: fabricate.py:263

Member Data Documentation

fabricate.AtimesRunner._builder
private

Definition at line 268 of file fabricate.py.

fabricate.AtimesRunner.atimes

Definition at line 269 of file fabricate.py.

Referenced by fabricate.AtimesRunner.__call__().

char object::name
inherited
short int object::number
inherited

Definition at line 115 of file novas.h.

cat_entry object::star
inherited

Definition at line 117 of file novas.h.

short int object::type
inherited

Definition at line 114 of file novas.h.


The documentation for this class was generated from the following file: