Пример #1
0
    def getDocuments(cls, database, tag=None, uid=None):
        helper = DocumentHelper(cls, database)

        startkey = []
        endkey = []

        if tag:
            startkey.append(tag)
            endkey.append(tag + "\u9999")
        else:
            startkey.append("_")
            endkey.append(u"\u9999")

        if uid:
            startkey.append(uid)
            endkey.append(uid + 1)

        if tag:
            for key, doc in helper.by_tag(startkey=startkey, endkey=endkey):
                yield doc

        else:
            kw = {}
            if startkey and endkey:
                kw["startkey"] = startkey
                kw["endkey"] = endkey

            for key, value in helper.by_tag(reduce=True, group_level=len(startkey), **kw):
                # This is done to spare a view, hopefully this shouldn't happen
                # very often and on a small dataset
                if uid != None and key[1] != uid:
                    continue

                yield cls(filename=key[0], dirpath=os.sep, mode=0555 | stat.S_IFDIR, type="application/x-directory")
Пример #2
0
class SyncLog(tsumufs.Debuggable):
  '''
  Class that implements a queue for storing synclog entries in. Used
  primarily by the SyncThread class.
  '''

  _syncDocuments = None
  _syncChanges   = None
  _changesSeqs   = None

  _lock          = threading.RLock()


  @benchmark
  def __init__(self):
    self._syncDocuments = DocumentHelper(tsumufs.SyncDocument,
                                         tsumufs.dbName,
                                         batch=True)
    self._syncChanges   = DocumentHelper(tsumufs.SyncChangeDocument,
                                         tsumufs.dbName,
                                         batch=True)
    self._changesSeqs   = DocumentHelper(tsumufs.ChangesSequenceDocument,
                                         tsumufs.dbName,
                                         batch=True)

  def checkpoint(self):
    '''
    Checkpoint the synclog to disk.
    '''

    self._syncChanges.commit()

  @benchmark
  def isNewFile(self, fusepath):
    '''
    Check to see if fusepath is a file the user created locally.

    Returns:
      Boolean

    Raises:
      Nothing
    '''

    try:
      self._lock.acquire()

      self.getChange(filename=fusepath, type='new', pk=True)

      return True

    except tsumufs.DocumentException, e:
      return False

    finally:
Пример #3
0
 def __init__(self):
   self._syncDocuments = DocumentHelper(tsumufs.SyncDocument,
                                        tsumufs.dbName,
                                        batch=True)
   self._syncChanges   = DocumentHelper(tsumufs.SyncChangeDocument,
                                        tsumufs.dbName,
                                        batch=True)
   self._changesSeqs   = DocumentHelper(tsumufs.ChangesSequenceDocument,
                                        tsumufs.dbName,
                                        batch=True)
Пример #4
0
  def createDesignDocuments(self):
    # Sync the design documents for the client's datatypes
    for doc_class in [ CachedRevisionDocument, DataRegionDocument, SyncChangeDocument,
                       FileChangeDocument, ChangesSequenceDocument, ChangesSequenceDocument,
                       SyncDocument, FriendDocument, NotificationDocument,
                       SortedByTypeSyncDocument, BuddySharesSyncDocument, FriendSyncDocument,
                       MySharesSyncDocument, TaggedSyncDocument ]:
        helper = DocumentHelper(doc_class, tsumufs.dbName)
        helper.sync()

    if not helper.database.get("_design/changes"):
        changesfilters = ChangesFiltersDocument()
        changesfilters._data['_id'] = "_design/changes"
        changesfilters.store(helper.database)

    if not helper.database.get("_design/replication"):
        repfilters = ReplicationFiltersDocument()
        repfilters._data['_id'] = "_design/replication"
        repfilters.store(helper.database)
Пример #5
0
    def notify(self, state):
        self.notifier = DocumentHelper(self.type, tsumufs.user.login)

        try:
            notification = self.notifier.by_subtype_and_initiator(
                key=[self.type.subtype.default, self.initiator], pk=True
            )
            notification.state = state
            self.notifier.update(notification)

        except DocumentException, e:
            self.notifier.create(initiator=self.initiator, target=tsumufs.user.login, state=state)
Пример #6
0
class EventNotifier(_Event):

    initiator = "tsumufs"

    def __init__(self, type, state=False):
        _Event.__init__(self)

        self.type = type

    def notify(self, state):
        self.notifier = DocumentHelper(self.type, tsumufs.user.login)

        try:
            notification = self.notifier.by_subtype_and_initiator(
                key=[self.type.subtype.default, self.initiator], pk=True
            )
            notification.state = state
            self.notifier.update(notification)

        except DocumentException, e:
            self.notifier.create(initiator=self.initiator, target=tsumufs.user.login, state=state)
