Example #1
0
    def install(self, path, name):
        """Moves the directory for the specified named cache to |path|.

    NamedCache must be open. path must be absolute, unicode and must not exist.

    Raises Error if cannot install the cache.
    """
        self._lock.assert_locked()
        logging.info('Installing named cache %r to %r', name, path)
        try:
            _check_abs(path)
            if os.path.isdir(path):
                raise Error('installation directory %r already exists' % path)

            rel_cache = self._lru.get(name)
            if rel_cache:
                abs_cache = os.path.join(self.root_dir, rel_cache)
                if os.path.isdir(abs_cache):
                    logging.info('Moving %r to %r', abs_cache, path)
                    file_path.ensure_tree(os.path.dirname(path))
                    fs.rename(abs_cache, path)
                    self._remove(name)
                    return

                logging.warning('directory for named cache %r does not exist',
                                name)
                self._remove(name)

            # The named cache does not exist, create an empty directory.
            # When uninstalling, we will move it back to the cache and create an
            # an entry.
            file_path.ensure_tree(path)
        except (OSError, Error) as ex:
            raise Error('cannot install cache named %r at %r: %s' %
                        (name, path, ex))
Example #2
0
    def uninstall(self, path, name):
        """Moves the cache directory back. Opposite to install().

    NamedCache must be open. path must be absolute and unicode.

    Raises NamedCacheError if cannot uninstall the cache.
    """
        logging.info('Uninstalling named cache %r from %r', name, path)
        with self._lock:
            try:
                if not os.path.isdir(path):
                    logging.warning(
                        'Directory %r does not exist anymore. Cache lost.',
                        path)
                    return

                rel_cache = self._lru.get(name)
                if rel_cache:
                    # Do not crash because cache already exists.
                    logging.warning('overwriting an existing named cache %r',
                                    name)
                    create_named_link = False
                else:
                    rel_cache = self._allocate_dir()
                    create_named_link = True

                # Move the dir and create an entry for the named cache.
                abs_cache = os.path.join(self.cache_dir, rel_cache)
                logging.info('Moving %r to %r', path, abs_cache)
                file_path.ensure_tree(os.path.dirname(abs_cache))
                fs.rename(path, abs_cache)
                self._lru.add(name, rel_cache)

                if create_named_link:
                    # Create symlink <cache_dir>/<named>/<name> -> <cache_dir>/<short
                    # name> for user convenience.
                    named_path = self._get_named_path(name)
                    if os.path.exists(named_path):
                        file_path.remove(named_path)
                    else:
                        file_path.ensure_tree(os.path.dirname(named_path))
                    try:
                        fs.symlink(abs_cache, named_path)
                        logging.info('Created symlink %r to %r', named_path,
                                     abs_cache)
                    except OSError:
                        # Ignore on Windows. It happens when running as a normal user or
                        # when UAC is enabled and the user is a filtered administrator
                        # account.
                        if sys.platform != 'win32':
                            raise
            except (IOError, OSError) as ex:
                raise NamedCacheError(
                    'cannot uninstall cache named %r at %r: %s' %
                    (name, path, ex))
    def install(self, dst, name):
        """Creates the directory |dst| and moves a previous named cache |name| if it
    was in the local named caches cache.

    dst must be absolute, unicode and must not exist.

    Returns the reused named cache size in bytes, or 0 if none was present.

    Raises NamedCacheError if cannot install the cache.
    """
        logging.info('NamedCache.install(%r, %r)', dst, name)
        with self._lock:
            try:
                if fs.isdir(dst):
                    raise NamedCacheError(
                        'installation directory %r already exists' % dst)

                # Remove the named symlink if it exists.
                link_name = self._get_named_path(name)
                if fs.exists(link_name):
                    # Remove the symlink itself, not its destination.
                    fs.remove(link_name)

                if name in self._lru:
                    rel_cache, size = self._lru.get(name)
                    abs_cache = os.path.join(self.cache_dir, rel_cache)
                    if fs.isdir(abs_cache):
                        logging.info('- reusing %r; size was %d', rel_cache,
                                     size)
                        file_path.ensure_tree(os.path.dirname(dst))
                        self._sudo_chown(abs_cache)
                        fs.rename(abs_cache, dst)
                        self._remove(name)
                        return size

                    logging.warning('- expected directory %r, does not exist',
                                    rel_cache)
                    self._remove(name)

                # The named cache does not exist, create an empty directory. When
                # uninstalling, we will move it back to the cache and create an an
                # entry.
                logging.info('- creating new directory')
                file_path.ensure_tree(dst)
                return 0
            except (IOError, OSError) as ex:
                # Raise using the original traceback.
                exc = NamedCacheError(
                    'cannot install cache named %r at %r: %s' %
                    (name, dst, ex))
                six.reraise(type(exc), exc, sys.exc_info()[2])
            finally:
                self._save()
