diff --git a/mayan/apps/mirroring/management/commands/mountindex.py b/mayan/apps/mirroring/management/commands/mountindex.py index 5d21aa69cb..1d9f70b293 100644 --- a/mayan/apps/mirroring/management/commands/mountindex.py +++ b/mayan/apps/mirroring/management/commands/mountindex.py @@ -1,15 +1,13 @@ from __future__ import unicode_literals import datetime -import logging - -from collections import defaultdict from errno import ENOENT -from stat import S_IFDIR, S_IFLNK, S_IFREG -from sys import argv, exit +import logging +from optparse import make_option +from stat import S_IFDIR, S_IFREG from time import time -from fuse import FUSE, FuseOSError, Operations, LoggingMixIn +from fuse import FUSE, FuseOSError, Operations import pytz from django.core import management @@ -19,12 +17,13 @@ from djcelery.models import IntervalSchedule, PeriodicTask from document_indexing.models import Index, IndexInstanceNode from documents.models import Document +MAX_FILE_DESCRIPTOR = 65535 +MIN_FILE_DESCRIPTOR = 0 logger = logging.getLogger(__name__) -class IndexFS(LoggingMixIn, Operations): - @staticmethod - def path_to_node(path, index, directory_only=True): +class IndexFS(Operations): + def _path_to_node(self, path, directory_only=True): logger.debug('path: %s', path) logger.debug('directory_only: %s', directory_only) @@ -32,12 +31,12 @@ class IndexFS(LoggingMixIn, Operations): logger.debug('parts: %s', parts) - directory = index.instance_root + node = self.index.instance_root if len(parts) > 1 and parts[1] != '': for part in parts[1:]: try: - directory = directory.children.get(value=part) + node = node.children.get(value=part) except IndexInstanceNode.DoesNotExist: logger.debug('%s does not exists', part) @@ -45,44 +44,50 @@ class IndexFS(LoggingMixIn, Operations): return None else: try: - result = directory.documents.get(label=part) - logger.debug('path %s is a valid file path', path) - return result + if node.index_template_node.link_documents: + result = node.documents.get(label=part) + logger.debug('path %s is a valid file path', path) + return result + else: + return None except Document.DoesNotExist: logger.debug('path %s is a file, but is not found', path) return None - logger.debug('directory: %s', directory) - #logger.debug('directory children: %s', get_children()) - logger.debug('directory is root: %s', directory.is_root_node()) + logger.debug('node: %s', node) + logger.debug('node is root: %s', node.is_root_node()) - return directory + return node - def __init__(self): - self.fd_count = 0 + def __init__(self, index_slug): + self.fd_count = MIN_FILE_DESCRIPTOR self.fd = {} - self.index = Index.objects.first() + try: + self.index = Index.objects.get(slug=index_slug) + except Index.DoesNotExist: + print 'Unknown index.' + exit(1) def getattr(self, path, fh=None): + logger.debug('path: %s, fh: %s', path, fh) + now = time() - result = IndexFS.path_to_node(path=path, index=self.index, directory_only=False) + result = self._path_to_node(path=path, directory_only=False) if not result: raise FuseOSError(ENOENT) if isinstance(result, IndexInstanceNode): return { - 'st_mode': (S_IFDIR | 0755), 'st_ctime': now, 'st_mtime': now, + 'st_mode': (S_IFDIR | 0555), 'st_ctime': now, 'st_mtime': now, 'st_atime': now, 'st_nlink': 2 } else: - now = time() - return { - 'st_mode': S_IFREG | 0755, + 'st_mode': (S_IFREG | 0555), 'st_ctime': (result.date_added.replace(tzinfo=None) - result.date_added.utcoffset() - datetime.datetime(1970, 1, 1)).total_seconds(), 'st_mtime': (result.latest_version.timestamp.replace(tzinfo=None) - result.latest_version.timestamp.utcoffset() - datetime.datetime(1970, 1, 1)).total_seconds(), - 'st_atime': now, 'st_nlink': 1, + 'st_atime': now, 'st_size': result.size } @@ -90,55 +95,45 @@ class IndexFS(LoggingMixIn, Operations): return '' def open(self, path, flags): - result = IndexFS.path_to_node(path=path, index=self.index, directory_only=False) + result = self._path_to_node(path=path, directory_only=False) if isinstance(result, Document): self.fd_count += 1 + if self.fd_count > MAX_FILE_DESCRIPTOR: + self.fb_count = MIN_FILE_DESCRIPTOR + # TODO: implement _get_next_file_descriptor() + # TODO: don't provide a file descriptor already in use self.fd[self.fd_count] = result.open() return self.fd_count else: raiseFuseOSError(ENOENT) + def release(self, path, fh): + self.fd[fh] = None + del(self.fd[fh]) + def read(self, path, size, offset, fh): return self.fd[self.fd_count].read(size) def readdir(self, path, fh): logger.debug('path: %s', path) - ''' - parts = path.split('/') + node = self._path_to_node(path=path, directory_only=True) - directory = self.index.instance_root - - if len(parts) > 1 and parts[1] != '': - for part in parts[1:]: - try: - directory = directory.children.get(value=part) - except IndexInstanceNode.DoesNotExist: - logger.debug('%s does not exists', part) - raise FuseOSError(ENOENT) - - logger.debug('directory: %s', directory) - ''' - - directory = IndexFS.path_to_node(path=path, index=self.index, directory_only=True) - - if not directory: + if not node: raiseFuseOSError(ENOENT) result = ['.', '..'] - directories = directory.get_children().order_by('value') + for child_node in node.get_children().values_list('value', flat=True): + if '/' not in child_node: + result.append(child_node) - for directory in directories: - value = directory.value.replace('/', '_') - result.append(value) - - if directory.index_template_node.link_documents: - for document in directory.documents.all(): - value = document.label.replace('/', '_') - result.append(value) + if node.index_template_node.link_documents: + for document in node.documents.all(): + if '/' not in document.label: + result.append(document.label) return result @@ -146,5 +141,21 @@ class IndexFS(LoggingMixIn, Operations): class Command(management.BaseCommand): help = 'Mount an index as a FUSE filesystem.' + option_list = management.BaseCommand.option_list + ( + make_option( + '--index', + action='store', + dest='index', + help='Index to mirror at the mount point.' + ), + + make_option( + '--mountpoint', + action='store', + dest='mountpoint', + help='Filesystem location at which to mount the selected index.' + ), + ) + def handle(self, *args, **options): - fuse = FUSE(IndexFS(), '/tmp/mnt', foreground=True) + fuse = FUSE(operations=IndexFS(index_slug=options['index']), mountpoint=options['mountpoint'], foreground=True)