Пример #7
0
    def getDocuments(cls, database, category=None, type=None):
        helper = DocumentHelper(SyncDocument, database)

        if type:
            assert category

            for key, doc in helper.by_type(key=[category, type]):
                yield doc

        else:
            if category:
                start = [category]
            else:
                start = []

            end = start + [{}]
            dirpath = "/" + "/".join(start)
            for key, doc in helper.by_type(startkey=start, endkey=end, group_level=len(start) + 1, reduce=True):

                yield cls(
                    filename=key[len(start)], dirpath=dirpath, mode=0555 | stat.S_IFDIR, type="application/x-directory"
                )
Пример #8
0
    def getDocuments(cls, database, buddy=None, *path):
        helper = DocumentHelper(cls, database)

        if len(path) > 0:
            login = get_user_infos(uid=int(buddy))["login"]
            for doc in helper.by_dir(key="/" + "/".join([login] + list(path))):
                yield doc

        elif buddy:
            uid = utils.get_user_infos(login=database.name)["uid"]
            provider = int(buddy)
            shared_dirs = {}
            startkey = [provider, uid]
            endkey = [provider + 1, uid]
            for key, doc in helper.by_provider_and_participant(startkey=startkey, endkey=endkey):
                if doc.type == "application/x-directory":
                    shared_dirs[doc.path] = doc
                else:
                    if doc.dirpath in shared_dirs:
                        continue
                yield doc

        else:
            uid = utils.get_user_infos(login=database.name)["uid"]
            for key, doc in helper.by_provider_and_participant(group_level=1, reduce=True):
                if key[0] != uid:
                    # Retrieve provider infos from gss api
                    infos = utils.get_user_infos(uid=key[0])
                    yield cls(
                        filename=infos["login"],
                        dirpath=os.sep,
                        mode=0555 | stat.S_IFDIR,
                        uid=infos["uid"],
                        gid=infos["gid"],
                        type="application/x-directory",
                    )
Пример #9
0
class View(tsumufs.Debuggable):
  '''
  Base class for tsumufs views development.
  Tsumufs views are virtual directories that provides custom presentation
  of the overlay files like sorting, custom appearance, staring, etc.
  This is possible since tsumufs based on CouchedFilesystem api from the
  python-ufo library that manage the metadatas of the filesystem in a
  CouchDb database.

  A tsumufs view is based on a python-ufo view, the minimal code required
  is the following:

    # Import the python-ufo view class
    from ufo.views import SortedByTypeSyncDocument

    class SortedByTypeView(View):

      # Name of the view.
      name = "Sorted by type"

      # Specify the levels of the view. Levels are the representation of
      # the depth levels of the view file tree.
      #
      # For the view that sort files by mimetype, an example tree could be:
      #
      # - "Sorted By Type" - "application"
      #                           - "pdf"
      #                           - "doc"
      #                           - "x-directory"
      #
      #                    - "text"
      #                           - "xml"
      #                           - "plain"
      #                           - "python"
      #                           - "x-empty"
      #
      levels = ['category', 'type']

      # Specify the python-ufo views class imported at head.
      docClass = SortedByTypeSyncDocument

    # Assign the tsumufs view class to the global variable viewClass
    # to allow to the view loader to know which class has to be
    # instantiated at startup.
    viewClass = SortedByTypeView

  All system calls could be called on a view instance by the views manager,
  so its could be overridden to provides a custom behavior in each view.
  If a system call is'nt overridden in the view class, the default system
  call for all view will be call.

  At the user side, views are accessible in the overlay mount point,
  in the directory specified by the tsumufs mount option 'viewspoint'.
  '''

  name = ""               # Displayed name of the view root directory.

  levels = []             # Ordered list of the depth levels names
                          # of the view.

  bindings = {}           # Hash of real files paths corresponding
                          # to virtual files paths in a view.

  docClass = None         # Document class of the view.

  fileClass = None        # File class of the view.

  viewDocuments = None    # Document helper to get the view documents.

  parentFolder = None     # Parent folder for the view.

  def __init__(self):
    self.viewDocuments = DocumentHelper(self.docClass, tsumufs.dbName)

    if not self.parentFolder:
      self.parentFolder = tsumufs.viewsPoint

  def getRootDocs(self):
    yield SyncDocument(dirpath=self.parentFolder,
                       filename=self.name,
                       mode=0555 | stat.S_IFDIR)

  def getDirents(self, path):
    '''
    Return the dirents from a view depth level. The levels correspond to
    the path nodes after the root directory of the view.

     - When the number of levels of the path is equal or higher than the
       number of the views ones, the returned document are documents
       contained in the filesystem. It's also called the 'file' level.

     - When the number of levels of the path is lower than the number of
       the views ones, documents returned are virtual folders that does'nt
       exist in the filesystem.

    This method computes the levels strings required to call the 'getDocuments'
    method of a view from the fusepath, and handles each returned documents to
    ensure unique filenames in the result dirents.
    '''

    fields = {}
    occurrences = {}

    if self.levels:
      filters = self.hackedPath(path).split('/')[1:]
      for index, filter in enumerate(filters):
        fields[self.levels[index]] = filter

    # Fills the result list with result filenames, handles duplicated
    # names and save the real paths corresponding to of virtual files paths
    # for further use.
    for doc in self.viewDocuments.getDocuments(**fields):
      try:
        if occurrences.has_key(doc.filename):
          occurrences[doc.filename] += 1
          filename, fileext = os.path.splitext(doc.filename)
          customname = filename + " (" + str(occurrences[doc.filename]) + ")" + fileext

        else:
          occurrences[doc.filename] = 0
          customname = doc.filename

        if self.isFileLevel(os.path.join(path, customname)):
          self.bindings[os.path.join(path, customname)] = os.path.join(doc.dirpath, doc.filename)

        doc.filename = customname

      except Exception, e:
        exc_info = sys.exc_info()

        self._debug('*** Unhandled exception occurred')
        self._debug('***     Type: %s' % str(exc_info[0]))
        self._debug('***    Value: %s' % str(exc_info[1]))
        self._debug('*** Traceback:')

        for line in traceback.extract_tb(exc_info[2]):
          self._debug('***    %s(%d) in %s: %s' % line)

        continue

      yield doc