Example #4
0
  def uninstall(self, path, name):
    """Moves the cache directory back. Opposite to install().

    NamedCache must be open. path must be absolute and unicode.

    Raises Error if cannot uninstall the cache.
    """
    logging.info('Uninstalling named cache %r from %r', name, path)
    try:
      _check_abs(path)
      if not os.path.isdir(path):
        logging.warning(
            'Directory %r does not exist anymore. Cache lost.', path)
        return

      rel_cache = self._lru.get(name)
      if rel_cache:
        # Do not crash because cache already exists.
        logging.warning('overwriting an existing named cache %r', name)
        create_named_link = False
      else:
        rel_cache = self._allocate_dir()
        create_named_link = True

      # Move the dir and create an entry for the named cache.
      abs_cache = os.path.join(self.root_dir, rel_cache)
      logging.info('Moving %r to %r', path, abs_cache)
      file_path.ensure_tree(os.path.dirname(abs_cache))
      fs.rename(path, abs_cache)
      self._lru.add(name, rel_cache)

      if create_named_link:
        # Create symlink <root_dir>/<named>/<name> -> <root_dir>/<short name>
        # for user convenience.
        named_path = self._get_named_path(name)
        if os.path.exists(named_path):
          file_path.remove(named_path)
        else:
          file_path.ensure_tree(os.path.dirname(named_path))
        fs.symlink(abs_cache, named_path)
        logging.info('Created symlink %r to %r', named_path, abs_cache)
    except (OSError, Error) as ex:
      raise Error(
          'cannot uninstall cache named %r at %r: %s' % (
            name, path, ex))
Example #5
0
    def install(self, path, name):
        """Moves the directory for the specified named cache to |path|.

    path must be absolute, unicode and must not exist.

    Raises NamedCacheError if cannot install the cache.
    """
        logging.info('Installing named cache %r to %r', name, path)
        with self._lock:
            try:
                if os.path.isdir(path):
                    raise NamedCacheError(
                        'installation directory %r already exists' % path)

                link_name = os.path.join(self.cache_dir, name)
                if fs.exists(link_name):
                    fs.rmtree(link_name)

                if name in self._lru:
                    rel_cache, _size = self._lru.get(name)
                    abs_cache = os.path.join(self.cache_dir, rel_cache)
                    if os.path.isdir(abs_cache):
                        logging.info('Moving %r to %r', abs_cache, path)
                        file_path.ensure_tree(os.path.dirname(path))
                        fs.rename(abs_cache, path)
                        self._remove(name)
                        return

                    logging.warning(
                        'directory for named cache %r does not exist at %s',
                        name, rel_cache)
                    self._remove(name)

                # The named cache does not exist, create an empty directory.
                # When uninstalling, we will move it back to the cache and create an
                # an entry.
                file_path.ensure_tree(path)
            except (IOError, OSError) as ex:
                raise NamedCacheError(
                    'cannot install cache named %r at %r: %s' %
                    (name, path, ex))
            finally:
                self._save()
