def _detect_changes(self,
                        locked_users,
                        operation_id=None,
                        UserChanges=UserChanges):
        def update_snapshot(result):
            changes.snapshot()
            return result

        def log_error(result):
            log_failure(
                result, "Error occured calling send_message in "
                "_detect_changes")

        self._provider.locked_users = locked_users
        changes = UserChanges(self._persist, self._provider)

        # Part of bug 1048576 remediation: If the flag file exists, we need to
        # do a full update of user data.
        full_refresh = os.path.exists(self.user_update_flag_file_path)
        if full_refresh:
            # Clear the record of what changes have been sent to the server in
            # order to force sending of all user data which will do one of two
            # things server side:  either the server has no user data at all,
            # in which case it will now have a complete copy, otherwise it
            # will have at least some user data which this message will
            # duplicate, provoking the server to note the inconsistency and
            # request a full resync of the user data.  Either way, the result
            # is the same: the client and server will be in sync with regard
            # to users.
            changes.clear()

        message = changes.create_diff()

        if message:
            message["type"] = "users"
            if operation_id:
                message["operation-id"] = operation_id
            result = self.registry.broker.send_message(message,
                                                       self._session_id,
                                                       urgent=True)
            result.addCallback(update_snapshot)

            # Part of bug 1048576 remediation:
            if full_refresh:
                # If we are doing a full refresh, we want to remove the flag
                # file that triggered the refresh if it completes successfully.
                result.addCallback(lambda _: self._remove_update_flag_file())

            result.addErrback(log_error)
            return result
    def test_clear(self):
        """
        L{UserChanges.clear} removes a snapshot, if present, returning
        the object to a pristine state.
        """
        users = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/sh")]
        groups = [("webdev", "x", 1000, ["jdoe"])]
        provider = FakeUserProvider(users=users, groups=groups)
        FakeUserInfo(provider=provider)

        changes = UserChanges(self.persist, provider)
        self.assertTrue(changes.create_diff())
        changes.snapshot()
        self.assertFalse(changes.create_diff())
        changes.clear()
        self.assertTrue(changes.create_diff())