Beispiel #1
0
    async def setxattr(self, inode, name, value, ctx):
        if inode != pyfuse3.ROOT_INODE or name != b'command':
            raise FUSEError(errno.ENOTSUP)

        if value == b'forget_entry':
            pyfuse3.invalidate_entry_async(pyfuse3.ROOT_INODE, self.hello_name)
        elif value == b'forget_inode':
            pyfuse3.invalidate_inode(self.hello_inode)
        elif value == b'store':
            pyfuse3.notify_store(self.hello_inode, offset=0,
                                 data=self.hello_data)
        else:
            raise FUSEError(errno.EINVAL)

        # Make sure that the request is pending before we return
        await trio.sleep(0.1)
Beispiel #2
0
    async def remove_tree(self, id_p0, name0):
        '''Remove directory tree'''

        if self.failsafe:
            raise FUSEError(errno.EPERM)

        log.debug('started with %d, %s', id_p0, name0)

        if self.inodes[id_p0].locked:
            raise FUSEError(errno.EPERM)

        id0 = self._lookup(id_p0, name0, ctx=None).id
        queue = [id0]  # Directories that we still need to delete
        batch_size = 200  # Entries to process before checkpointing
        stamp = time.time()  # Time of last checkpoint
        while queue:  # For every directory
            id_p = queue.pop()
            is_open = id_p in self.open_inodes

            # Per https://sqlite.org/isolation.html, results of removing rows
            # during select are undefined. Therefore, process data in chunks.
            # This is also a nice opportunity to release the GIL...
            query_chunk = self.db.get_list(
                'SELECT name, name_id, inode FROM contents_v WHERE '
                'parent_inode=? LIMIT %d' % batch_size, (id_p, ))
            reinserted = False
            for (name, name_id, id_) in query_chunk:
                if self.db.has_val(
                        'SELECT 1 FROM contents WHERE parent_inode=?',
                    (id_, )):
                    # First delete subdirectories
                    if not reinserted:
                        queue.append(id_p)
                        reinserted = True
                    queue.append(id_)
                else:
                    if is_open:
                        pyfuse3.invalidate_entry_async(id_p, name)
                    await self._remove(id_p, name, id_, force=True)

            if query_chunk and not reinserted:
                # Make sure to re-insert the directory to process the remaining
                # contents and delete the directory itself.
                queue.append(id_p)

            dt = time.time() - stamp
            batch_size = int(batch_size * CHECKPOINT_INTERVAL / dt)
            batch_size = min(batch_size, 200)  # somewhat arbitrary...
            batch_size = max(batch_size, 20000)
            log.debug('Adjusting batch_size to %d and yielding', batch_size)
            await trio.lowlevel.checkpoint()
            log.debug('re-acquired lock')
            stamp = time.time()

        if id_p0 in self.open_inodes:
            log.debug('invalidate_entry(%d, %r)', id_p0, name0)
            pyfuse3.invalidate_entry_async(id_p0, name0)
        await self._remove(id_p0, name0, id0, force=True)

        await self.forget([(id0, 1)])
        log.debug('finished')