Logo Search packages:      
Sourcecode: ubuntuone-client version File versions

def ubuntuone::syncdaemon::local_rescan::LocalRescan::_compare (   self,
  dirpath,
  dirnames,
  filenames,
  all_share_dirs,
  shr_path 
) [private]

Compare the directories with the info that should be there.

Definition at line 171 of file local_rescan.py.

00171                                                                               :
        '''Compare the directories with the info that should be there.'''
        log_debug("comparing directory %r", dirpath)

        # get the share info
        shouldbe = self._paths_filter(all_share_dirs, dirpath, len(shr_path))

        def despair(message, fullname, also_children=False, also_remove=None):
            '''Something went very bad with this node, converge!'''
            log_debug(message, fullname)
            try:
                os.rename(fullname, fullname + ".conflict")
            except OSError, e:
                m = "OSError %s when trying to move to conflict file/dir %r"
                log_warning(m, e, fullname)
            self.fsm.delete_metadata(fullname)

            # if asked, remove metadata por children
            if also_children:
                log_debug("Removing also metadata from %r children", fullname)
                for path, is_dir in self.fsm.get_paths_starting_with(fullname):
                    self.fsm.delete_metadata(path)

            # if asked, remove also that file
            if also_remove is not None:
                try:
                    os.remove(also_remove)
                except OSError, e:
                    m = "OSError %s when trying to remove file %r"
                    log_warning(m, e, fullname)

        def check_stat(fullname, statinfo):
            '''Generate event if stats differ.'''
            log_debug("comp yield STAT prv: %s", statinfo)
            newstat = os.stat(fullname)
            log_debug("comp yield STAT new: %s", newstat)
            if statinfo != newstat:
                events.append(('FS_FILE_CLOSE_WRITE', fullname))

        # check all directories
        to_scan_later = []
        events = []
        for dname in dirnames:
            fullname = os.path.join(dirpath, dname)
            if dname in shouldbe:
                is_dir, statinfo, changed = shouldbe.pop(dname)
                if not is_dir:
                    # it's there, but it's a file!
                    log_debug("comp yield: file %r became a dir!", fullname)
                    events.append(('FS_FILE_DELETE', fullname))
                    events.append(('FS_DIR_CREATE', fullname))
                else:
                    if changed == "SERVER":
                        # download interrupted
                        log_debug("comp yield: dir %r in SERVER", fullname)
                        mdobj = self.fsm.get_by_path(fullname)
                        self.fsm.set_by_mdid(mdobj.mdid,
                                             server_hash=mdobj.local_hash)
                        self.fsm.remove_partial(mdobj.node_id, mdobj.share_id)
                        to_scan_later.append(fullname)
                    elif changed == "NONE":
                        # it's old, we should scan it later
                        log_debug("comp yield: dir %r will be scaned later!",
                                                                      fullname)
                        to_scan_later.append(fullname)
                    else:
                        m = "Wrong 'changed' value for %r: " + changed
                        despair(m, fullname, also_children=True)

            else:
                # hey, it's new!
                log_debug("comp yield: directory %r is new!", fullname)
                events.append(('FS_DIR_CREATE', fullname))

        # check all files
        for fname in filenames:
            fullname = os.path.join(dirpath, fname)
            if fname in shouldbe:
                is_dir, statinfo, changed = shouldbe.pop(fname)
                if is_dir:
                    log_debug("comp yield: dir %r became a file!", fullname)
                    # it's there, but it's a directory!
                    events.append(('FS_DIR_DELETE', fullname))
                    events.append(('FS_FILE_CREATE', fullname))
                else:
                    if changed == "LOCAL":
                        # upload interrupted
                        log_debug("comp yield: file %r in LOCAL state!",
                                                                    fullname)
                        events.append(('FS_FILE_CLOSE_WRITE', fullname))
                    elif changed == "NONE":
                        # what about stat info?
                        log_debug("comp yield: file %r was here.. stat?",
                                                                    fullname)
                        check_stat(fullname, statinfo)
                    elif changed == "SERVER":
                        log_debug("comp yield: file %r in SERVER", fullname)
                        mdobj = self.fsm.get_by_path(fullname)
                        self.fsm.set_by_mdid(mdobj.mdid,
                                             server_hash=mdobj.local_hash)
                        self.fsm.remove_partial(mdobj.node_id, mdobj.share_id)
                        check_stat(fullname, statinfo)
                    else:
                        m = "Wrong 'changed' value for %r: " + changed
                        despair(m, fullname)

            else:
                if fname.endswith(".partial"):
                    # a partial file! it can be a standard file, or the one
                    # inside a dir (which will be deleted in that case)
                    realname = fname[:-8]
                    realfullname = fullname[:-8]
                    if realname not in shouldbe:
                        # this is the case of a .partial with no md at all!
                        m = "Found a .partial (%r) with no metadata, removing!"
                        log_debug(m, fullname)
                        os.remove(fullname)
                        continue

                    is_dir, statinfo, changed = shouldbe.pop(realname)
                    if is_dir:
                        m = ".partial of a file that MD says it's a dir: %r"
                        despair(m, realfullname, also_remove=fullname)
                    elif changed != "SERVER":
                        m = ".partial of a file that 'changed' != SERVER: %r"
                        despair(m, realfullname, also_remove=fullname)
                    else:
                        # download interrupted
                        m = "comp yield: file %r in SERVER state!"
                        log_debug(m, fullname)
                        mdobj = self.fsm.get_by_path(realfullname)
                        self.fsm.set_by_mdid(mdobj.mdid,
                                             server_hash=mdobj.local_hash)
                        self.fsm.remove_partial(mdobj.node_id, mdobj.share_id)
                        check_stat(fullname, statinfo)

                else:
                    # hey, it's new!
                    log_debug("comp yield: file %r is new!", fullname)
                    events.append(('FS_FILE_CREATE', fullname))

                    # if it's not empty, tell to hash it and uplod
                    if os.path.getsize(fullname):
                        events.append(('FS_FILE_CLOSE_WRITE', fullname))


        # all these don't exist anymore
        for name, (is_dir, statinfo, changed) in shouldbe.iteritems():
            fullname = os.path.join(dirpath, name)
            if is_dir:
                if changed not in ("SERVER", "NONE"):
                    # bad metadata
                    m = "Bad 'changed': removing MD from dir %r and children"
                    log_debug(m, fullname)
                    children = self.fsm.get_paths_starting_with(fullname)
                    for path, is_dir in children:
                        self.fsm.delete_metadata(path)
                    continue

                log_debug("comp yield: directory %r is gone!", fullname)
                # it's a directory, didn't have any info inside?
                base_path = fullname[len(shr_path)+1:]
                to_inform = []

                # get all the info inside that dir
                for shrpath, is_dir, statinfo, _, _ in all_share_dirs:
                    if shrpath.startswith(base_path):
                        qparts = len(shrpath.split(os.path.sep))
                        to_inform.append((qparts, shrpath, is_dir))

                # order everything from more path components to less (this
                # will assure correct upgoing walk in the tree)
                to_inform.sort(reverse=True)

                # inform deletion!
                for (_, name, is_dir) in to_inform:
                    fullname = os.path.join(shr_path, name)
                    if is_dir:
                        events.append(('FS_DIR_DELETE', fullname))
                    else:
                        events.append(('FS_FILE_DELETE', fullname))
            else:
                if changed not in ("SERVER", "NONE", "LOCAL"):
                    # bad metadata
                    m = "Bad 'changed': removing MD from file %r"
                    log_debug(m, fullname)
                    self.fsm.delete_metadata(fullname)
                    continue

                log_debug("comp yield: file %r is gone!", fullname)
                events.append(('FS_FILE_DELETE', fullname))
        return events, to_scan_later

    def _paths_filter(self, all_share_dirs, dirpath, len_shr_path):


Generated by  Doxygen 1.6.0   Back to index