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")
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:
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 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)
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)
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)
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" )
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", )
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
def __init__(self): self.viewDocuments = DocumentHelper(self.docClass, tsumufs.dbName) if not self.parentFolder: self.parentFolder = tsumufs.viewsPoint
def __init__(self): View.__init__(self) self._syncDocs = DocumentHelper(tsumufs.SyncDocument, tsumufs.dbName)
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)