def put_file(self,
                 name,
                 filename,
                 to_local_store=True,
                 to_remote_store=True,
                 compress_hint=True):
        """Adds file ``filename`` to the filetracker under the name ``name``.

           If the file already exists, a new version is created. In practice
           if the store does not support versioning, the file is overwritten.

           The file may be added to local store only (if ``to_remote_store`` is
           ``False``), to remote store only (if ``to_local_store`` is
           ``False``) or both. If only one store is configured, the values of
           ``to_local_store`` and ``to_remote_store`` are ignored.

           Local data store implemented in :class:`LocalDataStore` tries to not
           directly copy the data to the final cache destination, but uses
           hardlinking. Therefore you should not modify the file in-place
           later as this would be disastrous.

           If ``compress_hint`` is set to False, file is compressed on
           the server, instead of the client. This is generally not
           recommended, unless you know what you're doing.
        """

        if not to_local_store and not to_remote_store:
            raise ValueError("Neither to_local_store nor to_remote_store set "
                             "in a call to filetracker.Client.put_file")

        check_name(name)

        lock = None
        if self.local_store:
            lock = self.lock_manager.lock_for(name)
            lock.lock_exclusive()

        try:
            if (to_local_store or not self.remote_store) and self.local_store:
                versioned_name = self.local_store.add_file(name, filename)
            if (to_remote_store or not self.local_store) and self.remote_store:
                versioned_name = self.remote_store.add_file(
                        name, filename, compress_hint=compress_hint)
        finally:
            if lock:
                lock.close()

        return versioned_name