Example #6
0
    def uninstall(self, path, name):
        """Moves the cache directory back. Opposite to install().

    path must be absolute and unicode.

    Raises NamedCacheError if cannot uninstall the cache.
    """
        logging.info('Uninstalling named cache %r from %r', name, path)
        with self._lock:
            try:
                if not os.path.isdir(path):
                    logging.warning(
                        'Directory %r does not exist anymore. Cache lost.',
                        path)
                    return

                if name in self._lru:
                    # This shouldn't happen but just remove the preexisting one and move
                    # on.
                    logging.warning('overwriting an existing named cache %r',
                                    name)
                    self._remove(name)
                rel_cache = self._allocate_dir()

                # Move the dir and create an entry for the named cache.
                abs_cache = os.path.join(self.cache_dir, rel_cache)
                logging.info('Moving %r to %r', path, abs_cache)
                file_path.ensure_tree(os.path.dirname(abs_cache))
                fs.rename(path, abs_cache)

                # That succeeded, calculate its new size.
                size = _get_recursive_size(abs_cache)
                if not size:
                    # Do not save empty named cache.
                    return
                self._lru.add(name, (rel_cache, size))
                self._added.append(size)

                # Create symlink <cache_dir>/<named>/<name> -> <cache_dir>/<short name>
                # for user convenience.
                named_path = self._get_named_path(name)
                if os.path.exists(named_path):
                    file_path.remove(named_path)
                else:
                    file_path.ensure_tree(os.path.dirname(named_path))

                try:
                    fs.symlink(abs_cache, named_path)
                    logging.info('Created symlink %r to %r', named_path,
                                 abs_cache)
                except OSError:
                    # Ignore on Windows. It happens when running as a normal user or when
                    # UAC is enabled and the user is a filtered administrator account.
                    if sys.platform != 'win32':
                        raise
            except (IOError, OSError) as ex:
                raise NamedCacheError(
                    'cannot uninstall cache named %r at %r: %s' %
                    (name, path, ex))
            finally:
                self._save()
    def uninstall(self, src, name):
        """Moves the cache directory back into the named cache hive for an eventual
    reuse.

    The opposite of install().

    src must be absolute and unicode. Its content is moved back into the local
    named caches cache.

    Returns the named cache size in bytes.

    Raises NamedCacheError if cannot uninstall the cache.
    """
        logging.info('NamedCache.uninstall(%r, %r)', src, name)
        with self._lock:
            try:
                if not fs.isdir(src):
                    logging.warning(
                        'NamedCache: Directory %r does not exist anymore. Cache lost.',
                        src)
                    return

                if name in self._lru:
                    # This shouldn't happen but just remove the preexisting one and move
                    # on.
                    logging.error('- overwriting existing cache!')
                    self._remove(name)

                # Calculate the size of the named cache to keep. It's important because
                # if size is zero (it's empty), we do not want to add it back to the
                # named caches cache.
                size = _get_recursive_size(src)
                logging.info('- Size is %d', size)
                if not size:
                    # Do not save empty named cache.
                    return size

                # Move the dir and create an entry for the named cache.
                rel_cache = self._allocate_dir()
                abs_cache = os.path.join(self.cache_dir, rel_cache)
                logging.info('- Moving to %r', rel_cache)
                file_path.ensure_tree(os.path.dirname(abs_cache))
                fs.rename(src, abs_cache)

                self._lru.add(name, (rel_cache, size))
                self._added.append(size)

                # Create symlink <cache_dir>/<named>/<name> -> <cache_dir>/<short name>
                # for user convenience.
                named_path = self._get_named_path(name)
                if fs.exists(named_path):
                    file_path.remove(named_path)
                else:
                    file_path.ensure_tree(os.path.dirname(named_path))

                try:
                    fs.symlink(os.path.join(u'..', rel_cache), named_path)
                    logging.info('NamedCache: Created symlink %r to %r',
                                 named_path, abs_cache)
                except OSError:
                    # Ignore on Windows. It happens when running as a normal user or when
                    # UAC is enabled and the user is a filtered administrator account.
                    if sys.platform != 'win32':
                        raise
                return size
            except (IOError, OSError) as ex:
                # Raise using the original traceback.
                exc = NamedCacheError(
                    'cannot uninstall cache named %r at %r: %s' %
                    (name, src, ex))
                six.reraise(exc, None, sys.exc_info()[2])
            finally:
                # Call save() at every uninstall. The assumptions are:
                # - The total the number of named caches is low, so the state.json file
                #   is small, so the time it takes to write it to disk is short.
                # - The number of mapped named caches per task is low, so the number of
                #   times save() is called on tear-down isn't high enough to be
                #   significant.
                # - uninstall() sometimes throws due to file locking on Windows or
                #   access rights on Linux. We want to keep as many as possible.
                self._save()