Пример #10
0
  def __init__(self):
    self.viewDocuments = DocumentHelper(self.docClass, tsumufs.dbName)

    if not self.parentFolder:
      self.parentFolder = tsumufs.viewsPoint
Пример #11
0
    def __init__(self):
        View.__init__(self)

        self._syncDocs = DocumentHelper(tsumufs.SyncDocument, tsumufs.dbName)
Пример #12
0
class StaredByTagView(View, tsumufs.Debuggable):
    """
  Tsumufs view that sort the filesystem contents by tags.

  The first depth level of a view display all TAGS existing on
  files of the filesystem.

  This view is based on the python-ufo view TaggedSyncDocument,
  and provides custom behaviors for tag creation/deletion and
  assignment of tags to files.

  - Create a tag: mkdir in the 'tag' level of the view.
  - Delete a tag: unlink on a diretory in the 'tag' level of
                  a view.
  - Assign a tag: rename a file from the overlay to a directory
                  of the 'tag' level.
  """

    name = _("Stared by tag")

    levels = ["tag"]

    docClass = TaggedSyncDocument

    _pendingTags = []

    def __init__(self):
        View.__init__(self)

        self._syncDocs = DocumentHelper(tsumufs.SyncDocument, tsumufs.dbName)

    def getDirents(self, path):
        """
    Add to the result of getDirent on the parent call View,
    and add the pending tags dir to the dirents if path is at 'tag' level.
    """

        returned = []
        for dirent in View.getDirents(self, path):
            yield dirent
            returned.append(dirent.filename)

        if not path.count(os.sep):
            for tag in self._pendingTags:
                if tag not in returned:
                    yield self.docClass(filename=tag, mode=0555 | stat.S_IFDIR)
                else:
                    returned.remove(tag)

    def makeDir(self, path, mode, uid, gid):
        """
    Create a tag if path is at 'tag' level.
    """
        if self.isFileLevel(path):
            View.makeDir(self, path, mode)

        tag = os.path.basename(path)
        try:
            self._syncDocs.by_tag(key=tag, pk=True)
            raise OSError(errno.EEXIST, os.strerror(errno.EEXIST))

        except tsumufs.DocumentException, e:
            if tag in self._pendingTags:
                raise OSError(errno.EEXIST, os.strerror(errno.EEXIST))

            self._pendingTags.append(tag)